diff --git a/.gitignore b/.gitignore index c040854c9f..58ebd7be60 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ build # misc .DS_Store +.eslintcache *.pem # debug @@ -43,3 +44,4 @@ tsconfig.tsbuildinfo .notes .playwright-mcp shadcn-workspace +.codex-artifacts diff --git a/apps/v4/app/(app)/(root)/components/appearance-settings.tsx b/apps/v4/app/(app)/(root)/components/appearance-settings.tsx index 216c89f3e0..cf9609833e 100644 --- a/apps/v4/app/(app)/(root)/components/appearance-settings.tsx +++ b/apps/v4/app/(app)/(root)/components/appearance-settings.tsx @@ -1,8 +1,10 @@ "use client" import * as React from "react" -import { Button } from "@/examples/radix/ui/button" -import { ButtonGroup } from "@/examples/radix/ui/button-group" +import { IconMinus, IconPlus } from "@tabler/icons-react" + +import { Button } from "@/styles/radix-nova/ui/button" +import { ButtonGroup } from "@/styles/radix-nova/ui/button-group" import { Field, FieldContent, @@ -13,11 +15,10 @@ import { FieldSeparator, FieldSet, FieldTitle, -} from "@/examples/radix/ui/field" -import { Input } from "@/examples/radix/ui/input" -import { RadioGroup, RadioGroupItem } from "@/examples/radix/ui/radio-group" -import { Switch } from "@/examples/radix/ui/switch" -import { IconMinus, IconPlus } from "@tabler/icons-react" +} from "@/styles/radix-nova/ui/field" +import { Input } from "@/styles/radix-nova/ui/input" +import { RadioGroup, RadioGroupItem } from "@/styles/radix-nova/ui/radio-group" +import { Switch } from "@/styles/radix-nova/ui/switch" export function AppearanceSettings() { const [gpuCount, setGpuCount] = React.useState(8) diff --git a/apps/v4/app/(app)/(root)/components/button-group-demo.tsx b/apps/v4/app/(app)/(root)/components/button-group-demo.tsx index ccfc877544..e515c5fbda 100644 --- a/apps/v4/app/(app)/(root)/components/button-group-demo.tsx +++ b/apps/v4/app/(app)/(root)/components/button-group-demo.tsx @@ -1,8 +1,20 @@ "use client" import * as React from "react" -import { Button } from "@/examples/radix/ui/button" -import { ButtonGroup } from "@/examples/radix/ui/button-group" +import { + ArchiveIcon, + ArrowLeftIcon, + CalendarPlusIcon, + ClockIcon, + ListFilterIcon, + MailCheckIcon, + MoreHorizontalIcon, + TagIcon, + Trash2Icon, +} from "lucide-react" + +import { Button } from "@/styles/radix-nova/ui/button" +import { ButtonGroup } from "@/styles/radix-nova/ui/button-group" import { DropdownMenu, DropdownMenuContent, @@ -15,18 +27,7 @@ import { DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, -} from "@/examples/radix/ui/dropdown-menu" -import { - ArchiveIcon, - ArrowLeftIcon, - CalendarPlusIcon, - ClockIcon, - ListFilterIcon, - MailCheckIcon, - MoreHorizontalIcon, - TagIcon, - Trash2Icon, -} from "lucide-react" +} from "@/styles/radix-nova/ui/dropdown-menu" export function ButtonGroupDemo() { const [label, setLabel] = React.useState("personal") diff --git a/apps/v4/app/(app)/(root)/components/button-group-input-group.tsx b/apps/v4/app/(app)/(root)/components/button-group-input-group.tsx index 4fd4a4d964..fa871a5722 100644 --- a/apps/v4/app/(app)/(root)/components/button-group-input-group.tsx +++ b/apps/v4/app/(app)/(root)/components/button-group-input-group.tsx @@ -1,20 +1,21 @@ "use client" import * as React from "react" -import { Button } from "@/examples/radix/ui/button" -import { ButtonGroup } from "@/examples/radix/ui/button-group" +import { AudioLinesIcon, PlusIcon } from "lucide-react" + +import { Button } from "@/styles/radix-nova/ui/button" +import { ButtonGroup } from "@/styles/radix-nova/ui/button-group" import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, -} from "@/examples/radix/ui/input-group" +} from "@/styles/radix-nova/ui/input-group" import { Tooltip, TooltipContent, TooltipTrigger, -} from "@/examples/radix/ui/tooltip" -import { AudioLinesIcon, PlusIcon } from "lucide-react" +} from "@/styles/radix-nova/ui/tooltip" export function ButtonGroupInputGroup() { const [voiceEnabled, setVoiceEnabled] = React.useState(false) diff --git a/apps/v4/app/(app)/(root)/components/button-group-nested.tsx b/apps/v4/app/(app)/(root)/components/button-group-nested.tsx index e612ea740f..0226072797 100644 --- a/apps/v4/app/(app)/(root)/components/button-group-nested.tsx +++ b/apps/v4/app/(app)/(root)/components/button-group-nested.tsx @@ -1,9 +1,10 @@ "use client" -import { Button } from "@/examples/radix/ui/button" -import { ButtonGroup } from "@/examples/radix/ui/button-group" import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react" +import { Button } from "@/styles/radix-nova/ui/button" +import { ButtonGroup } from "@/styles/radix-nova/ui/button-group" + export function ButtonGroupNested() { return ( diff --git a/apps/v4/app/(app)/(root)/components/button-group-popover.tsx b/apps/v4/app/(app)/(root)/components/button-group-popover.tsx index 187b1c8787..e797d11e72 100644 --- a/apps/v4/app/(app)/(root)/components/button-group-popover.tsx +++ b/apps/v4/app/(app)/(root)/components/button-group-popover.tsx @@ -1,13 +1,14 @@ -import { Button } from "@/examples/radix/ui/button" -import { ButtonGroup } from "@/examples/radix/ui/button-group" +import { BotIcon, ChevronDownIcon } from "lucide-react" + +import { Button } from "@/styles/radix-nova/ui/button" +import { ButtonGroup } from "@/styles/radix-nova/ui/button-group" import { Popover, PopoverContent, PopoverTrigger, -} from "@/examples/radix/ui/popover" -import { Separator } from "@/examples/radix/ui/separator" -import { Textarea } from "@/examples/radix/ui/textarea" -import { BotIcon, ChevronDownIcon } from "lucide-react" +} from "@/styles/radix-nova/ui/popover" +import { Separator } from "@/styles/radix-nova/ui/separator" +import { Textarea } from "@/styles/radix-nova/ui/textarea" export function ButtonGroupPopover() { return ( diff --git a/apps/v4/app/(app)/(root)/components/empty-avatar-group.tsx b/apps/v4/app/(app)/(root)/components/empty-avatar-group.tsx index 72b9e968b1..39434bbdaa 100644 --- a/apps/v4/app/(app)/(root)/components/empty-avatar-group.tsx +++ b/apps/v4/app/(app)/(root)/components/empty-avatar-group.tsx @@ -1,10 +1,12 @@ +import { PlusIcon } from "lucide-react" + import { Avatar, AvatarFallback, AvatarGroup, AvatarImage, -} from "@/examples/radix/ui/avatar" -import { Button } from "@/examples/radix/ui/button" +} from "@/styles/radix-nova/ui/avatar" +import { Button } from "@/styles/radix-nova/ui/button" import { Empty, EmptyContent, @@ -12,8 +14,7 @@ import { EmptyHeader, EmptyMedia, EmptyTitle, -} from "@/examples/radix/ui/empty" -import { PlusIcon } from "lucide-react" +} from "@/styles/radix-nova/ui/empty" export function EmptyAvatarGroup() { return ( diff --git a/apps/v4/app/(app)/(root)/components/field-checkbox.tsx b/apps/v4/app/(app)/(root)/components/field-checkbox.tsx index 595cac1f41..8942fbd597 100644 --- a/apps/v4/app/(app)/(root)/components/field-checkbox.tsx +++ b/apps/v4/app/(app)/(root)/components/field-checkbox.tsx @@ -1,5 +1,5 @@ -import { Checkbox } from "@/examples/radix/ui/checkbox" -import { Field, FieldLabel } from "@/examples/radix/ui/field" +import { Checkbox } from "@/styles/radix-nova/ui/checkbox" +import { Field, FieldLabel } from "@/styles/radix-nova/ui/field" export function FieldCheckbox() { return ( diff --git a/apps/v4/app/(app)/(root)/components/field-demo.tsx b/apps/v4/app/(app)/(root)/components/field-demo.tsx index 0f54aa9cf6..a209ee6158 100644 --- a/apps/v4/app/(app)/(root)/components/field-demo.tsx +++ b/apps/v4/app/(app)/(root)/components/field-demo.tsx @@ -1,5 +1,5 @@ -import { Button } from "@/examples/radix/ui/button" -import { Checkbox } from "@/examples/radix/ui/checkbox" +import { Button } from "@/styles/radix-nova/ui/button" +import { Checkbox } from "@/styles/radix-nova/ui/checkbox" import { Field, FieldDescription, @@ -8,8 +8,8 @@ import { FieldLegend, FieldSeparator, FieldSet, -} from "@/examples/radix/ui/field" -import { Input } from "@/examples/radix/ui/input" +} from "@/styles/radix-nova/ui/field" +import { Input } from "@/styles/radix-nova/ui/input" import { Select, SelectContent, @@ -17,8 +17,8 @@ import { SelectItem, SelectTrigger, SelectValue, -} from "@/examples/radix/ui/select" -import { Textarea } from "@/examples/radix/ui/textarea" +} from "@/styles/radix-nova/ui/select" +import { Textarea } from "@/styles/radix-nova/ui/textarea" export function FieldDemo() { return ( diff --git a/apps/v4/app/(app)/(root)/components/field-hear.tsx b/apps/v4/app/(app)/(root)/components/field-hear.tsx index aa21c77d30..0d410f614a 100644 --- a/apps/v4/app/(app)/(root)/components/field-hear.tsx +++ b/apps/v4/app/(app)/(root)/components/field-hear.tsx @@ -1,5 +1,5 @@ -import { Card, CardContent } from "@/examples/radix/ui/card" -import { Checkbox } from "@/examples/radix/ui/checkbox" +import { Card, CardContent } from "@/styles/radix-nova/ui/card" +import { Checkbox } from "@/styles/radix-nova/ui/checkbox" import { Field, FieldDescription, @@ -8,7 +8,7 @@ import { FieldLegend, FieldSet, FieldTitle, -} from "@/examples/radix/ui/field" +} from "@/styles/radix-nova/ui/field" const options = [ { diff --git a/apps/v4/app/(app)/(root)/components/field-slider.tsx b/apps/v4/app/(app)/(root)/components/field-slider.tsx index b2ab12306c..cd44849c6f 100644 --- a/apps/v4/app/(app)/(root)/components/field-slider.tsx +++ b/apps/v4/app/(app)/(root)/components/field-slider.tsx @@ -1,8 +1,13 @@ "use client" import { useState } from "react" -import { Field, FieldDescription, FieldTitle } from "@/examples/radix/ui/field" -import { Slider } from "@/examples/radix/ui/slider" + +import { + Field, + FieldDescription, + FieldTitle, +} from "@/styles/radix-nova/ui/field" +import { Slider } from "@/styles/radix-nova/ui/slider" export function FieldSlider() { const [value, setValue] = useState([200, 800]) diff --git a/apps/v4/app/(app)/(root)/components/index.tsx b/apps/v4/app/(app)/(root)/components/index.tsx index 79640798e6..c00f9c06e1 100644 --- a/apps/v4/app/(app)/(root)/components/index.tsx +++ b/apps/v4/app/(app)/(root)/components/index.tsx @@ -1,4 +1,4 @@ -import { FieldSeparator } from "@/examples/radix/ui/field" +import { FieldSeparator } from "@/styles/radix-nova/ui/field" import { AppearanceSettings } from "./appearance-settings" import { ButtonGroupDemo } from "./button-group-demo" diff --git a/apps/v4/app/(app)/(root)/components/input-group-button.tsx b/apps/v4/app/(app)/(root)/components/input-group-button.tsx index c2ad283fbf..3880a6543f 100644 --- a/apps/v4/app/(app)/(root)/components/input-group-button.tsx +++ b/apps/v4/app/(app)/(root)/components/input-group-button.tsx @@ -1,19 +1,20 @@ "use client" import * as React from "react" +import { IconInfoCircle, IconStar } from "@tabler/icons-react" + import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, -} from "@/examples/radix/ui/input-group" -import { Label } from "@/examples/radix/ui/label" +} from "@/styles/radix-nova/ui/input-group" +import { Label } from "@/styles/radix-nova/ui/label" import { Popover, PopoverContent, PopoverTrigger, -} from "@/examples/radix/ui/popover" -import { IconInfoCircle, IconStar } from "@tabler/icons-react" +} from "@/styles/radix-nova/ui/popover" export function InputGroupButtonExample() { const [isFavorite, setIsFavorite] = React.useState(false) diff --git a/apps/v4/app/(app)/(root)/components/input-group-demo.tsx b/apps/v4/app/(app)/(root)/components/input-group-demo.tsx index ca6d52d8d4..2e4101f973 100644 --- a/apps/v4/app/(app)/(root)/components/input-group-demo.tsx +++ b/apps/v4/app/(app)/(root)/components/input-group-demo.tsx @@ -1,9 +1,12 @@ +import { IconCheck, IconInfoCircle, IconPlus } from "@tabler/icons-react" +import { ArrowUpIcon, Search } from "lucide-react" + import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "@/examples/radix/ui/dropdown-menu" +} from "@/styles/radix-nova/ui/dropdown-menu" import { InputGroup, InputGroupAddon, @@ -11,15 +14,13 @@ import { InputGroupInput, InputGroupText, InputGroupTextarea, -} from "@/examples/radix/ui/input-group" -import { Separator } from "@/examples/radix/ui/separator" +} from "@/styles/radix-nova/ui/input-group" +import { Separator } from "@/styles/radix-nova/ui/separator" import { Tooltip, TooltipContent, TooltipTrigger, -} from "@/examples/radix/ui/tooltip" -import { IconCheck, IconInfoCircle, IconPlus } from "@tabler/icons-react" -import { ArrowUpIcon, Search } from "lucide-react" +} from "@/styles/radix-nova/ui/tooltip" export function InputGroupDemo() { return ( @@ -88,7 +89,7 @@ export function InputGroupDemo() {
- +
diff --git a/apps/v4/app/(app)/(root)/components/item-demo.tsx b/apps/v4/app/(app)/(root)/components/item-demo.tsx index 2c97c53e99..9f128396c7 100644 --- a/apps/v4/app/(app)/(root)/components/item-demo.tsx +++ b/apps/v4/app/(app)/(root)/components/item-demo.tsx @@ -1,4 +1,6 @@ -import { Button } from "@/examples/radix/ui/button" +import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react" + +import { Button } from "@/styles/radix-nova/ui/button" import { Item, ItemActions, @@ -6,8 +8,7 @@ import { ItemDescription, ItemMedia, ItemTitle, -} from "@/examples/radix/ui/item" -import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react" +} from "@/styles/radix-nova/ui/item" export function ItemDemo() { return ( diff --git a/apps/v4/app/(app)/(root)/components/notion-prompt-form.tsx b/apps/v4/app/(app)/(root)/components/notion-prompt-form.tsx index 3e84b1ffa5..973c41cf3a 100644 --- a/apps/v4/app/(app)/(root)/components/notion-prompt-form.tsx +++ b/apps/v4/app/(app)/(root)/components/notion-prompt-form.tsx @@ -1,8 +1,24 @@ "use client" import { useMemo, useState } from "react" -import { Avatar, AvatarFallback, AvatarImage } from "@/examples/radix/ui/avatar" -import { Badge } from "@/examples/radix/ui/badge" +import { + IconApps, + IconArrowUp, + IconAt, + IconBook, + IconCircleDashedPlus, + IconPaperclip, + IconPlus, + IconWorld, + IconX, +} from "@tabler/icons-react" + +import { + Avatar, + AvatarFallback, + AvatarImage, +} from "@/styles/radix-nova/ui/avatar" +import { Badge } from "@/styles/radix-nova/ui/badge" import { Command, CommandEmpty, @@ -10,7 +26,7 @@ import { CommandInput, CommandItem, CommandList, -} from "@/examples/radix/ui/command" +} from "@/styles/radix-nova/ui/command" import { DropdownMenu, DropdownMenuCheckboxItem, @@ -23,36 +39,25 @@ import { DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, -} from "@/examples/radix/ui/dropdown-menu" -import { Field, FieldLabel } from "@/examples/radix/ui/field" +} from "@/styles/radix-nova/ui/dropdown-menu" +import { Field, FieldLabel } from "@/styles/radix-nova/ui/field" import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupTextarea, -} from "@/examples/radix/ui/input-group" +} from "@/styles/radix-nova/ui/input-group" import { Popover, PopoverContent, PopoverTrigger, -} from "@/examples/radix/ui/popover" -import { Switch } from "@/examples/radix/ui/switch" +} from "@/styles/radix-nova/ui/popover" +import { Switch } from "@/styles/radix-nova/ui/switch" import { Tooltip, TooltipContent, TooltipTrigger, -} from "@/examples/radix/ui/tooltip" -import { - IconApps, - IconArrowUp, - IconAt, - IconBook, - IconCircleDashedPlus, - IconPaperclip, - IconPlus, - IconWorld, - IconX, -} from "@tabler/icons-react" +} from "@/styles/radix-nova/ui/tooltip" const SAMPLE_DATA = { mentionable: [ diff --git a/apps/v4/app/(app)/(root)/components/spinner-badge.tsx b/apps/v4/app/(app)/(root)/components/spinner-badge.tsx index 3bff547115..3c6c7264d5 100644 --- a/apps/v4/app/(app)/(root)/components/spinner-badge.tsx +++ b/apps/v4/app/(app)/(root)/components/spinner-badge.tsx @@ -1,5 +1,5 @@ -import { Badge } from "@/examples/radix/ui/badge" -import { Spinner } from "@/examples/radix/ui/spinner" +import { Badge } from "@/styles/radix-nova/ui/badge" +import { Spinner } from "@/styles/radix-nova/ui/spinner" export function SpinnerBadge() { return ( diff --git a/apps/v4/app/(app)/(root)/components/spinner-empty.tsx b/apps/v4/app/(app)/(root)/components/spinner-empty.tsx index 1ff6b0b8b2..70914e98a7 100644 --- a/apps/v4/app/(app)/(root)/components/spinner-empty.tsx +++ b/apps/v4/app/(app)/(root)/components/spinner-empty.tsx @@ -1,4 +1,4 @@ -import { Button } from "@/examples/radix/ui/button" +import { Button } from "@/styles/radix-nova/ui/button" import { Empty, EmptyContent, @@ -6,8 +6,8 @@ import { EmptyHeader, EmptyMedia, EmptyTitle, -} from "@/examples/radix/ui/empty" -import { Spinner } from "@/examples/radix/ui/spinner" +} from "@/styles/radix-nova/ui/empty" +import { Spinner } from "@/styles/radix-nova/ui/spinner" export function SpinnerEmpty() { return ( diff --git a/apps/v4/app/(create)/components/accent-picker.tsx b/apps/v4/app/(app)/create/components/accent-picker.tsx similarity index 94% rename from apps/v4/app/(create)/components/accent-picker.tsx rename to apps/v4/app/(app)/create/components/accent-picker.tsx index 7ac45b58e7..ba5cc3d45f 100644 --- a/apps/v4/app/(create)/components/accent-picker.tsx +++ b/apps/v4/app/(app)/create/components/accent-picker.tsx @@ -1,7 +1,7 @@ "use client" import { MENU_ACCENTS, type MenuAccentValue } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -9,8 +9,8 @@ import { PickerRadioGroup, PickerRadioItem, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function MenuAccentPicker({ isMobile, diff --git a/apps/v4/app/(create)/components/action-menu.tsx b/apps/v4/app/(app)/create/components/action-menu.tsx similarity index 95% rename from apps/v4/app/(create)/components/action-menu.tsx rename to apps/v4/app/(app)/create/components/action-menu.tsx index 0e6b508ede..1b21088d42 100644 --- a/apps/v4/app/(create)/components/action-menu.tsx +++ b/apps/v4/app/(app)/create/components/action-menu.tsx @@ -1,6 +1,8 @@ "use client" import Script from "next/script" +import { type RegistryItem } from "shadcn/schema" + import { Command, CommandDialog, @@ -9,10 +11,8 @@ import { CommandInput, CommandItem, CommandList, -} from "@/examples/base/ui/command" -import { type RegistryItem } from "shadcn/schema" - -import { useActionMenu } from "@/app/(create)/hooks/use-action-menu" +} from "@/styles/base-nova/ui/command" +import { useActionMenu } from "@/app/(app)/create/hooks/use-action-menu" export const CMD_K_FORWARD_TYPE = "cmd-k-forward" diff --git a/apps/v4/app/(create)/components/base-color-picker.tsx b/apps/v4/app/(app)/create/components/base-color-picker.tsx similarity index 92% rename from apps/v4/app/(create)/components/base-color-picker.tsx rename to apps/v4/app/(app)/create/components/base-color-picker.tsx index e0d1ec1d7d..7dbf8cae8c 100644 --- a/apps/v4/app/(create)/components/base-color-picker.tsx +++ b/apps/v4/app/(app)/create/components/base-color-picker.tsx @@ -4,7 +4,7 @@ import * as React from "react" import { useMounted } from "@/hooks/use-mounted" import { BASE_COLORS, type BaseColorName } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -12,8 +12,8 @@ import { PickerRadioGroup, PickerRadioItem, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function BaseColorPicker({ isMobile, diff --git a/apps/v4/app/(create)/components/base-picker.tsx b/apps/v4/app/(app)/create/components/base-picker.tsx similarity index 94% rename from apps/v4/app/(create)/components/base-picker.tsx rename to apps/v4/app/(app)/create/components/base-picker.tsx index f43b11460d..43f611b36e 100644 --- a/apps/v4/app/(create)/components/base-picker.tsx +++ b/apps/v4/app/(app)/create/components/base-picker.tsx @@ -10,8 +10,8 @@ import { PickerRadioGroup, PickerRadioItem, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function BasePicker({ isMobile, diff --git a/apps/v4/app/(create)/components/chart-color-picker.tsx b/apps/v4/app/(app)/create/components/chart-color-picker.tsx similarity index 95% rename from apps/v4/app/(create)/components/chart-color-picker.tsx rename to apps/v4/app/(app)/create/components/chart-color-picker.tsx index 33b3a12a5e..3cc2b4636c 100644 --- a/apps/v4/app/(create)/components/chart-color-picker.tsx +++ b/apps/v4/app/(app)/create/components/chart-color-picker.tsx @@ -8,7 +8,7 @@ import { getThemesForBaseColor, type ChartColorName, } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -17,8 +17,8 @@ import { PickerRadioItem, PickerSeparator, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function ChartColorPicker({ isMobile, diff --git a/apps/v4/app/(create)/components/copy-preset.tsx b/apps/v4/app/(app)/create/components/copy-preset.tsx similarity index 89% rename from apps/v4/app/(create)/components/copy-preset.tsx rename to apps/v4/app/(app)/create/components/copy-preset.tsx index 7e94c8aec3..55024fbe4c 100644 --- a/apps/v4/app/(create)/components/copy-preset.tsx +++ b/apps/v4/app/(app)/create/components/copy-preset.tsx @@ -1,11 +1,11 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui/button" import { cn } from "@/lib/utils" import { copyToClipboardWithMeta } from "@/components/copy-button" -import { usePresetCode } from "@/app/(create)/hooks/use-design-system" +import { Button } from "@/styles/base-nova/ui/button" +import { usePresetCode } from "@/app/(app)/create/hooks/use-design-system" export function CopyPreset({ className }: React.ComponentProps) { const presetCode = usePresetCode() diff --git a/apps/v4/app/(create)/components/customizer.tsx b/apps/v4/app/(app)/create/components/customizer.tsx similarity index 62% rename from apps/v4/app/(create)/components/customizer.tsx rename to apps/v4/app/(app)/create/components/customizer.tsx index d42269307f..c462f73c7c 100644 --- a/apps/v4/app/(create)/components/customizer.tsx +++ b/apps/v4/app/(app)/create/components/customizer.tsx @@ -1,35 +1,36 @@ "use client" import * as React from "react" +import { type RegistryItem } from "shadcn/schema" + +import { useIsMobile } from "@/hooks/use-mobile" +import { getThemesForBaseColor, STYLES } from "@/registry/config" import { Card, CardContent, CardFooter, CardHeader, -} from "@/examples/base/ui/card" -import { FieldGroup, FieldSeparator } from "@/examples/base/ui/field" -import { type RegistryItem } from "shadcn/schema" - -import { useIsMobile } from "@/hooks/use-mobile" -import { getThemesForBaseColor, STYLES } from "@/registry/config" -import { MenuAccentPicker } from "@/app/(create)/components/accent-picker" -import { ActionMenu } from "@/app/(create)/components/action-menu" -import { BaseColorPicker } from "@/app/(create)/components/base-color-picker" -import { BasePicker } from "@/app/(create)/components/base-picker" -import { ChartColorPicker } from "@/app/(create)/components/chart-color-picker" -import { CopyPreset } from "@/app/(create)/components/copy-preset" -import { FontPicker } from "@/app/(create)/components/font-picker" -import { IconLibraryPicker } from "@/app/(create)/components/icon-library-picker" -import { MainMenu } from "@/app/(create)/components/main-menu" -import { MenuColorPicker } from "@/app/(create)/components/menu-picker" -import { RadiusPicker } from "@/app/(create)/components/radius-picker" -import { RandomButton } from "@/app/(create)/components/random-button" -import { ResetDialog } from "@/app/(create)/components/reset-button" -import { StylePicker } from "@/app/(create)/components/style-picker" -import { ThemePicker } from "@/app/(create)/components/theme-picker" -import { V0Button } from "@/app/(create)/components/v0-button" -import { FONT_HEADING_OPTIONS, FONTS } from "@/app/(create)/lib/fonts" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/styles/base-nova/ui/card" +import { FieldGroup, FieldSeparator } from "@/styles/base-nova/ui/field" +import { MenuAccentPicker } from "@/app/(app)/create/components/accent-picker" +import { ActionMenu } from "@/app/(app)/create/components/action-menu" +import { BaseColorPicker } from "@/app/(app)/create/components/base-color-picker" +import { BasePicker } from "@/app/(app)/create/components/base-picker" +import { ChartColorPicker } from "@/app/(app)/create/components/chart-color-picker" +import { CopyPreset } from "@/app/(app)/create/components/copy-preset" +import { FontPicker } from "@/app/(app)/create/components/font-picker" +import { IconLibraryPicker } from "@/app/(app)/create/components/icon-library-picker" +import { MainMenu } from "@/app/(app)/create/components/main-menu" +import { MenuColorPicker } from "@/app/(app)/create/components/menu-picker" +import { ProjectForm } from "@/app/(app)/create/components/project-form" +import { RadiusPicker } from "@/app/(app)/create/components/radius-picker" +import { RandomButton } from "@/app/(app)/create/components/random-button" +import { ResetDialog } from "@/app/(app)/create/components/reset-button" +import { StylePicker } from "@/app/(app)/create/components/style-picker" +import { ThemePicker } from "@/app/(app)/create/components/theme-picker" +import { V0Button } from "@/app/(app)/create/components/v0-button" +import { FONT_HEADING_OPTIONS, FONTS } from "@/app/(app)/create/lib/fonts" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function Customizer({ itemsByBase, @@ -56,7 +57,6 @@ export function Customizer({ - {isMobile && } + {isMobile && } - + + + + ) } diff --git a/apps/v4/app/(create)/components/design-system-provider.tsx b/apps/v4/app/(app)/create/components/design-system-provider.tsx similarity index 97% rename from apps/v4/app/(create)/components/design-system-provider.tsx rename to apps/v4/app/(app)/create/components/design-system-provider.tsx index c70d80872a..a06d973bc5 100644 --- a/apps/v4/app/(create)/components/design-system-provider.tsx +++ b/apps/v4/app/(app)/create/components/design-system-provider.tsx @@ -7,12 +7,12 @@ import { DEFAULT_CONFIG, type DesignSystemConfig, } from "@/registry/config" -import { useIframeMessageListener } from "@/app/(create)/hooks/use-iframe-sync" -import { FONTS } from "@/app/(create)/lib/fonts" +import { useIframeMessageListener } from "@/app/(app)/create/hooks/use-iframe-sync" +import { FONTS } from "@/app/(app)/create/lib/fonts" import { useDesignSystemSearchParams, type DesignSystemSearchParams, -} from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/lib/search-params" const THEME_STYLE_ELEMENT_ID = "design-system-theme-vars" const MANAGED_BODY_CLASS_PREFIXES = ["style-", "base-color-"] as const diff --git a/apps/v4/app/(create)/components/font-picker.tsx b/apps/v4/app/(app)/create/components/font-picker.tsx similarity index 93% rename from apps/v4/app/(create)/components/font-picker.tsx rename to apps/v4/app/(app)/create/components/font-picker.tsx index db2f1c0bc1..04a76e463f 100644 --- a/apps/v4/app/(create)/components/font-picker.tsx +++ b/apps/v4/app/(app)/create/components/font-picker.tsx @@ -2,7 +2,7 @@ import * as React from "react" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -12,12 +12,12 @@ import { PickerRadioItem, PickerSeparator, PickerTrigger, -} from "@/app/(create)/components/picker" -import { FONTS } from "@/app/(create)/lib/fonts" +} from "@/app/(app)/create/components/picker" +import { FONTS } from "@/app/(app)/create/lib/fonts" import { useDesignSystemSearchParams, type DesignSystemSearchParams, -} from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/lib/search-params" type FontPickerOption = { name: string @@ -97,7 +97,7 @@ export function FontPicker({
{label}
-
+
{displayFontName}
diff --git a/apps/v4/app/(create)/components/history-buttons.tsx b/apps/v4/app/(app)/create/components/history-buttons.tsx similarity index 95% rename from apps/v4/app/(create)/components/history-buttons.tsx rename to apps/v4/app/(app)/create/components/history-buttons.tsx index 391a798b5a..83f053cebc 100644 --- a/apps/v4/app/(create)/components/history-buttons.tsx +++ b/apps/v4/app/(app)/create/components/history-buttons.tsx @@ -1,11 +1,11 @@ "use client" import Script from "next/script" -import { Button } from "@/examples/base/ui/button" import { Redo02Icon, Undo02Icon } from "@hugeicons/core-free-icons" import { HugeiconsIcon } from "@hugeicons/react" -import { useHistory } from "@/app/(create)/hooks/use-history" +import { Button } from "@/styles/base-nova/ui/button" +import { useHistory } from "@/app/(app)/create/hooks/use-history" export const UNDO_FORWARD_TYPE = "undo-forward" export const REDO_FORWARD_TYPE = "redo-forward" diff --git a/apps/v4/app/(create)/components/icon-library-picker.tsx b/apps/v4/app/(app)/create/components/icon-library-picker.tsx similarity index 96% rename from apps/v4/app/(create)/components/icon-library-picker.tsx rename to apps/v4/app/(app)/create/components/icon-library-picker.tsx index 302bbc6fe3..f3a0c4c6ec 100644 --- a/apps/v4/app/(create)/components/icon-library-picker.tsx +++ b/apps/v4/app/(app)/create/components/icon-library-picker.tsx @@ -3,7 +3,7 @@ import * as React from "react" import { iconLibraries, type IconLibraryName } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -11,8 +11,8 @@ import { PickerRadioGroup, PickerRadioItem, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" const logos = { lucide: ( diff --git a/apps/v4/app/(app)/create/components/icon-placeholder.tsx b/apps/v4/app/(app)/create/components/icon-placeholder.tsx new file mode 100644 index 0000000000..a7f100648c --- /dev/null +++ b/apps/v4/app/(app)/create/components/icon-placeholder.tsx @@ -0,0 +1,75 @@ +"use client" + +import { lazy, Suspense } from "react" +import { SquareIcon } from "lucide-react" +import type { IconLibraryName } from "shadcn/icons" + +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" + +const IconLucide = lazy(() => + import("@/registry/icons/icon-lucide").then((mod) => ({ + default: mod.IconLucide, + })) +) + +const IconTabler = lazy(() => + import("@/registry/icons/icon-tabler").then((mod) => ({ + default: mod.IconTabler, + })) +) + +const IconHugeicons = lazy(() => + import("@/registry/icons/icon-hugeicons").then((mod) => ({ + default: mod.IconHugeicons, + })) +) + +const IconPhosphor = lazy(() => + import("@/registry/icons/icon-phosphor").then((mod) => ({ + default: mod.IconPhosphor, + })) +) + +const IconRemixicon = lazy(() => + import("@/registry/icons/icon-remixicon").then((mod) => ({ + default: mod.IconRemixicon, + })) +) + +// Preload all icon renderer modules so switching libraries is instant. +// These warm the browser module cache; React.lazy resolves immediately +// for modules that are already loaded. +void import("@/registry/icons/icon-lucide") +void import("@/registry/icons/icon-tabler") +void import("@/registry/icons/icon-hugeicons") +void import("@/registry/icons/icon-phosphor") +void import("@/registry/icons/icon-remixicon") + +export function IconPlaceholder({ + ...props +}: { + [K in IconLibraryName]: string +} & React.ComponentProps<"svg">) { + const [{ iconLibrary }] = useDesignSystemSearchParams() + const iconName = props[iconLibrary] + + if (!iconName) { + return null + } + + return ( + }> + {iconLibrary === "lucide" && } + {iconLibrary === "tabler" && } + {iconLibrary === "hugeicons" && ( + + )} + {iconLibrary === "phosphor" && ( + + )} + {iconLibrary === "remixicon" && ( + + )} + + ) +} diff --git a/apps/v4/app/(create)/components/item-explorer.tsx b/apps/v4/app/(app)/create/components/item-explorer.tsx similarity index 94% rename from apps/v4/app/(create)/components/item-explorer.tsx rename to apps/v4/app/(app)/create/components/item-explorer.tsx index 022dbd82ae..dc5a46af34 100644 --- a/apps/v4/app/(create)/components/item-explorer.tsx +++ b/apps/v4/app/(app)/create/components/item-explorer.tsx @@ -2,11 +2,16 @@ import * as React from "react" import Link from "next/link" +import { ChevronRightIcon } from "lucide-react" +import { type RegistryItem } from "shadcn/schema" + +import { cn } from "@/lib/utils" +import { type Base } from "@/registry/bases" import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from "@/examples/base/ui/collapsible" +} from "@/styles/base-nova/ui/collapsible" import { Sidebar, SidebarContent, @@ -15,14 +20,9 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, -} from "@/examples/base/ui/sidebar" -import { ChevronRightIcon } from "lucide-react" -import { type RegistryItem } from "shadcn/schema" - -import { cn } from "@/lib/utils" -import { type Base } from "@/registry/bases" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" -import { groupItemsByType } from "@/app/(create)/lib/utils" +} from "@/styles/base-nova/ui/sidebar" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" +import { groupItemsByType } from "@/app/(app)/create/lib/utils" const cachedGroupedItems = React.cache( (items: Pick[]) => { diff --git a/apps/v4/app/(create)/components/lock-button.tsx b/apps/v4/app/(app)/create/components/lock-button.tsx similarity index 92% rename from apps/v4/app/(create)/components/lock-button.tsx rename to apps/v4/app/(app)/create/components/lock-button.tsx index f082c2c8e1..067804d585 100644 --- a/apps/v4/app/(create)/components/lock-button.tsx +++ b/apps/v4/app/(app)/create/components/lock-button.tsx @@ -7,7 +7,10 @@ import { import { HugeiconsIcon } from "@hugeicons/react" import { cn } from "@/lib/utils" -import { useLocks, type LockableParam } from "@/app/(create)/hooks/use-locks" +import { + useLocks, + type LockableParam, +} from "@/app/(app)/create/hooks/use-locks" export function LockButton({ param, diff --git a/apps/v4/app/(create)/components/main-menu.tsx b/apps/v4/app/(app)/create/components/main-menu.tsx similarity index 85% rename from apps/v4/app/(create)/components/main-menu.tsx rename to apps/v4/app/(app)/create/components/main-menu.tsx index 6663ce680f..75c3839358 100644 --- a/apps/v4/app/(create)/components/main-menu.tsx +++ b/apps/v4/app/(app)/create/components/main-menu.tsx @@ -1,11 +1,11 @@ "use client" import * as React from "react" -import { type Button } from "@/examples/base/ui/button" import { Menu09Icon } from "@hugeicons/core-free-icons" import { HugeiconsIcon } from "@hugeicons/react" import { cn } from "@/lib/utils" +import { type Button } from "@/styles/base-nova/ui/button" import { Picker, PickerContent, @@ -14,12 +14,12 @@ import { PickerSeparator, PickerShortcut, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useActionMenuTrigger } from "@/app/(create)/hooks/use-action-menu" -import { useHistory } from "@/app/(create)/hooks/use-history" -import { useRandom } from "@/app/(create)/hooks/use-random" -import { useReset } from "@/app/(create)/hooks/use-reset" -import { useThemeToggle } from "@/app/(create)/hooks/use-theme-toggle" +} from "@/app/(app)/create/components/picker" +import { useActionMenuTrigger } from "@/app/(app)/create/hooks/use-action-menu" +import { useHistory } from "@/app/(app)/create/hooks/use-history" +import { useRandom } from "@/app/(app)/create/hooks/use-random" +import { useReset } from "@/app/(app)/create/hooks/use-reset" +import { useThemeToggle } from "@/app/(app)/create/hooks/use-theme-toggle" const APPLE_PLATFORM_REGEX = /Mac|iPhone|iPad|iPod/ diff --git a/apps/v4/app/(create)/components/menu-picker.tsx b/apps/v4/app/(app)/create/components/menu-picker.tsx similarity index 96% rename from apps/v4/app/(create)/components/menu-picker.tsx rename to apps/v4/app/(app)/create/components/menu-picker.tsx index ce86d7fc71..be9e692ce9 100644 --- a/apps/v4/app/(create)/components/menu-picker.tsx +++ b/apps/v4/app/(app)/create/components/menu-picker.tsx @@ -7,7 +7,7 @@ import { useTheme } from "next-themes" import { useMounted } from "@/hooks/use-mounted" import { type MenuColorValue } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -17,11 +17,11 @@ import { PickerRadioItem, PickerSeparator, PickerTrigger, -} from "@/app/(create)/components/picker" +} from "@/app/(app)/create/components/picker" import { isTranslucentMenuColor, useDesignSystemSearchParams, -} from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/lib/search-params" type ColorChoice = "default" | "inverted" type SurfaceChoice = "solid" | "translucent" diff --git a/apps/v4/app/(create)/components/mode-switcher.tsx b/apps/v4/app/(app)/create/components/mode-switcher.tsx similarity index 94% rename from apps/v4/app/(create)/components/mode-switcher.tsx rename to apps/v4/app/(app)/create/components/mode-switcher.tsx index 4356113c82..6cd8b4d94a 100644 --- a/apps/v4/app/(create)/components/mode-switcher.tsx +++ b/apps/v4/app/(app)/create/components/mode-switcher.tsx @@ -2,10 +2,10 @@ import * as React from "react" import Script from "next/script" -import { Button } from "@/examples/base/ui/button" import { cn } from "@/lib/utils" -import { useThemeToggle } from "@/app/(create)/hooks/use-theme-toggle" +import { Button } from "@/styles/base-nova/ui/button" +import { useThemeToggle } from "@/app/(app)/create/hooks/use-theme-toggle" export const DARK_MODE_FORWARD_TYPE = "dark-mode-forward" diff --git a/apps/v4/app/(create)/components/picker.tsx b/apps/v4/app/(app)/create/components/picker.tsx similarity index 98% rename from apps/v4/app/(create)/components/picker.tsx rename to apps/v4/app/(app)/create/components/picker.tsx index 8e2775389f..44b647d859 100644 --- a/apps/v4/app/(create)/components/picker.tsx +++ b/apps/v4/app/(app)/create/components/picker.tsx @@ -4,7 +4,7 @@ import * as React from "react" import { Menu as MenuPrimitive } from "@base-ui/react/menu" import { cn } from "@/registry/bases/base/lib/utils" -import { IconPlaceholder } from "@/app/(create)/components/icon-placeholder" +import { IconPlaceholder } from "@/app/(app)/create/components/icon-placeholder" function Picker({ ...props }: MenuPrimitive.Root.Props) { return @@ -19,7 +19,7 @@ function PickerTrigger({ className, ...props }: MenuPrimitive.Trigger.Props) {
- {style?.icon && ( -
- {React.cloneElement(style.icon, { - className: "size-4", - })} -
- )} {preset.description}
diff --git a/apps/v4/app/(create)/components/preview-style.tsx b/apps/v4/app/(app)/create/components/preview-style.tsx similarity index 100% rename from apps/v4/app/(create)/components/preview-style.tsx rename to apps/v4/app/(app)/create/components/preview-style.tsx diff --git a/apps/v4/app/(app)/create/components/preview-switcher.tsx b/apps/v4/app/(app)/create/components/preview-switcher.tsx new file mode 100644 index 0000000000..1daf933785 --- /dev/null +++ b/apps/v4/app/(app)/create/components/preview-switcher.tsx @@ -0,0 +1,37 @@ +"use client" + +import { Button } from "@/registry/new-york-v4/ui/button" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" + +const PREVIEW_ITEMS = [ + { label: "01", value: "preview-02" }, + { label: "02", value: "preview" }, +] + +export function PreviewSwitcher() { + const [params, setParams] = useDesignSystemSearchParams() + + const isPreview = + params.item === "preview" || params.item.startsWith("preview-0") + + if (!isPreview) { + return null + } + + return ( +
+ {PREVIEW_ITEMS.map((item) => ( + + ))} +
+ ) +} diff --git a/apps/v4/app/(create)/components/preview.tsx b/apps/v4/app/(app)/create/components/preview.tsx similarity index 86% rename from apps/v4/app/(create)/components/preview.tsx rename to apps/v4/app/(app)/create/components/preview.tsx index 06bbffcdbc..56ab4e6c5e 100644 --- a/apps/v4/app/(create)/components/preview.tsx +++ b/apps/v4/app/(app)/create/components/preview.tsx @@ -2,19 +2,20 @@ import * as React from "react" -import { CMD_K_FORWARD_TYPE } from "@/app/(create)/components/action-menu" +import { CMD_K_FORWARD_TYPE } from "@/app/(app)/create/components/action-menu" import { REDO_FORWARD_TYPE, UNDO_FORWARD_TYPE, -} from "@/app/(create)/components/history-buttons" -import { DARK_MODE_FORWARD_TYPE } from "@/app/(create)/components/mode-switcher" -import { RANDOMIZE_FORWARD_TYPE } from "@/app/(create)/components/random-button" -import { sendToIframe } from "@/app/(create)/hooks/use-iframe-sync" -import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset" +} from "@/app/(app)/create/components/history-buttons" +import { DARK_MODE_FORWARD_TYPE } from "@/app/(app)/create/components/mode-switcher" +import { PreviewSwitcher } from "@/app/(app)/create/components/preview-switcher" +import { RANDOMIZE_FORWARD_TYPE } from "@/app/(app)/create/components/random-button" +import { sendToIframe } from "@/app/(app)/create/hooks/use-iframe-sync" +import { RESET_FORWARD_TYPE } from "@/app/(app)/create/hooks/use-reset" import { serializeDesignSystemSearchParams, useDesignSystemSearchParams, -} from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/lib/search-params" // Hoisted — avoids recreating on every message event. (js-hoist-regexp) const MAC_REGEX = /Mac|iPhone|iPad|iPod/ @@ -147,6 +148,7 @@ export function Preview() { title="Preview" />
+ ) } diff --git a/apps/v4/app/(create)/components/project-form.tsx b/apps/v4/app/(app)/create/components/project-form.tsx similarity index 96% rename from apps/v4/app/(create)/components/project-form.tsx rename to apps/v4/app/(app)/create/components/project-form.tsx index 5e879cb318..5d900ae107 100644 --- a/apps/v4/app/(create)/components/project-form.tsx +++ b/apps/v4/app/(app)/create/components/project-form.tsx @@ -1,7 +1,14 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui/button" +import { Copy01Icon, Globe02Icon, Tick02Icon } from "@hugeicons/core-free-icons" +import { HugeiconsIcon } from "@hugeicons/react" + +import { cn } from "@/lib/utils" +import { useConfig } from "@/hooks/use-config" +import { copyToClipboardWithMeta } from "@/components/copy-button" +import { BASES, type BaseName } from "@/registry/config" +import { Button } from "@/styles/base-nova/ui/button" import { Dialog, DialogContent, @@ -10,7 +17,7 @@ import { DialogHeader, DialogTitle, DialogTrigger, -} from "@/examples/base/ui/dialog" +} from "@/styles/base-nova/ui/dialog" import { Field, FieldContent, @@ -20,33 +27,26 @@ import { FieldSeparator, FieldSet, FieldTitle, -} from "@/examples/base/ui/field" -import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group" -import { Switch } from "@/examples/base/ui/switch" +} from "@/styles/base-nova/ui/field" +import { RadioGroup, RadioGroupItem } from "@/styles/base-nova/ui/radio-group" +import { Switch } from "@/styles/base-nova/ui/switch" import { Tabs, TabsContent, TabsList, TabsTrigger, -} from "@/examples/base/ui/tabs" -import { Copy01Icon, Globe02Icon, Tick02Icon } from "@hugeicons/core-free-icons" -import { HugeiconsIcon } from "@hugeicons/react" - -import { cn } from "@/lib/utils" -import { useConfig } from "@/hooks/use-config" -import { copyToClipboardWithMeta } from "@/components/copy-button" -import { BASES, type BaseName } from "@/registry/config" -import { usePresetCode } from "@/app/(create)/hooks/use-design-system" +} from "@/styles/base-nova/ui/tabs" +import { usePresetCode } from "@/app/(app)/create/hooks/use-design-system" import { useDesignSystemSearchParams, type DesignSystemSearchParams, -} from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/lib/search-params" import { getFramework, getTemplateValue, NO_MONOREPO_FRAMEWORKS, TEMPLATES, -} from "@/app/(create)/lib/templates" +} from "@/app/(app)/create/lib/templates" const TURBOREPO_LOGO = 'Turborepo' diff --git a/apps/v4/app/(create)/components/radius-picker.tsx b/apps/v4/app/(app)/create/components/radius-picker.tsx similarity index 94% rename from apps/v4/app/(create)/components/radius-picker.tsx rename to apps/v4/app/(app)/create/components/radius-picker.tsx index 05653604bb..5107afa28c 100644 --- a/apps/v4/app/(create)/components/radius-picker.tsx +++ b/apps/v4/app/(app)/create/components/radius-picker.tsx @@ -3,7 +3,7 @@ import * as React from "react" import { RADII, type RadiusValue } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -12,8 +12,8 @@ import { PickerRadioItem, PickerSeparator, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function RadiusPicker({ isMobile, diff --git a/apps/v4/app/(create)/components/random-button.tsx b/apps/v4/app/(app)/create/components/random-button.tsx similarity index 91% rename from apps/v4/app/(create)/components/random-button.tsx rename to apps/v4/app/(app)/create/components/random-button.tsx index d57d2609ab..543fc88f00 100644 --- a/apps/v4/app/(create)/components/random-button.tsx +++ b/apps/v4/app/(app)/create/components/random-button.tsx @@ -1,13 +1,13 @@ "use client" import Script from "next/script" -import { Button } from "@/examples/base/ui/button" import { DiceFaces05Icon } from "@hugeicons/core-free-icons" import { HugeiconsIcon } from "@hugeicons/react" import { cn } from "@/lib/utils" -import { useRandom } from "@/app/(create)/hooks/use-random" -import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset" +import { Button } from "@/styles/base-nova/ui/button" +import { useRandom } from "@/app/(app)/create/hooks/use-random" +import { RESET_FORWARD_TYPE } from "@/app/(app)/create/hooks/use-reset" export const RANDOMIZE_FORWARD_TYPE = "randomize-forward" diff --git a/apps/v4/app/(create)/components/reset-button.tsx b/apps/v4/app/(app)/create/components/reset-button.tsx similarity index 89% rename from apps/v4/app/(create)/components/reset-button.tsx rename to apps/v4/app/(app)/create/components/reset-button.tsx index c68e4301c2..99ff122a8f 100644 --- a/apps/v4/app/(create)/components/reset-button.tsx +++ b/apps/v4/app/(app)/create/components/reset-button.tsx @@ -9,9 +9,8 @@ import { AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, -} from "@/examples/base/ui/alert-dialog" - -import { useReset } from "@/app/(create)/hooks/use-reset" +} from "@/styles/base-nova/ui/alert-dialog" +import { useReset } from "@/app/(app)/create/hooks/use-reset" export function ResetDialog() { const { showResetDialog, setShowResetDialog, confirmReset } = useReset() diff --git a/apps/v4/app/(create)/components/share-button.tsx b/apps/v4/app/(app)/create/components/share-button.tsx similarity index 87% rename from apps/v4/app/(create)/components/share-button.tsx rename to apps/v4/app/(app)/create/components/share-button.tsx index 51c118cf2e..c88a1ff490 100644 --- a/apps/v4/app/(create)/components/share-button.tsx +++ b/apps/v4/app/(app)/create/components/share-button.tsx @@ -1,13 +1,13 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui/button" import { Share03Icon, Tick02Icon } from "@hugeicons/core-free-icons" import { HugeiconsIcon } from "@hugeicons/react" import { copyToClipboardWithMeta } from "@/components/copy-button" -import { usePresetCode } from "@/app/(create)/hooks/use-design-system" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +import { Button } from "@/styles/base-nova/ui/button" +import { usePresetCode } from "@/app/(app)/create/hooks/use-design-system" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function ShareButton() { const [params] = useDesignSystemSearchParams() diff --git a/apps/v4/app/(create)/components/style-picker.tsx b/apps/v4/app/(app)/create/components/style-picker.tsx similarity index 91% rename from apps/v4/app/(create)/components/style-picker.tsx rename to apps/v4/app/(app)/create/components/style-picker.tsx index 511df2bca9..5d2dc2f975 100644 --- a/apps/v4/app/(create)/components/style-picker.tsx +++ b/apps/v4/app/(app)/create/components/style-picker.tsx @@ -3,7 +3,7 @@ import * as React from "react" import { type Style, type StyleName } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -11,8 +11,8 @@ import { PickerRadioGroup, PickerRadioItem, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function StylePicker({ styles, diff --git a/apps/v4/app/(create)/components/theme-picker.tsx b/apps/v4/app/(app)/create/components/theme-picker.tsx similarity index 94% rename from apps/v4/app/(create)/components/theme-picker.tsx rename to apps/v4/app/(app)/create/components/theme-picker.tsx index 00a7f52eaf..b3d3b47c69 100644 --- a/apps/v4/app/(create)/components/theme-picker.tsx +++ b/apps/v4/app/(app)/create/components/theme-picker.tsx @@ -4,7 +4,7 @@ import * as React from "react" import { useMounted } from "@/hooks/use-mounted" import { BASE_COLORS, type Theme, type ThemeName } from "@/registry/config" -import { LockButton } from "@/app/(create)/components/lock-button" +import { LockButton } from "@/app/(app)/create/components/lock-button" import { Picker, PickerContent, @@ -13,8 +13,8 @@ import { PickerRadioItem, PickerSeparator, PickerTrigger, -} from "@/app/(create)/components/picker" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/components/picker" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function ThemePicker({ themes, diff --git a/apps/v4/app/(create)/components/v0-button.tsx b/apps/v4/app/(app)/create/components/v0-button.tsx similarity index 88% rename from apps/v4/app/(create)/components/v0-button.tsx rename to apps/v4/app/(app)/create/components/v0-button.tsx index 627065d0e5..eaff8b17b5 100644 --- a/apps/v4/app/(create)/components/v0-button.tsx +++ b/apps/v4/app/(app)/create/components/v0-button.tsx @@ -1,14 +1,14 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui/button" -import { Skeleton } from "@/examples/base/ui/skeleton" import { cn } from "@/lib/utils" import { useIsMobile } from "@/hooks/use-mobile" import { useMounted } from "@/hooks/use-mounted" import { Icons } from "@/components/icons" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +import { Button } from "@/styles/base-nova/ui/button" +import { Skeleton } from "@/styles/base-nova/ui/skeleton" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" export function V0Button({ className }: { className?: string }) { const [params] = useDesignSystemSearchParams() diff --git a/apps/v4/app/(create)/components/welcome-dialog.tsx b/apps/v4/app/(app)/create/components/welcome-dialog.tsx similarity index 95% rename from apps/v4/app/(create)/components/welcome-dialog.tsx rename to apps/v4/app/(app)/create/components/welcome-dialog.tsx index 15a98d6d45..885df46a4a 100644 --- a/apps/v4/app/(create)/components/welcome-dialog.tsx +++ b/apps/v4/app/(app)/create/components/welcome-dialog.tsx @@ -1,7 +1,9 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui/button" + +import { Icons } from "@/components/icons" +import { Button } from "@/styles/base-nova/ui/button" import { Dialog, DialogClose, @@ -10,9 +12,7 @@ import { DialogFooter, DialogHeader, DialogTitle, -} from "@/examples/base/ui/dialog" - -import { Icons } from "@/components/icons" +} from "@/styles/base-nova/ui/dialog" const STORAGE_KEY = "shadcn-create-welcome-dialog" diff --git a/apps/v4/app/(create)/hooks/use-action-menu.ts b/apps/v4/app/(app)/create/hooks/use-action-menu.ts similarity index 95% rename from apps/v4/app/(create)/hooks/use-action-menu.ts rename to apps/v4/app/(app)/create/hooks/use-action-menu.ts index 59b03b975f..0ad363e74b 100644 --- a/apps/v4/app/(create)/hooks/use-action-menu.ts +++ b/apps/v4/app/(app)/create/hooks/use-action-menu.ts @@ -4,8 +4,8 @@ import * as React from "react" import { type RegistryItem } from "shadcn/schema" import useSWR from "swr" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" -import { groupItemsByType } from "@/app/(create)/lib/utils" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" +import { groupItemsByType } from "@/app/(app)/create/lib/utils" const ACTION_MENU_OPEN_KEY = "create:action-menu-open" diff --git a/apps/v4/app/(create)/hooks/use-design-system.ts b/apps/v4/app/(app)/create/hooks/use-design-system.ts similarity index 58% rename from apps/v4/app/(create)/hooks/use-design-system.ts rename to apps/v4/app/(app)/create/hooks/use-design-system.ts index 54a3368190..05f92c83e0 100644 --- a/apps/v4/app/(create)/hooks/use-design-system.ts +++ b/apps/v4/app/(app)/create/hooks/use-design-system.ts @@ -1,7 +1,7 @@ "use client" -import { getPresetCode } from "@/app/(create)/lib/preset-code" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +import { getPresetCode } from "@/app/(app)/create/lib/preset-code" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" // Returns the canonical preset code derived from the current search params. export function usePresetCode() { diff --git a/apps/v4/app/(create)/hooks/use-history.tsx b/apps/v4/app/(app)/create/hooks/use-history.tsx similarity index 100% rename from apps/v4/app/(create)/hooks/use-history.tsx rename to apps/v4/app/(app)/create/hooks/use-history.tsx diff --git a/apps/v4/app/(create)/hooks/use-iframe-sync.tsx b/apps/v4/app/(app)/create/hooks/use-iframe-sync.tsx similarity index 94% rename from apps/v4/app/(create)/hooks/use-iframe-sync.tsx rename to apps/v4/app/(app)/create/hooks/use-iframe-sync.tsx index ec0bc70ad3..64b4c58ae6 100644 --- a/apps/v4/app/(create)/hooks/use-iframe-sync.tsx +++ b/apps/v4/app/(app)/create/hooks/use-iframe-sync.tsx @@ -2,7 +2,7 @@ import * as React from "react" -import type { DesignSystemSearchParams } from "@/app/(create)/lib/search-params" +import type { DesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" type ParentToIframeMessage = { type: "design-system-params" diff --git a/apps/v4/app/(create)/hooks/use-locks.tsx b/apps/v4/app/(app)/create/hooks/use-locks.tsx similarity index 100% rename from apps/v4/app/(create)/hooks/use-locks.tsx rename to apps/v4/app/(app)/create/hooks/use-locks.tsx diff --git a/apps/v4/app/(create)/hooks/use-random.tsx b/apps/v4/app/(app)/create/hooks/use-random.tsx similarity index 96% rename from apps/v4/app/(create)/hooks/use-random.tsx rename to apps/v4/app/(app)/create/hooks/use-random.tsx index 6ed818ccc8..45867c8a0b 100644 --- a/apps/v4/app/(create)/hooks/use-random.tsx +++ b/apps/v4/app/(app)/create/hooks/use-random.tsx @@ -12,17 +12,17 @@ import { STYLES, type FontHeadingValue, } from "@/registry/config" -import { useLocks } from "@/app/(create)/hooks/use-locks" -import { FONTS } from "@/app/(create)/lib/fonts" +import { useLocks } from "@/app/(app)/create/hooks/use-locks" +import { FONTS } from "@/app/(app)/create/lib/fonts" import { applyBias, RANDOMIZE_BIASES, type RandomizeContext, -} from "@/app/(create)/lib/randomize-biases" +} from "@/app/(app)/create/lib/randomize-biases" import { isTranslucentMenuColor, useDesignSystemSearchParams, -} from "@/app/(create)/lib/search-params" +} from "@/app/(app)/create/lib/search-params" function randomItem(array: readonly T[]): T { return array[Math.floor(Math.random() * array.length)] diff --git a/apps/v4/app/(create)/hooks/use-reset.tsx b/apps/v4/app/(app)/create/hooks/use-reset.tsx similarity index 77% rename from apps/v4/app/(create)/hooks/use-reset.tsx rename to apps/v4/app/(app)/create/hooks/use-reset.tsx index ad90419fc2..52e6b78897 100644 --- a/apps/v4/app/(create)/hooks/use-reset.tsx +++ b/apps/v4/app/(app)/create/hooks/use-reset.tsx @@ -3,8 +3,8 @@ import * as React from "react" import useSWR from "swr" -import { DEFAULT_CONFIG } from "@/registry/config" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +import { DEFAULT_CONFIG, PRESETS } from "@/registry/config" +import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" const RESET_DIALOG_KEY = "create:reset-dialog-open" export const RESET_FORWARD_TYPE = "reset-forward" @@ -20,22 +20,27 @@ export function useReset() { }) const reset = React.useCallback(() => { + const preset = + PRESETS.find( + (preset) => preset.base === params.base && preset.style === params.style + ) ?? DEFAULT_CONFIG + setParams({ base: params.base, - style: DEFAULT_CONFIG.style, - baseColor: DEFAULT_CONFIG.baseColor, - theme: DEFAULT_CONFIG.theme, - chartColor: DEFAULT_CONFIG.chartColor, - iconLibrary: DEFAULT_CONFIG.iconLibrary, - font: DEFAULT_CONFIG.font, - fontHeading: DEFAULT_CONFIG.fontHeading, - menuAccent: DEFAULT_CONFIG.menuAccent, - menuColor: DEFAULT_CONFIG.menuColor, - radius: DEFAULT_CONFIG.radius, + style: params.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, template: DEFAULT_CONFIG.template, item: params.item, }) - }, [setParams, params.base, params.item]) + }, [setParams, params.base, params.style, params.item]) const handleShowResetDialogChange = React.useCallback( (open: boolean) => { diff --git a/apps/v4/app/(create)/hooks/use-theme-toggle.tsx b/apps/v4/app/(app)/create/hooks/use-theme-toggle.tsx similarity index 100% rename from apps/v4/app/(create)/hooks/use-theme-toggle.tsx rename to apps/v4/app/(app)/create/hooks/use-theme-toggle.tsx diff --git a/apps/v4/app/(create)/create/layout.tsx b/apps/v4/app/(app)/create/layout.tsx similarity index 66% rename from apps/v4/app/(create)/create/layout.tsx rename to apps/v4/app/(app)/create/layout.tsx index 6c80ef2294..a137fdbc4b 100644 --- a/apps/v4/app/(create)/create/layout.tsx +++ b/apps/v4/app/(app)/create/layout.tsx @@ -1,7 +1,7 @@ import { Suspense } from "react" -import { HistoryProvider } from "@/app/(create)/hooks/use-history" -import { LocksProvider } from "@/app/(create)/hooks/use-locks" +import { HistoryProvider } from "@/app/(app)/create/hooks/use-history" +import { LocksProvider } from "@/app/(app)/create/hooks/use-locks" export default function CreateLayout({ children, diff --git a/apps/v4/app/(create)/lib/api.ts b/apps/v4/app/(app)/create/lib/api.ts similarity index 97% rename from apps/v4/app/(create)/lib/api.ts rename to apps/v4/app/(app)/create/lib/api.ts index a44815d84d..d88bce87a0 100644 --- a/apps/v4/app/(create)/lib/api.ts +++ b/apps/v4/app/(app)/create/lib/api.ts @@ -6,7 +6,7 @@ import { BASES, getThemesForBaseColor, type BaseName } from "@/registry/config" import { ALLOWED_ITEM_TYPES, EXCLUDED_ITEMS, -} from "@/app/(create)/lib/constants" +} from "@/app/(app)/create/lib/constants" export async function getItemsForBase(base: BaseName) { const { Index } = await import("@/registry/bases/__index__") diff --git a/apps/v4/app/(create)/lib/constants.ts b/apps/v4/app/(app)/create/lib/constants.ts similarity index 100% rename from apps/v4/app/(create)/lib/constants.ts rename to apps/v4/app/(app)/create/lib/constants.ts diff --git a/apps/v4/app/(app)/create/lib/fonts.ts b/apps/v4/app/(app)/create/lib/fonts.ts new file mode 100644 index 0000000000..7deda364ff --- /dev/null +++ b/apps/v4/app/(app)/create/lib/fonts.ts @@ -0,0 +1,233 @@ +import { + DM_Sans, + Figtree, + Geist, + Geist_Mono, + IBM_Plex_Sans, + Instrument_Sans, + Inter, + JetBrains_Mono, + Lora, + Manrope, + Merriweather, + Montserrat, + Noto_Sans, + Noto_Serif, + Nunito_Sans, + Outfit, + Oxanium, + Playfair_Display, + Public_Sans, + Raleway, + Roboto, + Roboto_Slab, + Source_Sans_3, + Space_Grotesk, +} from "next/font/google" + +import { FONT_DEFINITIONS, type FontName } from "@/lib/font-definitions" + +type PreviewFont = ReturnType + +const geistSans = Geist({ + subsets: ["latin"], + variable: "--font-geist-sans", +}) + +const inter = Inter({ + subsets: ["latin"], + variable: "--font-inter", +}) + +const notoSans = Noto_Sans({ + subsets: ["latin"], + variable: "--font-noto-sans", +}) + +const nunitoSans = Nunito_Sans({ + subsets: ["latin"], + variable: "--font-nunito-sans", +}) + +const figtree = Figtree({ + subsets: ["latin"], + variable: "--font-figtree", +}) + +const roboto = Roboto({ + subsets: ["latin"], + variable: "--font-roboto", +}) + +const raleway = Raleway({ + subsets: ["latin"], + variable: "--font-raleway", +}) + +const dmSans = DM_Sans({ + subsets: ["latin"], + variable: "--font-dm-sans", +}) + +const publicSans = Public_Sans({ + subsets: ["latin"], + variable: "--font-public-sans", +}) + +const outfit = Outfit({ + subsets: ["latin"], + variable: "--font-outfit", +}) + +const oxanium = Oxanium({ + subsets: ["latin"], + variable: "--font-oxanium", +}) + +const manrope = Manrope({ + subsets: ["latin"], + variable: "--font-manrope", +}) + +const spaceGrotesk = Space_Grotesk({ + subsets: ["latin"], + variable: "--font-space-grotesk", +}) + +const montserrat = Montserrat({ + subsets: ["latin"], + variable: "--font-montserrat", +}) + +const ibmPlexSans = IBM_Plex_Sans({ + subsets: ["latin"], + variable: "--font-ibm-plex-sans", +}) + +const sourceSans3 = Source_Sans_3({ + subsets: ["latin"], + variable: "--font-source-sans-3", +}) + +const instrumentSans = Instrument_Sans({ + subsets: ["latin"], + variable: "--font-instrument-sans", +}) + +const jetbrainsMono = JetBrains_Mono({ + subsets: ["latin"], + variable: "--font-jetbrains-mono", +}) + +const geistMono = Geist_Mono({ + subsets: ["latin"], + variable: "--font-geist-mono", +}) + +const notoSerif = Noto_Serif({ + subsets: ["latin"], + variable: "--font-noto-serif", +}) + +const robotoSlab = Roboto_Slab({ + subsets: ["latin"], + variable: "--font-roboto-slab", +}) + +const merriweather = Merriweather({ + subsets: ["latin"], + variable: "--font-merriweather", +}) + +const lora = Lora({ + subsets: ["latin"], + variable: "--font-lora", +}) + +const playfairDisplay = Playfair_Display({ + subsets: ["latin"], + variable: "--font-playfair-display", +}) + +const PREVIEW_FONTS = { + geist: geistSans, + inter, + "noto-sans": notoSans, + "nunito-sans": nunitoSans, + figtree, + roboto, + raleway, + "dm-sans": dmSans, + "public-sans": publicSans, + outfit, + oxanium, + manrope, + "space-grotesk": spaceGrotesk, + montserrat, + "ibm-plex-sans": ibmPlexSans, + "source-sans-3": sourceSans3, + "instrument-sans": instrumentSans, + "jetbrains-mono": jetbrainsMono, + "geist-mono": geistMono, + "noto-serif": notoSerif, + "roboto-slab": robotoSlab, + merriweather, + lora, + "playfair-display": playfairDisplay, +} satisfies Record + +function createFontOption(name: FontName) { + const definition = FONT_DEFINITIONS.find((font) => font.name === name) + + if (!definition) { + throw new Error(`Unknown font definition: ${name}`) + } + + return { + name: definition.title, + value: definition.name, + font: PREVIEW_FONTS[name], + type: definition.type, + } as const +} + +export const FONTS = [ + createFontOption("geist"), + createFontOption("inter"), + createFontOption("noto-sans"), + createFontOption("nunito-sans"), + createFontOption("figtree"), + createFontOption("roboto"), + createFontOption("raleway"), + createFontOption("dm-sans"), + createFontOption("public-sans"), + createFontOption("outfit"), + createFontOption("oxanium"), + createFontOption("manrope"), + createFontOption("space-grotesk"), + createFontOption("montserrat"), + createFontOption("ibm-plex-sans"), + createFontOption("source-sans-3"), + createFontOption("instrument-sans"), + createFontOption("geist-mono"), + createFontOption("jetbrains-mono"), + createFontOption("noto-serif"), + createFontOption("roboto-slab"), + createFontOption("merriweather"), + createFontOption("lora"), + createFontOption("playfair-display"), +] as const + +export type Font = (typeof FONTS)[number] + +export const FONT_HEADING_OPTIONS = [ + { + name: "Inherit", + value: "inherit", + font: null, + type: "default", + }, + ...FONTS, +] as const + +export type FontHeadingOption = (typeof FONT_HEADING_OPTIONS)[number] diff --git a/apps/v4/app/(create)/lib/merge-theme.ts b/apps/v4/app/(app)/create/lib/merge-theme.ts similarity index 100% rename from apps/v4/app/(create)/lib/merge-theme.ts rename to apps/v4/app/(app)/create/lib/merge-theme.ts diff --git a/apps/v4/app/(create)/lib/preset-code.ts b/apps/v4/app/(app)/create/lib/preset-code.ts similarity index 100% rename from apps/v4/app/(create)/lib/preset-code.ts rename to apps/v4/app/(app)/create/lib/preset-code.ts diff --git a/apps/v4/app/(create)/lib/preset-query.test.ts b/apps/v4/app/(app)/create/lib/preset-query.test.ts similarity index 100% rename from apps/v4/app/(create)/lib/preset-query.test.ts rename to apps/v4/app/(app)/create/lib/preset-query.test.ts diff --git a/apps/v4/app/(create)/lib/preset-query.ts b/apps/v4/app/(app)/create/lib/preset-query.ts similarity index 100% rename from apps/v4/app/(create)/lib/preset-query.ts rename to apps/v4/app/(app)/create/lib/preset-query.ts diff --git a/apps/v4/app/(create)/lib/randomize-biases.ts b/apps/v4/app/(app)/create/lib/randomize-biases.ts similarity index 100% rename from apps/v4/app/(create)/lib/randomize-biases.ts rename to apps/v4/app/(app)/create/lib/randomize-biases.ts diff --git a/apps/v4/app/(app)/create/lib/search-params.ts b/apps/v4/app/(app)/create/lib/search-params.ts new file mode 100644 index 0000000000..bbaf7eff94 --- /dev/null +++ b/apps/v4/app/(app)/create/lib/search-params.ts @@ -0,0 +1,309 @@ +import * as React from "react" +import { useSearchParams } from "next/navigation" +import { useQueryStates } from "nuqs" +import { + createLoader, + createSerializer, + parseAsBoolean, + parseAsInteger, + parseAsString, + parseAsStringLiteral, + type inferParserType, + type Options, +} from "nuqs/server" +import { decodePreset, isPresetCode } from "shadcn/preset" + +import { + BASE_COLORS, + BASES, + DEFAULT_CONFIG, + getThemesForBaseColor, + iconLibraries, + MENU_ACCENTS, + MENU_COLORS, + RADII, + STYLES, + THEMES, + type BaseColorName, + type BaseName, + type ChartColorName, + type FontHeadingValue, + type FontValue, + type IconLibraryName, + type MenuAccentValue, + type MenuColorValue, + type RadiusValue, + type StyleName, + type ThemeName, +} from "@/registry/config" +import { FONTS } from "@/app/(app)/create/lib/fonts" +import { getPresetCode } from "@/app/(app)/create/lib/preset-code" +import { resolvePresetOverrides } from "@/app/(app)/create/lib/preset-query" + +const designSystemSearchParams = { + preset: parseAsString.withDefault("b2D0wqNxT"), + base: parseAsStringLiteral(BASES.map((b) => b.name)).withDefault( + DEFAULT_CONFIG.base + ), + item: parseAsString.withDefault("preview-02").withOptions({ shallow: true }), + iconLibrary: parseAsStringLiteral( + Object.values(iconLibraries).map((i) => i.name) + ).withDefault(DEFAULT_CONFIG.iconLibrary), + style: parseAsStringLiteral(STYLES.map((s) => s.name)).withDefault( + DEFAULT_CONFIG.style + ), + theme: parseAsStringLiteral(THEMES.map((t) => t.name)).withDefault( + DEFAULT_CONFIG.theme + ), + chartColor: parseAsStringLiteral( + THEMES.map((t) => t.name) + ).withDefault(DEFAULT_CONFIG.chartColor ?? "neutral"), + font: parseAsStringLiteral(FONTS.map((f) => f.value)).withDefault( + DEFAULT_CONFIG.font + ), + fontHeading: parseAsStringLiteral([ + "inherit", + ...FONTS.map((f) => f.value), + ]).withDefault(DEFAULT_CONFIG.fontHeading), + baseColor: parseAsStringLiteral( + BASE_COLORS.map((b) => b.name) + ).withDefault(DEFAULT_CONFIG.baseColor), + menuAccent: parseAsStringLiteral( + MENU_ACCENTS.map((a) => a.value) + ).withDefault(DEFAULT_CONFIG.menuAccent), + menuColor: parseAsStringLiteral( + MENU_COLORS.map((m) => m.value) + ).withDefault(DEFAULT_CONFIG.menuColor), + radius: parseAsStringLiteral( + RADII.map((r) => r.name) + ).withDefault("default"), + template: parseAsStringLiteral([ + "next", + "next-monorepo", + "start", + "start-monorepo", + "react-router", + "react-router-monorepo", + "vite", + "vite-monorepo", + "astro", + "astro-monorepo", + "laravel", + ] as const).withDefault("next"), + rtl: parseAsBoolean.withDefault(false), + size: parseAsInteger.withDefault(100), + custom: parseAsBoolean.withDefault(false), +} + +// Design system param keys that get encoded into the preset code. +const DESIGN_SYSTEM_KEYS = [ + "style", + "baseColor", + "theme", + "chartColor", + "iconLibrary", + "font", + "fontHeading", + "radius", + "menuAccent", + "menuColor", +] as const + +function normalizeFontHeading( + font: FontValue, + fontHeading: FontHeadingValue +): FontHeadingValue { + // Persist "same as body" as an explicit inherit sentinel so the body font + // can change later without freezing headings to a concrete previous value. + return fontHeading === font ? "inherit" : fontHeading +} + +// Non-design-system keys that get passed through as-is. +// `base` is not encoded in preset codes — it's an architectural choice, not visual. +const NON_DESIGN_SYSTEM_KEYS = [ + "base", + "item", + "preset", + "template", + "rtl", + "size", + "custom", +] as const + +export const loadDesignSystemSearchParams = createLoader( + designSystemSearchParams +) + +export const serializeDesignSystemSearchParams = createSerializer( + designSystemSearchParams +) + +export type DesignSystemSearchParams = inferParserType< + typeof designSystemSearchParams +> + +export function isTranslucentMenuColor( + menuColor?: MenuColorValue | null +): menuColor is "default-translucent" | "inverted-translucent" { + return ( + menuColor === "default-translucent" || menuColor === "inverted-translucent" + ) +} + +function normalizePartialDesignSystemParams( + params: Partial +): Partial { + if ( + params.menuAccent === "bold" && + isTranslucentMenuColor(params.menuColor ?? undefined) + ) { + return { + ...params, + menuAccent: "subtle", + } + } + + return params +} + +function normalizeDesignSystemParams( + params: DesignSystemSearchParams +): DesignSystemSearchParams { + let result = { + ...params, + fontHeading: normalizeFontHeading(params.font, params.fontHeading), + } + + // Validate theme and chartColor against baseColor. + if (result.baseColor) { + const available = getThemesForBaseColor(result.baseColor) + const themeValid = available.some((t) => t.name === result.theme) + const chartColorValid = available.some((t) => t.name === result.chartColor) + + if (!themeValid || !chartColorValid) { + const fallback = (available[0]?.name ?? result.baseColor) as ThemeName + result = { + ...result, + ...(!themeValid && { theme: fallback }), + ...(!chartColorValid && { chartColor: fallback as ChartColorName }), + } + } + } + + if ( + result.menuAccent === "bold" && + isTranslucentMenuColor(result.menuColor) + ) { + return { + ...result, + menuAccent: "subtle", + } + } + + return result +} + +// If preset param exists, decode it and overlay on raw params. +// V1 presets don't encode chartColor — fall back to the colored +// theme that base-color themes originally borrowed charts from. +type SearchParamsLike = Pick + +function resolvePresetParams( + rawParams: DesignSystemSearchParams, + searchParams: SearchParamsLike +) { + if (rawParams.preset && isPresetCode(rawParams.preset)) { + const decoded = decodePreset(rawParams.preset) + if (decoded) { + const presetOverrides = resolvePresetOverrides(searchParams, decoded) + return normalizeDesignSystemParams({ + ...decoded, + ...presetOverrides, + base: rawParams.base, + item: rawParams.item, + preset: rawParams.preset, + template: rawParams.template, + rtl: rawParams.rtl, + size: rawParams.size, + custom: rawParams.custom, + }) + } + } + return normalizeDesignSystemParams(rawParams) +} + +// Wraps nuqs useQueryStates with transparent preset encoding/decoding. +// - Reads: if ?preset=CODE is in the URL, decodes it and returns individual values. +// - Writes: when design system params are set, encodes them into a preset code. +export function useDesignSystemSearchParams(options: Options = {}) { + const searchParams = useSearchParams() + const [rawParams, rawSetParams] = useQueryStates(designSystemSearchParams, { + shallow: false, + history: "push", + ...options, + }) + + const params = React.useMemo( + () => resolvePresetParams(rawParams, searchParams), + [rawParams, searchParams] + ) + + // Use ref so setParams callback stays stable across renders. + const paramsRef = React.useRef(params) + React.useEffect(() => { + paramsRef.current = params + }, [params]) + + type RawSetParamsInput = Parameters[0] + + const setParams = React.useCallback( + ( + updates: + | Partial + | (( + old: DesignSystemSearchParams + ) => Partial), + setOptions?: Options + ) => { + const resolvedUpdates = normalizePartialDesignSystemParams( + typeof updates === "function" ? updates(paramsRef.current) : updates + ) + + const hasDesignSystemUpdate = DESIGN_SYSTEM_KEYS.some( + (key) => key in resolvedUpdates + ) + + if (!hasDesignSystemUpdate) { + // No design system change, pass through directly. + return rawSetParams(resolvedUpdates as RawSetParamsInput, setOptions) + } + + // Merge current decoded values with updates. + const merged = normalizeDesignSystemParams({ + ...paramsRef.current, + ...resolvedUpdates, + }) + // Encode design system fields into a preset code. + // Cast needed: merged values may include null from nuqs resets, + // but encodePreset handles missing values by falling back to defaults. + const code = getPresetCode(merged) + // Build update: set preset, clear individual DS params from URL. + const rawUpdate: Record = { preset: code } + for (const key of DESIGN_SYSTEM_KEYS) { + rawUpdate[key] = null + } + + // Pass through non-DS params that were explicitly in the update. + for (const key of NON_DESIGN_SYSTEM_KEYS) { + if (key in resolvedUpdates) { + rawUpdate[key] = (resolvedUpdates as Record)[key] + } + } + + return rawSetParams(rawUpdate as RawSetParamsInput, setOptions) + }, + [rawSetParams] + ) + + return [params, setParams] as const +} diff --git a/apps/v4/app/(create)/lib/templates.ts b/apps/v4/app/(app)/create/lib/templates.ts similarity index 100% rename from apps/v4/app/(create)/lib/templates.ts rename to apps/v4/app/(app)/create/lib/templates.ts diff --git a/apps/v4/app/(create)/lib/utils.ts b/apps/v4/app/(app)/create/lib/utils.ts similarity index 100% rename from apps/v4/app/(create)/lib/utils.ts rename to apps/v4/app/(app)/create/lib/utils.ts diff --git a/apps/v4/app/(create)/lib/v0.test.ts b/apps/v4/app/(app)/create/lib/v0.test.ts similarity index 98% rename from apps/v4/app/(create)/lib/v0.test.ts rename to apps/v4/app/(app)/create/lib/v0.test.ts index 125e1e3562..b21a4c9b4c 100644 --- a/apps/v4/app/(create)/lib/v0.test.ts +++ b/apps/v4/app/(app)/create/lib/v0.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" import { DEFAULT_CONFIG } from "@/registry/config" -import { buildV0Payload } from "@/app/(create)/lib/v0" +import { buildV0Payload } from "@/app/(app)/create/lib/v0" vi.mock("shadcn/schema", async () => { return await vi.importActual("shadcn/schema") diff --git a/apps/v4/app/(create)/lib/v0.ts b/apps/v4/app/(app)/create/lib/v0.ts similarity index 100% rename from apps/v4/app/(create)/lib/v0.ts rename to apps/v4/app/(app)/create/lib/v0.ts diff --git a/apps/v4/app/(create)/create/page.tsx b/apps/v4/app/(app)/create/page.tsx similarity index 64% rename from apps/v4/app/(create)/create/page.tsx rename to apps/v4/app/(app)/create/page.tsx index 1e21ef0098..40f6053168 100644 --- a/apps/v4/app/(create)/create/page.tsx +++ b/apps/v4/app/(app)/create/page.tsx @@ -2,12 +2,11 @@ import { type Metadata } from "next" import { siteConfig } from "@/lib/config" import { absoluteUrl } from "@/lib/utils" -import { SiteHeader } from "@/components/site-header" -import { Customizer } from "@/app/(create)/components/customizer" -import { PresetHandler } from "@/app/(create)/components/preset-handler" -import { Preview } from "@/app/(create)/components/preview" -import { WelcomeDialog } from "@/app/(create)/components/welcome-dialog" -import { getAllItems } from "@/app/(create)/lib/api" +import { Customizer } from "@/app/(app)/create/components/customizer" +import { PresetHandler } from "@/app/(app)/create/components/preset-handler" +import { Preview } from "@/app/(app)/create/components/preview" +import { WelcomeDialog } from "@/app/(app)/create/components/welcome-dialog" +import { getAllItems } from "@/app/(app)/create/lib/api" export const metadata: Metadata = { title: "New Project", @@ -42,20 +41,16 @@ export default async function CreatePage() { const itemsByBase = await getAllItems() return ( -
- -
+
- - -
+
+ + ) } diff --git a/apps/v4/app/(app)/docs/changelog/page.tsx b/apps/v4/app/(app)/docs/changelog/page.tsx index b9193beeb0..39e6814fef 100644 --- a/apps/v4/app/(app)/docs/changelog/page.tsx +++ b/apps/v4/app/(app)/docs/changelog/page.tsx @@ -1,11 +1,11 @@ import Link from "next/link" -import { Button } from "@/examples/radix/ui/button" import { mdxComponents } from "@/mdx-components" import { IconRss } from "@tabler/icons-react" import { getChangelogPages, type ChangelogPageData } from "@/lib/changelog" import { absoluteUrl } from "@/lib/utils" import { OpenInV0Cta } from "@/components/open-in-v0-cta" +import { Button } from "@/styles/radix-nova/ui/button" export const revalidate = false export const dynamic = "force-static" diff --git a/apps/v4/app/(app)/examples/rtl/components/appearance-settings.tsx b/apps/v4/app/(app)/examples/rtl/components/appearance-settings.tsx index eabe55bed9..42f442d665 100644 --- a/apps/v4/app/(app)/examples/rtl/components/appearance-settings.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/appearance-settings.tsx @@ -1,8 +1,11 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui-rtl/button" -import { ButtonGroup } from "@/examples/base/ui-rtl/button-group" +import { IconMinus, IconPlus } from "@tabler/icons-react" + +import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" +import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group" import { Field, FieldContent, @@ -13,13 +16,13 @@ import { FieldSeparator, FieldSet, FieldTitle, -} from "@/examples/base/ui-rtl/field" -import { Input } from "@/examples/base/ui-rtl/input" -import { RadioGroup, RadioGroupItem } from "@/examples/base/ui-rtl/radio-group" -import { Switch } from "@/examples/base/ui-rtl/switch" -import { IconMinus, IconPlus } from "@tabler/icons-react" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/field" +import { Input } from "@/styles/base-nova/ui-rtl/input" +import { + RadioGroup, + RadioGroupItem, +} from "@/styles/base-nova/ui-rtl/radio-group" +import { Switch } from "@/styles/base-nova/ui-rtl/switch" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/button-group-demo.tsx b/apps/v4/app/(app)/examples/rtl/components/button-group-demo.tsx index cda018e544..29f36b142d 100644 --- a/apps/v4/app/(app)/examples/rtl/components/button-group-demo.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/button-group-demo.tsx @@ -1,22 +1,6 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui-rtl/button" -import { ButtonGroup } from "@/examples/base/ui-rtl/button-group" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuGroup, - DropdownMenuItem, - DropdownMenuPortal, - DropdownMenuRadioGroup, - DropdownMenuRadioItem, - DropdownMenuSeparator, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuTrigger, -} from "@/examples/base/ui-rtl/dropdown-menu" import { ArchiveIcon, ArrowLeftIcon, @@ -30,6 +14,22 @@ import { } from "lucide-react" import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" +import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuPortal, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from "@/styles/base-nova/ui-rtl/dropdown-menu" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/button-group-input-group.tsx b/apps/v4/app/(app)/examples/rtl/components/button-group-input-group.tsx index 7493207b87..48b5fd6e06 100644 --- a/apps/v4/app/(app)/examples/rtl/components/button-group-input-group.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/button-group-input-group.tsx @@ -1,22 +1,22 @@ "use client" import * as React from "react" -import { Button } from "@/examples/base/ui-rtl/button" -import { ButtonGroup } from "@/examples/base/ui-rtl/button-group" +import { AudioLinesIcon, PlusIcon } from "lucide-react" + +import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" +import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group" import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, -} from "@/examples/base/ui-rtl/input-group" +} from "@/styles/base-nova/ui-rtl/input-group" import { Tooltip, TooltipContent, TooltipTrigger, -} from "@/examples/base/ui-rtl/tooltip" -import { AudioLinesIcon, PlusIcon } from "lucide-react" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/tooltip" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/button-group-nested.tsx b/apps/v4/app/(app)/examples/rtl/components/button-group-nested.tsx index 938c11d137..ed28aca572 100644 --- a/apps/v4/app/(app)/examples/rtl/components/button-group-nested.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/button-group-nested.tsx @@ -1,10 +1,10 @@ "use client" -import { Button } from "@/examples/base/ui-rtl/button" -import { ButtonGroup } from "@/examples/base/ui-rtl/button-group" import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react" import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" +import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/button-group-popover.tsx b/apps/v4/app/(app)/examples/rtl/components/button-group-popover.tsx index e570d0f5c1..e9a83fe052 100644 --- a/apps/v4/app/(app)/examples/rtl/components/button-group-popover.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/button-group-popover.tsx @@ -1,17 +1,17 @@ "use client" -import { Button } from "@/examples/base/ui-rtl/button" -import { ButtonGroup } from "@/examples/base/ui-rtl/button-group" +import { BotIcon, ChevronDownIcon } from "lucide-react" + +import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" +import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group" import { Popover, PopoverContent, PopoverTrigger, -} from "@/examples/base/ui-rtl/popover" -import { Separator } from "@/examples/base/ui-rtl/separator" -import { Textarea } from "@/examples/base/ui-rtl/textarea" -import { BotIcon, ChevronDownIcon } from "lucide-react" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/popover" +import { Separator } from "@/styles/base-nova/ui-rtl/separator" +import { Textarea } from "@/styles/base-nova/ui-rtl/textarea" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/empty-avatar-group.tsx b/apps/v4/app/(app)/examples/rtl/components/empty-avatar-group.tsx index 93760f87d1..7aeab40ad7 100644 --- a/apps/v4/app/(app)/examples/rtl/components/empty-avatar-group.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/empty-avatar-group.tsx @@ -1,12 +1,15 @@ "use client" +import { PlusIcon } from "lucide-react" + +import { useLanguageContext } from "@/components/language-selector" import { Avatar, AvatarFallback, AvatarGroup, AvatarImage, -} from "@/examples/base/ui-rtl/avatar" -import { Button } from "@/examples/base/ui-rtl/button" +} from "@/styles/base-nova/ui-rtl/avatar" +import { Button } from "@/styles/base-nova/ui-rtl/button" import { Empty, EmptyContent, @@ -14,10 +17,7 @@ import { EmptyHeader, EmptyMedia, EmptyTitle, -} from "@/examples/base/ui-rtl/empty" -import { PlusIcon } from "lucide-react" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/empty" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/field-checkbox.tsx b/apps/v4/app/(app)/examples/rtl/components/field-checkbox.tsx index 8c9f84c167..385d61d300 100644 --- a/apps/v4/app/(app)/examples/rtl/components/field-checkbox.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/field-checkbox.tsx @@ -1,9 +1,8 @@ "use client" -import { Checkbox } from "@/examples/base/ui-rtl/checkbox" -import { Field, FieldLabel } from "@/examples/base/ui-rtl/field" - import { useLanguageContext } from "@/components/language-selector" +import { Checkbox } from "@/styles/base-nova/ui-rtl/checkbox" +import { Field, FieldLabel } from "@/styles/base-nova/ui-rtl/field" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/field-demo.tsx b/apps/v4/app/(app)/examples/rtl/components/field-demo.tsx index 02cba58bbd..e8cddf6788 100644 --- a/apps/v4/app/(app)/examples/rtl/components/field-demo.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/field-demo.tsx @@ -1,7 +1,8 @@ "use client" -import { Button } from "@/examples/base/ui-rtl/button" -import { Checkbox } from "@/examples/base/ui-rtl/checkbox" +import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" +import { Checkbox } from "@/styles/base-nova/ui-rtl/checkbox" import { Field, FieldDescription, @@ -10,8 +11,8 @@ import { FieldLegend, FieldSeparator, FieldSet, -} from "@/examples/base/ui-rtl/field" -import { Input } from "@/examples/base/ui-rtl/input" +} from "@/styles/base-nova/ui-rtl/field" +import { Input } from "@/styles/base-nova/ui-rtl/input" import { Select, SelectContent, @@ -19,10 +20,8 @@ import { SelectItem, SelectTrigger, SelectValue, -} from "@/examples/base/ui-rtl/select" -import { Textarea } from "@/examples/base/ui-rtl/textarea" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/select" +import { Textarea } from "@/styles/base-nova/ui-rtl/textarea" const translations = { ar: { @@ -140,7 +139,7 @@ export function FieldDemo() {
{t.month} - @@ -157,7 +156,7 @@ export function FieldDemo() { {t.year} - diff --git a/apps/v4/app/(app)/examples/rtl/components/field-hear.tsx b/apps/v4/app/(app)/examples/rtl/components/field-hear.tsx index e982bfdc66..53e6946071 100644 --- a/apps/v4/app/(app)/examples/rtl/components/field-hear.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/field-hear.tsx @@ -1,7 +1,8 @@ "use client" -import { Card, CardContent } from "@/examples/base/ui-rtl/card" -import { Checkbox } from "@/examples/base/ui-rtl/checkbox" +import { useLanguageContext } from "@/components/language-selector" +import { Card, CardContent } from "@/styles/base-nova/ui-rtl/card" +import { Checkbox } from "@/styles/base-nova/ui-rtl/checkbox" import { Field, FieldDescription, @@ -10,9 +11,7 @@ import { FieldLegend, FieldSet, FieldTitle, -} from "@/examples/base/ui-rtl/field" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/field" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/field-slider.tsx b/apps/v4/app/(app)/examples/rtl/components/field-slider.tsx index 3e19b99171..de53c0f594 100644 --- a/apps/v4/app/(app)/examples/rtl/components/field-slider.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/field-slider.tsx @@ -1,14 +1,14 @@ "use client" import { useState } from "react" + +import { useLanguageContext } from "@/components/language-selector" import { Field, FieldDescription, FieldTitle, -} from "@/examples/base/ui-rtl/field" -import { Slider } from "@/examples/base/ui-rtl/slider" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/field" +import { Slider } from "@/styles/base-nova/ui-rtl/slider" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/index.tsx b/apps/v4/app/(app)/examples/rtl/components/index.tsx index 2c42054644..2544d7f75a 100644 --- a/apps/v4/app/(app)/examples/rtl/components/index.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/index.tsx @@ -1,13 +1,12 @@ "use client" -import { DirectionProvider } from "@/examples/base/ui-rtl/direction" -import { FieldSeparator } from "@/examples/base/ui-rtl/field" - import { LanguageProvider, LanguageSelector, useLanguageContext, } from "@/components/language-selector" +import { DirectionProvider } from "@/styles/base-nova/ui-rtl/direction" +import { FieldSeparator } from "@/styles/base-nova/ui-rtl/field" import { AppearanceSettings } from "./appearance-settings" import { ButtonGroupDemo } from "./button-group-demo" diff --git a/apps/v4/app/(app)/examples/rtl/components/input-group-button.tsx b/apps/v4/app/(app)/examples/rtl/components/input-group-button.tsx index 560d856206..9c47b7d483 100644 --- a/apps/v4/app/(app)/examples/rtl/components/input-group-button.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/input-group-button.tsx @@ -1,21 +1,21 @@ "use client" import * as React from "react" +import { IconInfoCircle, IconStar } from "@tabler/icons-react" + +import { useLanguageContext } from "@/components/language-selector" import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, -} from "@/examples/base/ui-rtl/input-group" -import { Label } from "@/examples/base/ui-rtl/label" +} from "@/styles/base-nova/ui-rtl/input-group" +import { Label } from "@/styles/base-nova/ui-rtl/label" import { Popover, PopoverContent, PopoverTrigger, -} from "@/examples/base/ui-rtl/popover" -import { IconInfoCircle, IconStar } from "@tabler/icons-react" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/popover" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/input-group-demo.tsx b/apps/v4/app/(app)/examples/rtl/components/input-group-demo.tsx index 59ccd0137e..95a5c141e9 100644 --- a/apps/v4/app/(app)/examples/rtl/components/input-group-demo.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/input-group-demo.tsx @@ -1,25 +1,5 @@ "use client" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/examples/base/ui-rtl/dropdown-menu" -import { - InputGroup, - InputGroupAddon, - InputGroupButton, - InputGroupInput, - InputGroupText, - InputGroupTextarea, -} from "@/examples/base/ui-rtl/input-group" -import { Separator } from "@/examples/base/ui-rtl/separator" -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from "@/examples/base/ui-rtl/tooltip" import { IconCheck, IconChevronDown, @@ -29,6 +9,26 @@ import { import { ArrowUpIcon, Search } from "lucide-react" import { useLanguageContext } from "@/components/language-selector" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/styles/base-nova/ui-rtl/dropdown-menu" +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupInput, + InputGroupText, + InputGroupTextarea, +} from "@/styles/base-nova/ui-rtl/input-group" +import { Separator } from "@/styles/base-nova/ui-rtl/separator" +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/styles/base-nova/ui-rtl/tooltip" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/item-demo.tsx b/apps/v4/app/(app)/examples/rtl/components/item-demo.tsx index 1abc42a656..0707f29d8a 100644 --- a/apps/v4/app/(app)/examples/rtl/components/item-demo.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/item-demo.tsx @@ -1,6 +1,9 @@ "use client" -import { Button } from "@/examples/base/ui-rtl/button" +import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react" + +import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" import { Item, ItemActions, @@ -8,10 +11,7 @@ import { ItemDescription, ItemMedia, ItemTitle, -} from "@/examples/base/ui-rtl/item" -import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/item" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/notion-prompt-form.tsx b/apps/v4/app/(app)/examples/rtl/components/notion-prompt-form.tsx index 3e6c89b624..7cbfdbc7f4 100644 --- a/apps/v4/app/(app)/examples/rtl/components/notion-prompt-form.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/notion-prompt-form.tsx @@ -1,47 +1,6 @@ "use client" import { useMemo, useState } from "react" -import { - Avatar, - AvatarFallback, - AvatarImage, -} from "@/examples/base/ui-rtl/avatar" -import { Badge } from "@/examples/base/ui-rtl/badge" -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, -} from "@/examples/base/ui-rtl/command" -import { - DropdownMenu, - DropdownMenuCheckboxItem, - DropdownMenuContent, - DropdownMenuGroup, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuTrigger, -} from "@/examples/base/ui-rtl/dropdown-menu" -import { Field, FieldLabel } from "@/examples/base/ui-rtl/field" -import { - InputGroup, - InputGroupAddon, - InputGroupButton, - InputGroupTextarea, -} from "@/examples/base/ui-rtl/input-group" -import { Popover, PopoverContent } from "@/examples/base/ui-rtl/popover" -import { Switch } from "@/examples/base/ui-rtl/switch" -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from "@/examples/base/ui-rtl/tooltip" import { IconApps, IconArrowUp, @@ -55,6 +14,47 @@ import { } from "@tabler/icons-react" import { useLanguageContext } from "@/components/language-selector" +import { + Avatar, + AvatarFallback, + AvatarImage, +} from "@/styles/base-nova/ui-rtl/avatar" +import { Badge } from "@/styles/base-nova/ui-rtl/badge" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/styles/base-nova/ui-rtl/command" +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from "@/styles/base-nova/ui-rtl/dropdown-menu" +import { Field, FieldLabel } from "@/styles/base-nova/ui-rtl/field" +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupTextarea, +} from "@/styles/base-nova/ui-rtl/input-group" +import { Popover, PopoverContent } from "@/styles/base-nova/ui-rtl/popover" +import { Switch } from "@/styles/base-nova/ui-rtl/switch" +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/styles/base-nova/ui-rtl/tooltip" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/spinner-badge.tsx b/apps/v4/app/(app)/examples/rtl/components/spinner-badge.tsx index 0aaac8330a..ba56a23bed 100644 --- a/apps/v4/app/(app)/examples/rtl/components/spinner-badge.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/spinner-badge.tsx @@ -1,9 +1,8 @@ "use client" -import { Badge } from "@/examples/base/ui-rtl/badge" -import { Spinner } from "@/examples/base/ui-rtl/spinner" - import { useLanguageContext } from "@/components/language-selector" +import { Badge } from "@/styles/base-nova/ui-rtl/badge" +import { Spinner } from "@/styles/base-nova/ui-rtl/spinner" const translations = { ar: { diff --git a/apps/v4/app/(app)/examples/rtl/components/spinner-empty.tsx b/apps/v4/app/(app)/examples/rtl/components/spinner-empty.tsx index abcfae9680..064b8dedeb 100644 --- a/apps/v4/app/(app)/examples/rtl/components/spinner-empty.tsx +++ b/apps/v4/app/(app)/examples/rtl/components/spinner-empty.tsx @@ -1,6 +1,7 @@ "use client" -import { Button } from "@/examples/base/ui-rtl/button" +import { useLanguageContext } from "@/components/language-selector" +import { Button } from "@/styles/base-nova/ui-rtl/button" import { Empty, EmptyContent, @@ -8,10 +9,8 @@ import { EmptyHeader, EmptyMedia, EmptyTitle, -} from "@/examples/base/ui-rtl/empty" -import { Spinner } from "@/examples/base/ui-rtl/spinner" - -import { useLanguageContext } from "@/components/language-selector" +} from "@/styles/base-nova/ui-rtl/empty" +import { Spinner } from "@/styles/base-nova/ui-rtl/spinner" const translations = { ar: { diff --git a/apps/v4/app/(app)/layout.tsx b/apps/v4/app/(app)/layout.tsx index a90385a247..ca5f8e1450 100644 --- a/apps/v4/app/(app)/layout.tsx +++ b/apps/v4/app/(app)/layout.tsx @@ -5,10 +5,10 @@ export default function AppLayout({ children }: { children: React.ReactNode }) { return (
-
{children}
+
{children}
) diff --git a/apps/v4/app/(app)/themes/layout.tsx b/apps/v4/app/(app)/themes/layout.tsx deleted file mode 100644 index 99951af1ae..0000000000 --- a/apps/v4/app/(app)/themes/layout.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { type Metadata } from "next" -import Link from "next/link" - -import { Announcement } from "@/components/announcement" -import { - PageActions, - PageHeader, - PageHeaderDescription, - PageHeaderHeading, -} from "@/components/page-header" -import { Button } from "@/registry/new-york-v4/ui/button" - -const title = "Pick a Color. Make it yours." -const description = - "Try our hand-picked themes. Copy and paste them into your project. New theme editor coming soon." - -export const metadata: Metadata = { - title, - description, - openGraph: { - images: [ - { - url: `/og?title=${encodeURIComponent( - title - )}&description=${encodeURIComponent(description)}`, - }, - ], - }, - twitter: { - card: "summary_large_image", - images: [ - { - url: `/og?title=${encodeURIComponent( - title - )}&description=${encodeURIComponent(description)}`, - }, - ], - }, -} - -export default function ThemesLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( -
- - - {title} - {description} - - - - - - {children} -
- ) -} diff --git a/apps/v4/app/(app)/themes/page.tsx b/apps/v4/app/(app)/themes/page.tsx deleted file mode 100644 index a9d44bd5f6..0000000000 --- a/apps/v4/app/(app)/themes/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { CardsDemo } from "@/components/cards" -import { ThemeCustomizer } from "@/components/theme-customizer" - -export const dynamic = "force-static" -export const revalidate = false - -export default function ThemesPage() { - return ( - <> -
-
- -
-
-
-
- -
-
- - ) -} diff --git a/apps/v4/app/(create)/components/icon-placeholder.tsx b/apps/v4/app/(create)/components/icon-placeholder.tsx index 83ce2cab86..f1c89e7f4f 100644 --- a/apps/v4/app/(create)/components/icon-placeholder.tsx +++ b/apps/v4/app/(create)/components/icon-placeholder.tsx @@ -1,75 +1,3 @@ "use client" -import { lazy, Suspense } from "react" -import { SquareIcon } from "lucide-react" -import type { IconLibraryName } from "shadcn/icons" - -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" - -const IconLucide = lazy(() => - import("@/registry/icons/icon-lucide").then((mod) => ({ - default: mod.IconLucide, - })) -) - -const IconTabler = lazy(() => - import("@/registry/icons/icon-tabler").then((mod) => ({ - default: mod.IconTabler, - })) -) - -const IconHugeicons = lazy(() => - import("@/registry/icons/icon-hugeicons").then((mod) => ({ - default: mod.IconHugeicons, - })) -) - -const IconPhosphor = lazy(() => - import("@/registry/icons/icon-phosphor").then((mod) => ({ - default: mod.IconPhosphor, - })) -) - -const IconRemixicon = lazy(() => - import("@/registry/icons/icon-remixicon").then((mod) => ({ - default: mod.IconRemixicon, - })) -) - -// Preload all icon renderer modules so switching libraries is instant. -// These warm the browser module cache; React.lazy resolves immediately -// for modules that are already loaded. -void import("@/registry/icons/icon-lucide") -void import("@/registry/icons/icon-tabler") -void import("@/registry/icons/icon-hugeicons") -void import("@/registry/icons/icon-phosphor") -void import("@/registry/icons/icon-remixicon") - -export function IconPlaceholder({ - ...props -}: { - [K in IconLibraryName]: string -} & React.ComponentProps<"svg">) { - const [{ iconLibrary }] = useDesignSystemSearchParams() - const iconName = props[iconLibrary] - - if (!iconName) { - return null - } - - return ( - }> - {iconLibrary === "lucide" && } - {iconLibrary === "tabler" && } - {iconLibrary === "hugeicons" && ( - - )} - {iconLibrary === "phosphor" && ( - - )} - {iconLibrary === "remixicon" && ( - - )} - - ) -} +export { IconPlaceholder } from "@/app/(app)/create/components/icon-placeholder" diff --git a/apps/v4/app/(create)/init/parse-config.ts b/apps/v4/app/(create)/init/parse-config.ts index 168bccc11a..5fdaa0c62e 100644 --- a/apps/v4/app/(create)/init/parse-config.ts +++ b/apps/v4/app/(create)/init/parse-config.ts @@ -4,7 +4,7 @@ import { designSystemConfigSchema, type DesignSystemConfig, } from "@/registry/config" -import { resolvePresetOverrides } from "@/app/(create)/lib/preset-query" +import { resolvePresetOverrides } from "@/app/(app)/create/lib/preset-query" // Parses design system config from URL search params. export function parseDesignSystemConfig(searchParams: URLSearchParams) { diff --git a/apps/v4/app/(create)/init/route.ts b/apps/v4/app/(create)/init/route.ts index e573548f7d..d8d0115b7e 100644 --- a/apps/v4/app/(create)/init/route.ts +++ b/apps/v4/app/(create)/init/route.ts @@ -4,8 +4,8 @@ import { isPresetCode } from "shadcn/preset" import { registryItemSchema } from "shadcn/schema" import { buildRegistryBase } from "@/registry/config" +import { getPresetCode } from "@/app/(app)/create/lib/preset-code" import { parseDesignSystemConfig } from "@/app/(create)/init/parse-config" -import { getPresetCode } from "@/app/(create)/lib/preset-code" export async function GET(request: NextRequest) { try { diff --git a/apps/v4/app/(create)/init/v0/route.ts b/apps/v4/app/(create)/init/v0/route.ts index 901909933a..635b8cf43c 100644 --- a/apps/v4/app/(create)/init/v0/route.ts +++ b/apps/v4/app/(create)/init/v0/route.ts @@ -2,9 +2,9 @@ import { after, NextResponse, type NextRequest } from "next/server" import { track } from "@vercel/analytics/server" import { isPresetCode } from "shadcn/preset" +import { getPresetCode } from "@/app/(app)/create/lib/preset-code" +import { buildV0Payload } from "@/app/(app)/create/lib/v0" import { parseDesignSystemConfig } from "@/app/(create)/init/parse-config" -import { getPresetCode } from "@/app/(create)/lib/preset-code" -import { buildV0Payload } from "@/app/(create)/lib/v0" export async function GET(request: NextRequest) { try { diff --git a/apps/v4/app/(create)/lib/fonts.ts b/apps/v4/app/(create)/lib/fonts.ts index 7deda364ff..b4b95e708e 100644 --- a/apps/v4/app/(create)/lib/fonts.ts +++ b/apps/v4/app/(create)/lib/fonts.ts @@ -1,233 +1 @@ -import { - DM_Sans, - Figtree, - Geist, - Geist_Mono, - IBM_Plex_Sans, - Instrument_Sans, - Inter, - JetBrains_Mono, - Lora, - Manrope, - Merriweather, - Montserrat, - Noto_Sans, - Noto_Serif, - Nunito_Sans, - Outfit, - Oxanium, - Playfair_Display, - Public_Sans, - Raleway, - Roboto, - Roboto_Slab, - Source_Sans_3, - Space_Grotesk, -} from "next/font/google" - -import { FONT_DEFINITIONS, type FontName } from "@/lib/font-definitions" - -type PreviewFont = ReturnType - -const geistSans = Geist({ - subsets: ["latin"], - variable: "--font-geist-sans", -}) - -const inter = Inter({ - subsets: ["latin"], - variable: "--font-inter", -}) - -const notoSans = Noto_Sans({ - subsets: ["latin"], - variable: "--font-noto-sans", -}) - -const nunitoSans = Nunito_Sans({ - subsets: ["latin"], - variable: "--font-nunito-sans", -}) - -const figtree = Figtree({ - subsets: ["latin"], - variable: "--font-figtree", -}) - -const roboto = Roboto({ - subsets: ["latin"], - variable: "--font-roboto", -}) - -const raleway = Raleway({ - subsets: ["latin"], - variable: "--font-raleway", -}) - -const dmSans = DM_Sans({ - subsets: ["latin"], - variable: "--font-dm-sans", -}) - -const publicSans = Public_Sans({ - subsets: ["latin"], - variable: "--font-public-sans", -}) - -const outfit = Outfit({ - subsets: ["latin"], - variable: "--font-outfit", -}) - -const oxanium = Oxanium({ - subsets: ["latin"], - variable: "--font-oxanium", -}) - -const manrope = Manrope({ - subsets: ["latin"], - variable: "--font-manrope", -}) - -const spaceGrotesk = Space_Grotesk({ - subsets: ["latin"], - variable: "--font-space-grotesk", -}) - -const montserrat = Montserrat({ - subsets: ["latin"], - variable: "--font-montserrat", -}) - -const ibmPlexSans = IBM_Plex_Sans({ - subsets: ["latin"], - variable: "--font-ibm-plex-sans", -}) - -const sourceSans3 = Source_Sans_3({ - subsets: ["latin"], - variable: "--font-source-sans-3", -}) - -const instrumentSans = Instrument_Sans({ - subsets: ["latin"], - variable: "--font-instrument-sans", -}) - -const jetbrainsMono = JetBrains_Mono({ - subsets: ["latin"], - variable: "--font-jetbrains-mono", -}) - -const geistMono = Geist_Mono({ - subsets: ["latin"], - variable: "--font-geist-mono", -}) - -const notoSerif = Noto_Serif({ - subsets: ["latin"], - variable: "--font-noto-serif", -}) - -const robotoSlab = Roboto_Slab({ - subsets: ["latin"], - variable: "--font-roboto-slab", -}) - -const merriweather = Merriweather({ - subsets: ["latin"], - variable: "--font-merriweather", -}) - -const lora = Lora({ - subsets: ["latin"], - variable: "--font-lora", -}) - -const playfairDisplay = Playfair_Display({ - subsets: ["latin"], - variable: "--font-playfair-display", -}) - -const PREVIEW_FONTS = { - geist: geistSans, - inter, - "noto-sans": notoSans, - "nunito-sans": nunitoSans, - figtree, - roboto, - raleway, - "dm-sans": dmSans, - "public-sans": publicSans, - outfit, - oxanium, - manrope, - "space-grotesk": spaceGrotesk, - montserrat, - "ibm-plex-sans": ibmPlexSans, - "source-sans-3": sourceSans3, - "instrument-sans": instrumentSans, - "jetbrains-mono": jetbrainsMono, - "geist-mono": geistMono, - "noto-serif": notoSerif, - "roboto-slab": robotoSlab, - merriweather, - lora, - "playfair-display": playfairDisplay, -} satisfies Record - -function createFontOption(name: FontName) { - const definition = FONT_DEFINITIONS.find((font) => font.name === name) - - if (!definition) { - throw new Error(`Unknown font definition: ${name}`) - } - - return { - name: definition.title, - value: definition.name, - font: PREVIEW_FONTS[name], - type: definition.type, - } as const -} - -export const FONTS = [ - createFontOption("geist"), - createFontOption("inter"), - createFontOption("noto-sans"), - createFontOption("nunito-sans"), - createFontOption("figtree"), - createFontOption("roboto"), - createFontOption("raleway"), - createFontOption("dm-sans"), - createFontOption("public-sans"), - createFontOption("outfit"), - createFontOption("oxanium"), - createFontOption("manrope"), - createFontOption("space-grotesk"), - createFontOption("montserrat"), - createFontOption("ibm-plex-sans"), - createFontOption("source-sans-3"), - createFontOption("instrument-sans"), - createFontOption("geist-mono"), - createFontOption("jetbrains-mono"), - createFontOption("noto-serif"), - createFontOption("roboto-slab"), - createFontOption("merriweather"), - createFontOption("lora"), - createFontOption("playfair-display"), -] as const - -export type Font = (typeof FONTS)[number] - -export const FONT_HEADING_OPTIONS = [ - { - name: "Inherit", - value: "inherit", - font: null, - type: "default", - }, - ...FONTS, -] as const - -export type FontHeadingOption = (typeof FONT_HEADING_OPTIONS)[number] +export * from "@/app/(app)/create/lib/fonts" diff --git a/apps/v4/app/(create)/lib/search-params.ts b/apps/v4/app/(create)/lib/search-params.ts index cbcd5a2272..da83a17918 100644 --- a/apps/v4/app/(create)/lib/search-params.ts +++ b/apps/v4/app/(create)/lib/search-params.ts @@ -1,309 +1 @@ -import * as React from "react" -import { useSearchParams } from "next/navigation" -import { useQueryStates } from "nuqs" -import { - createLoader, - createSerializer, - parseAsBoolean, - parseAsInteger, - parseAsString, - parseAsStringLiteral, - type inferParserType, - type Options, -} from "nuqs/server" -import { decodePreset, isPresetCode } from "shadcn/preset" - -import { - BASE_COLORS, - BASES, - DEFAULT_CONFIG, - getThemesForBaseColor, - iconLibraries, - MENU_ACCENTS, - MENU_COLORS, - RADII, - STYLES, - THEMES, - type BaseColorName, - type BaseName, - type ChartColorName, - type FontHeadingValue, - type FontValue, - type IconLibraryName, - type MenuAccentValue, - type MenuColorValue, - type RadiusValue, - type StyleName, - type ThemeName, -} from "@/registry/config" -import { FONTS } from "@/app/(create)/lib/fonts" -import { getPresetCode } from "@/app/(create)/lib/preset-code" -import { resolvePresetOverrides } from "@/app/(create)/lib/preset-query" - -const designSystemSearchParams = { - preset: parseAsString.withDefault("b0"), - base: parseAsStringLiteral(BASES.map((b) => b.name)).withDefault( - DEFAULT_CONFIG.base - ), - item: parseAsString.withDefault("preview").withOptions({ shallow: true }), - iconLibrary: parseAsStringLiteral( - Object.values(iconLibraries).map((i) => i.name) - ).withDefault(DEFAULT_CONFIG.iconLibrary), - style: parseAsStringLiteral(STYLES.map((s) => s.name)).withDefault( - DEFAULT_CONFIG.style - ), - theme: parseAsStringLiteral(THEMES.map((t) => t.name)).withDefault( - DEFAULT_CONFIG.theme - ), - chartColor: parseAsStringLiteral( - THEMES.map((t) => t.name) - ).withDefault(DEFAULT_CONFIG.chartColor ?? "neutral"), - font: parseAsStringLiteral(FONTS.map((f) => f.value)).withDefault( - DEFAULT_CONFIG.font - ), - fontHeading: parseAsStringLiteral([ - "inherit", - ...FONTS.map((f) => f.value), - ]).withDefault(DEFAULT_CONFIG.fontHeading), - baseColor: parseAsStringLiteral( - BASE_COLORS.map((b) => b.name) - ).withDefault(DEFAULT_CONFIG.baseColor), - menuAccent: parseAsStringLiteral( - MENU_ACCENTS.map((a) => a.value) - ).withDefault(DEFAULT_CONFIG.menuAccent), - menuColor: parseAsStringLiteral( - MENU_COLORS.map((m) => m.value) - ).withDefault(DEFAULT_CONFIG.menuColor), - radius: parseAsStringLiteral( - RADII.map((r) => r.name) - ).withDefault("default"), - template: parseAsStringLiteral([ - "next", - "next-monorepo", - "start", - "start-monorepo", - "react-router", - "react-router-monorepo", - "vite", - "vite-monorepo", - "astro", - "astro-monorepo", - "laravel", - ] as const).withDefault("next"), - rtl: parseAsBoolean.withDefault(false), - size: parseAsInteger.withDefault(100), - custom: parseAsBoolean.withDefault(false), -} - -// Design system param keys that get encoded into the preset code. -const DESIGN_SYSTEM_KEYS = [ - "style", - "baseColor", - "theme", - "chartColor", - "iconLibrary", - "font", - "fontHeading", - "radius", - "menuAccent", - "menuColor", -] as const - -function normalizeFontHeading( - font: FontValue, - fontHeading: FontHeadingValue -): FontHeadingValue { - // Persist "same as body" as an explicit inherit sentinel so the body font - // can change later without freezing headings to a concrete previous value. - return fontHeading === font ? "inherit" : fontHeading -} - -// Non-design-system keys that get passed through as-is. -// `base` is not encoded in preset codes — it's an architectural choice, not visual. -const NON_DESIGN_SYSTEM_KEYS = [ - "base", - "item", - "preset", - "template", - "rtl", - "size", - "custom", -] as const - -export const loadDesignSystemSearchParams = createLoader( - designSystemSearchParams -) - -export const serializeDesignSystemSearchParams = createSerializer( - designSystemSearchParams -) - -export type DesignSystemSearchParams = inferParserType< - typeof designSystemSearchParams -> - -export function isTranslucentMenuColor( - menuColor?: MenuColorValue | null -): menuColor is "default-translucent" | "inverted-translucent" { - return ( - menuColor === "default-translucent" || menuColor === "inverted-translucent" - ) -} - -function normalizePartialDesignSystemParams( - params: Partial -): Partial { - if ( - params.menuAccent === "bold" && - isTranslucentMenuColor(params.menuColor ?? undefined) - ) { - return { - ...params, - menuAccent: "subtle", - } - } - - return params -} - -function normalizeDesignSystemParams( - params: DesignSystemSearchParams -): DesignSystemSearchParams { - let result = { - ...params, - fontHeading: normalizeFontHeading(params.font, params.fontHeading), - } - - // Validate theme and chartColor against baseColor. - if (result.baseColor) { - const available = getThemesForBaseColor(result.baseColor) - const themeValid = available.some((t) => t.name === result.theme) - const chartColorValid = available.some((t) => t.name === result.chartColor) - - if (!themeValid || !chartColorValid) { - const fallback = (available[0]?.name ?? result.baseColor) as ThemeName - result = { - ...result, - ...(!themeValid && { theme: fallback }), - ...(!chartColorValid && { chartColor: fallback as ChartColorName }), - } - } - } - - if ( - result.menuAccent === "bold" && - isTranslucentMenuColor(result.menuColor) - ) { - return { - ...result, - menuAccent: "subtle", - } - } - - return result -} - -// If preset param exists, decode it and overlay on raw params. -// V1 presets don't encode chartColor — fall back to the colored -// theme that base-color themes originally borrowed charts from. -type SearchParamsLike = Pick - -function resolvePresetParams( - rawParams: DesignSystemSearchParams, - searchParams: SearchParamsLike -) { - if (rawParams.preset && isPresetCode(rawParams.preset)) { - const decoded = decodePreset(rawParams.preset) - if (decoded) { - const presetOverrides = resolvePresetOverrides(searchParams, decoded) - return normalizeDesignSystemParams({ - ...decoded, - ...presetOverrides, - base: rawParams.base, - item: rawParams.item, - preset: rawParams.preset, - template: rawParams.template, - rtl: rawParams.rtl, - size: rawParams.size, - custom: rawParams.custom, - }) - } - } - return normalizeDesignSystemParams(rawParams) -} - -// Wraps nuqs useQueryStates with transparent preset encoding/decoding. -// - Reads: if ?preset=CODE is in the URL, decodes it and returns individual values. -// - Writes: when design system params are set, encodes them into a preset code. -export function useDesignSystemSearchParams(options: Options = {}) { - const searchParams = useSearchParams() - const [rawParams, rawSetParams] = useQueryStates(designSystemSearchParams, { - shallow: false, - history: "push", - ...options, - }) - - const params = React.useMemo( - () => resolvePresetParams(rawParams, searchParams), - [rawParams, searchParams] - ) - - // Use ref so setParams callback stays stable across renders. - const paramsRef = React.useRef(params) - React.useEffect(() => { - paramsRef.current = params - }, [params]) - - type RawSetParamsInput = Parameters[0] - - const setParams = React.useCallback( - ( - updates: - | Partial - | (( - old: DesignSystemSearchParams - ) => Partial), - setOptions?: Options - ) => { - const resolvedUpdates = normalizePartialDesignSystemParams( - typeof updates === "function" ? updates(paramsRef.current) : updates - ) - - const hasDesignSystemUpdate = DESIGN_SYSTEM_KEYS.some( - (key) => key in resolvedUpdates - ) - - if (!hasDesignSystemUpdate) { - // No design system change, pass through directly. - return rawSetParams(resolvedUpdates as RawSetParamsInput, setOptions) - } - - // Merge current decoded values with updates. - const merged = normalizeDesignSystemParams({ - ...paramsRef.current, - ...resolvedUpdates, - }) - // Encode design system fields into a preset code. - // Cast needed: merged values may include null from nuqs resets, - // but encodePreset handles missing values by falling back to defaults. - const code = getPresetCode(merged) - // Build update: set preset, clear individual DS params from URL. - const rawUpdate: Record = { preset: code } - for (const key of DESIGN_SYSTEM_KEYS) { - rawUpdate[key] = null - } - - // Pass through non-DS params that were explicitly in the update. - for (const key of NON_DESIGN_SYSTEM_KEYS) { - if (key in resolvedUpdates) { - rawUpdate[key] = (resolvedUpdates as Record)[key] - } - } - - return rawSetParams(rawUpdate as RawSetParamsInput, setOptions) - }, - [rawSetParams] - ) - - return [params, setParams] as const -} +export * from "@/app/(app)/create/lib/search-params" diff --git a/apps/v4/app/(create)/preview/[base]/[name]/page.tsx b/apps/v4/app/(create)/preview/[base]/[name]/page.tsx index 50caaa386b..81de3e8ecd 100644 --- a/apps/v4/app/(create)/preview/[base]/[name]/page.tsx +++ b/apps/v4/app/(create)/preview/[base]/[name]/page.tsx @@ -6,17 +6,17 @@ import { siteConfig } from "@/lib/config" import { absoluteUrl } from "@/lib/utils" import { TailwindIndicator } from "@/components/tailwind-indicator" import { BASES, type Base, type BaseName } from "@/registry/config" -import { ActionMenuScript } from "@/app/(create)/components/action-menu" -import { DesignSystemProvider } from "@/app/(create)/components/design-system-provider" -import { HistoryScript } from "@/app/(create)/components/history-buttons" -import { DarkModeScript } from "@/app/(create)/components/mode-switcher" -import { PreviewStyle } from "@/app/(create)/components/preview-style" -import { RandomizeScript } from "@/app/(create)/components/random-button" +import { ActionMenuScript } from "@/app/(app)/create/components/action-menu" +import { DesignSystemProvider } from "@/app/(app)/create/components/design-system-provider" +import { HistoryScript } from "@/app/(app)/create/components/history-buttons" +import { DarkModeScript } from "@/app/(app)/create/components/mode-switcher" +import { PreviewStyle } from "@/app/(app)/create/components/preview-style" +import { RandomizeScript } from "@/app/(app)/create/components/random-button" import { getBaseComponent, getBaseItem, getItemsForBase, -} from "@/app/(create)/lib/api" +} from "@/app/(app)/create/lib/api" export const revalidate = false export const dynamic = "force-static" diff --git a/apps/v4/app/(examples)/dashboard-03/components/analytics-date-picker.tsx b/apps/v4/app/(examples)/dashboard-03/components/analytics-date-picker.tsx deleted file mode 100644 index 54a8ff7ab4..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/analytics-date-picker.tsx +++ /dev/null @@ -1,61 +0,0 @@ -"use client" - -import * as React from "react" -import { addDays, format } from "date-fns" -import { CalendarIcon } from "lucide-react" -import { type DateRange } from "react-day-picker" - -import { cn } from "@/lib/utils" -import { Button } from "@/registry/new-york-v4/ui/button" -import { Calendar } from "@/registry/new-york-v4/ui/calendar" -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/registry/new-york-v4/ui/popover" - -export function AnalyticsDatePicker() { - const [date, setDate] = React.useState({ - from: new Date(new Date().getFullYear(), 0, 20), - to: addDays(new Date(new Date().getFullYear(), 0, 20), 20), - }) - - return ( - - - - - - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/app-sidebar.tsx b/apps/v4/app/(examples)/dashboard-03/components/app-sidebar.tsx deleted file mode 100644 index cbae5e4c6f..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/app-sidebar.tsx +++ /dev/null @@ -1,84 +0,0 @@ -"use client" - -import * as React from "react" -import { - ChartLineIcon, - FileIcon, - HomeIcon, - LifeBuoy, - Send, - Settings2Icon, - ShoppingBagIcon, - ShoppingCartIcon, - UserIcon, -} from "lucide-react" - -import { Sidebar, SidebarContent } from "@/registry/new-york-v4/ui/sidebar" -import { NavMain } from "@/app/(examples)/dashboard-03/components/nav-main" -import { NavSecondary } from "@/app/(examples)/dashboard-03/components/nav-secondary" - -const data = { - navMain: [ - { - title: "Dashboard", - url: "/dashboard", - icon: HomeIcon, - }, - { - title: "Analytics", - url: "/dashboard/analytics", - icon: ChartLineIcon, - }, - { - title: "Orders", - url: "/dashboard/orders", - icon: ShoppingBagIcon, - }, - { - title: "Products", - url: "/dashboard/products", - icon: ShoppingCartIcon, - }, - { - title: "Invoices", - url: "/dashboard/invoices", - icon: FileIcon, - }, - { - title: "Customers", - url: "/dashboard/customers", - icon: UserIcon, - }, - { - title: "Settings", - url: "/dashboard/settings", - icon: Settings2Icon, - }, - ], - navSecondary: [ - { - title: "Support", - url: "#", - icon: LifeBuoy, - }, - { - title: "Feedback", - url: "#", - icon: Send, - }, - ], -} - -export function AppSidebar({ ...props }: React.ComponentProps) { - return ( - - - - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/chart-revenue.tsx b/apps/v4/app/(examples)/dashboard-03/components/chart-revenue.tsx deleted file mode 100644 index f6cc9eb946..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/chart-revenue.tsx +++ /dev/null @@ -1,110 +0,0 @@ -"use client" - -import { TrendingUp } from "lucide-react" -import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts" - -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/registry/new-york-v4/ui/card" -import { - ChartContainer, - ChartTooltip, - ChartTooltipContent, - type ChartConfig, -} from "@/registry/new-york-v4/ui/chart" - -const chartData = [ - { month: "January", desktop: 186, mobile: 80 }, - { month: "February", desktop: 305, mobile: 200 }, - { month: "March", desktop: 237, mobile: 120 }, - { month: "April", desktop: 73, mobile: 190 }, - { month: "May", desktop: 209, mobile: 130 }, - { month: "June", desktop: 346, mobile: 140 }, - { month: "July", desktop: 321, mobile: 275 }, - { month: "August", desktop: 132, mobile: 95 }, - { month: "September", desktop: 189, mobile: 225 }, - { month: "October", desktop: 302, mobile: 248 }, - { month: "November", desktop: 342, mobile: 285 }, - { month: "December", desktop: 328, mobile: 290 }, -] - -const chartConfig = { - desktop: { - label: "Desktop", - color: "var(--chart-1)", - }, - mobile: { - label: "Mobile", - color: "var(--chart-2)", - }, -} satisfies ChartConfig - -export function ChartRevenue() { - return ( - - - January - June 2024 - - $45,231.89 - - - - - - - value.slice(0, 3)} - /> - value.toLocaleString()} - domain={[0, "dataMax"]} - /> - } - /> - - - - - - -
- Trending up by 5.2% this month -
-
- Showing total visitors for the last 6 months -
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx b/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx deleted file mode 100644 index 472af3c5be..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx +++ /dev/null @@ -1,199 +0,0 @@ -"use client" - -import * as React from "react" -import { Label, Pie, PieChart, Sector } from "recharts" -import type { - PieSectorDataItem, - PieSectorShapeProps, -} from "recharts/types/polar/Pie" - -import { - Card, - CardAction, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "@/registry/new-york-v4/ui/card" -import { - ChartContainer, - ChartStyle, - ChartTooltip, - ChartTooltipContent, - type ChartConfig, -} from "@/registry/new-york-v4/ui/chart" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" - -const desktopData = [ - { month: "january", desktop: 186, fill: "var(--color-january)" }, - { month: "february", desktop: 305, fill: "var(--color-february)" }, - { month: "march", desktop: 237, fill: "var(--color-march)" }, - { month: "april", desktop: 173, fill: "var(--color-april)" }, - { month: "may", desktop: 209, fill: "var(--color-may)" }, -] - -const chartConfig = { - visitors: { - label: "Visitors", - }, - desktop: { - label: "Desktop", - }, - mobile: { - label: "Mobile", - }, - january: { - label: "January", - color: "var(--chart-1)", - }, - february: { - label: "February", - color: "var(--chart-2)", - }, - march: { - label: "March", - color: "var(--chart-3)", - }, - april: { - label: "April", - color: "var(--chart-4)", - }, - may: { - label: "May", - color: "var(--chart-5)", - }, -} satisfies ChartConfig - -export function ChartVisitors() { - const id = "pie-interactive" - const [activeMonth, setActiveMonth] = React.useState(desktopData[0].month) - - const activeIndex = React.useMemo( - () => desktopData.findIndex((item) => item.month === activeMonth), - [activeMonth] - ) - const months = React.useMemo(() => desktopData.map((item) => item.month), []) - - const renderPieShape = React.useCallback( - ({ index, outerRadius = 0, ...props }: PieSectorShapeProps) => { - if (index === activeIndex) { - return ( - - - - - ) - } - - return - }, - [activeIndex] - ) - - return ( - - - - January - June 2024 - 1,234 visitors - - - - - - - - } - /> - - - - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/mode-toggle.tsx b/apps/v4/app/(examples)/dashboard-03/components/mode-toggle.tsx deleted file mode 100644 index ca63bb877b..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/mode-toggle.tsx +++ /dev/null @@ -1,28 +0,0 @@ -"use client" - -import * as React from "react" -import { MoonIcon, SunIcon } from "lucide-react" -import { useTheme } from "next-themes" - -import { Button } from "@/registry/new-york-v4/ui/button" - -export function ModeToggle() { - const { setTheme, resolvedTheme } = useTheme() - - const toggleTheme = React.useCallback(() => { - setTheme(resolvedTheme === "dark" ? "light" : "dark") - }, [resolvedTheme, setTheme]) - - return ( - - ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/nav-main.tsx b/apps/v4/app/(examples)/dashboard-03/components/nav-main.tsx deleted file mode 100644 index e445bb29fe..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/nav-main.tsx +++ /dev/null @@ -1,91 +0,0 @@ -"use client" - -import { usePathname } from "next/navigation" -import { ChevronRight, type LucideIcon } from "lucide-react" - -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@/registry/new-york-v4/ui/collapsible" -import { - SidebarGroup, - SidebarGroupLabel, - SidebarMenu, - SidebarMenuAction, - SidebarMenuButton, - SidebarMenuItem, - SidebarMenuSub, - SidebarMenuSubButton, - SidebarMenuSubItem, -} from "@/registry/new-york-v4/ui/sidebar" - -export function NavMain({ - items, -}: { - items: { - title: string - url: string - icon: LucideIcon - isActive?: boolean - items?: { - title: string - url: string - }[] - disabled?: boolean - }[] -}) { - const pathname = usePathname() - - return ( - - Dashboard - - {items.map((item) => ( - - - - - - {item.title} - - - {item.items?.length ? ( - <> - - - - Toggle - - - - - {item.items?.map((subItem) => ( - - - - {subItem.title} - - - - ))} - - - - ) : null} - - - ))} - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/nav-secondary.tsx b/apps/v4/app/(examples)/dashboard-03/components/nav-secondary.tsx deleted file mode 100644 index 66924a12dc..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/nav-secondary.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from "react" -import { type LucideIcon } from "lucide-react" - -import { - SidebarGroup, - SidebarGroupContent, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "@/registry/new-york-v4/ui/sidebar" - -export function NavSecondary({ - items, - ...props -}: { - items: { - title: string - url: string - icon: LucideIcon - }[] -} & React.ComponentPropsWithoutRef) { - return ( - - - - {items.map((item) => ( - - - - - {item.title} - - - - ))} - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/nav-user.tsx b/apps/v4/app/(examples)/dashboard-03/components/nav-user.tsx deleted file mode 100644 index 12c05be3a2..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/nav-user.tsx +++ /dev/null @@ -1,90 +0,0 @@ -"use client" - -import { BadgeCheck, Bell, CreditCard, LogOut, Sparkles } from "lucide-react" - -import { - Avatar, - AvatarFallback, - AvatarImage, -} from "@/registry/new-york-v4/ui/avatar" -import { Button } from "@/registry/new-york-v4/ui/button" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuGroup, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@/registry/new-york-v4/ui/dropdown-menu" - -export function NavUser({ - user, -}: { - user: { - name: string - email: string - avatar: string - } -}) { - return ( - - - - - - -
- - - CN - -
- {user.name} - - {user.email} - -
-
-
- - - - - Upgrade to Pro - - - - - - - Account - - - - Billing - - - - Notifications - - - - - - Log out - -
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/products-table.tsx b/apps/v4/app/(examples)/dashboard-03/components/products-table.tsx deleted file mode 100644 index 2fb0ac58f6..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/products-table.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import { - ArrowUpDownIcon, - EllipsisVerticalIcon, - ListFilterIcon, - PlusIcon, -} from "lucide-react" - -import { Badge } from "@/registry/new-york-v4/ui/badge" -import { Button } from "@/registry/new-york-v4/ui/button" -import { - Card, - CardContent, - CardFooter, - CardHeader, -} from "@/registry/new-york-v4/ui/card" -import { Checkbox } from "@/registry/new-york-v4/ui/checkbox" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/registry/new-york-v4/ui/dropdown-menu" -import { - Pagination, - PaginationContent, - PaginationEllipsis, - PaginationItem, - PaginationLink, - PaginationNext, - PaginationPrevious, -} from "@/registry/new-york-v4/ui/pagination" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/registry/new-york-v4/ui/table" -import { Tabs, TabsList, TabsTrigger } from "@/registry/new-york-v4/ui/tabs" - -export function ProductsTable({ - products, -}: { - products: { - id: string - name: string - price: number - stock: number - dateAdded: string - status: string - }[] -}) { - return ( - - - - - All Products - In Stock - Low Stock - - - - - -
- - - - - -
-
- - - - - - - - Product - Price - Stock - Status - Date Added - - - - - {products.map((product) => ( - - - - - {product.name} - - ${product.price.toFixed(2)} - - {product.stock} - - - {product.status} - - - - {new Date(product.dateAdded).toLocaleDateString("en-US", { - month: "long", - day: "numeric", - year: "numeric", - })} - - - - - - - - Edit - - Delete - - - - - - ))} - -
-
- -
- Showing 1-10 of 100 products -
- - - - - - - 1 - - - - 2 - - - - 3 - - - - - - - - - -
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/search-form.tsx b/apps/v4/app/(examples)/dashboard-03/components/search-form.tsx deleted file mode 100644 index 0491880e4d..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/search-form.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Search } from "lucide-react" - -import { Label } from "@/registry/new-york-v4/ui/label" -import { SidebarInput } from "@/registry/new-york-v4/ui/sidebar" - -export function SearchForm({ ...props }: React.ComponentProps<"form">) { - return ( -
-
- - - -
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/components/site-header.tsx b/apps/v4/app/(examples)/dashboard-03/components/site-header.tsx deleted file mode 100644 index 4fad66816f..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/components/site-header.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client" - -import { Fragment, useMemo } from "react" -import { usePathname } from "next/navigation" -import { SidebarIcon } from "lucide-react" - -import { ThemeSelector } from "@/components/theme-selector" -import { SearchForm } from "@/registry/new-york-v4/blocks/sidebar-16/components/search-form" -import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/registry/new-york-v4/ui/breadcrumb" -import { Button } from "@/registry/new-york-v4/ui/button" -import { Separator } from "@/registry/new-york-v4/ui/separator" -import { useSidebar } from "@/registry/new-york-v4/ui/sidebar" -import { ModeToggle } from "@/app/(examples)/dashboard-03/components/mode-toggle" -import { NavUser } from "@/app/(examples)/dashboard-03/components/nav-user" - -export function SiteHeader() { - const { toggleSidebar } = useSidebar() - const pathname = usePathname() - - // Faux breadcrumbs for demo. - const breadcrumbs = useMemo(() => { - return pathname - .split("/") - .filter((path) => path !== "") - .map((path, index, array) => ({ - label: path, - href: `/${array.slice(0, index + 1).join("/")}`, - })) - }, [pathname]) - - return ( -
-
- - - - - - - Home - - - - {breadcrumbs.map((breadcrumb, index) => - index === breadcrumbs.length - 1 ? ( - - - {breadcrumb.label} - - - ) : ( - - - - {breadcrumb.label} - - - - - ) - )} - - -
- - - - -
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/customers/page.tsx b/apps/v4/app/(examples)/dashboard-03/customers/page.tsx deleted file mode 100644 index 512a007ea2..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/customers/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -export default function CustomersPage() { - return ( -
-
Input
-
Input 50
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/layout.tsx b/apps/v4/app/(examples)/dashboard-03/layout.tsx deleted file mode 100644 index 6b4daad53c..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/layout.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { cookies } from "next/headers" - -import { - SidebarInset, - SidebarProvider, -} from "@/registry/new-york-v4/ui/sidebar" -import { AppSidebar } from "@/app/(examples)/dashboard-03/components/app-sidebar" -import { SiteHeader } from "@/app/(examples)/dashboard-03/components/site-header" - -export default async function DashboardLayout({ - children, -}: { - children: React.ReactNode -}) { - const cookieStore = await cookies() - const defaultOpen = cookieStore.get("sidebar_state")?.value === "true" - - return ( -
- - -
- - {children} -
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/page.tsx b/apps/v4/app/(examples)/dashboard-03/page.tsx deleted file mode 100644 index 5cc7dce9c8..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/page.tsx +++ /dev/null @@ -1,206 +0,0 @@ -import { type Metadata } from "next" -import { - DownloadIcon, - FilterIcon, - TrendingDownIcon, - TrendingUpIcon, -} from "lucide-react" - -import { Badge } from "@/registry/new-york-v4/ui/badge" -import { Button } from "@/registry/new-york-v4/ui/button" -import { - Card, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/registry/new-york-v4/ui/card" -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "@/registry/new-york-v4/ui/tabs" -import { AnalyticsDatePicker } from "@/app/(examples)/dashboard-03/components/analytics-date-picker" -import { ChartRevenue } from "@/app/(examples)/dashboard-03/components/chart-revenue" -import { ChartVisitors } from "@/app/(examples)/dashboard-03/components/chart-visitors" -import { ProductsTable } from "@/app/(examples)/dashboard-03/components/products-table" - -export const metadata: Metadata = { - title: "Dashboard", - description: "An example dashboard to test the new components.", -} - -// Load from database. -const products = [ - { - id: "1", - name: "BJÖRKSNÄS Dining Table", - price: 599.99, - stock: 12, - dateAdded: "2023-06-15", - status: "In Stock", - }, - { - id: "2", - name: "POÄNG Armchair", - price: 249.99, - stock: 28, - dateAdded: "2023-07-22", - status: "In Stock", - }, - { - id: "3", - name: "MALM Bed Frame", - price: 399.99, - stock: 15, - dateAdded: "2023-08-05", - status: "In Stock", - }, - { - id: "4", - name: "KALLAX Shelf Unit", - price: 179.99, - stock: 32, - dateAdded: "2023-09-12", - status: "In Stock", - }, - { - id: "5", - name: "STOCKHOLM Rug", - price: 299.99, - stock: 8, - dateAdded: "2023-10-18", - status: "Low Stock", - }, - { - id: "6", - name: "KIVIK Sofa", - price: 899.99, - stock: 6, - dateAdded: "2023-11-02", - status: "Low Stock", - }, - { - id: "7", - name: "LISABO Coffee Table", - price: 149.99, - stock: 22, - dateAdded: "2023-11-29", - status: "In Stock", - }, - { - id: "8", - name: "HEMNES Bookcase", - price: 249.99, - stock: 17, - dateAdded: "2023-12-10", - status: "In Stock", - }, - { - id: "9", - name: "EKEDALEN Dining Chairs (Set of 2)", - price: 199.99, - stock: 14, - dateAdded: "2024-01-05", - status: "In Stock", - }, - { - id: "10", - name: "FRIHETEN Sleeper Sofa", - price: 799.99, - stock: 9, - dateAdded: "2024-01-18", - status: "Low Stock", - }, -] - -export default function DashboardPage() { - return ( -
- -
- - Overview - Analytics - Reports - - Exports - - -
- - - -
-
- -
- - - Total Revenue - $1,250.00 in the last 30 days - - - - - +12.5% - - - - - - New Customers - -12 customers from last month - - - - - -20% - - - - - - Active Accounts - +2,345 users from last month - - - - - +12.5% - - - - - - Growth Rate - +12.5% increase per month - - - - - +4.5% - - - -
-
- - -
- -
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard-03/settings/page.tsx b/apps/v4/app/(examples)/dashboard-03/settings/page.tsx deleted file mode 100644 index 76bbe89d44..0000000000 --- a/apps/v4/app/(examples)/dashboard-03/settings/page.tsx +++ /dev/null @@ -1,500 +0,0 @@ -import { type Metadata } from "next" - -import { cn } from "@/lib/utils" -import { Button } from "@/registry/new-york-v4/ui/button" -import { - Card, - CardAction, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/registry/new-york-v4/ui/card" -import { Checkbox } from "@/registry/new-york-v4/ui/checkbox" -import { Input } from "@/registry/new-york-v4/ui/input" -import { Label } from "@/registry/new-york-v4/ui/label" -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" -import { Switch } from "@/registry/new-york-v4/ui/switch" -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/registry/new-york-v4/ui/table" -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "@/registry/new-york-v4/ui/tabs" - -export const metadata: Metadata = { - title: "Settings", - description: "Manage your account settings", -} - -const timezones = [ - { - label: "Americas", - timezones: [ - { value: "America/New_York", label: "(GMT-5) New York" }, - { value: "America/Los_Angeles", label: "(GMT-8) Los Angeles" }, - { value: "America/Chicago", label: "(GMT-6) Chicago" }, - { value: "America/Toronto", label: "(GMT-5) Toronto" }, - { value: "America/Vancouver", label: "(GMT-8) Vancouver" }, - { value: "America/Sao_Paulo", label: "(GMT-3) São Paulo" }, - ], - }, - { - label: "Europe", - timezones: [ - { value: "Europe/London", label: "(GMT+0) London" }, - { value: "Europe/Paris", label: "(GMT+1) Paris" }, - { value: "Europe/Berlin", label: "(GMT+1) Berlin" }, - { value: "Europe/Rome", label: "(GMT+1) Rome" }, - { value: "Europe/Madrid", label: "(GMT+1) Madrid" }, - { value: "Europe/Amsterdam", label: "(GMT+1) Amsterdam" }, - ], - }, - { - label: "Asia/Pacific", - timezones: [ - { value: "Asia/Tokyo", label: "(GMT+9) Tokyo" }, - { value: "Asia/Shanghai", label: "(GMT+8) Shanghai" }, - { value: "Asia/Singapore", label: "(GMT+8) Singapore" }, - { value: "Asia/Dubai", label: "(GMT+4) Dubai" }, - { value: "Australia/Sydney", label: "(GMT+11) Sydney" }, - { value: "Asia/Seoul", label: "(GMT+9) Seoul" }, - ], - }, -] as const - -const loginHistory = [ - { - date: "2024-01-01", - ip: "192.168.1.1", - location: "New York, USA", - }, - { - date: "2023-12-29", - ip: "172.16.0.100", - location: "London, UK", - }, - { - date: "2023-12-28", - ip: "10.0.0.50", - location: "Toronto, Canada", - }, - { - date: "2023-12-25", - ip: "192.168.2.15", - location: "Sydney, Australia", - }, -] as const - -const activeSessions = [ - { - device: "MacBook Pro", - browser: "Chrome", - os: "macOS", - }, - { - device: "iPhone", - browser: "Safari", - os: "iOS", - }, - { - device: "iPad", - browser: "Safari", - os: "iOS", - }, - { - device: "Android Phone", - browser: "Chrome", - os: "Android", - }, -] as const - -export default function SettingsPage() { - return ( -
- -
- - Account - Security - Notifications - Privacy - -
- - - - Account Settings - - Make changes to your account here. - - - -
- - - - - - - - This is your public display name. - - - - - - - - - - - - - - - -
-
- - - -
- - - Notifications - - Manage how you receive notifications. - - - -
- - - - -
- - -
-
- - -
-
- - -
-
- - Choose how you want to receive notifications. - -
- - - -
- - -
-
- - -
-
- - -
-
- - Choose how you want to receive notifications. - -
-
-
-
- - - -
-
- - - - Security Settings - - Make changes to your security settings here. - - - -
- - - - - - - - This is your current password. - - - - - - - - - - - - - - - - - - - - - This will add an extra layer of security to your account. - Make this an extra long description to test the layout. - - - -
-
- - - -
- - - Login History - - Recent login activities on your account. - - - - - - - Date - - IP - - Location - - - - {loginHistory.map((login) => ( - - -
- {new Date(login.date).toLocaleDateString("en-US", { - year: "numeric", - month: "long", - day: "numeric", - })} - - {login.ip} - -
-
- - {login.ip} - - {login.location} -
- ))} -
-
-
-
- - - Active Sessions - - Current active sessions on your account. - - - - - - - - - - Device - Browser - OS - - - - {activeSessions.map((session) => ( - - {session.device} - {session.browser} - {session.os} - - ))} - -
-
-
-
-
-
- ) -} - -function FieldGroup({ children }: React.ComponentProps<"div">) { - return ( -
- {children} -
- ) -} - -function Field({ children, className, ...props }: React.ComponentProps<"div">) { - return ( -
- {children} -
- ) -} - -function FieldControl({ - children, - className, - ...props -}: React.ComponentProps<"div">) { - return ( -
- {children} -
- ) -} - -function FieldDescription({ - children, - className, - ...props -}: React.ComponentProps<"p">) { - return ( -

- {children} -

- ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/app-sidebar.tsx b/apps/v4/app/(examples)/dashboard/components/app-sidebar.tsx deleted file mode 100644 index 62bf35cb11..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/app-sidebar.tsx +++ /dev/null @@ -1,181 +0,0 @@ -"use client" - -import * as React from "react" -import { - IconCamera, - IconChartBar, - IconDashboard, - IconDatabase, - IconFileAi, - IconFileDescription, - IconFileWord, - IconFolder, - IconHelp, - IconInnerShadowTop, - IconListDetails, - IconReport, - IconSearch, - IconSettings, - IconUsers, -} from "@tabler/icons-react" - -import { - Sidebar, - SidebarContent, - SidebarFooter, - SidebarHeader, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "@/registry/new-york-v4/ui/sidebar" -import { NavDocuments } from "@/app/(examples)/dashboard/components/nav-documents" -import { NavMain } from "@/app/(examples)/dashboard/components/nav-main" -import { NavSecondary } from "@/app/(examples)/dashboard/components/nav-secondary" -import { NavUser } from "@/app/(examples)/dashboard/components/nav-user" - -const data = { - user: { - name: "shadcn", - email: "m@example.com", - avatar: "/avatars/shadcn.jpg", - }, - navMain: [ - { - title: "Dashboard", - url: "#", - icon: IconDashboard, - }, - { - title: "Lifecycle", - url: "#", - icon: IconListDetails, - }, - { - title: "Analytics", - url: "#", - icon: IconChartBar, - }, - { - title: "Projects", - url: "#", - icon: IconFolder, - }, - { - title: "Team", - url: "#", - icon: IconUsers, - }, - ], - navClouds: [ - { - title: "Capture", - icon: IconCamera, - isActive: true, - url: "#", - items: [ - { - title: "Active Proposals", - url: "#", - }, - { - title: "Archived", - url: "#", - }, - ], - }, - { - title: "Proposal", - icon: IconFileDescription, - url: "#", - items: [ - { - title: "Active Proposals", - url: "#", - }, - { - title: "Archived", - url: "#", - }, - ], - }, - { - title: "Prompts", - icon: IconFileAi, - url: "#", - items: [ - { - title: "Active Proposals", - url: "#", - }, - { - title: "Archived", - url: "#", - }, - ], - }, - ], - navSecondary: [ - { - title: "Settings", - url: "#", - icon: IconSettings, - }, - { - title: "Get Help", - url: "#", - icon: IconHelp, - }, - { - title: "Search", - url: "#", - icon: IconSearch, - }, - ], - documents: [ - { - name: "Data Library", - url: "#", - icon: IconDatabase, - }, - { - name: "Reports", - url: "#", - icon: IconReport, - }, - { - name: "Word Assistant", - url: "#", - icon: IconFileWord, - }, - ], -} - -export function AppSidebar({ ...props }: React.ComponentProps) { - return ( - - - - - - - - Acme Inc. - - - - - - - - - - - - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/chart-area-interactive.tsx b/apps/v4/app/(examples)/dashboard/components/chart-area-interactive.tsx deleted file mode 100644 index cb6b5fc22e..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/chart-area-interactive.tsx +++ /dev/null @@ -1,292 +0,0 @@ -"use client" - -import * as React from "react" -import { Area, AreaChart, CartesianGrid, XAxis } from "recharts" - -import { useIsMobile } from "@/registry/new-york-v4/hooks/use-mobile" -import { - Card, - CardAction, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "@/registry/new-york-v4/ui/card" -import { - ChartContainer, - ChartTooltip, - ChartTooltipContent, - type ChartConfig, -} from "@/registry/new-york-v4/ui/chart" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" -import { - ToggleGroup, - ToggleGroupItem, -} from "@/registry/new-york-v4/ui/toggle-group" - -export const description = "An interactive area chart" - -const chartData = [ - { date: "2024-04-01", desktop: 222, mobile: 150 }, - { date: "2024-04-02", desktop: 97, mobile: 180 }, - { date: "2024-04-03", desktop: 167, mobile: 120 }, - { date: "2024-04-04", desktop: 242, mobile: 260 }, - { date: "2024-04-05", desktop: 373, mobile: 290 }, - { date: "2024-04-06", desktop: 301, mobile: 340 }, - { date: "2024-04-07", desktop: 245, mobile: 180 }, - { date: "2024-04-08", desktop: 409, mobile: 320 }, - { date: "2024-04-09", desktop: 59, mobile: 110 }, - { date: "2024-04-10", desktop: 261, mobile: 190 }, - { date: "2024-04-11", desktop: 327, mobile: 350 }, - { date: "2024-04-12", desktop: 292, mobile: 210 }, - { date: "2024-04-13", desktop: 342, mobile: 380 }, - { date: "2024-04-14", desktop: 137, mobile: 220 }, - { date: "2024-04-15", desktop: 120, mobile: 170 }, - { date: "2024-04-16", desktop: 138, mobile: 190 }, - { date: "2024-04-17", desktop: 446, mobile: 360 }, - { date: "2024-04-18", desktop: 364, mobile: 410 }, - { date: "2024-04-19", desktop: 243, mobile: 180 }, - { date: "2024-04-20", desktop: 89, mobile: 150 }, - { date: "2024-04-21", desktop: 137, mobile: 200 }, - { date: "2024-04-22", desktop: 224, mobile: 170 }, - { date: "2024-04-23", desktop: 138, mobile: 230 }, - { date: "2024-04-24", desktop: 387, mobile: 290 }, - { date: "2024-04-25", desktop: 215, mobile: 250 }, - { date: "2024-04-26", desktop: 75, mobile: 130 }, - { date: "2024-04-27", desktop: 383, mobile: 420 }, - { date: "2024-04-28", desktop: 122, mobile: 180 }, - { date: "2024-04-29", desktop: 315, mobile: 240 }, - { date: "2024-04-30", desktop: 454, mobile: 380 }, - { date: "2024-05-01", desktop: 165, mobile: 220 }, - { date: "2024-05-02", desktop: 293, mobile: 310 }, - { date: "2024-05-03", desktop: 247, mobile: 190 }, - { date: "2024-05-04", desktop: 385, mobile: 420 }, - { date: "2024-05-05", desktop: 481, mobile: 390 }, - { date: "2024-05-06", desktop: 498, mobile: 520 }, - { date: "2024-05-07", desktop: 388, mobile: 300 }, - { date: "2024-05-08", desktop: 149, mobile: 210 }, - { date: "2024-05-09", desktop: 227, mobile: 180 }, - { date: "2024-05-10", desktop: 293, mobile: 330 }, - { date: "2024-05-11", desktop: 335, mobile: 270 }, - { date: "2024-05-12", desktop: 197, mobile: 240 }, - { date: "2024-05-13", desktop: 197, mobile: 160 }, - { date: "2024-05-14", desktop: 448, mobile: 490 }, - { date: "2024-05-15", desktop: 473, mobile: 380 }, - { date: "2024-05-16", desktop: 338, mobile: 400 }, - { date: "2024-05-17", desktop: 499, mobile: 420 }, - { date: "2024-05-18", desktop: 315, mobile: 350 }, - { date: "2024-05-19", desktop: 235, mobile: 180 }, - { date: "2024-05-20", desktop: 177, mobile: 230 }, - { date: "2024-05-21", desktop: 82, mobile: 140 }, - { date: "2024-05-22", desktop: 81, mobile: 120 }, - { date: "2024-05-23", desktop: 252, mobile: 290 }, - { date: "2024-05-24", desktop: 294, mobile: 220 }, - { date: "2024-05-25", desktop: 201, mobile: 250 }, - { date: "2024-05-26", desktop: 213, mobile: 170 }, - { date: "2024-05-27", desktop: 420, mobile: 460 }, - { date: "2024-05-28", desktop: 233, mobile: 190 }, - { date: "2024-05-29", desktop: 78, mobile: 130 }, - { date: "2024-05-30", desktop: 340, mobile: 280 }, - { date: "2024-05-31", desktop: 178, mobile: 230 }, - { date: "2024-06-01", desktop: 178, mobile: 200 }, - { date: "2024-06-02", desktop: 470, mobile: 410 }, - { date: "2024-06-03", desktop: 103, mobile: 160 }, - { date: "2024-06-04", desktop: 439, mobile: 380 }, - { date: "2024-06-05", desktop: 88, mobile: 140 }, - { date: "2024-06-06", desktop: 294, mobile: 250 }, - { date: "2024-06-07", desktop: 323, mobile: 370 }, - { date: "2024-06-08", desktop: 385, mobile: 320 }, - { date: "2024-06-09", desktop: 438, mobile: 480 }, - { date: "2024-06-10", desktop: 155, mobile: 200 }, - { date: "2024-06-11", desktop: 92, mobile: 150 }, - { date: "2024-06-12", desktop: 492, mobile: 420 }, - { date: "2024-06-13", desktop: 81, mobile: 130 }, - { date: "2024-06-14", desktop: 426, mobile: 380 }, - { date: "2024-06-15", desktop: 307, mobile: 350 }, - { date: "2024-06-16", desktop: 371, mobile: 310 }, - { date: "2024-06-17", desktop: 475, mobile: 520 }, - { date: "2024-06-18", desktop: 107, mobile: 170 }, - { date: "2024-06-19", desktop: 341, mobile: 290 }, - { date: "2024-06-20", desktop: 408, mobile: 450 }, - { date: "2024-06-21", desktop: 169, mobile: 210 }, - { date: "2024-06-22", desktop: 317, mobile: 270 }, - { date: "2024-06-23", desktop: 480, mobile: 530 }, - { date: "2024-06-24", desktop: 132, mobile: 180 }, - { date: "2024-06-25", desktop: 141, mobile: 190 }, - { date: "2024-06-26", desktop: 434, mobile: 380 }, - { date: "2024-06-27", desktop: 448, mobile: 490 }, - { date: "2024-06-28", desktop: 149, mobile: 200 }, - { date: "2024-06-29", desktop: 103, mobile: 160 }, - { date: "2024-06-30", desktop: 446, mobile: 400 }, -] - -const chartConfig = { - visitors: { - label: "Visitors", - }, - desktop: { - label: "Desktop", - color: "var(--primary)", - }, - mobile: { - label: "Mobile", - color: "var(--primary)", - }, -} satisfies ChartConfig - -export function ChartAreaInteractive() { - const isMobile = useIsMobile() - const [timeRange, setTimeRange] = React.useState("90d") - - React.useEffect(() => { - if (isMobile) { - setTimeRange("7d") - } - }, [isMobile]) - - const filteredData = chartData.filter((item) => { - const date = new Date(item.date) - const referenceDate = new Date("2024-06-30") - let daysToSubtract = 90 - if (timeRange === "30d") { - daysToSubtract = 30 - } else if (timeRange === "7d") { - daysToSubtract = 7 - } - const startDate = new Date(referenceDate) - startDate.setDate(startDate.getDate() - daysToSubtract) - return date >= startDate - }) - - return ( - - - Total Visitors - - - Total for the last 3 months - - Last 3 months - - - - Last 3 months - Last 30 days - Last 7 days - - - - - - - - - - - - - - - - - - - { - const date = new Date(value) - return date.toLocaleDateString("en-US", { - month: "short", - day: "numeric", - }) - }} - /> - { - return new Date(value).toLocaleDateString("en-US", { - month: "short", - day: "numeric", - }) - }} - indicator="dot" - /> - } - /> - - - - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/data-table.tsx b/apps/v4/app/(examples)/dashboard/components/data-table.tsx deleted file mode 100644 index def0a697fe..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/data-table.tsx +++ /dev/null @@ -1,807 +0,0 @@ -"use client" - -import * as React from "react" -import { - closestCenter, - DndContext, - KeyboardSensor, - MouseSensor, - TouchSensor, - useSensor, - useSensors, - type DragEndEvent, - type UniqueIdentifier, -} from "@dnd-kit/core" -import { restrictToVerticalAxis } from "@dnd-kit/modifiers" -import { - arrayMove, - SortableContext, - useSortable, - verticalListSortingStrategy, -} from "@dnd-kit/sortable" -import { CSS } from "@dnd-kit/utilities" -import { - IconChevronDown, - IconChevronLeft, - IconChevronRight, - IconChevronsLeft, - IconChevronsRight, - IconCircleCheckFilled, - IconDotsVertical, - IconGripVertical, - IconLayoutColumns, - IconLoader, - IconPlus, - IconTrendingUp, -} from "@tabler/icons-react" -import { - flexRender, - getCoreRowModel, - getFacetedRowModel, - getFacetedUniqueValues, - getFilteredRowModel, - getPaginationRowModel, - getSortedRowModel, - useReactTable, - type ColumnDef, - type ColumnFiltersState, - type Row, - type SortingState, - type VisibilityState, -} from "@tanstack/react-table" -import { Area, AreaChart, CartesianGrid, XAxis } from "recharts" -import { toast } from "sonner" -import { z } from "zod" - -import { useIsMobile } from "@/registry/new-york-v4/hooks/use-mobile" -import { Badge } from "@/registry/new-york-v4/ui/badge" -import { Button } from "@/registry/new-york-v4/ui/button" -import { - ChartContainer, - ChartTooltip, - ChartTooltipContent, - type ChartConfig, -} from "@/registry/new-york-v4/ui/chart" -import { Checkbox } from "@/registry/new-york-v4/ui/checkbox" -import { - Drawer, - DrawerClose, - DrawerContent, - DrawerDescription, - DrawerFooter, - DrawerHeader, - DrawerTitle, - DrawerTrigger, -} from "@/registry/new-york-v4/ui/drawer" -import { - DropdownMenu, - DropdownMenuCheckboxItem, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@/registry/new-york-v4/ui/dropdown-menu" -import { Input } from "@/registry/new-york-v4/ui/input" -import { Label } from "@/registry/new-york-v4/ui/label" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" -import { Separator } from "@/registry/new-york-v4/ui/separator" -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/registry/new-york-v4/ui/table" -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "@/registry/new-york-v4/ui/tabs" - -export const schema = z.object({ - id: z.number(), - header: z.string(), - type: z.string(), - status: z.string(), - target: z.string(), - limit: z.string(), - reviewer: z.string(), -}) - -// Create a separate component for the drag handle -function DragHandle({ id }: { id: number }) { - const { attributes, listeners } = useSortable({ - id, - }) - - return ( - - ) -} - -const columns: ColumnDef>[] = [ - { - id: "drag", - header: () => null, - cell: ({ row }) => , - }, - { - id: "select", - header: ({ table }) => ( -
- table.toggleAllPageRowsSelected(!!value)} - aria-label="Select all" - /> -
- ), - cell: ({ row }) => ( -
- row.toggleSelected(!!value)} - aria-label="Select row" - /> -
- ), - enableSorting: false, - enableHiding: false, - }, - { - accessorKey: "header", - header: "Header", - cell: ({ row }) => { - return - }, - enableHiding: false, - }, - { - accessorKey: "type", - header: "Section Type", - cell: ({ row }) => ( -
- - {row.original.type} - -
- ), - }, - { - accessorKey: "status", - header: "Status", - cell: ({ row }) => ( - - {row.original.status === "Done" ? ( - - ) : ( - - )} - {row.original.status} - - ), - }, - { - accessorKey: "target", - header: () =>
Target
, - cell: ({ row }) => ( -
{ - e.preventDefault() - toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), { - loading: `Saving ${row.original.header}`, - success: "Done", - error: "Error", - }) - }} - > - - -
- ), - }, - { - accessorKey: "limit", - header: () =>
Limit
, - cell: ({ row }) => ( -
{ - e.preventDefault() - toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), { - loading: `Saving ${row.original.header}`, - success: "Done", - error: "Error", - }) - }} - > - - -
- ), - }, - { - accessorKey: "reviewer", - header: "Reviewer", - cell: ({ row }) => { - const isAssigned = row.original.reviewer !== "Assign reviewer" - - if (isAssigned) { - return row.original.reviewer - } - - return ( - <> - - - - ) - }, - }, - { - id: "actions", - cell: () => ( - - - - - - Edit - Make a copy - Favorite - - Delete - - - ), - }, -] - -function DraggableRow({ row }: { row: Row> }) { - const { transform, transition, setNodeRef, isDragging } = useSortable({ - id: row.original.id, - }) - - return ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - ) -} - -export function DataTable({ - data: initialData, -}: { - data: z.infer[] -}) { - const [data, setData] = React.useState(() => initialData) - const [rowSelection, setRowSelection] = React.useState({}) - const [columnVisibility, setColumnVisibility] = - React.useState({}) - const [columnFilters, setColumnFilters] = React.useState( - [] - ) - const [sorting, setSorting] = React.useState([]) - const [pagination, setPagination] = React.useState({ - pageIndex: 0, - pageSize: 10, - }) - const sortableId = React.useId() - const sensors = useSensors( - useSensor(MouseSensor, {}), - useSensor(TouchSensor, {}), - useSensor(KeyboardSensor, {}) - ) - - const dataIds = React.useMemo( - () => data?.map(({ id }) => id) || [], - [data] - ) - - const table = useReactTable({ - data, - columns, - state: { - sorting, - columnVisibility, - rowSelection, - columnFilters, - pagination, - }, - getRowId: (row) => row.id.toString(), - enableRowSelection: true, - onRowSelectionChange: setRowSelection, - onSortingChange: setSorting, - onColumnFiltersChange: setColumnFilters, - onColumnVisibilityChange: setColumnVisibility, - onPaginationChange: setPagination, - getCoreRowModel: getCoreRowModel(), - getFilteredRowModel: getFilteredRowModel(), - getPaginationRowModel: getPaginationRowModel(), - getSortedRowModel: getSortedRowModel(), - getFacetedRowModel: getFacetedRowModel(), - getFacetedUniqueValues: getFacetedUniqueValues(), - }) - - function handleDragEnd(event: DragEndEvent) { - const { active, over } = event - if (active && over && active.id !== over.id) { - setData((data) => { - const oldIndex = dataIds.indexOf(active.id) - const newIndex = dataIds.indexOf(over.id) - return arrayMove(data, oldIndex, newIndex) - }) - } - } - - return ( - -
- - - - Outline - - Past Performance 3 - - - Key Personnel 2 - - Focus Documents - -
- - - - - - {table - .getAllColumns() - .filter( - (column) => - typeof column.accessorFn !== "undefined" && - column.getCanHide() - ) - .map((column) => { - return ( - - column.toggleVisibility(!!value) - } - > - {column.id} - - ) - })} - - - -
-
- -
- - - - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => { - return ( - - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ) - })} - - ))} - - - {table.getRowModel().rows?.length ? ( - - {table.getRowModel().rows.map((row) => ( - - ))} - - ) : ( - - - No results. - - - )} - -
-
-
-
-
- {table.getFilteredSelectedRowModel().rows.length} of{" "} - {table.getFilteredRowModel().rows.length} row(s) selected. -
-
-
- - -
-
- Page {table.getState().pagination.pageIndex + 1} of{" "} - {table.getPageCount()} -
-
- - - - -
-
-
-
- -
-
- -
-
- -
-
-
- ) -} - -const chartData = [ - { month: "January", desktop: 186, mobile: 80 }, - { month: "February", desktop: 305, mobile: 200 }, - { month: "March", desktop: 237, mobile: 120 }, - { month: "April", desktop: 73, mobile: 190 }, - { month: "May", desktop: 209, mobile: 130 }, - { month: "June", desktop: 214, mobile: 140 }, -] - -const chartConfig = { - desktop: { - label: "Desktop", - color: "var(--primary)", - }, - mobile: { - label: "Mobile", - color: "var(--primary)", - }, -} satisfies ChartConfig - -function TableCellViewer({ item }: { item: z.infer }) { - const isMobile = useIsMobile() - - return ( - - - - - - - {item.header} - - Showing total visitors for the last 6 months - - -
- {!isMobile && ( - <> - - - - value.slice(0, 3)} - hide - /> - } - /> - - - - - -
-
- Trending up by 5.2% this month{" "} - -
-
- Showing total visitors for the last 6 months. This is just - some random text to test the layout. It spans multiple lines - and should wrap around. -
-
- - - )} -
-
- - -
-
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
-
- - -
-
-
- - - - - - -
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/mode-toggle.tsx b/apps/v4/app/(examples)/dashboard/components/mode-toggle.tsx deleted file mode 100644 index 29c689878f..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/mode-toggle.tsx +++ /dev/null @@ -1,27 +0,0 @@ -"use client" - -import * as React from "react" -import { IconBrightness } from "@tabler/icons-react" -import { useTheme } from "next-themes" - -import { Button } from "@/registry/new-york-v4/ui/button" - -export function ModeToggle() { - const { setTheme, resolvedTheme } = useTheme() - - const toggleTheme = React.useCallback(() => { - setTheme(resolvedTheme === "dark" ? "light" : "dark") - }, [resolvedTheme, setTheme]) - - return ( - - ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/nav-documents.tsx b/apps/v4/app/(examples)/dashboard/components/nav-documents.tsx deleted file mode 100644 index 5a09c82b28..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/nav-documents.tsx +++ /dev/null @@ -1,92 +0,0 @@ -"use client" - -import { - IconDots, - IconFolder, - IconShare3, - IconTrash, - type Icon, -} from "@tabler/icons-react" - -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@/registry/new-york-v4/ui/dropdown-menu" -import { - SidebarGroup, - SidebarGroupLabel, - SidebarMenu, - SidebarMenuAction, - SidebarMenuButton, - SidebarMenuItem, - useSidebar, -} from "@/registry/new-york-v4/ui/sidebar" - -export function NavDocuments({ - items, -}: { - items: { - name: string - url: string - icon: Icon - }[] -}) { - const { isMobile } = useSidebar() - - return ( - - Documents - - {items.map((item) => ( - - - - - {item.name} - - - - - - - More - - - - - - Open - - - - Share - - - - - Delete - - - - - ))} - - - - More - - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/nav-main.tsx b/apps/v4/app/(examples)/dashboard/components/nav-main.tsx deleted file mode 100644 index 3fcecdd1a0..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/nav-main.tsx +++ /dev/null @@ -1,58 +0,0 @@ -"use client" - -import { IconCirclePlusFilled, IconMail, type Icon } from "@tabler/icons-react" - -import { Button } from "@/registry/new-york-v4/ui/button" -import { - SidebarGroup, - SidebarGroupContent, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "@/registry/new-york-v4/ui/sidebar" - -export function NavMain({ - items, -}: { - items: { - title: string - url: string - icon?: Icon - }[] -}) { - return ( - - - - - - - Quick Create - - - - - - {items.map((item) => ( - - - {item.icon && } - {item.title} - - - ))} - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/nav-secondary.tsx b/apps/v4/app/(examples)/dashboard/components/nav-secondary.tsx deleted file mode 100644 index e5177a9693..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/nav-secondary.tsx +++ /dev/null @@ -1,71 +0,0 @@ -"use client" - -import * as React from "react" -import { IconBrightness, type Icon } from "@tabler/icons-react" -import { useTheme } from "next-themes" - -import { - SidebarGroup, - SidebarGroupContent, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "@/registry/new-york-v4/ui/sidebar" -import { Skeleton } from "@/registry/new-york-v4/ui/skeleton" -import { Switch } from "@/registry/new-york-v4/ui/switch" - -export function NavSecondary({ - items, - ...props -}: { - items: { - title: string - url: string - icon: Icon - }[] -} & React.ComponentPropsWithoutRef) { - const { resolvedTheme, setTheme } = useTheme() - const [mounted, setMounted] = React.useState(false) - - React.useEffect(() => { - setMounted(true) - }, []) - - return ( - - - - {items.map((item) => ( - - - - - {item.title} - - - - ))} - - - - - - - - - ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/nav-user.tsx b/apps/v4/app/(examples)/dashboard/components/nav-user.tsx deleted file mode 100644 index bdb066d28e..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/nav-user.tsx +++ /dev/null @@ -1,110 +0,0 @@ -"use client" - -import { - IconCreditCard, - IconDotsVertical, - IconLogout, - IconNotification, - IconUserCircle, -} from "@tabler/icons-react" - -import { - Avatar, - AvatarFallback, - AvatarImage, -} from "@/registry/new-york-v4/ui/avatar" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuGroup, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@/registry/new-york-v4/ui/dropdown-menu" -import { - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, - useSidebar, -} from "@/registry/new-york-v4/ui/sidebar" - -export function NavUser({ - user, -}: { - user: { - name: string - email: string - avatar: string - } -}) { - const { isMobile } = useSidebar() - - return ( - - - - - - - - CN - -
- {user.name} - - {user.email} - -
- -
-
- - -
- - - CN - -
- {user.name} - - {user.email} - -
-
-
- - - - - Account - - - - Billing - - - - Notifications - - - - - - Log out - -
-
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/section-cards.tsx b/apps/v4/app/(examples)/dashboard/components/section-cards.tsx deleted file mode 100644 index 8419b5e92a..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/section-cards.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { IconTrendingDown, IconTrendingUp } from "@tabler/icons-react" - -import { Badge } from "@/registry/new-york-v4/ui/badge" -import { - Card, - CardAction, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/registry/new-york-v4/ui/card" - -export function SectionCards() { - return ( -
- - - Total Revenue - - $1,250.00 - - - - - +12.5% - - - - -
- Trending up this month -
-
- Visitors for the last 6 months -
-
-
- - - New Customers - - 1,234 - - - - - -20% - - - - -
- Down 20% this period -
-
- Acquisition needs attention -
-
-
- - - Active Accounts - - 45,678 - - - - - +12.5% - - - - -
- Strong user retention -
-
Engagement exceed targets
-
-
- - - Growth Rate - - 4.5% - - - - - +4.5% - - - - -
- Steady performance increase -
-
Meets growth projections
-
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/site-header.tsx b/apps/v4/app/(examples)/dashboard/components/site-header.tsx deleted file mode 100644 index 0796a0aa3a..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/site-header.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Button } from "@/registry/new-york-v4/ui/button" -import { Separator } from "@/registry/new-york-v4/ui/separator" -import { SidebarTrigger } from "@/registry/new-york-v4/ui/sidebar" -import { ModeToggle } from "@/app/(examples)/dashboard/components/mode-toggle" -import { ThemeSelector } from "@/app/(examples)/dashboard/components/theme-selector" - -export function SiteHeader() { - return ( -
-
- - -

Documents

-
- - - -
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard/components/theme-selector.tsx b/apps/v4/app/(examples)/dashboard/components/theme-selector.tsx deleted file mode 100644 index a9c2a8cc0a..0000000000 --- a/apps/v4/app/(examples)/dashboard/components/theme-selector.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client" - -import { useThemeConfig } from "@/components/active-theme" -import { Label } from "@/registry/new-york-v4/ui/label" -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectSeparator, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" - -const DEFAULT_THEMES = [ - { - name: "Default", - value: "default", - }, - { - name: "Blue", - value: "blue", - }, - { - name: "Green", - value: "green", - }, - { - name: "Amber", - value: "amber", - }, -] - -const SCALED_THEMES = [ - { - name: "Default", - value: "default-scaled", - }, - { - name: "Blue", - value: "blue-scaled", - }, -] - -const MONO_THEMES = [ - { - name: "Mono", - value: "mono-scaled", - }, -] - -export function ThemeSelector() { - const { activeTheme, setActiveTheme } = useThemeConfig() - - return ( -
- - -
- ) -} diff --git a/apps/v4/app/(examples)/dashboard/data.json b/apps/v4/app/(examples)/dashboard/data.json deleted file mode 100644 index ec0873641b..0000000000 --- a/apps/v4/app/(examples)/dashboard/data.json +++ /dev/null @@ -1,614 +0,0 @@ -[ - { - "id": 1, - "header": "Cover page", - "type": "Cover page", - "status": "In Process", - "target": "18", - "limit": "5", - "reviewer": "Eddie Lake" - }, - { - "id": 2, - "header": "Table of contents", - "type": "Table of contents", - "status": "Done", - "target": "29", - "limit": "24", - "reviewer": "Eddie Lake" - }, - { - "id": 3, - "header": "Executive summary", - "type": "Narrative", - "status": "Done", - "target": "10", - "limit": "13", - "reviewer": "Eddie Lake" - }, - { - "id": 4, - "header": "Technical approach", - "type": "Narrative", - "status": "Done", - "target": "27", - "limit": "23", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 5, - "header": "Design", - "type": "Narrative", - "status": "In Process", - "target": "2", - "limit": "16", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 6, - "header": "Capabilities", - "type": "Narrative", - "status": "In Process", - "target": "20", - "limit": "8", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 7, - "header": "Integration with existing systems", - "type": "Narrative", - "status": "In Process", - "target": "19", - "limit": "21", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 8, - "header": "Innovation and Advantages", - "type": "Narrative", - "status": "Done", - "target": "25", - "limit": "26", - "reviewer": "Assign reviewer" - }, - { - "id": 9, - "header": "Overview of EMR's Innovative Solutions", - "type": "Technical content", - "status": "Done", - "target": "7", - "limit": "23", - "reviewer": "Assign reviewer" - }, - { - "id": 10, - "header": "Advanced Algorithms and Machine Learning", - "type": "Narrative", - "status": "Done", - "target": "30", - "limit": "28", - "reviewer": "Assign reviewer" - }, - { - "id": 11, - "header": "Adaptive Communication Protocols", - "type": "Narrative", - "status": "Done", - "target": "9", - "limit": "31", - "reviewer": "Assign reviewer" - }, - { - "id": 12, - "header": "Advantages Over Current Technologies", - "type": "Narrative", - "status": "Done", - "target": "12", - "limit": "0", - "reviewer": "Assign reviewer" - }, - { - "id": 13, - "header": "Past Performance", - "type": "Narrative", - "status": "Done", - "target": "22", - "limit": "33", - "reviewer": "Assign reviewer" - }, - { - "id": 14, - "header": "Customer Feedback and Satisfaction Levels", - "type": "Narrative", - "status": "Done", - "target": "15", - "limit": "34", - "reviewer": "Assign reviewer" - }, - { - "id": 15, - "header": "Implementation Challenges and Solutions", - "type": "Narrative", - "status": "Done", - "target": "3", - "limit": "35", - "reviewer": "Assign reviewer" - }, - { - "id": 16, - "header": "Security Measures and Data Protection Policies", - "type": "Narrative", - "status": "In Process", - "target": "6", - "limit": "36", - "reviewer": "Assign reviewer" - }, - { - "id": 17, - "header": "Scalability and Future Proofing", - "type": "Narrative", - "status": "Done", - "target": "4", - "limit": "37", - "reviewer": "Assign reviewer" - }, - { - "id": 18, - "header": "Cost-Benefit Analysis", - "type": "Plain language", - "status": "Done", - "target": "14", - "limit": "38", - "reviewer": "Assign reviewer" - }, - { - "id": 19, - "header": "User Training and Onboarding Experience", - "type": "Narrative", - "status": "Done", - "target": "17", - "limit": "39", - "reviewer": "Assign reviewer" - }, - { - "id": 20, - "header": "Future Development Roadmap", - "type": "Narrative", - "status": "Done", - "target": "11", - "limit": "40", - "reviewer": "Assign reviewer" - }, - { - "id": 21, - "header": "System Architecture Overview", - "type": "Technical content", - "status": "In Process", - "target": "24", - "limit": "18", - "reviewer": "Maya Johnson" - }, - { - "id": 22, - "header": "Risk Management Plan", - "type": "Narrative", - "status": "Done", - "target": "15", - "limit": "22", - "reviewer": "Carlos Rodriguez" - }, - { - "id": 23, - "header": "Compliance Documentation", - "type": "Legal", - "status": "In Process", - "target": "31", - "limit": "27", - "reviewer": "Sarah Chen" - }, - { - "id": 24, - "header": "API Documentation", - "type": "Technical content", - "status": "Done", - "target": "8", - "limit": "12", - "reviewer": "Raj Patel" - }, - { - "id": 25, - "header": "User Interface Mockups", - "type": "Visual", - "status": "In Process", - "target": "19", - "limit": "25", - "reviewer": "Leila Ahmadi" - }, - { - "id": 26, - "header": "Database Schema", - "type": "Technical content", - "status": "Done", - "target": "22", - "limit": "20", - "reviewer": "Thomas Wilson" - }, - { - "id": 27, - "header": "Testing Methodology", - "type": "Technical content", - "status": "In Process", - "target": "17", - "limit": "14", - "reviewer": "Assign reviewer" - }, - { - "id": 28, - "header": "Deployment Strategy", - "type": "Narrative", - "status": "Done", - "target": "26", - "limit": "30", - "reviewer": "Eddie Lake" - }, - { - "id": 29, - "header": "Budget Breakdown", - "type": "Financial", - "status": "In Process", - "target": "13", - "limit": "16", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 30, - "header": "Market Analysis", - "type": "Research", - "status": "Done", - "target": "29", - "limit": "32", - "reviewer": "Sophia Martinez" - }, - { - "id": 31, - "header": "Competitor Comparison", - "type": "Research", - "status": "In Process", - "target": "21", - "limit": "19", - "reviewer": "Assign reviewer" - }, - { - "id": 32, - "header": "Maintenance Plan", - "type": "Technical content", - "status": "Done", - "target": "16", - "limit": "23", - "reviewer": "Alex Thompson" - }, - { - "id": 33, - "header": "User Personas", - "type": "Research", - "status": "In Process", - "target": "27", - "limit": "24", - "reviewer": "Nina Patel" - }, - { - "id": 34, - "header": "Accessibility Compliance", - "type": "Legal", - "status": "Done", - "target": "18", - "limit": "21", - "reviewer": "Assign reviewer" - }, - { - "id": 35, - "header": "Performance Metrics", - "type": "Technical content", - "status": "In Process", - "target": "23", - "limit": "26", - "reviewer": "David Kim" - }, - { - "id": 36, - "header": "Disaster Recovery Plan", - "type": "Technical content", - "status": "Done", - "target": "14", - "limit": "17", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 37, - "header": "Third-party Integrations", - "type": "Technical content", - "status": "In Process", - "target": "25", - "limit": "28", - "reviewer": "Eddie Lake" - }, - { - "id": 38, - "header": "User Feedback Summary", - "type": "Research", - "status": "Done", - "target": "20", - "limit": "15", - "reviewer": "Assign reviewer" - }, - { - "id": 39, - "header": "Localization Strategy", - "type": "Narrative", - "status": "In Process", - "target": "12", - "limit": "19", - "reviewer": "Maria Garcia" - }, - { - "id": 40, - "header": "Mobile Compatibility", - "type": "Technical content", - "status": "Done", - "target": "28", - "limit": "31", - "reviewer": "James Wilson" - }, - { - "id": 41, - "header": "Data Migration Plan", - "type": "Technical content", - "status": "In Process", - "target": "19", - "limit": "22", - "reviewer": "Assign reviewer" - }, - { - "id": 42, - "header": "Quality Assurance Protocols", - "type": "Technical content", - "status": "Done", - "target": "30", - "limit": "33", - "reviewer": "Priya Singh" - }, - { - "id": 43, - "header": "Stakeholder Analysis", - "type": "Research", - "status": "In Process", - "target": "11", - "limit": "14", - "reviewer": "Eddie Lake" - }, - { - "id": 44, - "header": "Environmental Impact Assessment", - "type": "Research", - "status": "Done", - "target": "24", - "limit": "27", - "reviewer": "Assign reviewer" - }, - { - "id": 45, - "header": "Intellectual Property Rights", - "type": "Legal", - "status": "In Process", - "target": "17", - "limit": "20", - "reviewer": "Sarah Johnson" - }, - { - "id": 46, - "header": "Customer Support Framework", - "type": "Narrative", - "status": "Done", - "target": "22", - "limit": "25", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 47, - "header": "Version Control Strategy", - "type": "Technical content", - "status": "In Process", - "target": "15", - "limit": "18", - "reviewer": "Assign reviewer" - }, - { - "id": 48, - "header": "Continuous Integration Pipeline", - "type": "Technical content", - "status": "Done", - "target": "26", - "limit": "29", - "reviewer": "Michael Chen" - }, - { - "id": 49, - "header": "Regulatory Compliance", - "type": "Legal", - "status": "In Process", - "target": "13", - "limit": "16", - "reviewer": "Assign reviewer" - }, - { - "id": 50, - "header": "User Authentication System", - "type": "Technical content", - "status": "Done", - "target": "28", - "limit": "31", - "reviewer": "Eddie Lake" - }, - { - "id": 51, - "header": "Data Analytics Framework", - "type": "Technical content", - "status": "In Process", - "target": "21", - "limit": "24", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 52, - "header": "Cloud Infrastructure", - "type": "Technical content", - "status": "Done", - "target": "16", - "limit": "19", - "reviewer": "Assign reviewer" - }, - { - "id": 53, - "header": "Network Security Measures", - "type": "Technical content", - "status": "In Process", - "target": "29", - "limit": "32", - "reviewer": "Lisa Wong" - }, - { - "id": 54, - "header": "Project Timeline", - "type": "Planning", - "status": "Done", - "target": "14", - "limit": "17", - "reviewer": "Eddie Lake" - }, - { - "id": 55, - "header": "Resource Allocation", - "type": "Planning", - "status": "In Process", - "target": "27", - "limit": "30", - "reviewer": "Assign reviewer" - }, - { - "id": 56, - "header": "Team Structure and Roles", - "type": "Planning", - "status": "Done", - "target": "20", - "limit": "23", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 57, - "header": "Communication Protocols", - "type": "Planning", - "status": "In Process", - "target": "15", - "limit": "18", - "reviewer": "Assign reviewer" - }, - { - "id": 58, - "header": "Success Metrics", - "type": "Planning", - "status": "Done", - "target": "30", - "limit": "33", - "reviewer": "Eddie Lake" - }, - { - "id": 59, - "header": "Internationalization Support", - "type": "Technical content", - "status": "In Process", - "target": "23", - "limit": "26", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 60, - "header": "Backup and Recovery Procedures", - "type": "Technical content", - "status": "Done", - "target": "18", - "limit": "21", - "reviewer": "Assign reviewer" - }, - { - "id": 61, - "header": "Monitoring and Alerting System", - "type": "Technical content", - "status": "In Process", - "target": "25", - "limit": "28", - "reviewer": "Daniel Park" - }, - { - "id": 62, - "header": "Code Review Guidelines", - "type": "Technical content", - "status": "Done", - "target": "12", - "limit": "15", - "reviewer": "Eddie Lake" - }, - { - "id": 63, - "header": "Documentation Standards", - "type": "Technical content", - "status": "In Process", - "target": "27", - "limit": "30", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 64, - "header": "Release Management Process", - "type": "Planning", - "status": "Done", - "target": "22", - "limit": "25", - "reviewer": "Assign reviewer" - }, - { - "id": 65, - "header": "Feature Prioritization Matrix", - "type": "Planning", - "status": "In Process", - "target": "19", - "limit": "22", - "reviewer": "Emma Davis" - }, - { - "id": 66, - "header": "Technical Debt Assessment", - "type": "Technical content", - "status": "Done", - "target": "24", - "limit": "27", - "reviewer": "Eddie Lake" - }, - { - "id": 67, - "header": "Capacity Planning", - "type": "Planning", - "status": "In Process", - "target": "21", - "limit": "24", - "reviewer": "Jamik Tashpulatov" - }, - { - "id": 68, - "header": "Service Level Agreements", - "type": "Legal", - "status": "Done", - "target": "26", - "limit": "29", - "reviewer": "Assign reviewer" - } -] diff --git a/apps/v4/app/(examples)/dashboard/layout.tsx b/apps/v4/app/(examples)/dashboard/layout.tsx deleted file mode 100644 index da69ec0595..0000000000 --- a/apps/v4/app/(examples)/dashboard/layout.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { cookies } from "next/headers" - -import { - SidebarInset, - SidebarProvider, -} from "@/registry/new-york-v4/ui/sidebar" -import { AppSidebar } from "@/app/(examples)/dashboard/components/app-sidebar" -import { SiteHeader } from "@/app/(examples)/dashboard/components/site-header" - -import "@/app/(examples)/dashboard/theme.css" - -export default async function DashboardLayout({ - children, -}: { - children: React.ReactNode -}) { - const cookieStore = await cookies() - const defaultOpen = cookieStore.get("sidebar_state")?.value === "true" - - return ( - - - - -
{children}
-
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard/page.tsx b/apps/v4/app/(examples)/dashboard/page.tsx deleted file mode 100644 index e6ea868938..0000000000 --- a/apps/v4/app/(examples)/dashboard/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ChartAreaInteractive } from "@/app/(examples)/dashboard/components/chart-area-interactive" -import { DataTable } from "@/app/(examples)/dashboard/components/data-table" -import { SectionCards } from "@/app/(examples)/dashboard/components/section-cards" -import data from "@/app/(examples)/dashboard/data.json" - -export default function Page() { - return ( -
-
- -
- -
- -
-
- ) -} diff --git a/apps/v4/app/(examples)/dashboard/theme.css b/apps/v4/app/(examples)/dashboard/theme.css deleted file mode 100644 index fd549d6677..0000000000 --- a/apps/v4/app/(examples)/dashboard/theme.css +++ /dev/null @@ -1,105 +0,0 @@ -body { - @apply overscroll-none bg-transparent; -} - -:root { - --font-sans: var(--font-inter); - --header-height: calc(var(--spacing) * 12 + 1px); -} - -.theme-scaled { - @media (min-width: 1024px) { - --radius: 0.6rem; - --text-lg: 1.05rem; - --text-base: 0.85rem; - --text-sm: 0.8rem; - --spacing: 0.222222rem; - } - - [data-slot="card"] { - --spacing: 0.16rem; - } - - [data-slot="select-trigger"], - [data-slot="toggle-group-item"] { - --spacing: 0.222222rem; - } -} - -.theme-default, -.theme-default-scaled { - --primary: var(--color-neutral-600); - --primary-foreground: var(--color-neutral-50); - - @variant dark { - --primary: var(--color-neutral-500); - --primary-foreground: var(--color-neutral-50); - } -} - -.theme-blue, -.theme-blue-scaled { - --primary: var(--color-blue-600); - --primary-foreground: var(--color-blue-50); - - @variant dark { - --primary: var(--color-blue-500); - --primary-foreground: var(--color-blue-50); - } -} - -.theme-green, -.theme-green-scaled { - --primary: var(--color-lime-600); - --primary-foreground: var(--color-lime-50); - - @variant dark { - --primary: var(--color-lime-600); - --primary-foreground: var(--color-lime-50); - } -} - -.theme-amber, -.theme-amber-scaled { - --primary: var(--color-amber-600); - --primary-foreground: var(--color-amber-50); - - @variant dark { - --primary: var(--color-amber-500); - --primary-foreground: var(--color-amber-50); - } -} - -.theme-mono, -.theme-mono-scaled { - --font-sans: var(--font-mono); - --primary: var(--color-neutral-600); - --primary-foreground: var(--color-neutral-50); - - @variant dark { - --primary: var(--color-neutral-500); - --primary-foreground: var(--color-neutral-50); - } - - .rounded-xs, - .rounded-sm, - .rounded-md, - .rounded-lg, - .rounded-xl { - @apply !rounded-none; - border-radius: 0; - } - - .shadow-xs, - .shadow-sm, - .shadow-md, - .shadow-lg, - .shadow-xl { - @apply !shadow-none; - } - - [data-slot="toggle-group"], - [data-slot="toggle-group-item"] { - @apply !rounded-none !shadow-none; - } -} diff --git a/apps/v4/app/(internal)/sink/(pages)/forms/appearance-settings.tsx b/apps/v4/app/(internal)/sink/(pages)/forms/appearance-settings.tsx deleted file mode 100644 index 9ca2857781..0000000000 --- a/apps/v4/app/(internal)/sink/(pages)/forms/appearance-settings.tsx +++ /dev/null @@ -1,168 +0,0 @@ -import Image from "next/image" -import { CheckIcon } from "lucide-react" - -import { - Field, - FieldContent, - FieldDescription, - FieldGroup, - FieldLabel, - FieldLegend, - FieldSeparator, - FieldSet, - FieldTitle, -} from "@/registry/new-york-v4/ui/field" -import { Label } from "@/registry/new-york-v4/ui/label" -import { - RadioGroup, - RadioGroupItem, -} from "@/registry/new-york-v4/ui/radio-group" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" -import { Switch } from "@/registry/new-york-v4/ui/switch" - -const modes = [ - { - name: "Light", - value: "light", - image: "/placeholder.svg", - }, - { - name: "Dark", - value: "dark", - image: "/placeholder.svg", - }, - { - name: "System", - value: "system", - image: "/placeholder.svg", - }, -] - -const accents = [ - { - name: "Blue", - value: "#007AFF", - }, - { - name: "Purple", - value: "#6A4695", - }, - { - name: "Red", - value: "#FF3B30", - }, - { - name: "Orange", - value: "#FF9500", - }, -] - -export function AppearanceSettings() { - return ( -
- Appearance - - Configure appearance. accent, scroll bar, and more. - - -
- Mode - - Select the mode to use for the appearance. - - - {modes.map((mode) => ( - - {mode.name} - - {mode.name} - - - - ))} - -
- - - - Accent - - Select the accent color to use for the appearance. - - -
- - {accents.map((accent) => ( - - ))} - -
-
- - - - Sidebar Icon Size - - Select the size of the sidebar icons. - - - - - - - - Wallpaper Tinting - - Allow the wallpaper to be tinted with the accent color. - - - - -
-
- ) -} diff --git a/apps/v4/app/(internal)/sink/(pages)/forms/chat-settings.tsx b/apps/v4/app/(internal)/sink/(pages)/forms/chat-settings.tsx deleted file mode 100644 index d77d3b81a4..0000000000 --- a/apps/v4/app/(internal)/sink/(pages)/forms/chat-settings.tsx +++ /dev/null @@ -1,463 +0,0 @@ -"use client" - -import { useState } from "react" -import { CircleIcon, InfoIcon } from "lucide-react" - -import { Button } from "@/registry/new-york-v4/ui/button" -import { Checkbox } from "@/registry/new-york-v4/ui/checkbox" -import { - Field, - FieldContent, - FieldDescription, - FieldGroup, - FieldLabel, - FieldSeparator, - FieldSet, - FieldTitle, -} from "@/registry/new-york-v4/ui/field" -import { - InputGroup, - InputGroupAddon, - InputGroupButton, - InputGroupInput, -} from "@/registry/new-york-v4/ui/input-group" -import { Kbd } from "@/registry/new-york-v4/ui/kbd" -import { - Select, - SelectContent, - SelectItem, - SelectSeparator, - SelectTrigger, - SelectValue, -} from "@/registry/new-york-v4/ui/select" -import { Switch } from "@/registry/new-york-v4/ui/switch" -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "@/registry/new-york-v4/ui/tabs" -import { Textarea } from "@/registry/new-york-v4/ui/textarea" -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from "@/registry/new-york-v4/ui/tooltip" - -const spokenLanguages = [ - { label: "English", value: "en" }, - { label: "Spanish", value: "es" }, - { label: "French", value: "fr" }, - { label: "German", value: "de" }, - { label: "Italian", value: "it" }, - { label: "Portuguese", value: "pt" }, - { label: "Russian", value: "ru" }, - { label: "Chinese", value: "zh" }, - { label: "Japanese", value: "ja" }, - { label: "Korean", value: "ko" }, - { label: "Arabic", value: "ar" }, - { label: "Hindi", value: "hi" }, - { label: "Bengali", value: "bn" }, - { label: "Telugu", value: "te" }, - { label: "Marathi", value: "mr" }, - { label: "Kannada", value: "kn" }, - { label: "Malayalam", value: "ml" }, -] - -const voices = [ - { label: "Samantha", value: "samantha" }, - { label: "Alex", value: "alex" }, - { label: "Fred", value: "fred" }, - { label: "Victoria", value: "victoria" }, - { label: "Tom", value: "tom" }, - { label: "Karen", value: "karen" }, - { label: "Sam", value: "sam" }, - { label: "Daniel", value: "daniel" }, -] - -const personalities = [ - { - label: "Friendly", - value: "friendly", - description: "Friendly and approachable.", - }, - { - label: "Professional", - value: "professional", - description: "Professional and authoritative.", - }, - { label: "Funny", value: "funny", description: "Funny and light-hearted." }, - { - label: "Sarcastic", - value: "sarcastic", - description: "Sarcastic and witty.", - }, - { label: "Cynical", value: "cynical", description: "Cynical and skeptical." }, -] - -const instructions = [ - { - label: "Witty", - value: "witty", - description: "Use quick and clever responses when appropriate.", - }, - { - label: "Professional", - value: "professional", - description: "Have a professional and authoritative tone.", - }, - { - label: "Funny", - value: "funny", - description: "Use humor and wit to engage the user.", - }, - { - label: "Sarcastic", - value: "sarcastic", - description: "Use sarcasm and wit to engage the user.", - }, - { - label: "Cynical", - value: "cynical", - description: "Use cynicism and skepticism to engage the user.", - }, -] - -export function ChatSettings() { - const [tab, setTab] = useState("general") - const [theme, setTheme] = useState("system") - const [accentColor, setAccentColor] = useState("default") - const [spokenLanguage, setSpokenLanguage] = useState("en") - const [voice, setVoice] = useState("samantha") - const [personality, setPersonality] = useState("friendly") - const [customInstructions, setCustomInstructions] = useState("") - - return ( -
- - - - General - Notifications - Personalization - Security - -
- -
- - - Theme - - - - - Accent Color - - - - - - - Spoken Language - - - For best results, select the language you mainly speak. If - it's not listed, it may still be supported via - auto-detection. - - - - - - - Voice - - - -
-
- - -
- Responses - - Get notified when ChatGPT responds to requests that take time, - like research or image generation. - - - - - - Push notifications - - - -
- -
- Tasks - - Get notified when tasks you've created have updates.{" "} - Manage tasks - - - - - - Push notifications - - - - - - Email notifications - - - -
-
-
- - - - Nickname - - - - - - - - - - - Used to identify you in the chat. N - - - - - - - - - More about you - - Tell us more about yourself. This will be used to help us - personalize your experience. - - -