snapshot of https://github.com/shadcn-ui/ui.git (main, 2026-09-15; blobs > 131072B omitted)
This commit is contained in:
125
apps/v4/app/(app)/(create)/components/preset-picker.tsx
Normal file
125
apps/v4/app/(app)/(create)/components/preset-picker.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
|
||||
import { STYLES, type Preset } from "@/registry/config"
|
||||
import {
|
||||
Picker,
|
||||
PickerContent,
|
||||
PickerGroup,
|
||||
PickerRadioGroup,
|
||||
PickerRadioItem,
|
||||
PickerTrigger,
|
||||
} from "@/app/(app)/(create)/components/picker"
|
||||
import { useDesignSystemSearchParams } from "@/app/(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">
|
||||
{preset.description}
|
||||
</div>
|
||||
</PickerRadioItem>
|
||||
)
|
||||
})}
|
||||
</PickerGroup>
|
||||
</PickerRadioGroup>
|
||||
</PickerContent>
|
||||
</Picker>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user