@neynar/ui 0.1.1
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/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/components/ui/accordion.d.ts +229 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +247 -0
- package/dist/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/components/ui/alert.d.ts +187 -0
- package/dist/components/ui/alert.d.ts.map +1 -0
- package/dist/components/ui/aspect-ratio.d.ts +94 -0
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
- package/dist/components/ui/avatar.d.ts +244 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/badge.d.ts +163 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +281 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/components/ui/button.d.ts +129 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/calendar.d.ts +169 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/card.d.ts +365 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/carousel.d.ts +369 -0
- package/dist/components/ui/carousel.d.ts.map +1 -0
- package/dist/components/ui/chart.d.ts +442 -0
- package/dist/components/ui/chart.d.ts.map +1 -0
- package/dist/components/ui/checkbox.d.ts +88 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/collapsible.d.ts +182 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/combobox.d.ts +270 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/command.d.ts +355 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/container.d.ts +102 -0
- package/dist/components/ui/container.d.ts.map +1 -0
- package/dist/components/ui/context-menu.d.ts +339 -0
- package/dist/components/ui/context-menu.d.ts.map +1 -0
- package/dist/components/ui/date-picker.d.ts +145 -0
- package/dist/components/ui/date-picker.d.ts.map +1 -0
- package/dist/components/ui/dialog.d.ts +322 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/drawer.d.ts +154 -0
- package/dist/components/ui/drawer.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +349 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/empty-state.d.ts +133 -0
- package/dist/components/ui/empty-state.d.ts.map +1 -0
- package/dist/components/ui/hover-card.d.ts +109 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/input.d.ts +89 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/label.d.ts +93 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/menubar.d.ts +306 -0
- package/dist/components/ui/menubar.d.ts.map +1 -0
- package/dist/components/ui/navigation-menu.d.ts +318 -0
- package/dist/components/ui/navigation-menu.d.ts.map +1 -0
- package/dist/components/ui/pagination.d.ts +343 -0
- package/dist/components/ui/pagination.d.ts.map +1 -0
- package/dist/components/ui/popover.d.ts +178 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/progress.d.ts +64 -0
- package/dist/components/ui/progress.d.ts.map +1 -0
- package/dist/components/ui/radio-group.d.ts +144 -0
- package/dist/components/ui/radio-group.d.ts.map +1 -0
- package/dist/components/ui/resizable.d.ts +164 -0
- package/dist/components/ui/resizable.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +82 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/select.d.ts +316 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/separator.d.ts +80 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/sheet.d.ts +346 -0
- package/dist/components/ui/sheet.d.ts.map +1 -0
- package/dist/components/ui/sidebar.d.ts +1561 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/skeleton.d.ts +66 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/slider.d.ts +95 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/sonner.d.ts +101 -0
- package/dist/components/ui/sonner.d.ts.map +1 -0
- package/dist/components/ui/stack.d.ts +192 -0
- package/dist/components/ui/stack.d.ts.map +1 -0
- package/dist/components/ui/stories/accordion.stories.d.ts +71 -0
- package/dist/components/ui/stories/accordion.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/alert-dialog.stories.d.ts +39 -0
- package/dist/components/ui/stories/alert-dialog.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/alert.stories.d.ts +48 -0
- package/dist/components/ui/stories/alert.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts +53 -0
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/avatar.stories.d.ts +49 -0
- package/dist/components/ui/stories/avatar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/badge.stories.d.ts +64 -0
- package/dist/components/ui/stories/badge.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/breadcrumb.stories.d.ts +27 -0
- package/dist/components/ui/stories/breadcrumb.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/button.stories.d.ts +92 -0
- package/dist/components/ui/stories/button.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/calendar.stories.d.ts +94 -0
- package/dist/components/ui/stories/calendar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/card.stories.d.ts +29 -0
- package/dist/components/ui/stories/card.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/carousel.stories.d.ts +42 -0
- package/dist/components/ui/stories/carousel.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/chart.stories.d.ts +51 -0
- package/dist/components/ui/stories/chart.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/checkbox.stories.d.ts +72 -0
- package/dist/components/ui/stories/checkbox.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/cn.stories.d.ts +19 -0
- package/dist/components/ui/stories/cn.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/collapsible.stories.d.ts +51 -0
- package/dist/components/ui/stories/collapsible.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/colors.stories.d.ts +31 -0
- package/dist/components/ui/stories/colors.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/combobox.stories.d.ts +89 -0
- package/dist/components/ui/stories/combobox.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/command.stories.d.ts +69 -0
- package/dist/components/ui/stories/command.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/container.stories.d.ts +42 -0
- package/dist/components/ui/stories/container.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/context-menu.stories.d.ts +32 -0
- package/dist/components/ui/stories/context-menu.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/date-picker.stories.d.ts +67 -0
- package/dist/components/ui/stories/date-picker.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/dialog.stories.d.ts +48 -0
- package/dist/components/ui/stories/dialog.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/drawer.stories.d.ts +33 -0
- package/dist/components/ui/stories/drawer.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/dropdown-menu.stories.d.ts +31 -0
- package/dist/components/ui/stories/dropdown-menu.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/empty-state.stories.d.ts +74 -0
- package/dist/components/ui/stories/empty-state.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/hover-card.stories.d.ts +35 -0
- package/dist/components/ui/stories/hover-card.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/input.stories.d.ts +69 -0
- package/dist/components/ui/stories/input.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/label.stories.d.ts +47 -0
- package/dist/components/ui/stories/label.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/menubar.stories.d.ts +39 -0
- package/dist/components/ui/stories/menubar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/navigation-menu.stories.d.ts +44 -0
- package/dist/components/ui/stories/navigation-menu.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/pagination.stories.d.ts +33 -0
- package/dist/components/ui/stories/pagination.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/popover.stories.d.ts +36 -0
- package/dist/components/ui/stories/popover.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/progress.stories.d.ts +38 -0
- package/dist/components/ui/stories/progress.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/radio-group.stories.d.ts +76 -0
- package/dist/components/ui/stories/radio-group.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/resizable.stories.d.ts +49 -0
- package/dist/components/ui/stories/resizable.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/scroll-area.stories.d.ts +35 -0
- package/dist/components/ui/stories/scroll-area.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/select.stories.d.ts +51 -0
- package/dist/components/ui/stories/select.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/separator.stories.d.ts +58 -0
- package/dist/components/ui/stories/separator.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/sheet.stories.d.ts +43 -0
- package/dist/components/ui/stories/sheet.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/sidebar.stories.d.ts +60 -0
- package/dist/components/ui/stories/sidebar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/skeleton.stories.d.ts +42 -0
- package/dist/components/ui/stories/skeleton.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/slider.stories.d.ts +99 -0
- package/dist/components/ui/stories/slider.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/sonner.stories.d.ts +9 -0
- package/dist/components/ui/stories/sonner.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/stack.stories.d.ts +39 -0
- package/dist/components/ui/stories/stack.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/switch.stories.d.ts +71 -0
- package/dist/components/ui/stories/switch.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/table.stories.d.ts +40 -0
- package/dist/components/ui/stories/table.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/tabs.stories.d.ts +62 -0
- package/dist/components/ui/stories/tabs.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/text-field.stories.d.ts +78 -0
- package/dist/components/ui/stories/text-field.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/textarea.stories.d.ts +57 -0
- package/dist/components/ui/stories/textarea.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/theme-toggle.stories.d.ts +71 -0
- package/dist/components/ui/stories/theme-toggle.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/theme.stories.d.ts +51 -0
- package/dist/components/ui/stories/theme.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/toggle-group.stories.d.ts +71 -0
- package/dist/components/ui/stories/toggle-group.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/toggle.stories.d.ts +78 -0
- package/dist/components/ui/stories/toggle.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/tooltip.stories.d.ts +37 -0
- package/dist/components/ui/stories/tooltip.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/typography.stories.d.ts +137 -0
- package/dist/components/ui/stories/typography.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/use-mobile.stories.d.ts +20 -0
- package/dist/components/ui/stories/use-mobile.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/use-theme.stories.d.ts +23 -0
- package/dist/components/ui/stories/use-theme.stories.d.ts.map +1 -0
- package/dist/components/ui/switch.d.ts +84 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/table.d.ts +321 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/tabs.d.ts +260 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/text-field.d.ts +157 -0
- package/dist/components/ui/text-field.d.ts.map +1 -0
- package/dist/components/ui/textarea.d.ts +84 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/theme-toggle.d.ts +105 -0
- package/dist/components/ui/theme-toggle.d.ts.map +1 -0
- package/dist/components/ui/theme.d.ts +110 -0
- package/dist/components/ui/theme.d.ts.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +133 -0
- package/dist/components/ui/toggle-group.d.ts.map +1 -0
- package/dist/components/ui/toggle.d.ts +84 -0
- package/dist/components/ui/toggle.d.ts.map +1 -0
- package/dist/components/ui/tooltip.d.ts +202 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/typography.d.ts +287 -0
- package/dist/components/ui/typography.d.ts.map +1 -0
- package/dist/hooks/use-mobile.d.ts +74 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-theme.d.ts +142 -0
- package/dist/hooks/use-theme.d.ts.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27498 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/utils.d.ts +43 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/llm/colors.md +273 -0
- package/docs/llm/components/buttons.md +68 -0
- package/docs/llm/components/cards.md +53 -0
- package/docs/llm/components/display.md +134 -0
- package/docs/llm/components/feedback.md +96 -0
- package/docs/llm/components/forms.md +90 -0
- package/docs/llm/components/layout.md +59 -0
- package/docs/llm/components/menus.md +70 -0
- package/docs/llm/components/navigation.md +80 -0
- package/docs/llm/components/overlays.md +83 -0
- package/docs/llm/components/tables.md +73 -0
- package/docs/llm/components/typography.md +199 -0
- package/docs/llm/components/utilities.md +114 -0
- package/docs/llm/guide.md +165 -0
- package/llms.txt +122 -0
- package/package.json +104 -0
- package/src/components/ui/accordion.tsx +285 -0
- package/src/components/ui/alert-dialog.tsx +387 -0
- package/src/components/ui/alert.tsx +243 -0
- package/src/components/ui/aspect-ratio.tsx +99 -0
- package/src/components/ui/avatar.tsx +288 -0
- package/src/components/ui/badge.tsx +205 -0
- package/src/components/ui/breadcrumb.tsx +378 -0
- package/src/components/ui/button.tsx +195 -0
- package/src/components/ui/calendar.tsx +371 -0
- package/src/components/ui/card.tsx +447 -0
- package/src/components/ui/carousel.tsx +624 -0
- package/src/components/ui/chart.tsx +802 -0
- package/src/components/ui/checkbox.tsx +113 -0
- package/src/components/ui/collapsible.tsx +207 -0
- package/src/components/ui/combobox.tsx +373 -0
- package/src/components/ui/command.tsx +518 -0
- package/src/components/ui/container.tsx +114 -0
- package/src/components/ui/context-menu.tsx +563 -0
- package/src/components/ui/date-picker.tsx +213 -0
- package/src/components/ui/dialog.tsx +447 -0
- package/src/components/ui/drawer.tsx +273 -0
- package/src/components/ui/dropdown-menu.tsx +578 -0
- package/src/components/ui/empty-state.tsx +145 -0
- package/src/components/ui/hover-card.tsx +144 -0
- package/src/components/ui/input.tsx +106 -0
- package/src/components/ui/label.tsx +110 -0
- package/src/components/ui/menubar.tsx +553 -0
- package/src/components/ui/navigation-menu.tsx +471 -0
- package/src/components/ui/pagination.tsx +456 -0
- package/src/components/ui/popover.tsx +216 -0
- package/src/components/ui/progress.tsx +88 -0
- package/src/components/ui/radio-group.tsx +183 -0
- package/src/components/ui/resizable.tsx +209 -0
- package/src/components/ui/scroll-area.tsx +132 -0
- package/src/components/ui/select.tsx +485 -0
- package/src/components/ui/separator.tsx +101 -0
- package/src/components/ui/sheet.tsx +495 -0
- package/src/components/ui/sidebar.tsx +2211 -0
- package/src/components/ui/skeleton.tsx +76 -0
- package/src/components/ui/slider.tsx +147 -0
- package/src/components/ui/sonner.tsx +120 -0
- package/src/components/ui/stack.tsx +180 -0
- package/src/components/ui/stories/accordion.stories.tsx +429 -0
- package/src/components/ui/stories/alert-dialog.stories.tsx +519 -0
- package/src/components/ui/stories/alert.stories.tsx +228 -0
- package/src/components/ui/stories/aspect-ratio.stories.tsx +200 -0
- package/src/components/ui/stories/avatar.stories.tsx +317 -0
- package/src/components/ui/stories/badge.stories.tsx +260 -0
- package/src/components/ui/stories/breadcrumb.stories.tsx +482 -0
- package/src/components/ui/stories/button.stories.tsx +266 -0
- package/src/components/ui/stories/calendar.stories.tsx +375 -0
- package/src/components/ui/stories/card.stories.tsx +308 -0
- package/src/components/ui/stories/carousel.stories.tsx +328 -0
- package/src/components/ui/stories/chart.stories.tsx +430 -0
- package/src/components/ui/stories/checkbox.stories.tsx +297 -0
- package/src/components/ui/stories/cn.stories.tsx +433 -0
- package/src/components/ui/stories/collapsible.stories.tsx +256 -0
- package/src/components/ui/stories/colors.stories.tsx +502 -0
- package/src/components/ui/stories/combobox.stories.tsx +301 -0
- package/src/components/ui/stories/command.stories.tsx +632 -0
- package/src/components/ui/stories/container.stories.tsx +250 -0
- package/src/components/ui/stories/context-menu.stories.tsx +446 -0
- package/src/components/ui/stories/date-picker.stories.tsx +378 -0
- package/src/components/ui/stories/dialog.stories.tsx +535 -0
- package/src/components/ui/stories/drawer.stories.tsx +364 -0
- package/src/components/ui/stories/dropdown-menu.stories.tsx +374 -0
- package/src/components/ui/stories/empty-state.stories.tsx +244 -0
- package/src/components/ui/stories/hover-card.stories.tsx +355 -0
- package/src/components/ui/stories/input.stories.tsx +289 -0
- package/src/components/ui/stories/label.stories.tsx +294 -0
- package/src/components/ui/stories/menubar.stories.tsx +764 -0
- package/src/components/ui/stories/navigation-menu.stories.tsx +539 -0
- package/src/components/ui/stories/pagination.stories.tsx +604 -0
- package/src/components/ui/stories/popover.stories.tsx +392 -0
- package/src/components/ui/stories/progress.stories.tsx +218 -0
- package/src/components/ui/stories/radio-group.stories.tsx +400 -0
- package/src/components/ui/stories/resizable.stories.tsx +417 -0
- package/src/components/ui/stories/scroll-area.stories.tsx +180 -0
- package/src/components/ui/stories/select.stories.tsx +389 -0
- package/src/components/ui/stories/separator.stories.tsx +192 -0
- package/src/components/ui/stories/sheet.stories.tsx +468 -0
- package/src/components/ui/stories/sidebar.stories.tsx +731 -0
- package/src/components/ui/stories/skeleton.stories.tsx +216 -0
- package/src/components/ui/stories/slider.stories.tsx +321 -0
- package/src/components/ui/stories/sonner.stories.tsx +373 -0
- package/src/components/ui/stories/stack.stories.tsx +222 -0
- package/src/components/ui/stories/switch.stories.tsx +202 -0
- package/src/components/ui/stories/table.stories.tsx +541 -0
- package/src/components/ui/stories/tabs.stories.tsx +544 -0
- package/src/components/ui/stories/text-field.stories.tsx +280 -0
- package/src/components/ui/stories/textarea.stories.tsx +245 -0
- package/src/components/ui/stories/theme-toggle.stories.tsx +275 -0
- package/src/components/ui/stories/theme.stories.tsx +412 -0
- package/src/components/ui/stories/toggle-group.stories.tsx +337 -0
- package/src/components/ui/stories/toggle.stories.tsx +325 -0
- package/src/components/ui/stories/tooltip.stories.tsx +444 -0
- package/src/components/ui/stories/typography.stories.tsx +1586 -0
- package/src/components/ui/stories/use-mobile.stories.tsx +420 -0
- package/src/components/ui/stories/use-theme.stories.tsx +531 -0
- package/src/components/ui/switch.tsx +106 -0
- package/src/components/ui/table.tsx +424 -0
- package/src/components/ui/tabs.tsx +316 -0
- package/src/components/ui/text-field.tsx +206 -0
- package/src/components/ui/textarea.tsx +98 -0
- package/src/components/ui/theme-toggle.tsx +185 -0
- package/src/components/ui/theme.tsx +148 -0
- package/src/components/ui/toggle-group.tsx +196 -0
- package/src/components/ui/toggle.tsx +115 -0
- package/src/components/ui/tooltip.tsx +253 -0
- package/src/components/ui/typography.tsx +468 -0
- package/src/hooks/use-mobile.ts +91 -0
- package/src/hooks/use-theme.ts +319 -0
- package/src/index.ts +77 -0
- package/src/lib/utils.ts +57 -0
- package/src/styles/globals.css +160 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Button variant configuration using class-variance-authority
|
|
9
|
+
*
|
|
10
|
+
* Defines all possible visual variants and sizes for the Button component.
|
|
11
|
+
* Uses Tailwind CSS 4 with custom CSS properties for theming.
|
|
12
|
+
*
|
|
13
|
+
* @see {@link https://cva.style/docs} - CVA documentation
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
*/
|
|
16
|
+
const buttonVariants = cva(
|
|
17
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
18
|
+
{
|
|
19
|
+
variants: {
|
|
20
|
+
/**
|
|
21
|
+
* Visual style variants for the button
|
|
22
|
+
*
|
|
23
|
+
* @variant default - Primary action button with brand colors
|
|
24
|
+
* @variant destructive - Dangerous actions (delete, remove, etc.)
|
|
25
|
+
* @variant outline - Secondary action with border
|
|
26
|
+
* @variant secondary - Alternative secondary styling
|
|
27
|
+
* @variant ghost - Minimal styling, often used in toolbars
|
|
28
|
+
* @variant link - Text-only button that looks like a link
|
|
29
|
+
*/
|
|
30
|
+
variant: {
|
|
31
|
+
default:
|
|
32
|
+
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
33
|
+
destructive:
|
|
34
|
+
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
35
|
+
outline:
|
|
36
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
37
|
+
secondary:
|
|
38
|
+
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
39
|
+
ghost:
|
|
40
|
+
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
41
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
42
|
+
},
|
|
43
|
+
/**
|
|
44
|
+
* Size variants for the button
|
|
45
|
+
*
|
|
46
|
+
* @size default - Standard button height (36px)
|
|
47
|
+
* @size sm - Small button height (32px)
|
|
48
|
+
* @size lg - Large button height (40px)
|
|
49
|
+
* @size icon - Square button for icons only (36px × 36px)
|
|
50
|
+
*/
|
|
51
|
+
size: {
|
|
52
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
53
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
54
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
55
|
+
icon: "size-9",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
defaultVariants: {
|
|
59
|
+
variant: "default",
|
|
60
|
+
size: "default",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Button - A versatile button component with multiple style variants and sizes
|
|
67
|
+
*
|
|
68
|
+
* The Button component is a fundamental UI element used to trigger actions or navigate
|
|
69
|
+
* through the application. Built on Radix UI's Slot primitive, it supports multiple
|
|
70
|
+
* visual variants, sizes, and can be composed with other components using the asChild
|
|
71
|
+
* prop for maximum flexibility. Icons placed within the button are automatically
|
|
72
|
+
* styled with proper spacing and sizing.
|
|
73
|
+
*
|
|
74
|
+
* @component
|
|
75
|
+
* @example
|
|
76
|
+
* ```tsx
|
|
77
|
+
* // Basic usage
|
|
78
|
+
* <Button>Click me</Button>
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```tsx
|
|
83
|
+
* // With variants and sizes
|
|
84
|
+
* <Button variant="outline" size="lg">Large Outline Button</Button>
|
|
85
|
+
* <Button variant="destructive" size="sm">Delete</Button>
|
|
86
|
+
* <Button variant="ghost">Ghost Button</Button>
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```tsx
|
|
91
|
+
* // With icons (automatically styled)
|
|
92
|
+
* import { Download, ArrowRight, Plus } from "lucide-react";
|
|
93
|
+
*
|
|
94
|
+
* <Button>
|
|
95
|
+
* <Download /> Download File
|
|
96
|
+
* </Button>
|
|
97
|
+
*
|
|
98
|
+
* <Button>
|
|
99
|
+
* Continue <ArrowRight />
|
|
100
|
+
* </Button>
|
|
101
|
+
*
|
|
102
|
+
* // Icon-only button
|
|
103
|
+
* <Button size="icon" aria-label="Add item">
|
|
104
|
+
* <Plus />
|
|
105
|
+
* </Button>
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```tsx
|
|
110
|
+
* // As other elements using asChild (composition pattern)
|
|
111
|
+
* import Link from "next/link";
|
|
112
|
+
*
|
|
113
|
+
* <Button asChild>
|
|
114
|
+
* <Link href="/dashboard">Go to Dashboard</Link>
|
|
115
|
+
* </Button>
|
|
116
|
+
*
|
|
117
|
+
* <Button asChild variant="outline">
|
|
118
|
+
* <a href="https://example.com" target="_blank" rel="noopener">
|
|
119
|
+
* External Link
|
|
120
|
+
* </a>
|
|
121
|
+
* </Button>
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```tsx
|
|
126
|
+
* // Form integration and states
|
|
127
|
+
* <Button disabled>Loading...</Button>
|
|
128
|
+
* <Button type="submit">Submit Form</Button>
|
|
129
|
+
* <Button aria-invalid={hasError}>Validate</Button>
|
|
130
|
+
*
|
|
131
|
+
* // Loading state with spinner
|
|
132
|
+
* <Button disabled>
|
|
133
|
+
* <LoadingSpinner className="size-4" />
|
|
134
|
+
* Processing...
|
|
135
|
+
* </Button>
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @accessibility
|
|
139
|
+
* - Supports keyboard navigation (Enter/Space to activate)
|
|
140
|
+
* - Properly handles disabled state with pointer-events-none and opacity
|
|
141
|
+
* - Focus visible ring (3px ring-ring/50) for keyboard navigation
|
|
142
|
+
* - Supports aria-invalid for form validation states with destructive ring
|
|
143
|
+
* - Icons are automatically marked as non-interactive (pointer-events-none)
|
|
144
|
+
* - Screen reader friendly with proper semantic button element
|
|
145
|
+
* - When used with asChild, preserves accessibility of child element
|
|
146
|
+
* - Icon-only buttons should include aria-label for screen readers
|
|
147
|
+
*
|
|
148
|
+
* @see {@link buttonVariants} - For all available style variants and sizes
|
|
149
|
+
* @see {@link https://ui.shadcn.com/docs/components/button} - shadcn/ui button documentation
|
|
150
|
+
* @since 1.0.0
|
|
151
|
+
*/
|
|
152
|
+
/**
|
|
153
|
+
* Button component props type
|
|
154
|
+
*
|
|
155
|
+
* Extends all standard HTML button attributes with additional variant and composition props.
|
|
156
|
+
*/
|
|
157
|
+
type ButtonProps = React.ComponentProps<"button"> &
|
|
158
|
+
VariantProps<typeof buttonVariants> & {
|
|
159
|
+
/**
|
|
160
|
+
* If true, the button will render its child element instead of a button element.
|
|
161
|
+
* This enables composition patterns like turning links into buttons.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```tsx
|
|
165
|
+
* <Button asChild>
|
|
166
|
+
* <Link href="/dashboard">Dashboard</Link>
|
|
167
|
+
* </Button>
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @default false
|
|
171
|
+
*/
|
|
172
|
+
asChild?: boolean;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
function Button({
|
|
176
|
+
className,
|
|
177
|
+
variant,
|
|
178
|
+
size,
|
|
179
|
+
asChild = false,
|
|
180
|
+
...props
|
|
181
|
+
}: ButtonProps) {
|
|
182
|
+
const Comp = asChild ? Slot : "button";
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<Comp
|
|
186
|
+
data-slot="button"
|
|
187
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
188
|
+
{...props}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
Button.displayName = "Button";
|
|
194
|
+
|
|
195
|
+
export { Button, buttonVariants, type ButtonProps };
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import {
|
|
3
|
+
ChevronDownIcon,
|
|
4
|
+
ChevronLeftIcon,
|
|
5
|
+
ChevronRightIcon,
|
|
6
|
+
} from "lucide-react";
|
|
7
|
+
import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
8
|
+
|
|
9
|
+
import { cn } from "@/lib/utils";
|
|
10
|
+
import { Button, buttonVariants } from "@/components/ui/button";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Calendar - A comprehensive date selection calendar component
|
|
14
|
+
*
|
|
15
|
+
* A fully-featured calendar component built on react-day-picker that provides intuitive
|
|
16
|
+
* date selection with extensive customization options. Supports single dates, date ranges,
|
|
17
|
+
* multiple dates, and custom validation rules with built-in accessibility features.
|
|
18
|
+
*
|
|
19
|
+
* @component
|
|
20
|
+
*
|
|
21
|
+
* @example Basic single date selection
|
|
22
|
+
* ```tsx
|
|
23
|
+
* const [date, setDate] = useState<Date | undefined>()
|
|
24
|
+
*
|
|
25
|
+
* <Calendar
|
|
26
|
+
* mode="single"
|
|
27
|
+
* selected={date}
|
|
28
|
+
* onSelect={setDate}
|
|
29
|
+
* className="rounded-md border"
|
|
30
|
+
* />
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example Date range selection with two months
|
|
34
|
+
* ```tsx
|
|
35
|
+
* const [dateRange, setDateRange] = useState<DateRange | undefined>()
|
|
36
|
+
*
|
|
37
|
+
* <Calendar
|
|
38
|
+
* mode="range"
|
|
39
|
+
* selected={dateRange}
|
|
40
|
+
* onSelect={setDateRange}
|
|
41
|
+
* numberOfMonths={2}
|
|
42
|
+
* className="rounded-md border"
|
|
43
|
+
* />
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @example Multiple date selection
|
|
47
|
+
* ```tsx
|
|
48
|
+
* const [dates, setDates] = useState<Date[] | undefined>()
|
|
49
|
+
*
|
|
50
|
+
* <Calendar
|
|
51
|
+
* mode="multiple"
|
|
52
|
+
* selected={dates}
|
|
53
|
+
* onSelect={setDates}
|
|
54
|
+
* className="rounded-md border"
|
|
55
|
+
* />
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example Calendar with disabled dates and custom validation
|
|
59
|
+
* ```tsx
|
|
60
|
+
* <Calendar
|
|
61
|
+
* mode="single"
|
|
62
|
+
* selected={date}
|
|
63
|
+
* onSelect={setDate}
|
|
64
|
+
* disabled={[
|
|
65
|
+
* { before: new Date() }, // Disable past dates
|
|
66
|
+
* { dayOfWeek: [0, 6] }, // Disable weekends
|
|
67
|
+
* { from: new Date(2024, 0, 15), to: new Date(2024, 0, 20) } // Disable range
|
|
68
|
+
* ]}
|
|
69
|
+
* className="rounded-md border"
|
|
70
|
+
* />
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @example Calendar with month/year dropdowns
|
|
74
|
+
* ```tsx
|
|
75
|
+
* <Calendar
|
|
76
|
+
* mode="single"
|
|
77
|
+
* captionLayout="dropdown"
|
|
78
|
+
* selected={date}
|
|
79
|
+
* onSelect={setDate}
|
|
80
|
+
* fromYear={2020}
|
|
81
|
+
* toYear={2030}
|
|
82
|
+
* className="rounded-md border"
|
|
83
|
+
* />
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @features
|
|
87
|
+
* - **Selection modes**: Single date, date ranges, multiple dates
|
|
88
|
+
* - **Navigation**: Month/year navigation with keyboard support
|
|
89
|
+
* - **Validation**: Flexible date disabling and validation rules
|
|
90
|
+
* - **Customization**: Multiple caption layouts, button variants, styling
|
|
91
|
+
* - **Internationalization**: Built-in locale support via react-day-picker
|
|
92
|
+
* - **Accessibility**: Full WCAG compliance with keyboard navigation
|
|
93
|
+
*
|
|
94
|
+
* @accessibility
|
|
95
|
+
* - **Keyboard Navigation**: Arrow keys for date navigation, Page Up/Down for months
|
|
96
|
+
* - **Screen Reader Support**: Comprehensive ARIA labels and announcements
|
|
97
|
+
* - **Focus Management**: Proper focus handling and restoration
|
|
98
|
+
* - **Standards Compliance**: WCAG 2.1 AA compliant
|
|
99
|
+
* - **RTL Support**: Right-to-left language support
|
|
100
|
+
*
|
|
101
|
+
* @performance
|
|
102
|
+
* The component is optimized for performance with minimal re-renders and efficient
|
|
103
|
+
* DOM updates. Large date ranges and multiple months are handled efficiently.
|
|
104
|
+
*
|
|
105
|
+
* @styling
|
|
106
|
+
* Fully customizable with Tailwind CSS classes. Supports CSS custom properties
|
|
107
|
+
* for cell sizing (`--cell-size`) and integrates with the design system theme.
|
|
108
|
+
*
|
|
109
|
+
* @see {@link CalendarDayButton} Individual day button component
|
|
110
|
+
* @see [react-day-picker docs](https://react-day-picker.js.org/) for advanced configuration
|
|
111
|
+
* @see {@link https://ui.shadcn.com/docs/components/calendar} - shadcn/ui Calendar documentation
|
|
112
|
+
* @since 1.0.0
|
|
113
|
+
*/
|
|
114
|
+
function Calendar({
|
|
115
|
+
className,
|
|
116
|
+
classNames,
|
|
117
|
+
showOutsideDays = true,
|
|
118
|
+
captionLayout = "label",
|
|
119
|
+
buttonVariant = "ghost",
|
|
120
|
+
formatters,
|
|
121
|
+
components,
|
|
122
|
+
...props
|
|
123
|
+
}: React.ComponentProps<typeof DayPicker> & {
|
|
124
|
+
/**
|
|
125
|
+
* Button variant for navigation arrows and interactive elements
|
|
126
|
+
*
|
|
127
|
+
* Controls the visual style of the previous/next month navigation buttons.
|
|
128
|
+
* Choose from shadcn/ui button variants to match your design system.
|
|
129
|
+
*
|
|
130
|
+
* @default "ghost"
|
|
131
|
+
* @example
|
|
132
|
+
* ```tsx
|
|
133
|
+
* // Outline style navigation buttons
|
|
134
|
+
* <Calendar buttonVariant="outline" />
|
|
135
|
+
*
|
|
136
|
+
* // Secondary style for subtle navigation
|
|
137
|
+
* <Calendar buttonVariant="secondary" />
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
buttonVariant?: React.ComponentProps<typeof Button>["variant"];
|
|
141
|
+
}) {
|
|
142
|
+
const defaultClassNames = getDefaultClassNames();
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<DayPicker
|
|
146
|
+
showOutsideDays={showOutsideDays}
|
|
147
|
+
className={cn(
|
|
148
|
+
"bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
|
149
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
150
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
151
|
+
className,
|
|
152
|
+
)}
|
|
153
|
+
captionLayout={captionLayout}
|
|
154
|
+
formatters={{
|
|
155
|
+
formatMonthDropdown: (date) =>
|
|
156
|
+
date.toLocaleString("default", { month: "short" }),
|
|
157
|
+
...formatters,
|
|
158
|
+
}}
|
|
159
|
+
classNames={{
|
|
160
|
+
root: cn("w-fit", defaultClassNames.root),
|
|
161
|
+
months: cn(
|
|
162
|
+
"flex gap-4 flex-col md:flex-row relative",
|
|
163
|
+
defaultClassNames.months,
|
|
164
|
+
),
|
|
165
|
+
month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
|
|
166
|
+
nav: cn(
|
|
167
|
+
"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
|
|
168
|
+
defaultClassNames.nav,
|
|
169
|
+
),
|
|
170
|
+
button_previous: cn(
|
|
171
|
+
buttonVariants({ variant: buttonVariant }),
|
|
172
|
+
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
|
|
173
|
+
defaultClassNames.button_previous,
|
|
174
|
+
),
|
|
175
|
+
button_next: cn(
|
|
176
|
+
buttonVariants({ variant: buttonVariant }),
|
|
177
|
+
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
|
|
178
|
+
defaultClassNames.button_next,
|
|
179
|
+
),
|
|
180
|
+
month_caption: cn(
|
|
181
|
+
"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
|
|
182
|
+
defaultClassNames.month_caption,
|
|
183
|
+
),
|
|
184
|
+
dropdowns: cn(
|
|
185
|
+
"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
|
|
186
|
+
defaultClassNames.dropdowns,
|
|
187
|
+
),
|
|
188
|
+
dropdown_root: cn(
|
|
189
|
+
"relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
|
|
190
|
+
defaultClassNames.dropdown_root,
|
|
191
|
+
),
|
|
192
|
+
dropdown: cn(
|
|
193
|
+
"absolute bg-popover inset-0 opacity-0",
|
|
194
|
+
defaultClassNames.dropdown,
|
|
195
|
+
),
|
|
196
|
+
caption_label: cn(
|
|
197
|
+
"select-none font-medium",
|
|
198
|
+
captionLayout === "label"
|
|
199
|
+
? "text-sm"
|
|
200
|
+
: "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
|
|
201
|
+
defaultClassNames.caption_label,
|
|
202
|
+
),
|
|
203
|
+
table: "w-full border-collapse",
|
|
204
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
205
|
+
weekday: cn(
|
|
206
|
+
"text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
|
|
207
|
+
defaultClassNames.weekday,
|
|
208
|
+
),
|
|
209
|
+
week: cn("flex w-full mt-2", defaultClassNames.week),
|
|
210
|
+
week_number_header: cn(
|
|
211
|
+
"select-none w-(--cell-size)",
|
|
212
|
+
defaultClassNames.week_number_header,
|
|
213
|
+
),
|
|
214
|
+
week_number: cn(
|
|
215
|
+
"text-[0.8rem] select-none text-muted-foreground",
|
|
216
|
+
defaultClassNames.week_number,
|
|
217
|
+
),
|
|
218
|
+
day: cn(
|
|
219
|
+
"relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
|
|
220
|
+
defaultClassNames.day,
|
|
221
|
+
),
|
|
222
|
+
range_start: cn(
|
|
223
|
+
"rounded-l-md bg-accent",
|
|
224
|
+
defaultClassNames.range_start,
|
|
225
|
+
),
|
|
226
|
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
|
227
|
+
range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
|
|
228
|
+
today: cn(
|
|
229
|
+
"bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
|
|
230
|
+
defaultClassNames.today,
|
|
231
|
+
),
|
|
232
|
+
outside: cn(
|
|
233
|
+
"text-muted-foreground aria-selected:text-muted-foreground",
|
|
234
|
+
defaultClassNames.outside,
|
|
235
|
+
),
|
|
236
|
+
disabled: cn(
|
|
237
|
+
"text-muted-foreground opacity-50",
|
|
238
|
+
defaultClassNames.disabled,
|
|
239
|
+
),
|
|
240
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
241
|
+
...classNames,
|
|
242
|
+
}}
|
|
243
|
+
components={{
|
|
244
|
+
Root: ({ className, rootRef, ...props }: { className?: string; rootRef?: React.Ref<HTMLDivElement> } & React.ComponentProps<"div">) => {
|
|
245
|
+
return (
|
|
246
|
+
<div
|
|
247
|
+
data-slot="calendar"
|
|
248
|
+
ref={rootRef}
|
|
249
|
+
className={cn(className)}
|
|
250
|
+
{...props}
|
|
251
|
+
/>
|
|
252
|
+
);
|
|
253
|
+
},
|
|
254
|
+
Chevron: ({ className, orientation, ...props }: { className?: string; orientation?: "left" | "right" | "up" | "down" } & React.ComponentProps<"svg">) => {
|
|
255
|
+
if (orientation === "left") {
|
|
256
|
+
return (
|
|
257
|
+
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (orientation === "right") {
|
|
262
|
+
return (
|
|
263
|
+
<ChevronRightIcon
|
|
264
|
+
className={cn("size-4", className)}
|
|
265
|
+
{...props}
|
|
266
|
+
/>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
<ChevronDownIcon className={cn("size-4", className)} {...props} />
|
|
272
|
+
);
|
|
273
|
+
},
|
|
274
|
+
DayButton: CalendarDayButton,
|
|
275
|
+
WeekNumber: ({ children, ...props }) => {
|
|
276
|
+
return (
|
|
277
|
+
<td {...props}>
|
|
278
|
+
<div className="flex size-(--cell-size) items-center justify-center text-center">
|
|
279
|
+
{children}
|
|
280
|
+
</div>
|
|
281
|
+
</td>
|
|
282
|
+
);
|
|
283
|
+
},
|
|
284
|
+
...components,
|
|
285
|
+
}}
|
|
286
|
+
{...props}
|
|
287
|
+
/>
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* CalendarDayButton - Individual day button component for calendar dates
|
|
293
|
+
*
|
|
294
|
+
* Renders a single interactive day button with appropriate styling for different states
|
|
295
|
+
* including selected, today, disabled, and range selection indicators. This component
|
|
296
|
+
* is used internally by the Calendar component but can be customized if needed.
|
|
297
|
+
*
|
|
298
|
+
* @component
|
|
299
|
+
* @example
|
|
300
|
+
* ```tsx
|
|
301
|
+
* // Used internally by Calendar component
|
|
302
|
+
* <CalendarDayButton
|
|
303
|
+
* day={dayObject}
|
|
304
|
+
* modifiers={{
|
|
305
|
+
* selected: true,
|
|
306
|
+
* today: false,
|
|
307
|
+
* disabled: false,
|
|
308
|
+
* range_start: false,
|
|
309
|
+
* range_end: false,
|
|
310
|
+
* range_middle: false
|
|
311
|
+
* }}
|
|
312
|
+
* />
|
|
313
|
+
* ```
|
|
314
|
+
*
|
|
315
|
+
* @param day - The day object containing date information from react-day-picker
|
|
316
|
+
* @param modifiers - State modifiers object controlling appearance and behavior
|
|
317
|
+
* @param modifiers.selected - Whether this day is currently selected
|
|
318
|
+
* @param modifiers.today - Whether this day represents today's date
|
|
319
|
+
* @param modifiers.disabled - Whether this day is disabled for selection
|
|
320
|
+
* @param modifiers.range_start - Whether this day is the start of a date range
|
|
321
|
+
* @param modifiers.range_end - Whether this day is the end of a date range
|
|
322
|
+
* @param modifiers.range_middle - Whether this day is in the middle of a date range
|
|
323
|
+
* @param modifiers.focused - Whether this day currently has keyboard focus
|
|
324
|
+
*
|
|
325
|
+
* @accessibility
|
|
326
|
+
* - **Keyboard Navigation**: Fully keyboard accessible with arrow key support
|
|
327
|
+
* - **Screen Reader Support**: Announces date and selection state to assistive technology
|
|
328
|
+
* - **Focus Management**: Proper focus indicators and focus restoration
|
|
329
|
+
* - **State Announcement**: Clear visual and auditory feedback for selection states
|
|
330
|
+
*
|
|
331
|
+
* @since 1.0.0
|
|
332
|
+
*/
|
|
333
|
+
function CalendarDayButton({
|
|
334
|
+
className,
|
|
335
|
+
day,
|
|
336
|
+
modifiers,
|
|
337
|
+
...props
|
|
338
|
+
}: React.ComponentProps<typeof DayButton>) {
|
|
339
|
+
const defaultClassNames = getDefaultClassNames();
|
|
340
|
+
|
|
341
|
+
const ref = React.useRef<HTMLButtonElement>(null);
|
|
342
|
+
React.useEffect(() => {
|
|
343
|
+
if (modifiers.focused) ref.current?.focus();
|
|
344
|
+
}, [modifiers.focused]);
|
|
345
|
+
|
|
346
|
+
return (
|
|
347
|
+
<Button
|
|
348
|
+
ref={ref}
|
|
349
|
+
variant="ghost"
|
|
350
|
+
size="icon"
|
|
351
|
+
data-day={day.date.toLocaleDateString()}
|
|
352
|
+
data-selected-single={
|
|
353
|
+
modifiers.selected &&
|
|
354
|
+
!modifiers.range_start &&
|
|
355
|
+
!modifiers.range_end &&
|
|
356
|
+
!modifiers.range_middle
|
|
357
|
+
}
|
|
358
|
+
data-range-start={modifiers.range_start}
|
|
359
|
+
data-range-end={modifiers.range_end}
|
|
360
|
+
data-range-middle={modifiers.range_middle}
|
|
361
|
+
className={cn(
|
|
362
|
+
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70",
|
|
363
|
+
defaultClassNames.day,
|
|
364
|
+
className,
|
|
365
|
+
)}
|
|
366
|
+
{...props}
|
|
367
|
+
/>
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export { Calendar, CalendarDayButton };
|