fix
@@ -133,7 +133,11 @@ export function useDesignSystemSearchParams(options: Options = {}) {
|
||||
|
||||
// Use ref so setParams callback stays stable across renders.
|
||||
const paramsRef = React.useRef(params)
|
||||
paramsRef.current = params
|
||||
React.useEffect(() => {
|
||||
paramsRef.current = params
|
||||
}, [params])
|
||||
|
||||
type RawSetParamsInput = Parameters<typeof rawSetParams>[0]
|
||||
|
||||
const setParams = React.useCallback(
|
||||
(
|
||||
@@ -153,7 +157,7 @@ export function useDesignSystemSearchParams(options: Options = {}) {
|
||||
|
||||
if (!hasDesignSystemUpdate) {
|
||||
// No design system change, pass through directly.
|
||||
return rawSetParams(resolvedUpdates as any, setOptions)
|
||||
return rawSetParams(resolvedUpdates as RawSetParamsInput, setOptions)
|
||||
}
|
||||
|
||||
// Merge current decoded values with updates.
|
||||
@@ -187,7 +191,7 @@ export function useDesignSystemSearchParams(options: Options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
return rawSetParams(rawUpdate as any, setOptions)
|
||||
return rawSetParams(rawUpdate as RawSetParamsInput, setOptions)
|
||||
},
|
||||
[rawSetParams]
|
||||
)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
export const EXPLORE_PRESETS: string[] = [
|
||||
"AuFzoPZ",
|
||||
"A1zDJJ",
|
||||
"A1DN5Lx2",
|
||||
"AbZIu0W",
|
||||
"AL1Qw4",
|
||||
"A2He4G",
|
||||
"A1DOCw6i",
|
||||
"A1D5CKfo",
|
||||
"AbYAmrx",
|
||||
"auFzoPZ",
|
||||
"a1zDJJ",
|
||||
"a1DN5Lx2",
|
||||
"abZIu0W",
|
||||
"a2r6bw",
|
||||
"a2He4G",
|
||||
"a1DOCw6i",
|
||||
"a1D5CKfo",
|
||||
"abYAmrx",
|
||||
]
|
||||
|
||||
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
BIN
apps/v4/public/presets/a2r6bw-dark.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
apps/v4/public/presets/a2r6bw-light.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
@@ -202,14 +202,14 @@ export default function PreviewExample() {
|
||||
}, [params.radius])
|
||||
|
||||
return (
|
||||
<ExampleWrapper className="w-full max-w-none! lg:p-0">
|
||||
<div>
|
||||
<Example
|
||||
containerClassName="col-span-2 max-w-none"
|
||||
className="bg-muted dark:bg-background flex min-h-svh flex-col items-center justify-center border-none sm:p-16"
|
||||
className="bg-muted dark:bg-background flex min-h-svh flex-col items-center justify-center border-none p-0 sm:p-0"
|
||||
>
|
||||
<div
|
||||
data-slot="capture-target"
|
||||
className="grid max-w-4xl gap-6 p-6 lg:grid-cols-2"
|
||||
className="grid max-w-4xl gap-6 p-8 lg:grid-cols-2"
|
||||
style={
|
||||
{
|
||||
"--radius": radiusValue,
|
||||
@@ -241,7 +241,7 @@ export default function PreviewExample() {
|
||||
key={variant}
|
||||
className="flex flex-col flex-wrap items-center gap-2"
|
||||
>
|
||||
<Card
|
||||
<Item
|
||||
className="ring-border aspect-square w-full bg-(--color) ring"
|
||||
style={
|
||||
{
|
||||
@@ -294,7 +294,7 @@ export default function PreviewExample() {
|
||||
<div className="flex flex-col gap-6">
|
||||
<Card className="hidden md:flex">
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-4 place-items-center gap-6 md:grid-cols-7">
|
||||
<div className="grid grid-cols-4 place-items-center gap-4 md:grid-cols-7">
|
||||
{PREVIEW_ICONS.map((icon, index) => (
|
||||
<Card
|
||||
key={index}
|
||||
@@ -313,7 +313,7 @@ export default function PreviewExample() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="flex-1">
|
||||
<CardContent className="flex flex-col gap-6">
|
||||
<CardContent className="flex flex-1 flex-col gap-6">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button>Default</Button>
|
||||
@@ -357,7 +357,7 @@ export default function PreviewExample() {
|
||||
<Field className="flex-row">
|
||||
<Input placeholder="Name" />
|
||||
</Field>
|
||||
<Field className="flex-row">
|
||||
<Field className="flex-1 flex-row">
|
||||
<Textarea placeholder="Message" className="resize-none" />
|
||||
</Field>
|
||||
<Slider
|
||||
@@ -503,6 +503,6 @@ export default function PreviewExample() {
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
</ExampleWrapper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -202,14 +202,14 @@ export default function PreviewExample() {
|
||||
}, [params.radius])
|
||||
|
||||
return (
|
||||
<ExampleWrapper className="w-full max-w-none! lg:p-0">
|
||||
<div>
|
||||
<Example
|
||||
containerClassName="col-span-2 max-w-none"
|
||||
className="bg-muted dark:bg-background flex min-h-svh flex-col items-center justify-center border-none sm:p-16"
|
||||
className="bg-muted dark:bg-background flex min-h-svh flex-col items-center justify-center border-none p-0 sm:p-0"
|
||||
>
|
||||
<div
|
||||
data-slot="capture-target"
|
||||
className="grid max-w-4xl gap-6 p-6 lg:grid-cols-2"
|
||||
className="grid max-w-4xl gap-6 p-8 lg:grid-cols-2"
|
||||
style={
|
||||
{
|
||||
"--radius": radiusValue,
|
||||
@@ -241,7 +241,7 @@ export default function PreviewExample() {
|
||||
key={variant}
|
||||
className="flex flex-col flex-wrap items-center gap-2"
|
||||
>
|
||||
<Card
|
||||
<Item
|
||||
className="ring-border aspect-square w-full bg-(--color) ring"
|
||||
style={
|
||||
{
|
||||
@@ -294,7 +294,7 @@ export default function PreviewExample() {
|
||||
<div className="flex flex-col gap-6">
|
||||
<Card className="hidden md:flex">
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-4 place-items-center gap-6 md:grid-cols-7">
|
||||
<div className="grid grid-cols-4 place-items-center gap-4 md:grid-cols-7">
|
||||
{PREVIEW_ICONS.map((icon, index) => (
|
||||
<Card
|
||||
key={index}
|
||||
@@ -313,7 +313,7 @@ export default function PreviewExample() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="flex-1">
|
||||
<CardContent className="flex flex-col gap-6">
|
||||
<CardContent className="flex flex-1 flex-col gap-6">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button>Default</Button>
|
||||
@@ -357,7 +357,7 @@ export default function PreviewExample() {
|
||||
<Field className="flex-row">
|
||||
<Input placeholder="Name" />
|
||||
</Field>
|
||||
<Field className="flex-row">
|
||||
<Field className="flex-1 flex-row">
|
||||
<Textarea placeholder="Message" className="resize-none" />
|
||||
</Field>
|
||||
<Slider
|
||||
@@ -505,6 +505,6 @@ export default function PreviewExample() {
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
</ExampleWrapper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { decodePreset } from "shadcn/preset"
|
||||
import { EXPLORE_PRESETS } from "../lib/explore"
|
||||
|
||||
const PRESETS_PATH = path.join(process.cwd(), "public/presets")
|
||||
const force = process.argv.includes("--force")
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Capture explore preset screenshots.
|
||||
@@ -16,11 +17,13 @@ async function captureScreenshots() {
|
||||
mkdirSync(PRESETS_PATH, { recursive: true })
|
||||
}
|
||||
|
||||
const presets = EXPLORE_PRESETS.filter((code) => {
|
||||
const lightPath = path.join(PRESETS_PATH, `${code}-light.png`)
|
||||
const darkPath = path.join(PRESETS_PATH, `${code}-dark.png`)
|
||||
return !existsSync(lightPath) || !existsSync(darkPath)
|
||||
})
|
||||
const presets = force
|
||||
? EXPLORE_PRESETS
|
||||
: EXPLORE_PRESETS.filter((code) => {
|
||||
const lightPath = path.join(PRESETS_PATH, `${code}-light.png`)
|
||||
const darkPath = path.join(PRESETS_PATH, `${code}-dark.png`)
|
||||
return !existsSync(lightPath) || !existsSync(darkPath)
|
||||
})
|
||||
|
||||
if (presets.length === 0) {
|
||||
console.log("✨ All screenshots exist, nothing to capture")
|
||||
@@ -57,7 +60,7 @@ async function captureScreenshots() {
|
||||
`${code}-${theme}.png`
|
||||
)
|
||||
|
||||
if (existsSync(screenshotPath)) {
|
||||
if (!force && existsSync(screenshotPath)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ describe("encodePreset / decodePreset", () => {
|
||||
|
||||
it("should start with the version character", () => {
|
||||
const code = encodePreset(DEFAULT_PRESET_CONFIG)
|
||||
expect(code[0]).toBe("A")
|
||||
expect(code[0]).toBe("a")
|
||||
})
|
||||
|
||||
it("should handle partial config by filling defaults", () => {
|
||||
@@ -153,7 +153,7 @@ describe("decodePreset edge cases", () => {
|
||||
})
|
||||
|
||||
it("should return null for wrong version prefix", () => {
|
||||
expect(decodePreset("B123")).toBeNull()
|
||||
expect(decodePreset("b123")).toBeNull()
|
||||
})
|
||||
|
||||
it("should return null for invalid base62 characters", () => {
|
||||
@@ -196,7 +196,7 @@ describe("isValidPreset", () => {
|
||||
|
||||
it("should return false for invalid codes", () => {
|
||||
expect(isValidPreset("")).toBe(false)
|
||||
expect(isValidPreset("B123")).toBe(false)
|
||||
expect(isValidPreset("b123")).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ export const DEFAULT_PRESET_CONFIG: PresetConfig = Object.fromEntries(
|
||||
const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
// Version prefix — 'A' = version 1.
|
||||
const VERSION_CHAR = "A"
|
||||
const VERSION_CHAR = "a"
|
||||
|
||||
export function toBase62(num: number) {
|
||||
if (num === 0) return "0"
|
||||
|
||||