@inui/design-system 0.0.0-stage → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +360 -2
- package/dist/components/ui/accordion.d.ts +44 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/accordion.js +86 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/ai-avatar.d.ts +46 -0
- package/dist/components/ui/ai-avatar.d.ts.map +1 -0
- package/dist/components/ui/ai-avatar.js +43 -0
- package/dist/components/ui/ai-avatar.js.map +1 -0
- package/dist/components/ui/ai-label.d.ts +118 -0
- package/dist/components/ui/ai-label.d.ts.map +1 -0
- package/dist/components/ui/ai-label.js +184 -0
- package/dist/components/ui/ai-label.js.map +1 -0
- package/dist/components/ui/ai-sparkle.d.ts +91 -0
- package/dist/components/ui/ai-sparkle.d.ts.map +1 -0
- package/dist/components/ui/ai-sparkle.js +200 -0
- package/dist/components/ui/ai-sparkle.js.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +79 -0
- package/dist/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/components/ui/alert-dialog.js +147 -0
- package/dist/components/ui/alert-dialog.js.map +1 -0
- package/dist/components/ui/alert.d.ts +71 -0
- package/dist/components/ui/alert.d.ts.map +1 -0
- package/dist/components/ui/alert.js +108 -0
- package/dist/components/ui/alert.js.map +1 -0
- package/dist/components/ui/aspect-ratio.d.ts +30 -0
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
- package/dist/components/ui/aspect-ratio.js +40 -0
- package/dist/components/ui/aspect-ratio.js.map +1 -0
- package/dist/components/ui/attachment.d.ts +74 -0
- package/dist/components/ui/attachment.d.ts.map +1 -0
- package/dist/components/ui/attachment.js +142 -0
- package/dist/components/ui/attachment.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +82 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/avatar.js +123 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +130 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +226 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +43 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/components/ui/breadcrumb.js +98 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/browser-tabs.d.ts +218 -0
- package/dist/components/ui/browser-tabs.d.ts.map +1 -0
- package/dist/components/ui/browser-tabs.js +528 -0
- package/dist/components/ui/browser-tabs.js.map +1 -0
- package/dist/components/ui/bubble.d.ts +80 -0
- package/dist/components/ui/bubble.d.ts.map +1 -0
- package/dist/components/ui/bubble.js +235 -0
- package/dist/components/ui/bubble.js.map +1 -0
- package/dist/components/ui/button-group.d.ts +60 -0
- package/dist/components/ui/button-group.d.ts.map +1 -0
- package/dist/components/ui/button-group.js +89 -0
- package/dist/components/ui/button-group.js.map +1 -0
- package/dist/components/ui/button.d.ts +157 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +144 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/calendar.d.ts +57 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/calendar.js +163 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/card.d.ts +96 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/card.js +131 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/carousel.d.ts +86 -0
- package/dist/components/ui/carousel.d.ts.map +1 -0
- package/dist/components/ui/carousel.js +207 -0
- package/dist/components/ui/carousel.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +54 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/checkbox.js +78 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +45 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.js +65 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/combobox.d.ts +111 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/combobox.js +264 -0
- package/dist/components/ui/combobox.js.map +1 -0
- package/dist/components/ui/command.d.ts +71 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/command.js +133 -0
- package/dist/components/ui/command.js.map +1 -0
- package/dist/components/ui/context-menu.d.ts +70 -0
- package/dist/components/ui/context-menu.d.ts.map +1 -0
- package/dist/components/ui/context-menu.js +163 -0
- package/dist/components/ui/context-menu.js.map +1 -0
- package/dist/components/ui/count-badge.d.ts +40 -0
- package/dist/components/ui/count-badge.d.ts.map +1 -0
- package/dist/components/ui/count-badge.js +43 -0
- package/dist/components/ui/count-badge.js.map +1 -0
- package/dist/components/ui/data-table.d.ts +1026 -0
- package/dist/components/ui/data-table.d.ts.map +1 -0
- package/dist/components/ui/data-table.js +3423 -0
- package/dist/components/ui/data-table.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +73 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dialog.js +145 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/direction.d.ts +35 -0
- package/dist/components/ui/direction.d.ts.map +1 -0
- package/dist/components/ui/direction.js +35 -0
- package/dist/components/ui/direction.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +53 -0
- package/dist/components/ui/drawer.d.ts.map +1 -0
- package/dist/components/ui/drawer.js +115 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +75 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.js +173 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/dropzone.d.ts +141 -0
- package/dist/components/ui/dropzone.d.ts.map +1 -0
- package/dist/components/ui/dropzone.js +257 -0
- package/dist/components/ui/dropzone.js.map +1 -0
- package/dist/components/ui/empty.d.ts +94 -0
- package/dist/components/ui/empty.d.ts.map +1 -0
- package/dist/components/ui/empty.js +149 -0
- package/dist/components/ui/empty.js.map +1 -0
- package/dist/components/ui/field.d.ts +122 -0
- package/dist/components/ui/field.d.ts.map +1 -0
- package/dist/components/ui/field.js +254 -0
- package/dist/components/ui/field.js.map +1 -0
- package/dist/components/ui/hover-card.d.ts +51 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/hover-card.js +101 -0
- package/dist/components/ui/hover-card.js.map +1 -0
- package/dist/components/ui/input-group.d.ts +62 -0
- package/dist/components/ui/input-group.d.ts.map +1 -0
- package/dist/components/ui/input-group.js +115 -0
- package/dist/components/ui/input-group.js.map +1 -0
- package/dist/components/ui/input-otp.d.ts +52 -0
- package/dist/components/ui/input-otp.d.ts.map +1 -0
- package/dist/components/ui/input-otp.js +89 -0
- package/dist/components/ui/input-otp.js.map +1 -0
- package/dist/components/ui/input.d.ts +47 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +47 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/item.d.ts +74 -0
- package/dist/components/ui/item.d.ts.map +1 -0
- package/dist/components/ui/item.js +176 -0
- package/dist/components/ui/item.js.map +1 -0
- package/dist/components/ui/kbd.d.ts +41 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.js +58 -0
- package/dist/components/ui/kbd.js.map +1 -0
- package/dist/components/ui/key-value-pair.d.ts +56 -0
- package/dist/components/ui/key-value-pair.d.ts.map +1 -0
- package/dist/components/ui/key-value-pair.js +110 -0
- package/dist/components/ui/key-value-pair.js.map +1 -0
- package/dist/components/ui/label.d.ts +83 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +85 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/marker.d.ts +54 -0
- package/dist/components/ui/marker.d.ts.map +1 -0
- package/dist/components/ui/marker.js +79 -0
- package/dist/components/ui/marker.js.map +1 -0
- package/dist/components/ui/menubar.d.ts +72 -0
- package/dist/components/ui/menubar.d.ts.map +1 -0
- package/dist/components/ui/menubar.js +174 -0
- package/dist/components/ui/menubar.js.map +1 -0
- package/dist/components/ui/message-scroller.d.ts +53 -0
- package/dist/components/ui/message-scroller.d.ts.map +1 -0
- package/dist/components/ui/message-scroller.js +95 -0
- package/dist/components/ui/message-scroller.js.map +1 -0
- package/dist/components/ui/message.d.ts +63 -0
- package/dist/components/ui/message.d.ts.map +1 -0
- package/dist/components/ui/message.js +92 -0
- package/dist/components/ui/message.js.map +1 -0
- package/dist/components/ui/meta-list.d.ts +55 -0
- package/dist/components/ui/meta-list.d.ts.map +1 -0
- package/dist/components/ui/meta-list.js +75 -0
- package/dist/components/ui/meta-list.js.map +1 -0
- package/dist/components/ui/native-select.d.ts +51 -0
- package/dist/components/ui/native-select.d.ts.map +1 -0
- package/dist/components/ui/native-select.js +75 -0
- package/dist/components/ui/native-select.js.map +1 -0
- package/dist/components/ui/navigation-menu.d.ts +56 -0
- package/dist/components/ui/navigation-menu.d.ts.map +1 -0
- package/dist/components/ui/navigation-menu.js +116 -0
- package/dist/components/ui/navigation-menu.js.map +1 -0
- package/dist/components/ui/page-header.d.ts +223 -0
- package/dist/components/ui/page-header.d.ts.map +1 -0
- package/dist/components/ui/page-header.js +233 -0
- package/dist/components/ui/page-header.js.map +1 -0
- package/dist/components/ui/pagination.d.ts +68 -0
- package/dist/components/ui/pagination.d.ts.map +1 -0
- package/dist/components/ui/pagination.js +145 -0
- package/dist/components/ui/pagination.js.map +1 -0
- package/dist/components/ui/popover.d.ts +61 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/popover.js +144 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/progress.d.ts +35 -0
- package/dist/components/ui/progress.d.ts.map +1 -0
- package/dist/components/ui/progress.js +46 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/components/ui/questionnaire.d.ts +92 -0
- package/dist/components/ui/questionnaire.d.ts.map +1 -0
- package/dist/components/ui/questionnaire.js +277 -0
- package/dist/components/ui/questionnaire.js.map +1 -0
- package/dist/components/ui/radio-group.d.ts +50 -0
- package/dist/components/ui/radio-group.d.ts.map +1 -0
- package/dist/components/ui/radio-group.js +65 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/resizable.d.ts +44 -0
- package/dist/components/ui/resizable.d.ts.map +1 -0
- package/dist/components/ui/resizable.js +73 -0
- package/dist/components/ui/resizable.js.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +55 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.js +72 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/select.d.ts +274 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/select.js +609 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/separator.d.ts +31 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/separator.js +38 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/sheet.d.ts +59 -0
- package/dist/components/ui/sheet.d.ts.map +1 -0
- package/dist/components/ui/sheet.js +128 -0
- package/dist/components/ui/sheet.js.map +1 -0
- package/dist/components/ui/sidebar.d.ts +166 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/sidebar.js +512 -0
- package/dist/components/ui/sidebar.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +35 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +46 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/slider.d.ts +39 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/slider.js +75 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +56 -0
- package/dist/components/ui/sonner.d.ts.map +1 -0
- package/dist/components/ui/sonner.js +96 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/spinner.d.ts +37 -0
- package/dist/components/ui/spinner.d.ts.map +1 -0
- package/dist/components/ui/spinner.js +51 -0
- package/dist/components/ui/spinner.js.map +1 -0
- package/dist/components/ui/stepper.d.ts +84 -0
- package/dist/components/ui/stepper.d.ts.map +1 -0
- package/dist/components/ui/stepper.js +145 -0
- package/dist/components/ui/stepper.js.map +1 -0
- package/dist/components/ui/switch.d.ts +36 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/switch.js +44 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/table.d.ts +80 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/table.js +130 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.d.ts +87 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/tabs.js +128 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +35 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/textarea.js +38 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/time-picker.d.ts +58 -0
- package/dist/components/ui/time-picker.d.ts.map +1 -0
- package/dist/components/ui/time-picker.js +188 -0
- package/dist/components/ui/time-picker.js.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +52 -0
- package/dist/components/ui/toggle-group.d.ts.map +1 -0
- package/dist/components/ui/toggle-group.js +94 -0
- package/dist/components/ui/toggle-group.js.map +1 -0
- package/dist/components/ui/toggle.d.ts +50 -0
- package/dist/components/ui/toggle.d.ts.map +1 -0
- package/dist/components/ui/toggle.js +70 -0
- package/dist/components/ui/toggle.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +51 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +78 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/hooks/use-dark-mode.d.ts +2 -0
- package/dist/hooks/use-dark-mode.d.ts.map +1 -0
- package/dist/hooks/use-dark-mode.js +36 -0
- package/dist/hooks/use-dark-mode.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +2 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-mobile.js +20 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/lib/scope.d.ts +64 -0
- package/dist/lib/scope.d.ts.map +1 -0
- package/dist/lib/scope.js +74 -0
- package/dist/lib/scope.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +11 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/theme-tokens.css +537 -0
- package/dist/theme.css +417 -0
- package/package.json +103 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questionnaire.js","names":[],"sources":["../../../src/components/ui/questionnaire.tsx"],"sourcesContent":["\"use client\"\n\n/**\n * Questionnaire — multi-step form that shows one question at a time.\n *\n * Wraps the `@shadcn/react` Questionnaire primitive (Root, Item, Choice,\n * Input, Previous/Skip/Next/Submit), which handles step sequencing,\n * navigation, and validation; the root renders a <form> that tracks the\n * active item. MMDS styles choices as bordered, checkbox/radio-style cards\n * and lays out Previous/Skip/Next/Submit in a fixed 3-column grid.\n */\n\nimport * as React from \"react\"\nimport { Questionnaire as QuestionnairePrimitive } from \"@shadcn/react/questionnaire\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants, type Button } from \"@/components/ui/button\"\nimport { CheckIcon } from \"lucide-react\"\n\n// QuestionnaireTitle only ever renders a <legend> (labels the surrounding\n// <fieldset>, not any control inside it) and QuestionnaireInput's\n// underlying primitive carries no aria-labelledby/aria-describedby link\n// back to it — unlike Choice steps, which get a real <label> for free.\n// This threads Title's/Description's ids to the Input within the same\n// QuestionnaireItem so free-text steps get an accessible name and\n// description without every consumer wiring it by hand.\nconst QuestionnaireLabelContext = React.createContext<{\n titleId: string | null\n setTitleId: (id: string | null) => void\n descriptionId: string | null\n setDescriptionId: (id: string | null) => void\n} | null>(null)\n\nfunction Questionnaire({\n className,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Root>) {\n return (\n <QuestionnairePrimitive.Root\n data-slot=\"questionnaire\"\n className={cn(\"flex w-full min-w-0 flex-col gap-4\", className)}\n {...props}\n />\n )\n}\n\nfunction QuestionnaireProgress({\n className,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Progress>) {\n return (\n <QuestionnairePrimitive.Progress\n data-slot=\"questionnaire-progress\"\n className={cn(\n \"min-h-[1lh] w-fit min-w-[14ch] text-xs font-medium text-muted-foreground tabular-nums\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction QuestionnaireItem({\n className,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Item>) {\n const [titleId, setTitleId] = React.useState<string | null>(null)\n const [descriptionId, setDescriptionId] = React.useState<string | null>(\n null\n )\n const labelContext = React.useMemo(\n () => ({ titleId, setTitleId, descriptionId, setDescriptionId }),\n [titleId, descriptionId]\n )\n\n return (\n <QuestionnaireLabelContext.Provider value={labelContext}>\n <QuestionnairePrimitive.Item\n data-slot=\"questionnaire-item\"\n className={cn(\n \"flex min-w-0 flex-col gap-4 border-0 p-0 outline-none\",\n className\n )}\n {...props}\n />\n </QuestionnaireLabelContext.Provider>\n )\n}\n\nfunction QuestionnaireTitle({\n className,\n id,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Title>) {\n const generatedId = React.useId()\n const titleId = id ?? generatedId\n const labelContext = React.useContext(QuestionnaireLabelContext)\n\n React.useLayoutEffect(() => {\n labelContext?.setTitleId(titleId)\n return () => labelContext?.setTitleId(null)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [titleId])\n\n return (\n <QuestionnairePrimitive.Title\n data-slot=\"questionnaire-title\"\n id={titleId}\n className={cn(\n \"text-base leading-snug font-medium text-pretty [&:not(:has(~[data-slot=questionnaire-description]))]:mb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction QuestionnaireDescription({\n className,\n id,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Description>) {\n const generatedId = React.useId()\n const descriptionId = id ?? generatedId\n const labelContext = React.useContext(QuestionnaireLabelContext)\n\n React.useLayoutEffect(() => {\n labelContext?.setDescriptionId(descriptionId)\n return () => labelContext?.setDescriptionId(null)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [descriptionId])\n\n return (\n <QuestionnairePrimitive.Description\n data-slot=\"questionnaire-description\"\n id={descriptionId}\n className={cn(\"text-sm text-pretty text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction QuestionnaireChoices({\n className,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Choices>) {\n return (\n <QuestionnairePrimitive.Choices\n data-slot=\"questionnaire-choices\"\n className={cn(\n \"group/questionnaire-choices grid min-w-0 gap-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction QuestionnaireChoice({\n children,\n className,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Choice>) {\n return (\n <QuestionnairePrimitive.Choice\n data-slot=\"questionnaire-choice\"\n className={cn(\n \"group/questionnaire-choice relative flex min-h-11 cursor-pointer items-start gap-2.5 rounded-lg border border-input bg-transparent px-3 py-2.5 text-start text-sm transition-colors outline-none select-none hover:bg-muted/50 has-[>input:focus-visible]:border-ring has-[>input:focus-visible]:ring-3 has-[>input:focus-visible]:ring-ring/50 data-invalid:border-destructive dark:bg-input/20 data-checked:border-primary/40 data-checked:bg-muted dark:data-checked:bg-muted\",\n \"data-disabled:pointer-events-none data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <QuestionnairePrimitive.ChoiceInput\n data-slot=\"questionnaire-choice-input\"\n className=\"absolute inset-0 z-10 size-full cursor-pointer opacity-0\"\n />\n <span\n aria-hidden=\"true\"\n data-slot=\"questionnaire-choice-indicator\"\n className=\"pointer-events-none relative flex size-4 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-[4px] border border-input group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 group-data-[type=radio]/questionnaire-choice:rounded-full group-data-checked/questionnaire-choice:border-primary group-data-checked/questionnaire-choice:bg-primary group-data-checked/questionnaire-choice:text-primary-foreground dark:bg-input/30 dark:group-data-checked/questionnaire-choice:bg-primary\"\n >\n <span\n data-slot=\"questionnaire-choice-indicator-dot\"\n className=\"hidden size-2 rounded-full bg-primary-foreground group-data-[type=checkbox]/questionnaire-choice:hidden group-data-checked/questionnaire-choice:block\"\n />\n <CheckIcon\n data-slot=\"questionnaire-choice-indicator-check\"\n className=\"hidden size-3.5 group-data-[type=radio]/questionnaire-choice:hidden group-data-checked/questionnaire-choice:block\"\n />\n </span>\n <QuestionnairePrimitive.ChoiceLabel\n data-slot=\"questionnaire-choice-label\"\n className=\"flex min-w-0 flex-1 flex-col gap-0.5 leading-snug\"\n >\n {children}\n </QuestionnairePrimitive.ChoiceLabel>\n <QuestionnairePrimitive.ChoiceShortcut\n data-slot=\"questionnaire-choice-shortcut\"\n className=\"pointer-events-none ms-auto hidden size-5 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-md border border-input bg-background font-mono text-[0.625rem] leading-none font-medium text-muted-foreground group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 group-data-[shortcut]/questionnaire-choice:inline-flex\"\n />\n </QuestionnairePrimitive.Choice>\n )\n}\n\nfunction QuestionnaireChoiceDescription({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"questionnaire-choice-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction QuestionnaireInput({\n className,\n \"aria-labelledby\": ariaLabelledby,\n \"aria-describedby\": ariaDescribedby,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Input>) {\n const labelContext = React.useContext(QuestionnaireLabelContext)\n // Only fall back to Title/Description's ids when the consumer hasn't\n // already supplied their own — an explicit aria-label/aria-labelledby\n // always wins.\n const resolvedLabelledby =\n ariaLabelledby ??\n (!props[\"aria-label\"] ? labelContext?.titleId ?? undefined : undefined)\n const resolvedDescribedby =\n ariaDescribedby ?? labelContext?.descriptionId ?? undefined\n\n return (\n <div\n data-slot=\"questionnaire-input-wrapper\"\n className=\"group/questionnaire-input relative w-full min-w-0\"\n >\n <QuestionnairePrimitive.Input\n data-slot=\"questionnaire-input\"\n aria-labelledby={resolvedLabelledby}\n aria-describedby={resolvedDescribedby}\n className={cn(\n \"h-8 min-h-11 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-[color,box-shadow,background-color] outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 sm:min-h-0 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\n \"selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction QuestionnaireError({\n className,\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Error>) {\n return (\n <QuestionnairePrimitive.Error\n data-slot=\"questionnaire-error\"\n className={cn(\"mt-2 text-sm text-destructive\", className)}\n {...props}\n />\n )\n}\n\nfunction QuestionnaireActions({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"questionnaire-actions\"\n className={cn(\n \"grid min-h-11 w-full grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-2 sm:min-h-8\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction QuestionnairePrevious({\n children,\n className,\n size = \"default\",\n variant = \"outline\",\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Previous> &\n Pick<React.ComponentProps<typeof Button>, \"size\" | \"variant\">) {\n return (\n <QuestionnairePrimitive.Previous\n data-slot=\"questionnaire-previous\"\n data-size={size}\n data-variant={variant}\n className={cn(\n buttonVariants({ size, variant }),\n \"col-start-1 row-start-1 min-h-11 justify-self-start sm:min-h-0\",\n className\n )}\n {...props}\n >\n {children ?? \"Previous\"}\n </QuestionnairePrimitive.Previous>\n )\n}\n\nfunction QuestionnaireSkip({\n children,\n className,\n size = \"default\",\n variant = \"outline\",\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Skip> &\n Pick<React.ComponentProps<typeof Button>, \"size\" | \"variant\">) {\n return (\n <QuestionnairePrimitive.Skip\n data-slot=\"questionnaire-skip\"\n data-size={size}\n data-variant={variant}\n className={cn(\n buttonVariants({ size, variant }),\n \"col-start-2 row-start-1 min-h-11 justify-self-end sm:min-h-0\",\n className\n )}\n {...props}\n >\n {children ?? \"Skip\"}\n </QuestionnairePrimitive.Skip>\n )\n}\n\nfunction QuestionnaireNext({\n children,\n className,\n size = \"default\",\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Next> &\n Pick<React.ComponentProps<typeof Button>, \"size\" | \"variant\">) {\n return (\n <QuestionnairePrimitive.Next\n data-slot=\"questionnaire-next\"\n data-size={size}\n data-variant={variant}\n className={cn(\n buttonVariants({ size, variant }),\n \"col-start-3 row-start-1 min-h-11 justify-self-end sm:min-h-0\",\n className\n )}\n {...props}\n >\n {children ?? \"Next\"}\n </QuestionnairePrimitive.Next>\n )\n}\n\nfunction QuestionnaireSubmit({\n children,\n className,\n size = \"default\",\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof QuestionnairePrimitive.Submit> &\n Pick<React.ComponentProps<typeof Button>, \"size\" | \"variant\">) {\n return (\n <QuestionnairePrimitive.Submit\n data-slot=\"questionnaire-submit\"\n data-size={size}\n data-variant={variant}\n className={cn(\n buttonVariants({ size, variant }),\n \"col-start-3 row-start-1 min-h-11 justify-self-end sm:min-h-0\",\n className\n )}\n {...props}\n >\n {children ?? \"Submit\"}\n </QuestionnairePrimitive.Submit>\n )\n}\n\nexport {\n Questionnaire,\n QuestionnaireActions,\n QuestionnaireChoice,\n QuestionnaireChoiceDescription,\n QuestionnaireChoices,\n QuestionnaireDescription,\n QuestionnaireError,\n QuestionnaireInput,\n QuestionnaireItem,\n QuestionnaireNext,\n QuestionnairePrevious,\n QuestionnaireProgress,\n QuestionnaireSkip,\n QuestionnaireSubmit,\n QuestionnaireTitle,\n}\n\n/**\n * WHEN TO USE\n * - Guided multi-step intake, onboarding, or surveys where only one question is shown at a time.\n * - Flows that need per-step required/skip logic and a progress indicator.\n *\n * NOT WHEN\n * - All fields should be visible at once in a single form — use Field + FieldSet instead.\n * - Sections don't need to be shown in sequence — use Tabs instead.\n *\n * KEY RULES\n * - `items` on Questionnaire declares the sequence of entries and which are `required`; each QuestionnaireItem matches an entry by `name`.\n * - A QuestionnaireItem's `required`/`multiple` props should match its entry in `items` — `multiple` renders a checkbox-style choice group instead of radio-style.\n * - `shortcuts=\"letters\"` on Questionnaire adds A/B/C key hints to each QuestionnaireChoice.\n * - QuestionnairePrevious / QuestionnaireSkip / QuestionnaireNext / QuestionnaireSubmit manage their own visibility based on step position — render all of them and let the primitive decide which shows.\n * - QuestionnaireError only renders when the active item fails validation (e.g. a required choice wasn't picked).\n * - QuestionnaireInput automatically picks up `aria-labelledby`/`aria-describedby` from the\n * QuestionnaireTitle/QuestionnaireDescription rendered in the same QuestionnaireItem (unlike\n * Choice steps, a free-text step has no native `<label>` wrapping it) — pass an explicit\n * `aria-label`/`aria-labelledby` yourself only if you need to override that default.\n *\n * USAGE\n * <Questionnaire\n * items={[\n * { name: \"base\", required: true, choices: [{ value: \"radix\" }, { value: \"base-ui\" }] },\n * { name: \"notes\" },\n * ]}\n * >\n * <QuestionnaireProgress />\n * <QuestionnaireItem name=\"base\" required>\n * <QuestionnaireTitle>Which primitive base do you use?</QuestionnaireTitle>\n * <QuestionnaireChoices>\n * <QuestionnaireChoice value=\"radix\">Radix UI</QuestionnaireChoice>\n * <QuestionnaireChoice value=\"base-ui\">Base UI</QuestionnaireChoice>\n * </QuestionnaireChoices>\n * <QuestionnaireError>Pick one to continue.</QuestionnaireError>\n * </QuestionnaireItem>\n * <QuestionnaireItem name=\"notes\">\n * <QuestionnaireTitle>Anything else?</QuestionnaireTitle>\n * <QuestionnaireInput type=\"text\" placeholder=\"Optional\" />\n * </QuestionnaireItem>\n * <QuestionnaireActions>\n * <QuestionnairePrevious>Back</QuestionnairePrevious>\n * <QuestionnaireNext>Next</QuestionnaireNext>\n * <QuestionnaireSubmit>Submit</QuestionnaireSubmit>\n * </QuestionnaireActions>\n * </Questionnaire>\n *\n * // Letter shortcuts (A/B/C hints on choices)\n * <Questionnaire\n * shortcuts=\"letters\"\n * items={[{ name: \"spice\", required: true, choices: [{ value: \"turmeric\" }] }]}\n * >\n * <QuestionnaireItem name=\"spice\" required>\n * <QuestionnaireTitle>Pick a spice</QuestionnaireTitle>\n * <QuestionnaireChoices>\n * <QuestionnaireChoice value=\"turmeric\">Turmeric</QuestionnaireChoice>\n * </QuestionnaireChoices>\n * </QuestionnaireItem>\n * <QuestionnaireActions>\n * <QuestionnaireSubmit>Submit</QuestionnaireSubmit>\n * </QuestionnaireActions>\n * </Questionnaire>\n */\n"],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RadioGroup — exclusive selection from a small, always-visible set.
|
|
3
|
+
*
|
|
4
|
+
* Built on the Radix RadioGroup primitive. Error styling is driven off
|
|
5
|
+
* `aria-invalid` on the group/items instead of a prop, and the selected-dot
|
|
6
|
+
* indicator is a plain filled circle rather than an icon.
|
|
7
|
+
*/
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
|
|
10
|
+
declare function RadioGroup({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Root>): React.JSX.Element;
|
|
11
|
+
declare function RadioGroupItem({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Item>): React.JSX.Element;
|
|
12
|
+
export { RadioGroup, RadioGroupItem };
|
|
13
|
+
/**
|
|
14
|
+
* WHEN TO USE
|
|
15
|
+
* - Choosing exactly one option from roughly 2–5 choices that should all stay visible at once
|
|
16
|
+
*
|
|
17
|
+
* NOT WHEN
|
|
18
|
+
* - More than ~5 options, or the list is dynamic/long — use Select
|
|
19
|
+
* - A single boolean — use Checkbox or Switch
|
|
20
|
+
* - More than one option can be chosen — use a list of Checkbox
|
|
21
|
+
*
|
|
22
|
+
* KEY RULES
|
|
23
|
+
* - RadioGroup lays out its items in a grid (vertical by default); pass a `className`
|
|
24
|
+
* like `flex gap-4` for a horizontal row
|
|
25
|
+
* - Wrap each RadioGroupItem in a Label so its text is a clickable target and is announced
|
|
26
|
+
* - Error state is driven entirely by `aria-invalid` — there is no `error` prop
|
|
27
|
+
* - `disabled` on an individual RadioGroupItem disables just that option
|
|
28
|
+
* - An AI-recommended choice is marked once, at the GROUP, never beside an individual option:
|
|
29
|
+
* a radio group holds exactly one value, so AI chose for the group (unlike Checkbox, where
|
|
30
|
+
* each option is its own boolean and can carry its own marker). Put `AILabel` beside the
|
|
31
|
+
* FieldLegend in a `flex items-center` row (`mb-0` on the legend, `mb-1.5` on the row so the
|
|
32
|
+
* two share a centre line; `aria-labelledby` on the FieldSet since the legend is no longer
|
|
33
|
+
* its first child) and keep the options as plain `<Label>`-wrapped items. Pass AILabel
|
|
34
|
+
* `edited={value !== aiValue}` and an `onRevert` that re-selects it, so picking another option
|
|
35
|
+
* turns the marker into an undo button (AILabel's own override/undo morph, same as
|
|
36
|
+
* Input/Select/Textarea/Checkbox). See AI/RadioGroup.
|
|
37
|
+
*
|
|
38
|
+
* USAGE
|
|
39
|
+
* <RadioGroup defaultValue="comfortable">
|
|
40
|
+
* <Label className="flex items-center gap-2">
|
|
41
|
+
* <RadioGroupItem value="comfortable" />
|
|
42
|
+
* Comfortable
|
|
43
|
+
* </Label>
|
|
44
|
+
* <Label className="flex items-center gap-2">
|
|
45
|
+
* <RadioGroupItem value="compact" />
|
|
46
|
+
* Compact
|
|
47
|
+
* </Label>
|
|
48
|
+
* </RadioGroup>
|
|
49
|
+
*/
|
|
50
|
+
//# sourceMappingURL=radio-group.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../../src/components/ui/radio-group.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAI5D,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,qBAQvD;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,qBAkBvD;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAA;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { cn } from "../../lib/utils.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { RadioGroup as RadioGroup$1 } from "radix-ui";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/ui/radio-group.tsx
|
|
6
|
+
function RadioGroup({ className, ...props }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(RadioGroup$1.Root, {
|
|
8
|
+
"data-slot": "radio-group",
|
|
9
|
+
className: cn("grid w-full gap-2", className),
|
|
10
|
+
...props
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function RadioGroupItem({ className, ...props }) {
|
|
14
|
+
return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
|
|
15
|
+
"data-slot": "radio-group-item",
|
|
16
|
+
className: cn("group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary", className),
|
|
17
|
+
...props,
|
|
18
|
+
children: /* @__PURE__ */ jsx(RadioGroup$1.Indicator, {
|
|
19
|
+
"data-slot": "radio-group-indicator",
|
|
20
|
+
className: "flex size-4 items-center justify-center",
|
|
21
|
+
children: /* @__PURE__ */ jsx("span", { className: "absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground" })
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* WHEN TO USE
|
|
27
|
+
* - Choosing exactly one option from roughly 2–5 choices that should all stay visible at once
|
|
28
|
+
*
|
|
29
|
+
* NOT WHEN
|
|
30
|
+
* - More than ~5 options, or the list is dynamic/long — use Select
|
|
31
|
+
* - A single boolean — use Checkbox or Switch
|
|
32
|
+
* - More than one option can be chosen — use a list of Checkbox
|
|
33
|
+
*
|
|
34
|
+
* KEY RULES
|
|
35
|
+
* - RadioGroup lays out its items in a grid (vertical by default); pass a `className`
|
|
36
|
+
* like `flex gap-4` for a horizontal row
|
|
37
|
+
* - Wrap each RadioGroupItem in a Label so its text is a clickable target and is announced
|
|
38
|
+
* - Error state is driven entirely by `aria-invalid` — there is no `error` prop
|
|
39
|
+
* - `disabled` on an individual RadioGroupItem disables just that option
|
|
40
|
+
* - An AI-recommended choice is marked once, at the GROUP, never beside an individual option:
|
|
41
|
+
* a radio group holds exactly one value, so AI chose for the group (unlike Checkbox, where
|
|
42
|
+
* each option is its own boolean and can carry its own marker). Put `AILabel` beside the
|
|
43
|
+
* FieldLegend in a `flex items-center` row (`mb-0` on the legend, `mb-1.5` on the row so the
|
|
44
|
+
* two share a centre line; `aria-labelledby` on the FieldSet since the legend is no longer
|
|
45
|
+
* its first child) and keep the options as plain `<Label>`-wrapped items. Pass AILabel
|
|
46
|
+
* `edited={value !== aiValue}` and an `onRevert` that re-selects it, so picking another option
|
|
47
|
+
* turns the marker into an undo button (AILabel's own override/undo morph, same as
|
|
48
|
+
* Input/Select/Textarea/Checkbox). See AI/RadioGroup.
|
|
49
|
+
*
|
|
50
|
+
* USAGE
|
|
51
|
+
* <RadioGroup defaultValue="comfortable">
|
|
52
|
+
* <Label className="flex items-center gap-2">
|
|
53
|
+
* <RadioGroupItem value="comfortable" />
|
|
54
|
+
* Comfortable
|
|
55
|
+
* </Label>
|
|
56
|
+
* <Label className="flex items-center gap-2">
|
|
57
|
+
* <RadioGroupItem value="compact" />
|
|
58
|
+
* Compact
|
|
59
|
+
* </Label>
|
|
60
|
+
* </RadioGroup>
|
|
61
|
+
*/
|
|
62
|
+
//#endregion
|
|
63
|
+
export { RadioGroup, RadioGroupItem };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=radio-group.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio-group.js","names":[],"sources":["../../../src/components/ui/radio-group.tsx"],"sourcesContent":["/**\n * RadioGroup — exclusive selection from a small, always-visible set.\n *\n * Built on the Radix RadioGroup primitive. Error styling is driven off\n * `aria-invalid` on the group/items instead of a prop, and the selected-dot\n * indicator is a plain filled circle rather than an icon.\n */\n\nimport * as React from \"react\"\nimport { RadioGroup as RadioGroupPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction RadioGroup({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n return (\n <RadioGroupPrimitive.Root\n data-slot=\"radio-group\"\n className={cn(\"grid w-full gap-2\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n return (\n <RadioGroupPrimitive.Item\n data-slot=\"radio-group-item\"\n className={cn(\n \"group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary\",\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"flex size-4 items-center justify-center\"\n >\n <span className=\"absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n\n/**\n * WHEN TO USE\n * - Choosing exactly one option from roughly 2–5 choices that should all stay visible at once\n *\n * NOT WHEN\n * - More than ~5 options, or the list is dynamic/long — use Select\n * - A single boolean — use Checkbox or Switch\n * - More than one option can be chosen — use a list of Checkbox\n *\n * KEY RULES\n * - RadioGroup lays out its items in a grid (vertical by default); pass a `className`\n * like `flex gap-4` for a horizontal row\n * - Wrap each RadioGroupItem in a Label so its text is a clickable target and is announced\n * - Error state is driven entirely by `aria-invalid` — there is no `error` prop\n * - `disabled` on an individual RadioGroupItem disables just that option\n * - An AI-recommended choice is marked once, at the GROUP, never beside an individual option:\n * a radio group holds exactly one value, so AI chose for the group (unlike Checkbox, where\n * each option is its own boolean and can carry its own marker). Put `AILabel` beside the\n * FieldLegend in a `flex items-center` row (`mb-0` on the legend, `mb-1.5` on the row so the\n * two share a centre line; `aria-labelledby` on the FieldSet since the legend is no longer\n * its first child) and keep the options as plain `<Label>`-wrapped items. Pass AILabel\n * `edited={value !== aiValue}` and an `onRevert` that re-selects it, so picking another option\n * turns the marker into an undo button (AILabel's own override/undo morph, same as\n * Input/Select/Textarea/Checkbox). See AI/RadioGroup.\n *\n * USAGE\n * <RadioGroup defaultValue=\"comfortable\">\n * <Label className=\"flex items-center gap-2\">\n * <RadioGroupItem value=\"comfortable\" />\n * Comfortable\n * </Label>\n * <Label className=\"flex items-center gap-2\">\n * <RadioGroupItem value=\"compact\" />\n * Compact\n * </Label>\n * </RadioGroup>\n */\n"],"mappings":";;;;;AAaA,SAAS,WAAW,EAClB,WACA,GAAG,SACqD;CACxD,OACE,oBAAC,aAAoB,MAArB;EACE,aAAU;EACV,WAAW,GAAG,qBAAqB,SAAS;EAC5C,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,eAAe,EACtB,WACA,GAAG,SACqD;CACxD,OACE,oBAAC,aAAoB,MAArB;EACE,aAAU;EACV,WAAW,GACT,upBACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,aAAoB,WAArB;GACE,aAAU;GACV,WAAU;GAEV,UAAA,oBAAC,QAAD,EAAM,WAAU,wGAAyG,CAAA;EAC5F,CAAA;CACP,CAAA;AAE9B"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ResizablePanelGroup — draggable split panes, on react-resizable-panels v4.
|
|
3
|
+
*
|
|
4
|
+
* Follows the react-resizable-panels v4 API: orientation is set via
|
|
5
|
+
* `orientation` ("horizontal" | "vertical"), not the older `direction` prop.
|
|
6
|
+
*/
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import * as ResizablePrimitive from "react-resizable-panels";
|
|
9
|
+
declare function ResizablePanelGroup({ className, ...props }: ResizablePrimitive.GroupProps): React.JSX.Element;
|
|
10
|
+
declare function ResizablePanel({ elementRef, ...props }: ResizablePrimitive.PanelProps): React.JSX.Element;
|
|
11
|
+
declare function ResizableHandle({ withHandle, className, "aria-label": ariaLabel, ...props }: ResizablePrimitive.SeparatorProps & {
|
|
12
|
+
withHandle?: boolean;
|
|
13
|
+
}): React.JSX.Element;
|
|
14
|
+
export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
|
|
15
|
+
/**
|
|
16
|
+
* WHEN TO USE
|
|
17
|
+
* - User-adjustable split layouts — editor plus preview, list plus detail,
|
|
18
|
+
* IDE-style panes where the split ratio should be draggable.
|
|
19
|
+
*
|
|
20
|
+
* NOT WHEN
|
|
21
|
+
* - A fixed layout where the split never needs to change — use CSS grid,
|
|
22
|
+
* it's lighter weight.
|
|
23
|
+
* - Collapsible primary side navigation — use Sidebar, which has its own
|
|
24
|
+
* offcanvas/icon-collapse behavior; this is for peer content panes.
|
|
25
|
+
* - Content that should float above the page — use an overlay component.
|
|
26
|
+
*
|
|
27
|
+
* KEY RULES
|
|
28
|
+
* - Orientation is `orientation` ("horizontal" | "vertical") on
|
|
29
|
+
* ResizablePanelGroup — this is the v4 react-resizable-panels API; it is
|
|
30
|
+
* NOT `direction`, which is the older/deprecated prop name.
|
|
31
|
+
* - Give each ResizablePanel a `defaultSize` (percentage) so the initial
|
|
32
|
+
* split is deterministic — sizes across panels in a group should sum to 100.
|
|
33
|
+
* - `ResizableHandle withHandle` draws a visible grip; omit it for a bare
|
|
34
|
+
* drag line.
|
|
35
|
+
* - Groups can nest for layouts split on more than one axis.
|
|
36
|
+
*
|
|
37
|
+
* USAGE
|
|
38
|
+
* <ResizablePanelGroup orientation="horizontal" className="h-48 rounded-xl border">
|
|
39
|
+
* <ResizablePanel defaultSize={50}>...</ResizablePanel>
|
|
40
|
+
* <ResizableHandle withHandle />
|
|
41
|
+
* <ResizablePanel defaultSize={50}>...</ResizablePanel>
|
|
42
|
+
* </ResizablePanelGroup>
|
|
43
|
+
*/
|
|
44
|
+
//# sourceMappingURL=resizable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../../src/components/ui/resizable.tsx"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,kBAAkB,MAAM,wBAAwB,CAAA;AAI5D,iBAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,UAAU,qBAW/B;AAED,iBAAS,cAAc,CAAC,EACtB,UAAU,EACV,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,UAAU,qBA0B/B;AAED,iBAAS,eAAe,CAAC,EACvB,UAAU,EACV,SAAS,EACT,YAAY,EAAE,SAAS,EACvB,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,cAAc,GAAG;IACrC,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,qBAqBA;AAED,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAA;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../lib/utils.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import * as ResizablePrimitive from "react-resizable-panels";
|
|
6
|
+
//#region src/components/ui/resizable.tsx
|
|
7
|
+
/**
|
|
8
|
+
* ResizablePanelGroup — draggable split panes, on react-resizable-panels v4.
|
|
9
|
+
*
|
|
10
|
+
* Follows the react-resizable-panels v4 API: orientation is set via
|
|
11
|
+
* `orientation` ("horizontal" | "vertical"), not the older `direction` prop.
|
|
12
|
+
*/
|
|
13
|
+
function ResizablePanelGroup({ className, ...props }) {
|
|
14
|
+
return /* @__PURE__ */ jsx(ResizablePrimitive.Group, {
|
|
15
|
+
"data-slot": "resizable-panel-group",
|
|
16
|
+
className: cn("flex h-full w-full aria-[orientation=vertical]:flex-col", className),
|
|
17
|
+
...props
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function ResizablePanel({ elementRef, ...props }) {
|
|
21
|
+
const setElementRef = React.useCallback((el) => {
|
|
22
|
+
if (el?.firstElementChild instanceof HTMLElement) el.firstElementChild.tabIndex = 0;
|
|
23
|
+
if (typeof elementRef === "function") elementRef(el);
|
|
24
|
+
else if (elementRef) elementRef.current = el;
|
|
25
|
+
}, [elementRef]);
|
|
26
|
+
return /* @__PURE__ */ jsx(ResizablePrimitive.Panel, {
|
|
27
|
+
"data-slot": "resizable-panel",
|
|
28
|
+
elementRef: setElementRef,
|
|
29
|
+
...props
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function ResizableHandle({ withHandle, className, "aria-label": ariaLabel, ...props }) {
|
|
33
|
+
return /* @__PURE__ */ jsx(ResizablePrimitive.Separator, {
|
|
34
|
+
"data-slot": "resizable-handle",
|
|
35
|
+
"aria-label": ariaLabel ?? "Resize panel",
|
|
36
|
+
className: cn("relative flex w-px items-center justify-center bg-border ring-offset-background after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-hidden aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90", className),
|
|
37
|
+
...props,
|
|
38
|
+
children: withHandle && /* @__PURE__ */ jsx("div", { className: "z-10 flex h-6 w-1 shrink-0 rounded-lg bg-border" })
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* WHEN TO USE
|
|
43
|
+
* - User-adjustable split layouts — editor plus preview, list plus detail,
|
|
44
|
+
* IDE-style panes where the split ratio should be draggable.
|
|
45
|
+
*
|
|
46
|
+
* NOT WHEN
|
|
47
|
+
* - A fixed layout where the split never needs to change — use CSS grid,
|
|
48
|
+
* it's lighter weight.
|
|
49
|
+
* - Collapsible primary side navigation — use Sidebar, which has its own
|
|
50
|
+
* offcanvas/icon-collapse behavior; this is for peer content panes.
|
|
51
|
+
* - Content that should float above the page — use an overlay component.
|
|
52
|
+
*
|
|
53
|
+
* KEY RULES
|
|
54
|
+
* - Orientation is `orientation` ("horizontal" | "vertical") on
|
|
55
|
+
* ResizablePanelGroup — this is the v4 react-resizable-panels API; it is
|
|
56
|
+
* NOT `direction`, which is the older/deprecated prop name.
|
|
57
|
+
* - Give each ResizablePanel a `defaultSize` (percentage) so the initial
|
|
58
|
+
* split is deterministic — sizes across panels in a group should sum to 100.
|
|
59
|
+
* - `ResizableHandle withHandle` draws a visible grip; omit it for a bare
|
|
60
|
+
* drag line.
|
|
61
|
+
* - Groups can nest for layouts split on more than one axis.
|
|
62
|
+
*
|
|
63
|
+
* USAGE
|
|
64
|
+
* <ResizablePanelGroup orientation="horizontal" className="h-48 rounded-xl border">
|
|
65
|
+
* <ResizablePanel defaultSize={50}>...</ResizablePanel>
|
|
66
|
+
* <ResizableHandle withHandle />
|
|
67
|
+
* <ResizablePanel defaultSize={50}>...</ResizablePanel>
|
|
68
|
+
* </ResizablePanelGroup>
|
|
69
|
+
*/
|
|
70
|
+
//#endregion
|
|
71
|
+
export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=resizable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resizable.js","names":[],"sources":["../../../src/components/ui/resizable.tsx"],"sourcesContent":["\"use client\"\n\n/**\n * ResizablePanelGroup — draggable split panes, on react-resizable-panels v4.\n *\n * Follows the react-resizable-panels v4 API: orientation is set via\n * `orientation` (\"horizontal\" | \"vertical\"), not the older `direction` prop.\n */\n\nimport * as React from \"react\"\nimport * as ResizablePrimitive from \"react-resizable-panels\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction ResizablePanelGroup({\n className,\n ...props\n}: ResizablePrimitive.GroupProps) {\n return (\n <ResizablePrimitive.Group\n data-slot=\"resizable-panel-group\"\n className={cn(\n \"flex h-full w-full aria-[orientation=vertical]:flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ResizablePanel({\n elementRef,\n ...props\n}: ResizablePrimitive.PanelProps) {\n // react-resizable-panels renders Panel as two nested divs — an outer one\n // (where `elementRef`/arbitrary props land) and an inner one, not exposed\n // via props at all, that actually carries `overflow: auto`. A tabIndex on\n // the outer div doesn't help a keyboard user reach the part that scrolls,\n // so this reaches one level in via the DOM to tag that inner div directly.\n const setElementRef = React.useCallback(\n (el: HTMLDivElement | null) => {\n if (el?.firstElementChild instanceof HTMLElement) {\n el.firstElementChild.tabIndex = 0\n }\n if (typeof elementRef === \"function\") elementRef(el)\n else if (elementRef) {\n ;(elementRef as React.RefObject<HTMLDivElement | null>).current = el\n }\n },\n [elementRef]\n )\n\n return (\n <ResizablePrimitive.Panel\n data-slot=\"resizable-panel\"\n elementRef={setElementRef}\n {...props}\n />\n )\n}\n\nfunction ResizableHandle({\n withHandle,\n className,\n \"aria-label\": ariaLabel,\n ...props\n}: ResizablePrimitive.SeparatorProps & {\n withHandle?: boolean\n}) {\n return (\n <ResizablePrimitive.Separator\n data-slot=\"resizable-handle\"\n // Falls back to a generic accessible name when the consumer doesn't\n // pass one — this keyboard-focusable, arrow-key-resizable control had\n // none at all otherwise (4.1.2). Direction-agnostic text since the\n // handle's own orientation is a runtime `aria-orientation`, not\n // knowable here at the type level.\n aria-label={ariaLabel ?? \"Resize panel\"}\n className={cn(\n \"relative flex w-px items-center justify-center bg-border ring-offset-background after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-hidden aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90\",\n className\n )}\n {...props}\n >\n {withHandle && (\n <div className=\"z-10 flex h-6 w-1 shrink-0 rounded-lg bg-border\" />\n )}\n </ResizablePrimitive.Separator>\n )\n}\n\nexport { ResizableHandle, ResizablePanel, ResizablePanelGroup }\n\n/**\n * WHEN TO USE\n * - User-adjustable split layouts — editor plus preview, list plus detail,\n * IDE-style panes where the split ratio should be draggable.\n *\n * NOT WHEN\n * - A fixed layout where the split never needs to change — use CSS grid,\n * it's lighter weight.\n * - Collapsible primary side navigation — use Sidebar, which has its own\n * offcanvas/icon-collapse behavior; this is for peer content panes.\n * - Content that should float above the page — use an overlay component.\n *\n * KEY RULES\n * - Orientation is `orientation` (\"horizontal\" | \"vertical\") on\n * ResizablePanelGroup — this is the v4 react-resizable-panels API; it is\n * NOT `direction`, which is the older/deprecated prop name.\n * - Give each ResizablePanel a `defaultSize` (percentage) so the initial\n * split is deterministic — sizes across panels in a group should sum to 100.\n * - `ResizableHandle withHandle` draws a visible grip; omit it for a bare\n * drag line.\n * - Groups can nest for layouts split on more than one axis.\n *\n * USAGE\n * <ResizablePanelGroup orientation=\"horizontal\" className=\"h-48 rounded-xl border\">\n * <ResizablePanel defaultSize={50}>...</ResizablePanel>\n * <ResizableHandle withHandle />\n * <ResizablePanel defaultSize={50}>...</ResizablePanel>\n * </ResizablePanelGroup>\n */\n"],"mappings":";;;;;;;;;;;;AAcA,SAAS,oBAAoB,EAC3B,WACA,GAAG,SAC6B;CAChC,OACE,oBAAC,mBAAmB,OAApB;EACE,aAAU;EACV,WAAW,GACT,2DACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,eAAe,EACtB,YACA,GAAG,SAC6B;CAMhC,MAAM,gBAAgB,MAAM,aACzB,OAA8B;EAC7B,IAAI,IAAI,6BAA6B,aACnC,GAAG,kBAAkB,WAAW;EAElC,IAAI,OAAO,eAAe,YAAY,WAAW,EAAE;OAC9C,IAAI,YACN,WAAuD,UAAU;CAEtE,GACA,CAAC,UAAU,CACb;CAEA,OACE,oBAAC,mBAAmB,OAApB;EACE,aAAU;EACV,YAAY;EACZ,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,gBAAgB,EACvB,YACA,WACA,cAAc,WACd,GAAG,SAGF;CACD,OACE,oBAAC,mBAAmB,WAApB;EACE,aAAU;EAMV,cAAY,aAAa;EACzB,WAAW,GACT,wkBACA,SACF;EACA,GAAI;EAEH,UAAA,cACC,oBAAC,OAAD,EAAK,WAAU,kDAAmD,CAAA;CAExC,CAAA;AAElC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ScrollArea — region with a styled custom scrollbar.
|
|
3
|
+
*
|
|
4
|
+
* Built on the Radix ScrollArea primitive. The thumb is styled from the
|
|
5
|
+
* `--color-border` token, a vertical ScrollBar is rendered by default, and
|
|
6
|
+
* the viewport's edges fade toward whatever's
|
|
7
|
+
* scrolled past (via the `scroll-fade` utility shipped in `shadcn/tailwind.css`,
|
|
8
|
+
* already imported in index.css) — same mechanism MessageScroller's viewport
|
|
9
|
+
* already uses, here defaulted to the vertical axis via `viewportClassName`.
|
|
10
|
+
*/
|
|
11
|
+
import * as React from "react";
|
|
12
|
+
import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
|
|
13
|
+
declare function ScrollArea({ className, viewportClassName, children, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.Root> & {
|
|
14
|
+
/** Defaults to `scroll-fade-y` — pass `scroll-fade-x` for a horizontal
|
|
15
|
+
* ScrollArea (paired with `<ScrollBar orientation="horizontal" />`), or
|
|
16
|
+
* `scroll-fade-none` to turn it off. Full replacement, not merged with
|
|
17
|
+
* the default, since only one scroll axis fades at a time. */
|
|
18
|
+
viewportClassName?: string;
|
|
19
|
+
}): React.JSX.Element;
|
|
20
|
+
declare function ScrollBar({ className, orientation, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>): React.JSX.Element;
|
|
21
|
+
export { ScrollArea, ScrollBar };
|
|
22
|
+
/**
|
|
23
|
+
* WHEN TO USE
|
|
24
|
+
* - A list or panel constrained to a fixed height that needs a scrollbar
|
|
25
|
+
* matching the design system instead of the browser's native one.
|
|
26
|
+
* - Horizontal card/chip strips (e.g. a filmstrip of thumbnails).
|
|
27
|
+
*
|
|
28
|
+
* NOT WHEN
|
|
29
|
+
* - Whole-page scrolling — leave that to the browser; wrapping the page
|
|
30
|
+
* root in ScrollArea fights native scroll restoration and anchor links.
|
|
31
|
+
* - Content that already fits without overflow — it adds DOM/JS for nothing.
|
|
32
|
+
*
|
|
33
|
+
* KEY RULES
|
|
34
|
+
* - A vertical scrollbar renders by default. For horizontal overflow you
|
|
35
|
+
* must add an explicit `<ScrollBar orientation="horizontal" />` child —
|
|
36
|
+
* it is not inferred from content width.
|
|
37
|
+
* - The scrollable region needs an explicit height (or a bounded flex/grid
|
|
38
|
+
* ancestor) via `className` on ScrollArea — it doesn't scroll on its own.
|
|
39
|
+
* - The viewport fades vertically by default; pass `viewportClassName="scroll-fade-x"`
|
|
40
|
+
* for a horizontal ScrollArea, or `"scroll-fade-none"` to turn the fade off entirely.
|
|
41
|
+
*
|
|
42
|
+
* USAGE
|
|
43
|
+
* <ScrollArea className="h-64 w-56 rounded-md border">
|
|
44
|
+
* <div className="p-4">...</div>
|
|
45
|
+
* </ScrollArea>
|
|
46
|
+
*
|
|
47
|
+
* <ScrollArea
|
|
48
|
+
* className="w-80 rounded-md border whitespace-nowrap"
|
|
49
|
+
* viewportClassName="scroll-fade-x"
|
|
50
|
+
* >
|
|
51
|
+
* <div className="flex gap-3 p-4">...</div>
|
|
52
|
+
* <ScrollBar orientation="horizontal" />
|
|
53
|
+
* </ScrollArea>
|
|
54
|
+
*/
|
|
55
|
+
//# sourceMappingURL=scroll-area.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../../src/components/ui/scroll-area.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAI5D,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,iBAAmC,EACnC,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG;IACzD;;;kEAG8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,qBAqBA;AAED,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,WAAwB,EACxB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,mBAAmB,CAAC,qBAkBtE;AAED,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAA;AAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { cn } from "../../lib/utils.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { ScrollArea as ScrollArea$1 } from "radix-ui";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/ui/scroll-area.tsx
|
|
6
|
+
function ScrollArea({ className, viewportClassName = "scroll-fade-y", children, ...props }) {
|
|
7
|
+
return /* @__PURE__ */ jsxs(ScrollArea$1.Root, {
|
|
8
|
+
"data-slot": "scroll-area",
|
|
9
|
+
className: cn("relative", className),
|
|
10
|
+
...props,
|
|
11
|
+
children: [
|
|
12
|
+
/* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
|
|
13
|
+
"data-slot": "scroll-area-viewport",
|
|
14
|
+
tabIndex: 0,
|
|
15
|
+
className: cn("size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1", viewportClassName),
|
|
16
|
+
children
|
|
17
|
+
}),
|
|
18
|
+
/* @__PURE__ */ jsx(ScrollBar, {}),
|
|
19
|
+
/* @__PURE__ */ jsx(ScrollArea$1.Corner, {})
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function ScrollBar({ className, orientation = "vertical", ...props }) {
|
|
24
|
+
return /* @__PURE__ */ jsx(ScrollArea$1.ScrollAreaScrollbar, {
|
|
25
|
+
"data-slot": "scroll-area-scrollbar",
|
|
26
|
+
"data-orientation": orientation,
|
|
27
|
+
orientation,
|
|
28
|
+
className: cn("flex touch-none p-px transition-colors select-none data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:border-t data-[orientation=horizontal]:border-t-transparent data-[orientation=vertical]:h-full data-[orientation=vertical]:w-2.5 data-[orientation=vertical]:border-l data-[orientation=vertical]:border-l-transparent", className),
|
|
29
|
+
...props,
|
|
30
|
+
children: /* @__PURE__ */ jsx(ScrollArea$1.ScrollAreaThumb, {
|
|
31
|
+
"data-slot": "scroll-area-thumb",
|
|
32
|
+
className: "relative flex-1 rounded-full bg-border"
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* WHEN TO USE
|
|
38
|
+
* - A list or panel constrained to a fixed height that needs a scrollbar
|
|
39
|
+
* matching the design system instead of the browser's native one.
|
|
40
|
+
* - Horizontal card/chip strips (e.g. a filmstrip of thumbnails).
|
|
41
|
+
*
|
|
42
|
+
* NOT WHEN
|
|
43
|
+
* - Whole-page scrolling — leave that to the browser; wrapping the page
|
|
44
|
+
* root in ScrollArea fights native scroll restoration and anchor links.
|
|
45
|
+
* - Content that already fits without overflow — it adds DOM/JS for nothing.
|
|
46
|
+
*
|
|
47
|
+
* KEY RULES
|
|
48
|
+
* - A vertical scrollbar renders by default. For horizontal overflow you
|
|
49
|
+
* must add an explicit `<ScrollBar orientation="horizontal" />` child —
|
|
50
|
+
* it is not inferred from content width.
|
|
51
|
+
* - The scrollable region needs an explicit height (or a bounded flex/grid
|
|
52
|
+
* ancestor) via `className` on ScrollArea — it doesn't scroll on its own.
|
|
53
|
+
* - The viewport fades vertically by default; pass `viewportClassName="scroll-fade-x"`
|
|
54
|
+
* for a horizontal ScrollArea, or `"scroll-fade-none"` to turn the fade off entirely.
|
|
55
|
+
*
|
|
56
|
+
* USAGE
|
|
57
|
+
* <ScrollArea className="h-64 w-56 rounded-md border">
|
|
58
|
+
* <div className="p-4">...</div>
|
|
59
|
+
* </ScrollArea>
|
|
60
|
+
*
|
|
61
|
+
* <ScrollArea
|
|
62
|
+
* className="w-80 rounded-md border whitespace-nowrap"
|
|
63
|
+
* viewportClassName="scroll-fade-x"
|
|
64
|
+
* >
|
|
65
|
+
* <div className="flex gap-3 p-4">...</div>
|
|
66
|
+
* <ScrollBar orientation="horizontal" />
|
|
67
|
+
* </ScrollArea>
|
|
68
|
+
*/
|
|
69
|
+
//#endregion
|
|
70
|
+
export { ScrollArea, ScrollBar };
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=scroll-area.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll-area.js","names":[],"sources":["../../../src/components/ui/scroll-area.tsx"],"sourcesContent":["/**\n * ScrollArea — region with a styled custom scrollbar.\n *\n * Built on the Radix ScrollArea primitive. The thumb is styled from the\n * `--color-border` token, a vertical ScrollBar is rendered by default, and\n * the viewport's edges fade toward whatever's\n * scrolled past (via the `scroll-fade` utility shipped in `shadcn/tailwind.css`,\n * already imported in index.css) — same mechanism MessageScroller's viewport\n * already uses, here defaulted to the vertical axis via `viewportClassName`.\n */\n\nimport * as React from \"react\"\nimport { ScrollArea as ScrollAreaPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction ScrollArea({\n className,\n viewportClassName = \"scroll-fade-y\",\n children,\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Root> & {\n /** Defaults to `scroll-fade-y` — pass `scroll-fade-x` for a horizontal\n * ScrollArea (paired with `<ScrollBar orientation=\"horizontal\" />`), or\n * `scroll-fade-none` to turn it off. Full replacement, not merged with\n * the default, since only one scroll axis fades at a time. */\n viewportClassName?: string\n}) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn(\"relative\", className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n tabIndex={0}\n className={cn(\n \"size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1\",\n viewportClassName\n )}\n >\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n )\n}\n\nfunction ScrollBar({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {\n return (\n <ScrollAreaPrimitive.ScrollAreaScrollbar\n data-slot=\"scroll-area-scrollbar\"\n data-orientation={orientation}\n orientation={orientation}\n className={cn(\n \"flex touch-none p-px transition-colors select-none data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:border-t data-[orientation=horizontal]:border-t-transparent data-[orientation=vertical]:h-full data-[orientation=vertical]:w-2.5 data-[orientation=vertical]:border-l data-[orientation=vertical]:border-l-transparent\",\n className\n )}\n {...props}\n >\n <ScrollAreaPrimitive.ScrollAreaThumb\n data-slot=\"scroll-area-thumb\"\n className=\"relative flex-1 rounded-full bg-border\"\n />\n </ScrollAreaPrimitive.ScrollAreaScrollbar>\n )\n}\n\nexport { ScrollArea, ScrollBar }\n\n/**\n * WHEN TO USE\n * - A list or panel constrained to a fixed height that needs a scrollbar\n * matching the design system instead of the browser's native one.\n * - Horizontal card/chip strips (e.g. a filmstrip of thumbnails).\n *\n * NOT WHEN\n * - Whole-page scrolling — leave that to the browser; wrapping the page\n * root in ScrollArea fights native scroll restoration and anchor links.\n * - Content that already fits without overflow — it adds DOM/JS for nothing.\n *\n * KEY RULES\n * - A vertical scrollbar renders by default. For horizontal overflow you\n * must add an explicit `<ScrollBar orientation=\"horizontal\" />` child —\n * it is not inferred from content width.\n * - The scrollable region needs an explicit height (or a bounded flex/grid\n * ancestor) via `className` on ScrollArea — it doesn't scroll on its own.\n * - The viewport fades vertically by default; pass `viewportClassName=\"scroll-fade-x\"`\n * for a horizontal ScrollArea, or `\"scroll-fade-none\"` to turn the fade off entirely.\n *\n * USAGE\n * <ScrollArea className=\"h-64 w-56 rounded-md border\">\n * <div className=\"p-4\">...</div>\n * </ScrollArea>\n *\n * <ScrollArea\n * className=\"w-80 rounded-md border whitespace-nowrap\"\n * viewportClassName=\"scroll-fade-x\"\n * >\n * <div className=\"flex gap-3 p-4\">...</div>\n * <ScrollBar orientation=\"horizontal\" />\n * </ScrollArea>\n */\n"],"mappings":";;;;;AAgBA,SAAS,WAAW,EAClB,WACA,oBAAoB,iBACpB,UACA,GAAG,SAOF;CACD,OACE,qBAAC,aAAoB,MAArB;EACE,aAAU;EACV,WAAW,GAAG,YAAY,SAAS;EACnC,GAAI;EAHN,UAAA;GAKE,oBAAC,aAAoB,UAArB;IACE,aAAU;IACV,UAAU;IACV,WAAW,GACT,sJACA,iBACF;IAEC;GAC2B,CAAA;GAC9B,oBAAC,WAAD,CAAY,CAAA;GACZ,oBAAC,aAAoB,QAArB,CAA6B,CAAA;EACL;;AAE9B;AAEA,SAAS,UAAU,EACjB,WACA,cAAc,YACd,GAAG,SACoE;CACvE,OACE,oBAAC,aAAoB,qBAArB;EACE,aAAU;EACV,oBAAkB;EACL;EACb,WAAW,GACT,sXACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,aAAoB,iBAArB;GACE,aAAU;GACV,WAAU;EACX,CAAA;CACsC,CAAA;AAE7C"}
|