mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-11 09:51:40 +00:00
* feat: chart color * fix * fix * fix: chart color * chore: changeset * chore: restore directory registry formatting * feat: add fontHeading * feat: rebuild registry * fix: v0 * refactor * fix * fix * fix * fix * fix * fix: refactor preset handling * fix * fix * fix
133 lines
3.7 KiB
TypeScript
133 lines
3.7 KiB
TypeScript
"use client"
|
|
|
|
import * as React from "react"
|
|
|
|
import { STYLES, type Preset } from "@/registry/config"
|
|
import {
|
|
Picker,
|
|
PickerContent,
|
|
PickerGroup,
|
|
PickerRadioGroup,
|
|
PickerRadioItem,
|
|
PickerTrigger,
|
|
} from "@/app/(create)/components/picker"
|
|
import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params"
|
|
|
|
export function PresetPicker({
|
|
presets,
|
|
isMobile,
|
|
anchorRef,
|
|
}: {
|
|
presets: readonly Preset[]
|
|
isMobile: boolean
|
|
anchorRef: React.RefObject<HTMLDivElement | null>
|
|
}) {
|
|
const [params, setParams] = useDesignSystemSearchParams()
|
|
|
|
const currentPreset = React.useMemo(() => {
|
|
return presets.find(
|
|
(preset) =>
|
|
preset.base === params.base &&
|
|
preset.style === params.style &&
|
|
preset.baseColor === params.baseColor &&
|
|
preset.theme === params.theme &&
|
|
preset.chartColor === params.chartColor &&
|
|
preset.iconLibrary === params.iconLibrary &&
|
|
preset.font === params.font &&
|
|
preset.fontHeading === params.fontHeading &&
|
|
preset.menuAccent === params.menuAccent &&
|
|
preset.menuColor === params.menuColor &&
|
|
preset.radius === params.radius
|
|
)
|
|
}, [
|
|
presets,
|
|
params.base,
|
|
params.style,
|
|
params.baseColor,
|
|
params.theme,
|
|
params.chartColor,
|
|
params.iconLibrary,
|
|
params.font,
|
|
params.fontHeading,
|
|
params.menuAccent,
|
|
params.menuColor,
|
|
params.radius,
|
|
])
|
|
|
|
// Filter presets for current base only
|
|
const currentBasePresets = React.useMemo(() => {
|
|
return presets.filter((preset) => preset.base === params.base)
|
|
}, [presets, params.base])
|
|
|
|
const handlePresetChange = (value: string) => {
|
|
const preset = presets.find((p) => p.title === value)
|
|
if (!preset) {
|
|
return
|
|
}
|
|
|
|
// Update all params including base.
|
|
setParams({
|
|
base: preset.base,
|
|
style: preset.style,
|
|
baseColor: preset.baseColor,
|
|
theme: preset.theme,
|
|
chartColor: preset.chartColor,
|
|
iconLibrary: preset.iconLibrary,
|
|
font: preset.font,
|
|
fontHeading: preset.fontHeading,
|
|
menuAccent: preset.menuAccent,
|
|
menuColor: preset.menuColor,
|
|
radius: preset.radius,
|
|
custom: false,
|
|
})
|
|
}
|
|
|
|
return (
|
|
<Picker>
|
|
<PickerTrigger>
|
|
<div className="flex flex-col justify-start text-left">
|
|
<div className="text-xs text-muted-foreground">Preset</div>
|
|
<div className="line-clamp-1 text-sm font-medium text-foreground">
|
|
{currentPreset?.description ?? "Custom"}
|
|
</div>
|
|
</div>
|
|
</PickerTrigger>
|
|
<PickerContent
|
|
anchor={isMobile ? anchorRef : undefined}
|
|
side={isMobile ? "top" : "right"}
|
|
align={isMobile ? "center" : "start"}
|
|
className="md:w-72"
|
|
>
|
|
<PickerRadioGroup
|
|
value={currentPreset?.title ?? ""}
|
|
onValueChange={handlePresetChange}
|
|
>
|
|
<PickerGroup>
|
|
{currentBasePresets.map((preset) => {
|
|
const style = STYLES.find((s) => s.name === preset.style)
|
|
return (
|
|
<PickerRadioItem
|
|
key={preset.title}
|
|
value={preset.title}
|
|
closeOnClick={isMobile}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
{style?.icon && (
|
|
<div className="flex size-4 shrink-0 items-center justify-center">
|
|
{React.cloneElement(style.icon, {
|
|
className: "size-4",
|
|
})}
|
|
</div>
|
|
)}
|
|
{preset.description}
|
|
</div>
|
|
</PickerRadioItem>
|
|
)
|
|
})}
|
|
</PickerGroup>
|
|
</PickerRadioGroup>
|
|
</PickerContent>
|
|
</Picker>
|
|
)
|
|
}
|