From b3a7a2a8f5ec572e95e005b843764ffee2fa05aa Mon Sep 17 00:00:00 2001 From: Maofeng Date: Sat, 25 Jul 2026 06:03:12 +0800 Subject: [PATCH] feat: add Base UI Tailwind component library Add composable wrappers for 37 Base UI component families. Expose primitive and convenience APIs with shared styling utilities. Add the registry manifest, installer CLI, generation and export checks. Include a smoke example covering primitive and shadcn-style imports. --- cli/index.mjs | 308 +++ examples/smoke.tsx | 39 + manifest.json | 1777 +++++++++++++++++ scripts/check-ui-exports.mjs | 33 + scripts/generate-manifest.mjs | 166 ++ scripts/normalize-component-docs.mjs | 338 ++++ src/components/ui/accordion/header.tsx | 26 + src/components/ui/accordion/index.ts | 30 + src/components/ui/accordion/item.tsx | 23 + src/components/ui/accordion/panel.tsx | 26 + src/components/ui/accordion/root.tsx | 26 + src/components/ui/accordion/trigger.tsx | 26 + src/components/ui/alert-dialog/backdrop.tsx | 27 + src/components/ui/alert-dialog/close.tsx | 26 + src/components/ui/alert-dialog/content.tsx | 20 + .../ui/alert-dialog/description.tsx | 26 + src/components/ui/alert-dialog/index.ts | 52 + src/components/ui/alert-dialog/popup.tsx | 27 + src/components/ui/alert-dialog/portal.tsx | 29 + src/components/ui/alert-dialog/root.tsx | 23 + src/components/ui/alert-dialog/title.tsx | 26 + src/components/ui/alert-dialog/trigger.tsx | 26 + src/components/ui/alert-dialog/viewport.tsx | 26 + src/components/ui/autocomplete/arrow.tsx | 26 + src/components/ui/autocomplete/backdrop.tsx | 26 + src/components/ui/autocomplete/clear.tsx | 26 + src/components/ui/autocomplete/collection.tsx | 23 + src/components/ui/autocomplete/empty.tsx | 26 + .../ui/autocomplete/group-label.tsx | 26 + src/components/ui/autocomplete/group.tsx | 26 + src/components/ui/autocomplete/icon.tsx | 26 + src/components/ui/autocomplete/index.ts | 92 + .../ui/autocomplete/input-group.tsx | 26 + src/components/ui/autocomplete/input.tsx | 26 + src/components/ui/autocomplete/item.tsx | 26 + src/components/ui/autocomplete/list.tsx | 26 + src/components/ui/autocomplete/popup.tsx | 25 + src/components/ui/autocomplete/portal.tsx | 23 + src/components/ui/autocomplete/positioner.tsx | 26 + src/components/ui/autocomplete/root.tsx | 23 + src/components/ui/autocomplete/row.tsx | 26 + src/components/ui/autocomplete/trigger.tsx | 26 + src/components/ui/autocomplete/value.tsx | 26 + src/components/ui/avatar/fallback.tsx | 26 + src/components/ui/avatar/image.tsx | 26 + src/components/ui/avatar/index.ts | 22 + src/components/ui/avatar/root.tsx | 26 + src/components/ui/button/index.ts | 4 + src/components/ui/button/root.tsx | 26 + src/components/ui/checkbox-group/index.ts | 4 + src/components/ui/checkbox-group/root.tsx | 21 + src/components/ui/checkbox/index.ts | 18 + src/components/ui/checkbox/indicator.tsx | 26 + src/components/ui/checkbox/root.tsx | 26 + src/components/ui/collapsible/index.ts | 22 + src/components/ui/collapsible/panel.tsx | 26 + src/components/ui/collapsible/root.tsx | 26 + src/components/ui/collapsible/trigger.tsx | 26 + src/components/ui/combobox/arrow.tsx | 26 + src/components/ui/combobox/backdrop.tsx | 26 + src/components/ui/combobox/chip-remove.tsx | 23 + src/components/ui/combobox/chip.tsx | 23 + src/components/ui/combobox/chips.tsx | 23 + src/components/ui/combobox/clear.tsx | 26 + src/components/ui/combobox/collection.tsx | 23 + src/components/ui/combobox/empty.tsx | 26 + src/components/ui/combobox/group-label.tsx | 26 + src/components/ui/combobox/group.tsx | 26 + src/components/ui/combobox/icon.tsx | 26 + src/components/ui/combobox/index.ts | 112 ++ src/components/ui/combobox/input-group.tsx | 26 + src/components/ui/combobox/input.tsx | 26 + src/components/ui/combobox/item-indicator.tsx | 26 + src/components/ui/combobox/item.tsx | 26 + src/components/ui/combobox/label.tsx | 26 + src/components/ui/combobox/list.tsx | 26 + src/components/ui/combobox/popup.tsx | 25 + src/components/ui/combobox/portal.tsx | 23 + src/components/ui/combobox/positioner.tsx | 26 + src/components/ui/combobox/root.tsx | 23 + src/components/ui/combobox/row.tsx | 26 + src/components/ui/combobox/trigger.tsx | 26 + src/components/ui/combobox/value.tsx | 26 + src/components/ui/context-menu/arrow.tsx | 26 + src/components/ui/context-menu/backdrop.tsx | 26 + .../context-menu/checkbox-item-indicator.tsx | 26 + .../ui/context-menu/checkbox-item.tsx | 26 + .../ui/context-menu/group-label.tsx | 26 + src/components/ui/context-menu/group.tsx | 23 + src/components/ui/context-menu/index.ts | 85 + src/components/ui/context-menu/item.tsx | 26 + src/components/ui/context-menu/link-item.tsx | 26 + src/components/ui/context-menu/popup.tsx | 26 + src/components/ui/context-menu/portal.tsx | 23 + src/components/ui/context-menu/positioner.tsx | 26 + .../ui/context-menu/radio-group.tsx | 23 + .../ui/context-menu/radio-item-indicator.tsx | 26 + src/components/ui/context-menu/radio-item.tsx | 26 + src/components/ui/context-menu/root.tsx | 23 + .../ui/context-menu/submenu-root.tsx | 23 + .../ui/context-menu/submenu-trigger.tsx | 26 + src/components/ui/context-menu/trigger.tsx | 26 + src/components/ui/dialog/backdrop.tsx | 25 + src/components/ui/dialog/close.tsx | 26 + src/components/ui/dialog/content.tsx | 20 + src/components/ui/dialog/description.tsx | 26 + src/components/ui/dialog/index.ts | 52 + src/components/ui/dialog/popup.tsx | 25 + src/components/ui/dialog/portal.tsx | 29 + src/components/ui/dialog/root.tsx | 23 + src/components/ui/dialog/title.tsx | 26 + src/components/ui/dialog/trigger.tsx | 26 + src/components/ui/dialog/viewport.tsx | 25 + src/components/ui/drawer/backdrop.tsx | 25 + src/components/ui/drawer/close.tsx | 26 + src/components/ui/drawer/content.tsx | 26 + src/components/ui/drawer/description.tsx | 26 + .../ui/drawer/indent-background.tsx | 23 + src/components/ui/drawer/indent.tsx | 23 + src/components/ui/drawer/index.ts | 70 + src/components/ui/drawer/popup.tsx | 25 + src/components/ui/drawer/portal.tsx | 29 + src/components/ui/drawer/provider.tsx | 23 + src/components/ui/drawer/root.tsx | 23 + src/components/ui/drawer/swipe-area.tsx | 23 + src/components/ui/drawer/title.tsx | 26 + src/components/ui/drawer/trigger.tsx | 26 + src/components/ui/drawer/viewport.tsx | 25 + .../ui/drawer/virtual-keyboard-provider.tsx | 23 + src/components/ui/field/control.tsx | 26 + src/components/ui/field/description.tsx | 26 + src/components/ui/field/error.tsx | 26 + src/components/ui/field/index.ts | 38 + src/components/ui/field/item.tsx | 23 + src/components/ui/field/label.tsx | 26 + src/components/ui/field/root.tsx | 26 + src/components/ui/field/validity.tsx | 23 + src/components/ui/fieldset/index.ts | 18 + src/components/ui/fieldset/legend.tsx | 26 + src/components/ui/fieldset/root.tsx | 23 + src/components/ui/form/index.ts | 4 + src/components/ui/form/root.tsx | 21 + src/components/ui/input/index.ts | 4 + src/components/ui/input/root.tsx | 21 + src/components/ui/menu/arrow.tsx | 26 + src/components/ui/menu/backdrop.tsx | 26 + .../ui/menu/checkbox-item-indicator.tsx | 26 + src/components/ui/menu/checkbox-item.tsx | 26 + src/components/ui/menu/group-label.tsx | 26 + src/components/ui/menu/group.tsx | 23 + src/components/ui/menu/index.ts | 90 + src/components/ui/menu/item.tsx | 26 + src/components/ui/menu/link-item.tsx | 26 + src/components/ui/menu/popup.tsx | 25 + src/components/ui/menu/portal.tsx | 30 + src/components/ui/menu/positioner.tsx | 24 + src/components/ui/menu/radio-group.tsx | 23 + .../ui/menu/radio-item-indicator.tsx | 26 + src/components/ui/menu/radio-item.tsx | 26 + src/components/ui/menu/root.tsx | 23 + src/components/ui/menu/submenu-root.tsx | 23 + src/components/ui/menu/submenu-trigger.tsx | 26 + src/components/ui/menu/trigger.tsx | 26 + src/components/ui/menu/viewport.tsx | 26 + src/components/ui/menubar/index.ts | 4 + src/components/ui/menubar/root.tsx | 21 + src/components/ui/meter/index.ts | 30 + src/components/ui/meter/indicator.tsx | 26 + src/components/ui/meter/label.tsx | 26 + src/components/ui/meter/root.tsx | 26 + src/components/ui/meter/track.tsx | 26 + src/components/ui/meter/value.tsx | 26 + src/components/ui/navigation-menu/arrow.tsx | 26 + .../ui/navigation-menu/backdrop.tsx | 26 + src/components/ui/navigation-menu/content.tsx | 26 + src/components/ui/navigation-menu/icon.tsx | 26 + src/components/ui/navigation-menu/index.ts | 62 + src/components/ui/navigation-menu/item.tsx | 23 + src/components/ui/navigation-menu/link.tsx | 26 + src/components/ui/navigation-menu/list.tsx | 26 + src/components/ui/navigation-menu/popup.tsx | 25 + src/components/ui/navigation-menu/portal.tsx | 29 + .../ui/navigation-menu/positioner.tsx | 25 + src/components/ui/navigation-menu/root.tsx | 23 + src/components/ui/navigation-menu/trigger.tsx | 26 + .../ui/navigation-menu/viewport.tsx | 26 + src/components/ui/number-field/decrement.tsx | 26 + src/components/ui/number-field/group.tsx | 26 + src/components/ui/number-field/increment.tsx | 26 + src/components/ui/number-field/index.ts | 38 + src/components/ui/number-field/input.tsx | 26 + src/components/ui/number-field/root.tsx | 23 + .../ui/number-field/scrub-area-cursor.tsx | 23 + src/components/ui/number-field/scrub-area.tsx | 23 + src/components/ui/otp-field/index.ts | 21 + src/components/ui/otp-field/input.tsx | 26 + src/components/ui/otp-field/root.tsx | 23 + src/components/ui/popover/arrow.tsx | 26 + src/components/ui/popover/backdrop.tsx | 26 + src/components/ui/popover/close.tsx | 26 + src/components/ui/popover/content.tsx | 23 + src/components/ui/popover/description.tsx | 26 + src/components/ui/popover/index.ts | 60 + src/components/ui/popover/popup.tsx | 26 + src/components/ui/popover/portal.tsx | 23 + src/components/ui/popover/positioner.tsx | 26 + src/components/ui/popover/root.tsx | 23 + src/components/ui/popover/title.tsx | 26 + src/components/ui/popover/trigger.tsx | 26 + src/components/ui/popover/viewport.tsx | 26 + src/components/ui/preview-card/arrow.tsx | 26 + src/components/ui/preview-card/backdrop.tsx | 26 + src/components/ui/preview-card/content.tsx | 23 + src/components/ui/preview-card/index.ts | 48 + src/components/ui/preview-card/popup.tsx | 26 + src/components/ui/preview-card/portal.tsx | 23 + src/components/ui/preview-card/positioner.tsx | 26 + src/components/ui/preview-card/root.tsx | 23 + src/components/ui/preview-card/trigger.tsx | 26 + src/components/ui/preview-card/viewport.tsx | 26 + src/components/ui/progress/index.ts | 30 + src/components/ui/progress/indicator.tsx | 26 + src/components/ui/progress/label.tsx | 26 + src/components/ui/progress/root.tsx | 26 + src/components/ui/progress/track.tsx | 26 + src/components/ui/progress/value.tsx | 26 + src/components/ui/radio/index.ts | 18 + src/components/ui/radio/indicator.tsx | 26 + src/components/ui/radio/root.tsx | 26 + src/components/ui/scroll-area/content.tsx | 25 + src/components/ui/scroll-area/corner.tsx | 24 + src/components/ui/scroll-area/index.ts | 34 + src/components/ui/scroll-area/root.tsx | 25 + src/components/ui/scroll-area/scrollbar.tsx | 28 + src/components/ui/scroll-area/thumb.tsx | 26 + src/components/ui/scroll-area/viewport.tsx | 25 + src/components/ui/select/arrow.tsx | 26 + src/components/ui/select/backdrop.tsx | 26 + src/components/ui/select/group-label.tsx | 26 + src/components/ui/select/group.tsx | 26 + src/components/ui/select/icon.tsx | 26 + src/components/ui/select/index.ts | 88 + src/components/ui/select/item-indicator.tsx | 26 + src/components/ui/select/item-text.tsx | 26 + src/components/ui/select/item.tsx | 25 + src/components/ui/select/label.tsx | 26 + src/components/ui/select/list.tsx | 26 + src/components/ui/select/popup.tsx | 25 + src/components/ui/select/portal.tsx | 29 + src/components/ui/select/positioner.tsx | 26 + src/components/ui/select/root.tsx | 23 + .../ui/select/scroll-down-arrow.tsx | 26 + src/components/ui/select/scroll-up-arrow.tsx | 26 + src/components/ui/select/separator.tsx | 24 + src/components/ui/select/trigger.tsx | 25 + src/components/ui/select/value.tsx | 26 + src/components/ui/separator/index.ts | 4 + src/components/ui/separator/root.tsx | 21 + src/components/ui/slider/control.tsx | 26 + src/components/ui/slider/index.ts | 38 + src/components/ui/slider/indicator.tsx | 26 + src/components/ui/slider/label.tsx | 26 + src/components/ui/slider/root.tsx | 26 + src/components/ui/slider/thumb.tsx | 26 + src/components/ui/slider/track.tsx | 26 + src/components/ui/slider/value.tsx | 26 + src/components/ui/switch/index.ts | 18 + src/components/ui/switch/root.tsx | 25 + src/components/ui/switch/thumb.tsx | 25 + src/components/ui/tabs/index.ts | 30 + src/components/ui/tabs/indicator.tsx | 26 + src/components/ui/tabs/list.tsx | 26 + src/components/ui/tabs/panel.tsx | 26 + src/components/ui/tabs/root.tsx | 26 + src/components/ui/tabs/tab.tsx | 26 + src/components/ui/toast/action.tsx | 26 + src/components/ui/toast/arrow.tsx | 26 + src/components/ui/toast/close.tsx | 26 + src/components/ui/toast/content.tsx | 26 + src/components/ui/toast/description.tsx | 26 + src/components/ui/toast/index.ts | 62 + src/components/ui/toast/portal.tsx | 29 + src/components/ui/toast/positioner.tsx | 26 + src/components/ui/toast/provider.tsx | 23 + src/components/ui/toast/root.tsx | 25 + src/components/ui/toast/title.tsx | 26 + src/components/ui/toast/viewport.tsx | 26 + src/components/ui/toggle-group/index.ts | 4 + src/components/ui/toggle-group/root.tsx | 22 + src/components/ui/toggle/index.ts | 4 + src/components/ui/toggle/root.tsx | 25 + src/components/ui/toolbar/button.tsx | 25 + src/components/ui/toolbar/group.tsx | 24 + src/components/ui/toolbar/index.ts | 34 + src/components/ui/toolbar/input.tsx | 26 + src/components/ui/toolbar/link.tsx | 25 + src/components/ui/toolbar/root.tsx | 25 + src/components/ui/toolbar/separator.tsx | 26 + src/components/ui/tooltip/arrow.tsx | 26 + src/components/ui/tooltip/content.tsx | 21 + src/components/ui/tooltip/index.ts | 48 + src/components/ui/tooltip/popup.tsx | 26 + src/components/ui/tooltip/portal.tsx | 23 + src/components/ui/tooltip/positioner.tsx | 26 + src/components/ui/tooltip/provider.tsx | 23 + src/components/ui/tooltip/root.tsx | 23 + src/components/ui/tooltip/trigger.tsx | 26 + src/components/ui/tooltip/viewport.tsx | 26 + src/lib/portal-container.tsx | 25 + src/lib/utils.ts | 6 + src/styles/globals.css | 98 + 311 files changed, 10879 insertions(+) create mode 100755 cli/index.mjs create mode 100644 examples/smoke.tsx create mode 100644 manifest.json create mode 100644 scripts/check-ui-exports.mjs create mode 100644 scripts/generate-manifest.mjs create mode 100644 scripts/normalize-component-docs.mjs create mode 100644 src/components/ui/accordion/header.tsx create mode 100644 src/components/ui/accordion/index.ts create mode 100644 src/components/ui/accordion/item.tsx create mode 100644 src/components/ui/accordion/panel.tsx create mode 100644 src/components/ui/accordion/root.tsx create mode 100644 src/components/ui/accordion/trigger.tsx create mode 100644 src/components/ui/alert-dialog/backdrop.tsx create mode 100644 src/components/ui/alert-dialog/close.tsx create mode 100644 src/components/ui/alert-dialog/content.tsx create mode 100644 src/components/ui/alert-dialog/description.tsx create mode 100644 src/components/ui/alert-dialog/index.ts create mode 100644 src/components/ui/alert-dialog/popup.tsx create mode 100644 src/components/ui/alert-dialog/portal.tsx create mode 100644 src/components/ui/alert-dialog/root.tsx create mode 100644 src/components/ui/alert-dialog/title.tsx create mode 100644 src/components/ui/alert-dialog/trigger.tsx create mode 100644 src/components/ui/alert-dialog/viewport.tsx create mode 100644 src/components/ui/autocomplete/arrow.tsx create mode 100644 src/components/ui/autocomplete/backdrop.tsx create mode 100644 src/components/ui/autocomplete/clear.tsx create mode 100644 src/components/ui/autocomplete/collection.tsx create mode 100644 src/components/ui/autocomplete/empty.tsx create mode 100644 src/components/ui/autocomplete/group-label.tsx create mode 100644 src/components/ui/autocomplete/group.tsx create mode 100644 src/components/ui/autocomplete/icon.tsx create mode 100644 src/components/ui/autocomplete/index.ts create mode 100644 src/components/ui/autocomplete/input-group.tsx create mode 100644 src/components/ui/autocomplete/input.tsx create mode 100644 src/components/ui/autocomplete/item.tsx create mode 100644 src/components/ui/autocomplete/list.tsx create mode 100644 src/components/ui/autocomplete/popup.tsx create mode 100644 src/components/ui/autocomplete/portal.tsx create mode 100644 src/components/ui/autocomplete/positioner.tsx create mode 100644 src/components/ui/autocomplete/root.tsx create mode 100644 src/components/ui/autocomplete/row.tsx create mode 100644 src/components/ui/autocomplete/trigger.tsx create mode 100644 src/components/ui/autocomplete/value.tsx create mode 100644 src/components/ui/avatar/fallback.tsx create mode 100644 src/components/ui/avatar/image.tsx create mode 100644 src/components/ui/avatar/index.ts create mode 100644 src/components/ui/avatar/root.tsx create mode 100644 src/components/ui/button/index.ts create mode 100644 src/components/ui/button/root.tsx create mode 100644 src/components/ui/checkbox-group/index.ts create mode 100644 src/components/ui/checkbox-group/root.tsx create mode 100644 src/components/ui/checkbox/index.ts create mode 100644 src/components/ui/checkbox/indicator.tsx create mode 100644 src/components/ui/checkbox/root.tsx create mode 100644 src/components/ui/collapsible/index.ts create mode 100644 src/components/ui/collapsible/panel.tsx create mode 100644 src/components/ui/collapsible/root.tsx create mode 100644 src/components/ui/collapsible/trigger.tsx create mode 100644 src/components/ui/combobox/arrow.tsx create mode 100644 src/components/ui/combobox/backdrop.tsx create mode 100644 src/components/ui/combobox/chip-remove.tsx create mode 100644 src/components/ui/combobox/chip.tsx create mode 100644 src/components/ui/combobox/chips.tsx create mode 100644 src/components/ui/combobox/clear.tsx create mode 100644 src/components/ui/combobox/collection.tsx create mode 100644 src/components/ui/combobox/empty.tsx create mode 100644 src/components/ui/combobox/group-label.tsx create mode 100644 src/components/ui/combobox/group.tsx create mode 100644 src/components/ui/combobox/icon.tsx create mode 100644 src/components/ui/combobox/index.ts create mode 100644 src/components/ui/combobox/input-group.tsx create mode 100644 src/components/ui/combobox/input.tsx create mode 100644 src/components/ui/combobox/item-indicator.tsx create mode 100644 src/components/ui/combobox/item.tsx create mode 100644 src/components/ui/combobox/label.tsx create mode 100644 src/components/ui/combobox/list.tsx create mode 100644 src/components/ui/combobox/popup.tsx create mode 100644 src/components/ui/combobox/portal.tsx create mode 100644 src/components/ui/combobox/positioner.tsx create mode 100644 src/components/ui/combobox/root.tsx create mode 100644 src/components/ui/combobox/row.tsx create mode 100644 src/components/ui/combobox/trigger.tsx create mode 100644 src/components/ui/combobox/value.tsx create mode 100644 src/components/ui/context-menu/arrow.tsx create mode 100644 src/components/ui/context-menu/backdrop.tsx create mode 100644 src/components/ui/context-menu/checkbox-item-indicator.tsx create mode 100644 src/components/ui/context-menu/checkbox-item.tsx create mode 100644 src/components/ui/context-menu/group-label.tsx create mode 100644 src/components/ui/context-menu/group.tsx create mode 100644 src/components/ui/context-menu/index.ts create mode 100644 src/components/ui/context-menu/item.tsx create mode 100644 src/components/ui/context-menu/link-item.tsx create mode 100644 src/components/ui/context-menu/popup.tsx create mode 100644 src/components/ui/context-menu/portal.tsx create mode 100644 src/components/ui/context-menu/positioner.tsx create mode 100644 src/components/ui/context-menu/radio-group.tsx create mode 100644 src/components/ui/context-menu/radio-item-indicator.tsx create mode 100644 src/components/ui/context-menu/radio-item.tsx create mode 100644 src/components/ui/context-menu/root.tsx create mode 100644 src/components/ui/context-menu/submenu-root.tsx create mode 100644 src/components/ui/context-menu/submenu-trigger.tsx create mode 100644 src/components/ui/context-menu/trigger.tsx create mode 100644 src/components/ui/dialog/backdrop.tsx create mode 100644 src/components/ui/dialog/close.tsx create mode 100644 src/components/ui/dialog/content.tsx create mode 100644 src/components/ui/dialog/description.tsx create mode 100644 src/components/ui/dialog/index.ts create mode 100644 src/components/ui/dialog/popup.tsx create mode 100644 src/components/ui/dialog/portal.tsx create mode 100644 src/components/ui/dialog/root.tsx create mode 100644 src/components/ui/dialog/title.tsx create mode 100644 src/components/ui/dialog/trigger.tsx create mode 100644 src/components/ui/dialog/viewport.tsx create mode 100644 src/components/ui/drawer/backdrop.tsx create mode 100644 src/components/ui/drawer/close.tsx create mode 100644 src/components/ui/drawer/content.tsx create mode 100644 src/components/ui/drawer/description.tsx create mode 100644 src/components/ui/drawer/indent-background.tsx create mode 100644 src/components/ui/drawer/indent.tsx create mode 100644 src/components/ui/drawer/index.ts create mode 100644 src/components/ui/drawer/popup.tsx create mode 100644 src/components/ui/drawer/portal.tsx create mode 100644 src/components/ui/drawer/provider.tsx create mode 100644 src/components/ui/drawer/root.tsx create mode 100644 src/components/ui/drawer/swipe-area.tsx create mode 100644 src/components/ui/drawer/title.tsx create mode 100644 src/components/ui/drawer/trigger.tsx create mode 100644 src/components/ui/drawer/viewport.tsx create mode 100644 src/components/ui/drawer/virtual-keyboard-provider.tsx create mode 100644 src/components/ui/field/control.tsx create mode 100644 src/components/ui/field/description.tsx create mode 100644 src/components/ui/field/error.tsx create mode 100644 src/components/ui/field/index.ts create mode 100644 src/components/ui/field/item.tsx create mode 100644 src/components/ui/field/label.tsx create mode 100644 src/components/ui/field/root.tsx create mode 100644 src/components/ui/field/validity.tsx create mode 100644 src/components/ui/fieldset/index.ts create mode 100644 src/components/ui/fieldset/legend.tsx create mode 100644 src/components/ui/fieldset/root.tsx create mode 100644 src/components/ui/form/index.ts create mode 100644 src/components/ui/form/root.tsx create mode 100644 src/components/ui/input/index.ts create mode 100644 src/components/ui/input/root.tsx create mode 100644 src/components/ui/menu/arrow.tsx create mode 100644 src/components/ui/menu/backdrop.tsx create mode 100644 src/components/ui/menu/checkbox-item-indicator.tsx create mode 100644 src/components/ui/menu/checkbox-item.tsx create mode 100644 src/components/ui/menu/group-label.tsx create mode 100644 src/components/ui/menu/group.tsx create mode 100644 src/components/ui/menu/index.ts create mode 100644 src/components/ui/menu/item.tsx create mode 100644 src/components/ui/menu/link-item.tsx create mode 100644 src/components/ui/menu/popup.tsx create mode 100644 src/components/ui/menu/portal.tsx create mode 100644 src/components/ui/menu/positioner.tsx create mode 100644 src/components/ui/menu/radio-group.tsx create mode 100644 src/components/ui/menu/radio-item-indicator.tsx create mode 100644 src/components/ui/menu/radio-item.tsx create mode 100644 src/components/ui/menu/root.tsx create mode 100644 src/components/ui/menu/submenu-root.tsx create mode 100644 src/components/ui/menu/submenu-trigger.tsx create mode 100644 src/components/ui/menu/trigger.tsx create mode 100644 src/components/ui/menu/viewport.tsx create mode 100644 src/components/ui/menubar/index.ts create mode 100644 src/components/ui/menubar/root.tsx create mode 100644 src/components/ui/meter/index.ts create mode 100644 src/components/ui/meter/indicator.tsx create mode 100644 src/components/ui/meter/label.tsx create mode 100644 src/components/ui/meter/root.tsx create mode 100644 src/components/ui/meter/track.tsx create mode 100644 src/components/ui/meter/value.tsx create mode 100644 src/components/ui/navigation-menu/arrow.tsx create mode 100644 src/components/ui/navigation-menu/backdrop.tsx create mode 100644 src/components/ui/navigation-menu/content.tsx create mode 100644 src/components/ui/navigation-menu/icon.tsx create mode 100644 src/components/ui/navigation-menu/index.ts create mode 100644 src/components/ui/navigation-menu/item.tsx create mode 100644 src/components/ui/navigation-menu/link.tsx create mode 100644 src/components/ui/navigation-menu/list.tsx create mode 100644 src/components/ui/navigation-menu/popup.tsx create mode 100644 src/components/ui/navigation-menu/portal.tsx create mode 100644 src/components/ui/navigation-menu/positioner.tsx create mode 100644 src/components/ui/navigation-menu/root.tsx create mode 100644 src/components/ui/navigation-menu/trigger.tsx create mode 100644 src/components/ui/navigation-menu/viewport.tsx create mode 100644 src/components/ui/number-field/decrement.tsx create mode 100644 src/components/ui/number-field/group.tsx create mode 100644 src/components/ui/number-field/increment.tsx create mode 100644 src/components/ui/number-field/index.ts create mode 100644 src/components/ui/number-field/input.tsx create mode 100644 src/components/ui/number-field/root.tsx create mode 100644 src/components/ui/number-field/scrub-area-cursor.tsx create mode 100644 src/components/ui/number-field/scrub-area.tsx create mode 100644 src/components/ui/otp-field/index.ts create mode 100644 src/components/ui/otp-field/input.tsx create mode 100644 src/components/ui/otp-field/root.tsx create mode 100644 src/components/ui/popover/arrow.tsx create mode 100644 src/components/ui/popover/backdrop.tsx create mode 100644 src/components/ui/popover/close.tsx create mode 100644 src/components/ui/popover/content.tsx create mode 100644 src/components/ui/popover/description.tsx create mode 100644 src/components/ui/popover/index.ts create mode 100644 src/components/ui/popover/popup.tsx create mode 100644 src/components/ui/popover/portal.tsx create mode 100644 src/components/ui/popover/positioner.tsx create mode 100644 src/components/ui/popover/root.tsx create mode 100644 src/components/ui/popover/title.tsx create mode 100644 src/components/ui/popover/trigger.tsx create mode 100644 src/components/ui/popover/viewport.tsx create mode 100644 src/components/ui/preview-card/arrow.tsx create mode 100644 src/components/ui/preview-card/backdrop.tsx create mode 100644 src/components/ui/preview-card/content.tsx create mode 100644 src/components/ui/preview-card/index.ts create mode 100644 src/components/ui/preview-card/popup.tsx create mode 100644 src/components/ui/preview-card/portal.tsx create mode 100644 src/components/ui/preview-card/positioner.tsx create mode 100644 src/components/ui/preview-card/root.tsx create mode 100644 src/components/ui/preview-card/trigger.tsx create mode 100644 src/components/ui/preview-card/viewport.tsx create mode 100644 src/components/ui/progress/index.ts create mode 100644 src/components/ui/progress/indicator.tsx create mode 100644 src/components/ui/progress/label.tsx create mode 100644 src/components/ui/progress/root.tsx create mode 100644 src/components/ui/progress/track.tsx create mode 100644 src/components/ui/progress/value.tsx create mode 100644 src/components/ui/radio/index.ts create mode 100644 src/components/ui/radio/indicator.tsx create mode 100644 src/components/ui/radio/root.tsx create mode 100644 src/components/ui/scroll-area/content.tsx create mode 100644 src/components/ui/scroll-area/corner.tsx create mode 100644 src/components/ui/scroll-area/index.ts create mode 100644 src/components/ui/scroll-area/root.tsx create mode 100644 src/components/ui/scroll-area/scrollbar.tsx create mode 100644 src/components/ui/scroll-area/thumb.tsx create mode 100644 src/components/ui/scroll-area/viewport.tsx create mode 100644 src/components/ui/select/arrow.tsx create mode 100644 src/components/ui/select/backdrop.tsx create mode 100644 src/components/ui/select/group-label.tsx create mode 100644 src/components/ui/select/group.tsx create mode 100644 src/components/ui/select/icon.tsx create mode 100644 src/components/ui/select/index.ts create mode 100644 src/components/ui/select/item-indicator.tsx create mode 100644 src/components/ui/select/item-text.tsx create mode 100644 src/components/ui/select/item.tsx create mode 100644 src/components/ui/select/label.tsx create mode 100644 src/components/ui/select/list.tsx create mode 100644 src/components/ui/select/popup.tsx create mode 100644 src/components/ui/select/portal.tsx create mode 100644 src/components/ui/select/positioner.tsx create mode 100644 src/components/ui/select/root.tsx create mode 100644 src/components/ui/select/scroll-down-arrow.tsx create mode 100644 src/components/ui/select/scroll-up-arrow.tsx create mode 100644 src/components/ui/select/separator.tsx create mode 100644 src/components/ui/select/trigger.tsx create mode 100644 src/components/ui/select/value.tsx create mode 100644 src/components/ui/separator/index.ts create mode 100644 src/components/ui/separator/root.tsx create mode 100644 src/components/ui/slider/control.tsx create mode 100644 src/components/ui/slider/index.ts create mode 100644 src/components/ui/slider/indicator.tsx create mode 100644 src/components/ui/slider/label.tsx create mode 100644 src/components/ui/slider/root.tsx create mode 100644 src/components/ui/slider/thumb.tsx create mode 100644 src/components/ui/slider/track.tsx create mode 100644 src/components/ui/slider/value.tsx create mode 100644 src/components/ui/switch/index.ts create mode 100644 src/components/ui/switch/root.tsx create mode 100644 src/components/ui/switch/thumb.tsx create mode 100644 src/components/ui/tabs/index.ts create mode 100644 src/components/ui/tabs/indicator.tsx create mode 100644 src/components/ui/tabs/list.tsx create mode 100644 src/components/ui/tabs/panel.tsx create mode 100644 src/components/ui/tabs/root.tsx create mode 100644 src/components/ui/tabs/tab.tsx create mode 100644 src/components/ui/toast/action.tsx create mode 100644 src/components/ui/toast/arrow.tsx create mode 100644 src/components/ui/toast/close.tsx create mode 100644 src/components/ui/toast/content.tsx create mode 100644 src/components/ui/toast/description.tsx create mode 100644 src/components/ui/toast/index.ts create mode 100644 src/components/ui/toast/portal.tsx create mode 100644 src/components/ui/toast/positioner.tsx create mode 100644 src/components/ui/toast/provider.tsx create mode 100644 src/components/ui/toast/root.tsx create mode 100644 src/components/ui/toast/title.tsx create mode 100644 src/components/ui/toast/viewport.tsx create mode 100644 src/components/ui/toggle-group/index.ts create mode 100644 src/components/ui/toggle-group/root.tsx create mode 100644 src/components/ui/toggle/index.ts create mode 100644 src/components/ui/toggle/root.tsx create mode 100644 src/components/ui/toolbar/button.tsx create mode 100644 src/components/ui/toolbar/group.tsx create mode 100644 src/components/ui/toolbar/index.ts create mode 100644 src/components/ui/toolbar/input.tsx create mode 100644 src/components/ui/toolbar/link.tsx create mode 100644 src/components/ui/toolbar/root.tsx create mode 100644 src/components/ui/toolbar/separator.tsx create mode 100644 src/components/ui/tooltip/arrow.tsx create mode 100644 src/components/ui/tooltip/content.tsx create mode 100644 src/components/ui/tooltip/index.ts create mode 100644 src/components/ui/tooltip/popup.tsx create mode 100644 src/components/ui/tooltip/portal.tsx create mode 100644 src/components/ui/tooltip/positioner.tsx create mode 100644 src/components/ui/tooltip/provider.tsx create mode 100644 src/components/ui/tooltip/root.tsx create mode 100644 src/components/ui/tooltip/trigger.tsx create mode 100644 src/components/ui/tooltip/viewport.tsx create mode 100644 src/lib/portal-container.tsx create mode 100644 src/lib/utils.ts create mode 100644 src/styles/globals.css diff --git a/cli/index.mjs b/cli/index.mjs new file mode 100755 index 0000000..1d4938b --- /dev/null +++ b/cli/index.mjs @@ -0,0 +1,308 @@ +#!/usr/bin/env node +import { accessSync } from "node:fs" +import { access, copyFile, mkdir, readFile, writeFile } from "node:fs/promises" +import path from "node:path" +import process from "node:process" +import { fileURLToPath } from "node:url" + +const command = process.argv[2] +const args = process.argv.slice(3) +const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..") +const bundledManifestPath = path.join(packageRoot, "manifest.json") +const configFileName = "base-ui-tailwind.json" + +main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)) + process.exit(1) +}) + +async function main() { + if (!command || command === "-h" || command === "--help") { + printHelp() + return + } + + if (command === "init") { + await initProject(parseOptions(args)) + return + } + + if (command === "add") { + await addItems(parseOptions(args)) + return + } + + throw new Error(`Unknown command: ${command}`) +} + +async function initProject(options) { + const cwd = path.resolve(options.cwd ?? process.cwd()) + const configPath = path.join(cwd, configFileName) + const localManifestPath = path.join(cwd, "manifest.json") + const config = { + manifest: options.manifest ?? ((await exists(localManifestPath)) ? "manifest.json" : bundledManifestPath), + aliases: { + ui: "components/ui", + lib: "lib", + }, + } + + if (!options.force && (await exists(configPath))) { + console.log(`${configFileName} already exists. Use --force to overwrite it.`) + return + } + + await mkdir(path.join(cwd, config.aliases.ui), { recursive: true }) + await mkdir(path.join(cwd, config.aliases.lib), { recursive: true }) + await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`) + console.log(`Created ${path.relative(process.cwd(), configPath) || configFileName}.`) +} + +async function addItems(options) { + const names = options._.filter((item) => !item.startsWith("-")) + if (names.length === 0) { + throw new Error("Usage: base-ui-tailwind add ") + } + + const cwd = path.resolve(options.cwd ?? process.cwd()) + const config = await loadConfig(cwd) + const manifestRef = options.manifest ?? config.manifest ?? bundledManifestPath + const manifest = await loadManifest(manifestRef, cwd) + const selected = resolveItems(manifest, names) + const files = collectFiles(manifest, selected) + const written = [] + const skipped = [] + const packageDependencies = collectPackageDependencies(manifest, selected) + + for (const file of files) { + const targetPath = path.join(cwd, resolveTargetPath(file.target, config.aliases)) + if (!options.overwrite && (await exists(targetPath))) { + skipped.push(path.relative(cwd, targetPath)) + continue + } + + if (!options.dryRun) { + await mkdir(path.dirname(targetPath), { recursive: true }) + const source = await readSourceFile(file.path, manifestRef, cwd) + if (source.kind === "local") { + await copyFile(source.path, targetPath) + } else { + await writeFile(targetPath, source.contents) + } + } + + written.push(path.relative(cwd, targetPath)) + } + + if (written.length > 0) { + console.log(`${options.dryRun ? "Would add" : "Added"}:`) + for (const file of written) { + console.log(` ${file}`) + } + } + + if (skipped.length > 0) { + console.log("Skipped existing files:") + for (const file of skipped) { + console.log(` ${file}`) + } + console.log("Use --overwrite to replace existing files.") + } + + if (packageDependencies.length > 0) { + console.log("Required packages:") + console.log(` ${packageDependencies.join(" ")}`) + } +} + +function resolveItems(manifest, names) { + const resolved = new Set() + const queue = [...names] + + while (queue.length > 0) { + const name = queue.shift() + const item = manifest.items?.[name] + if (!item) { + throw new Error(`Manifest item not found: ${name}`) + } + if (resolved.has(name)) { + continue + } + + resolved.add(name) + for (const dependency of item.localDependencies ?? []) { + queue.push(dependency) + } + } + + return [...resolved] +} + +function collectFiles(manifest, names) { + const files = [] + const seen = new Set() + + for (const name of names) { + for (const file of manifest.items[name].files ?? []) { + const key = file.target + if (!seen.has(key)) { + seen.add(key) + files.push(file) + } + } + } + + return files +} + +function collectPackageDependencies(manifest, names) { + const dependencies = new Set() + + for (const name of names) { + for (const dependency of manifest.items[name].dependencies ?? []) { + dependencies.add(dependency) + } + } + + return [...dependencies].sort((a, b) => a.localeCompare(b)) +} + +async function loadConfig(cwd) { + const configPath = path.join(cwd, configFileName) + if (!(await exists(configPath))) { + return { + manifest: undefined, + aliases: { + ui: "components/ui", + lib: "lib", + }, + } + } + + const config = JSON.parse(await readFile(configPath, "utf8")) + return { + manifest: config.manifest, + aliases: { + ui: config.aliases?.ui ?? "components/ui", + lib: config.aliases?.lib ?? "lib", + }, + } +} + +async function loadManifest(manifestRef, cwd) { + const contents = isUrl(manifestRef) + ? await fetchText(manifestRef) + : await readFile(resolveLocalPath(manifestRef, cwd), "utf8") + + const manifest = JSON.parse(contents) + if (!manifest.items || typeof manifest.items !== "object") { + throw new Error("Invalid manifest: missing items.") + } + return manifest +} + +async function readSourceFile(filePath, manifestRef, cwd) { + if (isUrl(manifestRef)) { + return { + kind: "remote", + contents: await fetchText(new URL(filePath, manifestRef).toString()), + } + } + + return { + kind: "local", + path: path.join(path.dirname(resolveLocalPath(manifestRef, cwd)), filePath), + } +} + +function resolveTargetPath(target, aliases) { + if (target.startsWith("src/components/ui/")) { + return path.join(aliases.ui, target.slice("src/components/ui/".length)) + } + + if (target.startsWith("src/lib/")) { + return path.join(aliases.lib, target.slice("src/lib/".length)) + } + + if (target.startsWith("components/ui/")) { + return path.join(aliases.ui, target.slice("components/ui/".length)) + } + + if (target.startsWith("lib/")) { + return path.join(aliases.lib, target.slice("lib/".length)) + } + + return target +} + +function resolveLocalPath(value, cwd) { + if (path.isAbsolute(value)) { + return value + } + + const projectPath = path.resolve(cwd, value) + return value === "manifest.json" && !existsSync(projectPath) ? bundledManifestPath : projectPath +} + +function parseOptions(values) { + const options = { _: [] } + + for (let index = 0; index < values.length; index += 1) { + const value = values[index] + + if (value === "--cwd") { + options.cwd = values[++index] + } else if (value === "--manifest") { + options.manifest = values[++index] + } else if (value === "--force") { + options.force = true + } else if (value === "--overwrite") { + options.overwrite = true + } else if (value === "--dry-run") { + options.dryRun = true + } else { + options._.push(value) + } + } + + return options +} + +async function fetchText(url) { + const response = await fetch(url) + if (!response.ok) { + throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`) + } + return response.text() +} + +function existsSync(filePath) { + try { + accessSync(filePath) + return true + } catch { + return false + } +} + +async function exists(filePath) { + try { + await access(filePath) + return true + } catch { + return false + } +} + +function isUrl(value) { + return /^https?:\/\//.test(value) +} + +function printHelp() { + console.log(`base-ui-tailwind + +Usage: + base-ui-tailwind init [--manifest ] [--cwd ] [--force] + base-ui-tailwind add [--manifest ] [--cwd ] [--overwrite] [--dry-run] +`) +} diff --git a/examples/smoke.tsx b/examples/smoke.tsx new file mode 100644 index 0000000..bc619ef --- /dev/null +++ b/examples/smoke.tsx @@ -0,0 +1,39 @@ +import Dialog, { + Dialog as ShadcnDialog, + DialogClose, + DialogContent, + DialogDescription, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import Button, { Button as UIButton } from "@/components/ui/button" + +export function Smoke() { + return ( +
+ + Named button + + + Primitive dialog + + + + Primitive dialog + Default namespace API. + Close + + + + + + Named dialog + + Named dialog + Named shadcn-style API. + Close + + +
+ ) +} diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..06ceffb --- /dev/null +++ b/manifest.json @@ -0,0 +1,1777 @@ +{ + "name": "base-ui-tailwind", + "version": "0.0.0", + "generatedAt": "2026-07-24T21:53:13.965Z", + "command": "base-ui-tailwind", + "configFile": "base-ui-tailwind.json", + "dependencies": { + "@base-ui/react": "^1.6.0", + "clsx": "^2.1.1", + "lucide-react": "^1.23.0", + "tailwind-merge": "^3.6.0" + }, + "items": { + "utils/portal-container": { + "name": "utils/portal-container", + "type": "util", + "description": "Utility source for portal-container.", + "dependencies": [ + "react" + ], + "files": [ + { + "path": "src/lib/portal-container.tsx", + "target": "lib/portal-container.tsx" + } + ] + }, + "utils/utils": { + "name": "utils/utils", + "type": "util", + "description": "Utility source for utils.", + "dependencies": [ + "clsx", + "tailwind-merge" + ], + "files": [ + { + "path": "src/lib/utils.ts", + "target": "lib/utils.ts" + } + ] + }, + "accordion": { + "name": "accordion", + "type": "component", + "description": "Accordion component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/accordion/header.tsx", + "target": "components/ui/accordion/header.tsx" + }, + { + "path": "src/components/ui/accordion/index.ts", + "target": "components/ui/accordion/index.ts" + }, + { + "path": "src/components/ui/accordion/item.tsx", + "target": "components/ui/accordion/item.tsx" + }, + { + "path": "src/components/ui/accordion/panel.tsx", + "target": "components/ui/accordion/panel.tsx" + }, + { + "path": "src/components/ui/accordion/root.tsx", + "target": "components/ui/accordion/root.tsx" + }, + { + "path": "src/components/ui/accordion/trigger.tsx", + "target": "components/ui/accordion/trigger.tsx" + } + ] + }, + "alert-dialog": { + "name": "alert-dialog", + "type": "component", + "description": "Alert Dialog component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/alert-dialog/backdrop.tsx", + "target": "components/ui/alert-dialog/backdrop.tsx" + }, + { + "path": "src/components/ui/alert-dialog/close.tsx", + "target": "components/ui/alert-dialog/close.tsx" + }, + { + "path": "src/components/ui/alert-dialog/content.tsx", + "target": "components/ui/alert-dialog/content.tsx" + }, + { + "path": "src/components/ui/alert-dialog/description.tsx", + "target": "components/ui/alert-dialog/description.tsx" + }, + { + "path": "src/components/ui/alert-dialog/index.ts", + "target": "components/ui/alert-dialog/index.ts" + }, + { + "path": "src/components/ui/alert-dialog/popup.tsx", + "target": "components/ui/alert-dialog/popup.tsx" + }, + { + "path": "src/components/ui/alert-dialog/portal.tsx", + "target": "components/ui/alert-dialog/portal.tsx" + }, + { + "path": "src/components/ui/alert-dialog/root.tsx", + "target": "components/ui/alert-dialog/root.tsx" + }, + { + "path": "src/components/ui/alert-dialog/title.tsx", + "target": "components/ui/alert-dialog/title.tsx" + }, + { + "path": "src/components/ui/alert-dialog/trigger.tsx", + "target": "components/ui/alert-dialog/trigger.tsx" + }, + { + "path": "src/components/ui/alert-dialog/viewport.tsx", + "target": "components/ui/alert-dialog/viewport.tsx" + } + ] + }, + "autocomplete": { + "name": "autocomplete", + "type": "component", + "description": "Autocomplete component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/autocomplete/arrow.tsx", + "target": "components/ui/autocomplete/arrow.tsx" + }, + { + "path": "src/components/ui/autocomplete/backdrop.tsx", + "target": "components/ui/autocomplete/backdrop.tsx" + }, + { + "path": "src/components/ui/autocomplete/clear.tsx", + "target": "components/ui/autocomplete/clear.tsx" + }, + { + "path": "src/components/ui/autocomplete/collection.tsx", + "target": "components/ui/autocomplete/collection.tsx" + }, + { + "path": "src/components/ui/autocomplete/empty.tsx", + "target": "components/ui/autocomplete/empty.tsx" + }, + { + "path": "src/components/ui/autocomplete/group-label.tsx", + "target": "components/ui/autocomplete/group-label.tsx" + }, + { + "path": "src/components/ui/autocomplete/group.tsx", + "target": "components/ui/autocomplete/group.tsx" + }, + { + "path": "src/components/ui/autocomplete/icon.tsx", + "target": "components/ui/autocomplete/icon.tsx" + }, + { + "path": "src/components/ui/autocomplete/index.ts", + "target": "components/ui/autocomplete/index.ts" + }, + { + "path": "src/components/ui/autocomplete/input-group.tsx", + "target": "components/ui/autocomplete/input-group.tsx" + }, + { + "path": "src/components/ui/autocomplete/input.tsx", + "target": "components/ui/autocomplete/input.tsx" + }, + { + "path": "src/components/ui/autocomplete/item.tsx", + "target": "components/ui/autocomplete/item.tsx" + }, + { + "path": "src/components/ui/autocomplete/list.tsx", + "target": "components/ui/autocomplete/list.tsx" + }, + { + "path": "src/components/ui/autocomplete/popup.tsx", + "target": "components/ui/autocomplete/popup.tsx" + }, + { + "path": "src/components/ui/autocomplete/portal.tsx", + "target": "components/ui/autocomplete/portal.tsx" + }, + { + "path": "src/components/ui/autocomplete/positioner.tsx", + "target": "components/ui/autocomplete/positioner.tsx" + }, + { + "path": "src/components/ui/autocomplete/root.tsx", + "target": "components/ui/autocomplete/root.tsx" + }, + { + "path": "src/components/ui/autocomplete/row.tsx", + "target": "components/ui/autocomplete/row.tsx" + }, + { + "path": "src/components/ui/autocomplete/trigger.tsx", + "target": "components/ui/autocomplete/trigger.tsx" + }, + { + "path": "src/components/ui/autocomplete/value.tsx", + "target": "components/ui/autocomplete/value.tsx" + } + ] + }, + "avatar": { + "name": "avatar", + "type": "component", + "description": "Avatar component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/avatar/fallback.tsx", + "target": "components/ui/avatar/fallback.tsx" + }, + { + "path": "src/components/ui/avatar/image.tsx", + "target": "components/ui/avatar/image.tsx" + }, + { + "path": "src/components/ui/avatar/index.ts", + "target": "components/ui/avatar/index.ts" + }, + { + "path": "src/components/ui/avatar/root.tsx", + "target": "components/ui/avatar/root.tsx" + } + ] + }, + "button": { + "name": "button", + "type": "component", + "description": "Button component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/button/index.ts", + "target": "components/ui/button/index.ts" + }, + { + "path": "src/components/ui/button/root.tsx", + "target": "components/ui/button/root.tsx" + } + ] + }, + "checkbox": { + "name": "checkbox", + "type": "component", + "description": "Checkbox component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/checkbox/index.ts", + "target": "components/ui/checkbox/index.ts" + }, + { + "path": "src/components/ui/checkbox/indicator.tsx", + "target": "components/ui/checkbox/indicator.tsx" + }, + { + "path": "src/components/ui/checkbox/root.tsx", + "target": "components/ui/checkbox/root.tsx" + } + ] + }, + "checkbox-group": { + "name": "checkbox-group", + "type": "component", + "description": "Checkbox Group component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/checkbox-group/index.ts", + "target": "components/ui/checkbox-group/index.ts" + }, + { + "path": "src/components/ui/checkbox-group/root.tsx", + "target": "components/ui/checkbox-group/root.tsx" + } + ] + }, + "collapsible": { + "name": "collapsible", + "type": "component", + "description": "Collapsible component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/collapsible/index.ts", + "target": "components/ui/collapsible/index.ts" + }, + { + "path": "src/components/ui/collapsible/panel.tsx", + "target": "components/ui/collapsible/panel.tsx" + }, + { + "path": "src/components/ui/collapsible/root.tsx", + "target": "components/ui/collapsible/root.tsx" + }, + { + "path": "src/components/ui/collapsible/trigger.tsx", + "target": "components/ui/collapsible/trigger.tsx" + } + ] + }, + "combobox": { + "name": "combobox", + "type": "component", + "description": "Combobox component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/combobox/arrow.tsx", + "target": "components/ui/combobox/arrow.tsx" + }, + { + "path": "src/components/ui/combobox/backdrop.tsx", + "target": "components/ui/combobox/backdrop.tsx" + }, + { + "path": "src/components/ui/combobox/chip-remove.tsx", + "target": "components/ui/combobox/chip-remove.tsx" + }, + { + "path": "src/components/ui/combobox/chip.tsx", + "target": "components/ui/combobox/chip.tsx" + }, + { + "path": "src/components/ui/combobox/chips.tsx", + "target": "components/ui/combobox/chips.tsx" + }, + { + "path": "src/components/ui/combobox/clear.tsx", + "target": "components/ui/combobox/clear.tsx" + }, + { + "path": "src/components/ui/combobox/collection.tsx", + "target": "components/ui/combobox/collection.tsx" + }, + { + "path": "src/components/ui/combobox/empty.tsx", + "target": "components/ui/combobox/empty.tsx" + }, + { + "path": "src/components/ui/combobox/group-label.tsx", + "target": "components/ui/combobox/group-label.tsx" + }, + { + "path": "src/components/ui/combobox/group.tsx", + "target": "components/ui/combobox/group.tsx" + }, + { + "path": "src/components/ui/combobox/icon.tsx", + "target": "components/ui/combobox/icon.tsx" + }, + { + "path": "src/components/ui/combobox/index.ts", + "target": "components/ui/combobox/index.ts" + }, + { + "path": "src/components/ui/combobox/input-group.tsx", + "target": "components/ui/combobox/input-group.tsx" + }, + { + "path": "src/components/ui/combobox/input.tsx", + "target": "components/ui/combobox/input.tsx" + }, + { + "path": "src/components/ui/combobox/item-indicator.tsx", + "target": "components/ui/combobox/item-indicator.tsx" + }, + { + "path": "src/components/ui/combobox/item.tsx", + "target": "components/ui/combobox/item.tsx" + }, + { + "path": "src/components/ui/combobox/label.tsx", + "target": "components/ui/combobox/label.tsx" + }, + { + "path": "src/components/ui/combobox/list.tsx", + "target": "components/ui/combobox/list.tsx" + }, + { + "path": "src/components/ui/combobox/popup.tsx", + "target": "components/ui/combobox/popup.tsx" + }, + { + "path": "src/components/ui/combobox/portal.tsx", + "target": "components/ui/combobox/portal.tsx" + }, + { + "path": "src/components/ui/combobox/positioner.tsx", + "target": "components/ui/combobox/positioner.tsx" + }, + { + "path": "src/components/ui/combobox/root.tsx", + "target": "components/ui/combobox/root.tsx" + }, + { + "path": "src/components/ui/combobox/row.tsx", + "target": "components/ui/combobox/row.tsx" + }, + { + "path": "src/components/ui/combobox/trigger.tsx", + "target": "components/ui/combobox/trigger.tsx" + }, + { + "path": "src/components/ui/combobox/value.tsx", + "target": "components/ui/combobox/value.tsx" + } + ] + }, + "context-menu": { + "name": "context-menu", + "type": "component", + "description": "Context Menu component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/context-menu/arrow.tsx", + "target": "components/ui/context-menu/arrow.tsx" + }, + { + "path": "src/components/ui/context-menu/backdrop.tsx", + "target": "components/ui/context-menu/backdrop.tsx" + }, + { + "path": "src/components/ui/context-menu/checkbox-item-indicator.tsx", + "target": "components/ui/context-menu/checkbox-item-indicator.tsx" + }, + { + "path": "src/components/ui/context-menu/checkbox-item.tsx", + "target": "components/ui/context-menu/checkbox-item.tsx" + }, + { + "path": "src/components/ui/context-menu/group-label.tsx", + "target": "components/ui/context-menu/group-label.tsx" + }, + { + "path": "src/components/ui/context-menu/group.tsx", + "target": "components/ui/context-menu/group.tsx" + }, + { + "path": "src/components/ui/context-menu/index.ts", + "target": "components/ui/context-menu/index.ts" + }, + { + "path": "src/components/ui/context-menu/item.tsx", + "target": "components/ui/context-menu/item.tsx" + }, + { + "path": "src/components/ui/context-menu/link-item.tsx", + "target": "components/ui/context-menu/link-item.tsx" + }, + { + "path": "src/components/ui/context-menu/popup.tsx", + "target": "components/ui/context-menu/popup.tsx" + }, + { + "path": "src/components/ui/context-menu/portal.tsx", + "target": "components/ui/context-menu/portal.tsx" + }, + { + "path": "src/components/ui/context-menu/positioner.tsx", + "target": "components/ui/context-menu/positioner.tsx" + }, + { + "path": "src/components/ui/context-menu/radio-group.tsx", + "target": "components/ui/context-menu/radio-group.tsx" + }, + { + "path": "src/components/ui/context-menu/radio-item-indicator.tsx", + "target": "components/ui/context-menu/radio-item-indicator.tsx" + }, + { + "path": "src/components/ui/context-menu/radio-item.tsx", + "target": "components/ui/context-menu/radio-item.tsx" + }, + { + "path": "src/components/ui/context-menu/root.tsx", + "target": "components/ui/context-menu/root.tsx" + }, + { + "path": "src/components/ui/context-menu/submenu-root.tsx", + "target": "components/ui/context-menu/submenu-root.tsx" + }, + { + "path": "src/components/ui/context-menu/submenu-trigger.tsx", + "target": "components/ui/context-menu/submenu-trigger.tsx" + }, + { + "path": "src/components/ui/context-menu/trigger.tsx", + "target": "components/ui/context-menu/trigger.tsx" + } + ] + }, + "dialog": { + "name": "dialog", + "type": "component", + "description": "Dialog component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/dialog/backdrop.tsx", + "target": "components/ui/dialog/backdrop.tsx" + }, + { + "path": "src/components/ui/dialog/close.tsx", + "target": "components/ui/dialog/close.tsx" + }, + { + "path": "src/components/ui/dialog/content.tsx", + "target": "components/ui/dialog/content.tsx" + }, + { + "path": "src/components/ui/dialog/description.tsx", + "target": "components/ui/dialog/description.tsx" + }, + { + "path": "src/components/ui/dialog/index.ts", + "target": "components/ui/dialog/index.ts" + }, + { + "path": "src/components/ui/dialog/popup.tsx", + "target": "components/ui/dialog/popup.tsx" + }, + { + "path": "src/components/ui/dialog/portal.tsx", + "target": "components/ui/dialog/portal.tsx" + }, + { + "path": "src/components/ui/dialog/root.tsx", + "target": "components/ui/dialog/root.tsx" + }, + { + "path": "src/components/ui/dialog/title.tsx", + "target": "components/ui/dialog/title.tsx" + }, + { + "path": "src/components/ui/dialog/trigger.tsx", + "target": "components/ui/dialog/trigger.tsx" + }, + { + "path": "src/components/ui/dialog/viewport.tsx", + "target": "components/ui/dialog/viewport.tsx" + } + ] + }, + "drawer": { + "name": "drawer", + "type": "component", + "description": "Drawer component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/drawer/backdrop.tsx", + "target": "components/ui/drawer/backdrop.tsx" + }, + { + "path": "src/components/ui/drawer/close.tsx", + "target": "components/ui/drawer/close.tsx" + }, + { + "path": "src/components/ui/drawer/content.tsx", + "target": "components/ui/drawer/content.tsx" + }, + { + "path": "src/components/ui/drawer/description.tsx", + "target": "components/ui/drawer/description.tsx" + }, + { + "path": "src/components/ui/drawer/indent-background.tsx", + "target": "components/ui/drawer/indent-background.tsx" + }, + { + "path": "src/components/ui/drawer/indent.tsx", + "target": "components/ui/drawer/indent.tsx" + }, + { + "path": "src/components/ui/drawer/index.ts", + "target": "components/ui/drawer/index.ts" + }, + { + "path": "src/components/ui/drawer/popup.tsx", + "target": "components/ui/drawer/popup.tsx" + }, + { + "path": "src/components/ui/drawer/portal.tsx", + "target": "components/ui/drawer/portal.tsx" + }, + { + "path": "src/components/ui/drawer/provider.tsx", + "target": "components/ui/drawer/provider.tsx" + }, + { + "path": "src/components/ui/drawer/root.tsx", + "target": "components/ui/drawer/root.tsx" + }, + { + "path": "src/components/ui/drawer/swipe-area.tsx", + "target": "components/ui/drawer/swipe-area.tsx" + }, + { + "path": "src/components/ui/drawer/title.tsx", + "target": "components/ui/drawer/title.tsx" + }, + { + "path": "src/components/ui/drawer/trigger.tsx", + "target": "components/ui/drawer/trigger.tsx" + }, + { + "path": "src/components/ui/drawer/viewport.tsx", + "target": "components/ui/drawer/viewport.tsx" + }, + { + "path": "src/components/ui/drawer/virtual-keyboard-provider.tsx", + "target": "components/ui/drawer/virtual-keyboard-provider.tsx" + } + ] + }, + "field": { + "name": "field", + "type": "component", + "description": "Field component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/field/control.tsx", + "target": "components/ui/field/control.tsx" + }, + { + "path": "src/components/ui/field/description.tsx", + "target": "components/ui/field/description.tsx" + }, + { + "path": "src/components/ui/field/error.tsx", + "target": "components/ui/field/error.tsx" + }, + { + "path": "src/components/ui/field/index.ts", + "target": "components/ui/field/index.ts" + }, + { + "path": "src/components/ui/field/item.tsx", + "target": "components/ui/field/item.tsx" + }, + { + "path": "src/components/ui/field/label.tsx", + "target": "components/ui/field/label.tsx" + }, + { + "path": "src/components/ui/field/root.tsx", + "target": "components/ui/field/root.tsx" + }, + { + "path": "src/components/ui/field/validity.tsx", + "target": "components/ui/field/validity.tsx" + } + ] + }, + "fieldset": { + "name": "fieldset", + "type": "component", + "description": "Fieldset component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/fieldset/index.ts", + "target": "components/ui/fieldset/index.ts" + }, + { + "path": "src/components/ui/fieldset/legend.tsx", + "target": "components/ui/fieldset/legend.tsx" + }, + { + "path": "src/components/ui/fieldset/root.tsx", + "target": "components/ui/fieldset/root.tsx" + } + ] + }, + "form": { + "name": "form", + "type": "component", + "description": "Form component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/form/index.ts", + "target": "components/ui/form/index.ts" + }, + { + "path": "src/components/ui/form/root.tsx", + "target": "components/ui/form/root.tsx" + } + ] + }, + "input": { + "name": "input", + "type": "component", + "description": "Input component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/input/index.ts", + "target": "components/ui/input/index.ts" + }, + { + "path": "src/components/ui/input/root.tsx", + "target": "components/ui/input/root.tsx" + } + ] + }, + "menu": { + "name": "menu", + "type": "component", + "description": "Menu component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/menu/arrow.tsx", + "target": "components/ui/menu/arrow.tsx" + }, + { + "path": "src/components/ui/menu/backdrop.tsx", + "target": "components/ui/menu/backdrop.tsx" + }, + { + "path": "src/components/ui/menu/checkbox-item-indicator.tsx", + "target": "components/ui/menu/checkbox-item-indicator.tsx" + }, + { + "path": "src/components/ui/menu/checkbox-item.tsx", + "target": "components/ui/menu/checkbox-item.tsx" + }, + { + "path": "src/components/ui/menu/group-label.tsx", + "target": "components/ui/menu/group-label.tsx" + }, + { + "path": "src/components/ui/menu/group.tsx", + "target": "components/ui/menu/group.tsx" + }, + { + "path": "src/components/ui/menu/index.ts", + "target": "components/ui/menu/index.ts" + }, + { + "path": "src/components/ui/menu/item.tsx", + "target": "components/ui/menu/item.tsx" + }, + { + "path": "src/components/ui/menu/link-item.tsx", + "target": "components/ui/menu/link-item.tsx" + }, + { + "path": "src/components/ui/menu/popup.tsx", + "target": "components/ui/menu/popup.tsx" + }, + { + "path": "src/components/ui/menu/portal.tsx", + "target": "components/ui/menu/portal.tsx" + }, + { + "path": "src/components/ui/menu/positioner.tsx", + "target": "components/ui/menu/positioner.tsx" + }, + { + "path": "src/components/ui/menu/radio-group.tsx", + "target": "components/ui/menu/radio-group.tsx" + }, + { + "path": "src/components/ui/menu/radio-item-indicator.tsx", + "target": "components/ui/menu/radio-item-indicator.tsx" + }, + { + "path": "src/components/ui/menu/radio-item.tsx", + "target": "components/ui/menu/radio-item.tsx" + }, + { + "path": "src/components/ui/menu/root.tsx", + "target": "components/ui/menu/root.tsx" + }, + { + "path": "src/components/ui/menu/submenu-root.tsx", + "target": "components/ui/menu/submenu-root.tsx" + }, + { + "path": "src/components/ui/menu/submenu-trigger.tsx", + "target": "components/ui/menu/submenu-trigger.tsx" + }, + { + "path": "src/components/ui/menu/trigger.tsx", + "target": "components/ui/menu/trigger.tsx" + }, + { + "path": "src/components/ui/menu/viewport.tsx", + "target": "components/ui/menu/viewport.tsx" + } + ] + }, + "menubar": { + "name": "menubar", + "type": "component", + "description": "Menubar component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/menubar/index.ts", + "target": "components/ui/menubar/index.ts" + }, + { + "path": "src/components/ui/menubar/root.tsx", + "target": "components/ui/menubar/root.tsx" + } + ] + }, + "meter": { + "name": "meter", + "type": "component", + "description": "Meter component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/meter/index.ts", + "target": "components/ui/meter/index.ts" + }, + { + "path": "src/components/ui/meter/indicator.tsx", + "target": "components/ui/meter/indicator.tsx" + }, + { + "path": "src/components/ui/meter/label.tsx", + "target": "components/ui/meter/label.tsx" + }, + { + "path": "src/components/ui/meter/root.tsx", + "target": "components/ui/meter/root.tsx" + }, + { + "path": "src/components/ui/meter/track.tsx", + "target": "components/ui/meter/track.tsx" + }, + { + "path": "src/components/ui/meter/value.tsx", + "target": "components/ui/meter/value.tsx" + } + ] + }, + "navigation-menu": { + "name": "navigation-menu", + "type": "component", + "description": "Navigation Menu component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/navigation-menu/arrow.tsx", + "target": "components/ui/navigation-menu/arrow.tsx" + }, + { + "path": "src/components/ui/navigation-menu/backdrop.tsx", + "target": "components/ui/navigation-menu/backdrop.tsx" + }, + { + "path": "src/components/ui/navigation-menu/content.tsx", + "target": "components/ui/navigation-menu/content.tsx" + }, + { + "path": "src/components/ui/navigation-menu/icon.tsx", + "target": "components/ui/navigation-menu/icon.tsx" + }, + { + "path": "src/components/ui/navigation-menu/index.ts", + "target": "components/ui/navigation-menu/index.ts" + }, + { + "path": "src/components/ui/navigation-menu/item.tsx", + "target": "components/ui/navigation-menu/item.tsx" + }, + { + "path": "src/components/ui/navigation-menu/link.tsx", + "target": "components/ui/navigation-menu/link.tsx" + }, + { + "path": "src/components/ui/navigation-menu/list.tsx", + "target": "components/ui/navigation-menu/list.tsx" + }, + { + "path": "src/components/ui/navigation-menu/popup.tsx", + "target": "components/ui/navigation-menu/popup.tsx" + }, + { + "path": "src/components/ui/navigation-menu/portal.tsx", + "target": "components/ui/navigation-menu/portal.tsx" + }, + { + "path": "src/components/ui/navigation-menu/positioner.tsx", + "target": "components/ui/navigation-menu/positioner.tsx" + }, + { + "path": "src/components/ui/navigation-menu/root.tsx", + "target": "components/ui/navigation-menu/root.tsx" + }, + { + "path": "src/components/ui/navigation-menu/trigger.tsx", + "target": "components/ui/navigation-menu/trigger.tsx" + }, + { + "path": "src/components/ui/navigation-menu/viewport.tsx", + "target": "components/ui/navigation-menu/viewport.tsx" + } + ] + }, + "number-field": { + "name": "number-field", + "type": "component", + "description": "Number Field component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/number-field/decrement.tsx", + "target": "components/ui/number-field/decrement.tsx" + }, + { + "path": "src/components/ui/number-field/group.tsx", + "target": "components/ui/number-field/group.tsx" + }, + { + "path": "src/components/ui/number-field/increment.tsx", + "target": "components/ui/number-field/increment.tsx" + }, + { + "path": "src/components/ui/number-field/index.ts", + "target": "components/ui/number-field/index.ts" + }, + { + "path": "src/components/ui/number-field/input.tsx", + "target": "components/ui/number-field/input.tsx" + }, + { + "path": "src/components/ui/number-field/root.tsx", + "target": "components/ui/number-field/root.tsx" + }, + { + "path": "src/components/ui/number-field/scrub-area-cursor.tsx", + "target": "components/ui/number-field/scrub-area-cursor.tsx" + }, + { + "path": "src/components/ui/number-field/scrub-area.tsx", + "target": "components/ui/number-field/scrub-area.tsx" + } + ] + }, + "otp-field": { + "name": "otp-field", + "type": "component", + "description": "Otp Field component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/otp-field/index.ts", + "target": "components/ui/otp-field/index.ts" + }, + { + "path": "src/components/ui/otp-field/input.tsx", + "target": "components/ui/otp-field/input.tsx" + }, + { + "path": "src/components/ui/otp-field/root.tsx", + "target": "components/ui/otp-field/root.tsx" + } + ] + }, + "popover": { + "name": "popover", + "type": "component", + "description": "Popover component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/popover/arrow.tsx", + "target": "components/ui/popover/arrow.tsx" + }, + { + "path": "src/components/ui/popover/backdrop.tsx", + "target": "components/ui/popover/backdrop.tsx" + }, + { + "path": "src/components/ui/popover/close.tsx", + "target": "components/ui/popover/close.tsx" + }, + { + "path": "src/components/ui/popover/content.tsx", + "target": "components/ui/popover/content.tsx" + }, + { + "path": "src/components/ui/popover/description.tsx", + "target": "components/ui/popover/description.tsx" + }, + { + "path": "src/components/ui/popover/index.ts", + "target": "components/ui/popover/index.ts" + }, + { + "path": "src/components/ui/popover/popup.tsx", + "target": "components/ui/popover/popup.tsx" + }, + { + "path": "src/components/ui/popover/portal.tsx", + "target": "components/ui/popover/portal.tsx" + }, + { + "path": "src/components/ui/popover/positioner.tsx", + "target": "components/ui/popover/positioner.tsx" + }, + { + "path": "src/components/ui/popover/root.tsx", + "target": "components/ui/popover/root.tsx" + }, + { + "path": "src/components/ui/popover/title.tsx", + "target": "components/ui/popover/title.tsx" + }, + { + "path": "src/components/ui/popover/trigger.tsx", + "target": "components/ui/popover/trigger.tsx" + }, + { + "path": "src/components/ui/popover/viewport.tsx", + "target": "components/ui/popover/viewport.tsx" + } + ] + }, + "preview-card": { + "name": "preview-card", + "type": "component", + "description": "Preview Card component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/preview-card/arrow.tsx", + "target": "components/ui/preview-card/arrow.tsx" + }, + { + "path": "src/components/ui/preview-card/backdrop.tsx", + "target": "components/ui/preview-card/backdrop.tsx" + }, + { + "path": "src/components/ui/preview-card/content.tsx", + "target": "components/ui/preview-card/content.tsx" + }, + { + "path": "src/components/ui/preview-card/index.ts", + "target": "components/ui/preview-card/index.ts" + }, + { + "path": "src/components/ui/preview-card/popup.tsx", + "target": "components/ui/preview-card/popup.tsx" + }, + { + "path": "src/components/ui/preview-card/portal.tsx", + "target": "components/ui/preview-card/portal.tsx" + }, + { + "path": "src/components/ui/preview-card/positioner.tsx", + "target": "components/ui/preview-card/positioner.tsx" + }, + { + "path": "src/components/ui/preview-card/root.tsx", + "target": "components/ui/preview-card/root.tsx" + }, + { + "path": "src/components/ui/preview-card/trigger.tsx", + "target": "components/ui/preview-card/trigger.tsx" + }, + { + "path": "src/components/ui/preview-card/viewport.tsx", + "target": "components/ui/preview-card/viewport.tsx" + } + ] + }, + "progress": { + "name": "progress", + "type": "component", + "description": "Progress component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/progress/index.ts", + "target": "components/ui/progress/index.ts" + }, + { + "path": "src/components/ui/progress/indicator.tsx", + "target": "components/ui/progress/indicator.tsx" + }, + { + "path": "src/components/ui/progress/label.tsx", + "target": "components/ui/progress/label.tsx" + }, + { + "path": "src/components/ui/progress/root.tsx", + "target": "components/ui/progress/root.tsx" + }, + { + "path": "src/components/ui/progress/track.tsx", + "target": "components/ui/progress/track.tsx" + }, + { + "path": "src/components/ui/progress/value.tsx", + "target": "components/ui/progress/value.tsx" + } + ] + }, + "radio": { + "name": "radio", + "type": "component", + "description": "Radio component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/radio/index.ts", + "target": "components/ui/radio/index.ts" + }, + { + "path": "src/components/ui/radio/indicator.tsx", + "target": "components/ui/radio/indicator.tsx" + }, + { + "path": "src/components/ui/radio/root.tsx", + "target": "components/ui/radio/root.tsx" + } + ] + }, + "scroll-area": { + "name": "scroll-area", + "type": "component", + "description": "Scroll Area component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/scroll-area/content.tsx", + "target": "components/ui/scroll-area/content.tsx" + }, + { + "path": "src/components/ui/scroll-area/corner.tsx", + "target": "components/ui/scroll-area/corner.tsx" + }, + { + "path": "src/components/ui/scroll-area/index.ts", + "target": "components/ui/scroll-area/index.ts" + }, + { + "path": "src/components/ui/scroll-area/root.tsx", + "target": "components/ui/scroll-area/root.tsx" + }, + { + "path": "src/components/ui/scroll-area/scrollbar.tsx", + "target": "components/ui/scroll-area/scrollbar.tsx" + }, + { + "path": "src/components/ui/scroll-area/thumb.tsx", + "target": "components/ui/scroll-area/thumb.tsx" + }, + { + "path": "src/components/ui/scroll-area/viewport.tsx", + "target": "components/ui/scroll-area/viewport.tsx" + } + ] + }, + "select": { + "name": "select", + "type": "component", + "description": "Select component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/select/arrow.tsx", + "target": "components/ui/select/arrow.tsx" + }, + { + "path": "src/components/ui/select/backdrop.tsx", + "target": "components/ui/select/backdrop.tsx" + }, + { + "path": "src/components/ui/select/group-label.tsx", + "target": "components/ui/select/group-label.tsx" + }, + { + "path": "src/components/ui/select/group.tsx", + "target": "components/ui/select/group.tsx" + }, + { + "path": "src/components/ui/select/icon.tsx", + "target": "components/ui/select/icon.tsx" + }, + { + "path": "src/components/ui/select/index.ts", + "target": "components/ui/select/index.ts" + }, + { + "path": "src/components/ui/select/item-indicator.tsx", + "target": "components/ui/select/item-indicator.tsx" + }, + { + "path": "src/components/ui/select/item-text.tsx", + "target": "components/ui/select/item-text.tsx" + }, + { + "path": "src/components/ui/select/item.tsx", + "target": "components/ui/select/item.tsx" + }, + { + "path": "src/components/ui/select/label.tsx", + "target": "components/ui/select/label.tsx" + }, + { + "path": "src/components/ui/select/list.tsx", + "target": "components/ui/select/list.tsx" + }, + { + "path": "src/components/ui/select/popup.tsx", + "target": "components/ui/select/popup.tsx" + }, + { + "path": "src/components/ui/select/portal.tsx", + "target": "components/ui/select/portal.tsx" + }, + { + "path": "src/components/ui/select/positioner.tsx", + "target": "components/ui/select/positioner.tsx" + }, + { + "path": "src/components/ui/select/root.tsx", + "target": "components/ui/select/root.tsx" + }, + { + "path": "src/components/ui/select/scroll-down-arrow.tsx", + "target": "components/ui/select/scroll-down-arrow.tsx" + }, + { + "path": "src/components/ui/select/scroll-up-arrow.tsx", + "target": "components/ui/select/scroll-up-arrow.tsx" + }, + { + "path": "src/components/ui/select/separator.tsx", + "target": "components/ui/select/separator.tsx" + }, + { + "path": "src/components/ui/select/trigger.tsx", + "target": "components/ui/select/trigger.tsx" + }, + { + "path": "src/components/ui/select/value.tsx", + "target": "components/ui/select/value.tsx" + } + ] + }, + "separator": { + "name": "separator", + "type": "component", + "description": "Separator component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/separator/index.ts", + "target": "components/ui/separator/index.ts" + }, + { + "path": "src/components/ui/separator/root.tsx", + "target": "components/ui/separator/root.tsx" + } + ] + }, + "slider": { + "name": "slider", + "type": "component", + "description": "Slider component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/slider/control.tsx", + "target": "components/ui/slider/control.tsx" + }, + { + "path": "src/components/ui/slider/index.ts", + "target": "components/ui/slider/index.ts" + }, + { + "path": "src/components/ui/slider/indicator.tsx", + "target": "components/ui/slider/indicator.tsx" + }, + { + "path": "src/components/ui/slider/label.tsx", + "target": "components/ui/slider/label.tsx" + }, + { + "path": "src/components/ui/slider/root.tsx", + "target": "components/ui/slider/root.tsx" + }, + { + "path": "src/components/ui/slider/thumb.tsx", + "target": "components/ui/slider/thumb.tsx" + }, + { + "path": "src/components/ui/slider/track.tsx", + "target": "components/ui/slider/track.tsx" + }, + { + "path": "src/components/ui/slider/value.tsx", + "target": "components/ui/slider/value.tsx" + } + ] + }, + "switch": { + "name": "switch", + "type": "component", + "description": "Switch component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/switch/index.ts", + "target": "components/ui/switch/index.ts" + }, + { + "path": "src/components/ui/switch/root.tsx", + "target": "components/ui/switch/root.tsx" + }, + { + "path": "src/components/ui/switch/thumb.tsx", + "target": "components/ui/switch/thumb.tsx" + } + ] + }, + "tabs": { + "name": "tabs", + "type": "component", + "description": "Tabs component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/tabs/index.ts", + "target": "components/ui/tabs/index.ts" + }, + { + "path": "src/components/ui/tabs/indicator.tsx", + "target": "components/ui/tabs/indicator.tsx" + }, + { + "path": "src/components/ui/tabs/list.tsx", + "target": "components/ui/tabs/list.tsx" + }, + { + "path": "src/components/ui/tabs/panel.tsx", + "target": "components/ui/tabs/panel.tsx" + }, + { + "path": "src/components/ui/tabs/root.tsx", + "target": "components/ui/tabs/root.tsx" + }, + { + "path": "src/components/ui/tabs/tab.tsx", + "target": "components/ui/tabs/tab.tsx" + } + ] + }, + "toast": { + "name": "toast", + "type": "component", + "description": "Toast component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toast/action.tsx", + "target": "components/ui/toast/action.tsx" + }, + { + "path": "src/components/ui/toast/arrow.tsx", + "target": "components/ui/toast/arrow.tsx" + }, + { + "path": "src/components/ui/toast/close.tsx", + "target": "components/ui/toast/close.tsx" + }, + { + "path": "src/components/ui/toast/content.tsx", + "target": "components/ui/toast/content.tsx" + }, + { + "path": "src/components/ui/toast/description.tsx", + "target": "components/ui/toast/description.tsx" + }, + { + "path": "src/components/ui/toast/index.ts", + "target": "components/ui/toast/index.ts" + }, + { + "path": "src/components/ui/toast/portal.tsx", + "target": "components/ui/toast/portal.tsx" + }, + { + "path": "src/components/ui/toast/positioner.tsx", + "target": "components/ui/toast/positioner.tsx" + }, + { + "path": "src/components/ui/toast/provider.tsx", + "target": "components/ui/toast/provider.tsx" + }, + { + "path": "src/components/ui/toast/root.tsx", + "target": "components/ui/toast/root.tsx" + }, + { + "path": "src/components/ui/toast/title.tsx", + "target": "components/ui/toast/title.tsx" + }, + { + "path": "src/components/ui/toast/viewport.tsx", + "target": "components/ui/toast/viewport.tsx" + } + ] + }, + "toggle": { + "name": "toggle", + "type": "component", + "description": "Toggle component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toggle/index.ts", + "target": "components/ui/toggle/index.ts" + }, + { + "path": "src/components/ui/toggle/root.tsx", + "target": "components/ui/toggle/root.tsx" + } + ] + }, + "toggle-group": { + "name": "toggle-group", + "type": "component", + "description": "Toggle Group component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toggle-group/index.ts", + "target": "components/ui/toggle-group/index.ts" + }, + { + "path": "src/components/ui/toggle-group/root.tsx", + "target": "components/ui/toggle-group/root.tsx" + } + ] + }, + "toolbar": { + "name": "toolbar", + "type": "component", + "description": "Toolbar component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toolbar/button.tsx", + "target": "components/ui/toolbar/button.tsx" + }, + { + "path": "src/components/ui/toolbar/group.tsx", + "target": "components/ui/toolbar/group.tsx" + }, + { + "path": "src/components/ui/toolbar/index.ts", + "target": "components/ui/toolbar/index.ts" + }, + { + "path": "src/components/ui/toolbar/input.tsx", + "target": "components/ui/toolbar/input.tsx" + }, + { + "path": "src/components/ui/toolbar/link.tsx", + "target": "components/ui/toolbar/link.tsx" + }, + { + "path": "src/components/ui/toolbar/root.tsx", + "target": "components/ui/toolbar/root.tsx" + }, + { + "path": "src/components/ui/toolbar/separator.tsx", + "target": "components/ui/toolbar/separator.tsx" + } + ] + }, + "tooltip": { + "name": "tooltip", + "type": "component", + "description": "Tooltip component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/tooltip/arrow.tsx", + "target": "components/ui/tooltip/arrow.tsx" + }, + { + "path": "src/components/ui/tooltip/content.tsx", + "target": "components/ui/tooltip/content.tsx" + }, + { + "path": "src/components/ui/tooltip/index.ts", + "target": "components/ui/tooltip/index.ts" + }, + { + "path": "src/components/ui/tooltip/popup.tsx", + "target": "components/ui/tooltip/popup.tsx" + }, + { + "path": "src/components/ui/tooltip/portal.tsx", + "target": "components/ui/tooltip/portal.tsx" + }, + { + "path": "src/components/ui/tooltip/positioner.tsx", + "target": "components/ui/tooltip/positioner.tsx" + }, + { + "path": "src/components/ui/tooltip/provider.tsx", + "target": "components/ui/tooltip/provider.tsx" + }, + { + "path": "src/components/ui/tooltip/root.tsx", + "target": "components/ui/tooltip/root.tsx" + }, + { + "path": "src/components/ui/tooltip/trigger.tsx", + "target": "components/ui/tooltip/trigger.tsx" + }, + { + "path": "src/components/ui/tooltip/viewport.tsx", + "target": "components/ui/tooltip/viewport.tsx" + } + ] + } + } +} diff --git a/scripts/check-ui-exports.mjs b/scripts/check-ui-exports.mjs new file mode 100644 index 0000000..0eee965 --- /dev/null +++ b/scripts/check-ui-exports.mjs @@ -0,0 +1,33 @@ +import { readdir, readFile } from "node:fs/promises" +import path from "node:path" + +const uiComponentsPath = path.join("src", "components", "ui") +const componentEntries = await readdir(uiComponentsPath, { withFileTypes: true }) +const components = componentEntries + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .sort((a, b) => a.localeCompare(b)) + +const failures = [] + +for (const component of components) { + const indexPath = path.join(uiComponentsPath, component, "index.ts") + try { + const source = await readFile(indexPath, "utf8") + if (!source.includes("export default")) { + failures.push(`${indexPath}: missing default export`) + } + } catch (error) { + if (error.code !== "ENOENT") { + throw error + } + failures.push(`${indexPath}: missing file`) + } +} + +if (failures.length > 0) { + console.error(failures.join("\n")) + process.exit(1) +} + +console.log(`Checked ${components.length} component exports.`) diff --git a/scripts/generate-manifest.mjs b/scripts/generate-manifest.mjs new file mode 100644 index 0000000..1e958ef --- /dev/null +++ b/scripts/generate-manifest.mjs @@ -0,0 +1,166 @@ +import { readdir, readFile, writeFile } from "node:fs/promises" +import path from "node:path" +import process from "node:process" + +const root = process.cwd() +const sourceDir = path.join(root, "src") +const componentsDir = path.join(sourceDir, "components", "ui") +const libDir = path.join(sourceDir, "lib") +const outputPath = path.join(root, "manifest.json") + +const packageJson = JSON.parse(await readFile(path.join(root, "package.json"), "utf8")) +const components = await listDirectories(componentsDir) +const utils = await listFiles(libDir) + +const items = {} + +for (const file of utils) { + const name = path.basename(file, path.extname(file)) + const source = await readFile(path.join(root, file), "utf8") + const target = stripSourcePrefix(file) + items[`utils/${name}`] = { + name: `utils/${name}`, + type: "util", + description: `Utility source for ${name}.`, + dependencies: collectPackageDependencies(source), + files: [ + { + path: file, + target, + }, + ], + } +} + +for (const component of components) { + const componentFiles = await listFiles(path.join("src", "components", "ui", component)) + const sources = await Promise.all( + componentFiles.map(async (file) => readFile(path.join(root, file), "utf8")), + ) + const source = sources.join("\n") + + items[component] = { + name: component, + type: "component", + description: `${toTitle(component)} component wrapper for Base UI and Tailwind CSS.`, + dependencies: collectPackageDependencies(source), + localDependencies: collectLocalDependencies(source, component, components, utils), + files: componentFiles.map((file) => ({ + path: file, + target: stripSourcePrefix(file), + })), + } +} + +const manifest = { + name: "base-ui-tailwind", + version: packageJson.version ?? "0.0.0", + generatedAt: new Date().toISOString(), + command: "base-ui-tailwind", + configFile: "base-ui-tailwind.json", + dependencies: { + "@base-ui/react": packageJson.dependencies?.["@base-ui/react"], + "clsx": packageJson.dependencies?.clsx, + "lucide-react": packageJson.dependencies?.["lucide-react"], + "tailwind-merge": packageJson.dependencies?.["tailwind-merge"], + }, + items, +} + +await writeFile(outputPath, `${JSON.stringify(manifest, null, 2)}\n`) +console.log(`Generated manifest.json with ${Object.keys(items).length} items.`) + +async function listDirectories(directory) { + const entries = await readdir(directory, { withFileTypes: true }) + return entries + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .sort((a, b) => a.localeCompare(b)) +} + +async function listFiles(relativeOrAbsoluteDirectory) { + const absoluteDirectory = path.isAbsolute(relativeOrAbsoluteDirectory) + ? relativeOrAbsoluteDirectory + : path.join(root, relativeOrAbsoluteDirectory) + const relativeDirectory = path.relative(root, absoluteDirectory) + const entries = await readdir(absoluteDirectory, { withFileTypes: true }) + const files = [] + + for (const entry of entries) { + const relativePath = path.join(relativeDirectory, entry.name) + const absolutePath = path.join(absoluteDirectory, entry.name) + if (entry.isDirectory()) { + files.push(...(await listFiles(absolutePath))) + } else if (entry.isFile()) { + files.push(relativePath.split(path.sep).join("/")) + } + } + + return files.sort((a, b) => a.localeCompare(b)) +} + +function collectPackageDependencies(source) { + const dependencies = new Set() + const importPattern = /from\s+["']([^"']+)["']|import\s+["']([^"']+)["']/g + + for (const match of source.matchAll(importPattern)) { + const specifier = match[1] ?? match[2] + if (!specifier || specifier.startsWith(".") || specifier.startsWith("@/")) { + continue + } + + dependencies.add(getPackageName(specifier)) + } + + return [...dependencies].sort((a, b) => a.localeCompare(b)) +} + +function collectLocalDependencies(source, component, components, utils) { + const dependencies = new Set() + const localPattern = /from\s+["']@\/([^"']+)["']|import\s+["']@\/([^"']+)["']/g + + for (const match of source.matchAll(localPattern)) { + const specifier = match[1] ?? match[2] + if (!specifier) { + continue + } + + const componentMatch = specifier.match(/^components\/ui\/([^/]+)/) + if (componentMatch && componentMatch[1] !== component && components.includes(componentMatch[1])) { + dependencies.add(componentMatch[1]) + continue + } + + const utilMatch = specifier.match(/^lib\/([^/]+)/) + if (utilMatch) { + const utilPath = utils.find( + (file) => file === `src/lib/${utilMatch[1]}.ts` || file === `src/lib/${utilMatch[1]}.tsx`, + ) + if (utilPath) { + dependencies.add(`utils/${path.basename(utilPath, path.extname(utilPath))}`) + } + } + } + + return [...dependencies].sort((a, b) => a.localeCompare(b)) +} + +function stripSourcePrefix(file) { + return file.startsWith("src/") ? file.slice("src/".length) : file +} + +function getPackageName(specifier) { + if (specifier.startsWith("@")) { + const [scope, name] = specifier.split("/") + return `${scope}/${name}` + } + + return specifier.split("/")[0] +} + +function toTitle(value) { + return value + .split("-") + .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) + .join(" ") +} diff --git a/scripts/normalize-component-docs.mjs b/scripts/normalize-component-docs.mjs new file mode 100644 index 0000000..a4b0665 --- /dev/null +++ b/scripts/normalize-component-docs.mjs @@ -0,0 +1,338 @@ +import fs from "node:fs" +import path from "node:path" + +const root = process.cwd() +const contentDir = path.join(root, "site/src/content/components") +const uiDir = path.join(root, "src/components/ui") +const examplesDir = path.join(root, "site/src/examples/components") +const finished = new Set(["menu", "context-menu", "navigation-menu"]) + +const names = { + "alert-dialog": "AlertDialog", + "checkbox-group": "CheckboxGroup", + "context-menu": "ContextMenu", + "navigation-menu": "NavigationMenu", + "number-field": "NumberField", + "otp-field": "OtpField", + "preview-card": "PreviewCard", + "scroll-area": "ScrollArea", + "toggle-group": "ToggleGroup", +} + +const officialSlugs = { + "otp-field": "otp-field", +} + +for (const file of fs.readdirSync(contentDir).sort()) { + if (!file.endsWith(".mdx")) continue + + const slug = file.replace(/\.mdx$/, "") + if (finished.has(slug)) continue + + const filePath = path.join(contentDir, file) + const current = fs.readFileSync(filePath, "utf8") + const title = current.match(/^# (.+)$/m)?.[1] ?? titleCase(slug) + const component = names[slug] ?? title.replace(/[^A-Za-z0-9]/g, "") + const parts = readParts(slug) + const exampleSrc = `components/${slug}/${slug}.tsx` + const hasTopExample = fs.existsSync(path.join(examplesDir, slug, `${slug}.tsx`)) + const intro = readIntro(current, title) + const baseStyle = readSectionCode(current, "Base UI Style") ?? makeBaseStyle(slug, component, parts) + const shadcnStyle = + readSectionCode(current, "Shadcn Style") ?? + readSectionCode(current, "Named Import Style") ?? + makeNamedStyle(slug, component, parts) + const examples = readExamples(current, title, slug, exampleSrc, hasTopExample) + + const next = [ + `# ${title}`, + "", + intro || `${title} wraps Base UI's ${title.toLowerCase()} primitive with the Tailwind classes from the official Base UI example.`, + "", + hasTopExample ? `::example{src="${exampleSrc}"}` : "", + "", + "## Anatomy", + "", + "### Base UI Style", + "", + fenced(baseStyle), + "", + "### Shadcn Style", + "", + fenced(shadcnStyle), + "", + "## Composition", + "", + `Use the following composition to build \`${component}\`:`, + "", + "```txt", + makeComposition(component, parts).join("\n"), + "```", + "", + "## Examples", + "", + examples.trim(), + "", + makeApi(slug, title, component, parts), + "", + ] + .filter((line, index, array) => !(line === "" && array[index - 1] === "")) + .join("\n") + + fs.writeFileSync(filePath, next) +} + +function readParts(slug) { + const indexPath = path.join(uiDir, slug, "index.ts") + if (!fs.existsSync(indexPath)) return ["Root"] + + const source = fs.readFileSync(indexPath, "utf8") + const objectMatch = source.match(/const\s+\w+\s*=\s*\{([\s\S]*?)\n\}/) + if (!objectMatch) return ["Root"] + + const parts = [] + for (const line of objectMatch[1].split("\n")) { + const match = line.match(/^\s*([A-Za-z][A-Za-z0-9]*):/) + if (!match) continue + const part = match[1] + if (part[0] === part[0].toLowerCase()) continue + if (!parts.includes(part)) parts.push(part) + } + return parts.length ? parts : ["Root"] +} + +function readIntro(source, title) { + const start = source.indexOf(`# ${title}`) + if (start === -1) return "" + let rest = source.slice(start + title.length + 3) + const stops = ["\n`] + for (const part of parts.filter((part) => part !== "Root").slice(0, 5)) { + lines.push(` <${component}.${part} />`) + } + lines.push(``) + return lines.join("\n") +} + +function makeNamedStyle(slug, component, parts) { + const named = parts.map((part) => (part === "Root" ? component : `${component}${part}`)) + return [ + "import {", + ...named.slice(0, 8).map((name) => ` ${name},`), + `} from "@/components/ui/${slug}"`, + ].join("\n") +} + +function makeComposition(component, parts) { + const has = (part) => parts.includes(part) + const portalChildren = [] + if (has("Backdrop")) portalChildren.push(`${component}Backdrop`) + if (has("Positioner")) { + const popupChildren = [] + for (const part of ["Arrow", "Viewport", "List", "Collection", "Group", "Item", "Empty"]) { + if (has(part)) popupChildren.push(`${component}${part}`) + } + portalChildren.push({ + label: `${component}Positioner`, + children: has("Popup") ? [{ label: `${component}Popup`, children: popupChildren }] : popupChildren, + }) + } else if (has("Popup")) { + portalChildren.push(`${component}Popup`) + } + + const children = [] + const leading = ["Trigger", "Label", "Input", "Control", "Track", "Thumb", "Image", "Fallback", "Group"] + for (const part of leading) { + if (has(part)) children.push(`${component}${part}`) + } + if (has("Portal")) { + children.push({ label: `${component}Portal`, children: portalChildren }) + } + for (const part of parts) { + if (part === "Root" || leading.includes(part) || part === "Portal" || part === "Backdrop" || part === "Positioner" || part === "Popup") { + continue + } + const label = part === "Separator" ? `${component}.Separator` : `${component}${part}` + if (!treeHas(children, label)) children.push(label) + } + return renderTree({ label: component, children }) +} + +function treeHas(children, label) { + for (const child of children) { + if (typeof child === "string" && child === label) return true + if (typeof child === "object") { + if (child.label === label) return true + if (treeHas(child.children ?? [], label)) return true + } + } + return false +} + +function renderTree(node, prefix = "") { + const lines = [prefix ? `${prefix}${node.label}` : node.label] + const children = node.children ?? [] + children.forEach((child, index) => { + const last = index === children.length - 1 + const branch = last ? "└── " : "├── " + const nextPrefix = prefix + (last ? " " : "│ ") + if (typeof child === "string") { + lines.push(`${prefix}${branch}${child}`) + } else { + lines.push(`${prefix}${branch}${child.label}`) + lines.push(...renderChildren(child.children ?? [], nextPrefix)) + } + }) + return lines +} + +function renderChildren(children, prefix) { + const lines = [] + children.forEach((child, index) => { + const last = index === children.length - 1 + const branch = last ? "└── " : "├── " + const nextPrefix = prefix + (last ? " " : "│ ") + if (typeof child === "string") { + lines.push(`${prefix}${branch}${child}`) + } else { + lines.push(`${prefix}${branch}${child.label}`) + lines.push(...renderChildren(child.children ?? [], nextPrefix)) + } + }) + return lines +} + +function makeApi(slug, title, component, parts) { + const official = `https://base-ui.com/react/components/${officialSlugs[slug] ?? slug}#api-reference` + const sections = parts.map((part) => makeApiPart(component, part)).join("\n\n") + return [ + "## API Reference", + "", + `Official API: [Base UI ${title} API](${official}).`, + "", + `This wrapper preserves the underlying Base UI ${title} API. Styled parts forward \`className\`, \`style\`, and \`render\` where Base UI supports them.`, + "", + sections, + ].join("\n") +} + +function makeApiPart(component, part) { + const heading = part === "Root" ? "Root" : part + const label = part === "Root" ? component : `${component}.${part}` + const rows = apiRows(part) + return [ + `### ${heading}`, + "", + `\`${label}\` exposes the corresponding Base UI part with the wrapper's Tailwind styles.`, + "", + "| Prop | Type | Default | Description |", + "| --- | --- | --- | --- |", + ...rows, + ].join("\n") +} + +function apiRows(part) { + if (part === "Root") { + return [ + "| `defaultValue` / `defaultOpen` | `any` | - | Initial uncontrolled value or open state when supported. |", + "| `value` / `open` | `any` | - | Controlled value or open state when supported. |", + "| `onValueChange` / `onOpenChange` | `function` | - | Called when controlled state changes. |", + "| `children` | `React.ReactNode` | - | Child parts rendered inside the root. |", + ] + } + if (part === "Portal") { + return [ + "| `container` | `HTMLElement \\| RefObject` | `document.body` | Element that receives portal content. |", + "| `keepMounted` | `boolean` | `false` | Keeps children mounted when closed. |", + "| `children` | `React.ReactNode` | - | Floating content. |", + ] + } + if (part === "Positioner") { + return [ + "| `side` | `Side` | - | Preferred side for floating content. |", + "| `align` | `Align` | - | Alignment on the selected side. |", + "| `sideOffset` | `number \\| OffsetFunction` | `0` | Distance from the anchor. |", + "| `collisionAvoidance` | `CollisionAvoidance` | - | Controls flip and shift behavior. |", + "| `className` | `string \\| (state) => string` | - | Classes for placement state. |", + ] + } + if (["Trigger", "Item", "LinkItem", "Link", "Button", "Close", "Action"].includes(part)) { + return [ + "| `disabled` | `boolean` | `false` | Prevents user interaction when supported. |", + "| `onClick` | `function` | - | Called when the element is pressed. |", + "| `className` | `string \\| (state) => string` | - | Classes for interactive state. |", + "| `render` | `ReactElement \\| (props, state) => ReactElement` | - | Replaces the rendered element. |", + "| `children` | `React.ReactNode` | - | Visible content. |", + ] + } + if (["CheckboxItem", "RadioGroup", "RadioItem"].includes(part)) { + return [ + "| `checked` / `value` | `any` | - | Controlled checked or selected state when supported. |", + "| `defaultChecked` / `defaultValue` | `any` | - | Initial uncontrolled state when supported. |", + "| `onCheckedChange` / `onValueChange` | `function` | - | Called when selection changes. |", + "| `disabled` | `boolean` | `false` | Prevents user interaction. |", + "| `className` | `string \\| (state) => string` | - | Classes for checked, highlighted, and disabled state. |", + ] + } + return [ + "| `className` | `string \\| (state) => string` | - | Classes for the part state. |", + "| `style` | `React.CSSProperties \\| (state) => React.CSSProperties` | - | Inline style or state-based style. |", + "| `render` | `ReactElement \\| (props, state) => ReactElement` | - | Replaces the rendered element when supported. |", + "| `children` | `React.ReactNode` | - | Child content when the part accepts children. |", + ] +} + +function fenced(value) { + return ["```tsx", value.trim(), "```"].join("\n") +} + +function titleCase(slug) { + return slug + .split("-") + .map((word) => word[0].toUpperCase() + word.slice(1)) + .join(" ") +} + +function escapeRegExp(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") +} diff --git a/src/components/ui/accordion/header.tsx b/src/components/ui/accordion/header.tsx new file mode 100644 index 0000000..60e6474 --- /dev/null +++ b/src/components/ui/accordion/header.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Accordion as BaseAccordion } from "@base-ui/react/accordion" +import { cn } from "@/lib/utils" + +export type AccordionHeaderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAccordionHeader = BaseAccordion.Header as React.ElementType + +export const AccordionHeader = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionHeader.displayName = "AccordionHeader" diff --git a/src/components/ui/accordion/index.ts b/src/components/ui/accordion/index.ts new file mode 100644 index 0000000..175aa55 --- /dev/null +++ b/src/components/ui/accordion/index.ts @@ -0,0 +1,30 @@ +import { AccordionRoot } from "./root" +import { AccordionItem } from "./item" +import { AccordionHeader } from "./header" +import { AccordionTrigger } from "./trigger" +import { AccordionPanel } from "./panel" + +const AccordionPrimitive = { + Root: AccordionRoot, + Item: AccordionItem, + Header: AccordionHeader, + Trigger: AccordionTrigger, + Panel: AccordionPanel, +} + +export default AccordionPrimitive + +export { + AccordionRoot as Accordion, + AccordionRoot, + AccordionItem, + AccordionHeader, + AccordionTrigger, + AccordionPanel, +} + +export type { AccordionRootProps } from "./root" +export type { AccordionItemProps } from "./item" +export type { AccordionHeaderProps } from "./header" +export type { AccordionTriggerProps } from "./trigger" +export type { AccordionPanelProps } from "./panel" diff --git a/src/components/ui/accordion/item.tsx b/src/components/ui/accordion/item.tsx new file mode 100644 index 0000000..8457890 --- /dev/null +++ b/src/components/ui/accordion/item.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Accordion as BaseAccordion } from "@base-ui/react/accordion" +import { cn } from "@/lib/utils" + +export type AccordionItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAccordionItem = BaseAccordion.Item as React.ElementType + +export const AccordionItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionItem.displayName = "AccordionItem" diff --git a/src/components/ui/accordion/panel.tsx b/src/components/ui/accordion/panel.tsx new file mode 100644 index 0000000..3b03f58 --- /dev/null +++ b/src/components/ui/accordion/panel.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Accordion as BaseAccordion } from "@base-ui/react/accordion" +import { cn } from "@/lib/utils" + +export type AccordionPanelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAccordionPanel = BaseAccordion.Panel as React.ElementType + +export const AccordionPanel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionPanel.displayName = "AccordionPanel" diff --git a/src/components/ui/accordion/root.tsx b/src/components/ui/accordion/root.tsx new file mode 100644 index 0000000..3d0b294 --- /dev/null +++ b/src/components/ui/accordion/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Accordion as BaseAccordion } from "@base-ui/react/accordion" +import { cn } from "@/lib/utils" + +export type AccordionRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAccordionRoot = BaseAccordion.Root as React.ElementType + +export const AccordionRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionRoot.displayName = "AccordionRoot" diff --git a/src/components/ui/accordion/trigger.tsx b/src/components/ui/accordion/trigger.tsx new file mode 100644 index 0000000..008b00d --- /dev/null +++ b/src/components/ui/accordion/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Accordion as BaseAccordion } from "@base-ui/react/accordion" +import { cn } from "@/lib/utils" + +export type AccordionTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAccordionTrigger = BaseAccordion.Trigger as React.ElementType + +export const AccordionTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionTrigger.displayName = "AccordionTrigger" diff --git a/src/components/ui/alert-dialog/backdrop.tsx b/src/components/ui/alert-dialog/backdrop.tsx new file mode 100644 index 0000000..b1207b6 --- /dev/null +++ b/src/components/ui/alert-dialog/backdrop.tsx @@ -0,0 +1,27 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogBackdrop = BaseAlertDialog.Backdrop as React.ElementType + +export const AlertDialogBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogBackdrop.displayName = "AlertDialogBackdrop" diff --git a/src/components/ui/alert-dialog/close.tsx b/src/components/ui/alert-dialog/close.tsx new file mode 100644 index 0000000..b49e0f0 --- /dev/null +++ b/src/components/ui/alert-dialog/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogClose = BaseAlertDialog.Close as React.ElementType + +export const AlertDialogClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogClose.displayName = "AlertDialogClose" diff --git a/src/components/ui/alert-dialog/content.tsx b/src/components/ui/alert-dialog/content.tsx new file mode 100644 index 0000000..57b9c29 --- /dev/null +++ b/src/components/ui/alert-dialog/content.tsx @@ -0,0 +1,20 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { AlertDialogBackdrop } from "./backdrop" +import { AlertDialogPortal } from "./portal" +import { AlertDialogPopup, type AlertDialogPopupProps } from "./popup" + +export type AlertDialogContentProps = AlertDialogPopupProps + +export const AlertDialogContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + ), +) + +AlertDialogContent.displayName = "AlertDialogContent" diff --git a/src/components/ui/alert-dialog/description.tsx b/src/components/ui/alert-dialog/description.tsx new file mode 100644 index 0000000..6a003ae --- /dev/null +++ b/src/components/ui/alert-dialog/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogDescription = BaseAlertDialog.Description as React.ElementType + +export const AlertDialogDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogDescription.displayName = "AlertDialogDescription" diff --git a/src/components/ui/alert-dialog/index.ts b/src/components/ui/alert-dialog/index.ts new file mode 100644 index 0000000..ae22916 --- /dev/null +++ b/src/components/ui/alert-dialog/index.ts @@ -0,0 +1,52 @@ +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { AlertDialogRoot } from "./root" +import { AlertDialogBackdrop } from "./backdrop" +import { AlertDialogClose } from "./close" +import { AlertDialogDescription } from "./description" +import { AlertDialogPopup } from "./popup" +import { AlertDialogPortal } from "./portal" +import { AlertDialogTitle } from "./title" +import { AlertDialogTrigger } from "./trigger" +import { AlertDialogViewport } from "./viewport" +import { AlertDialogContent } from "./content" + +const AlertDialogPrimitive = { + Root: AlertDialogRoot, + Backdrop: AlertDialogBackdrop, + Close: AlertDialogClose, + Description: AlertDialogDescription, + Popup: AlertDialogPopup, + Portal: AlertDialogPortal, + Title: AlertDialogTitle, + Trigger: AlertDialogTrigger, + Viewport: AlertDialogViewport, + createHandle: BaseAlertDialog.createHandle, +} + +export default AlertDialogPrimitive + +export { + AlertDialogRoot as AlertDialog, + AlertDialogRoot, + AlertDialogBackdrop, + AlertDialogClose, + AlertDialogDescription, + AlertDialogPopup, + AlertDialogPortal, + AlertDialogTitle, + AlertDialogTrigger, + AlertDialogViewport, + AlertDialogContent, + BaseAlertDialog, +} + +export type { AlertDialogRootProps } from "./root" +export type { AlertDialogBackdropProps } from "./backdrop" +export type { AlertDialogCloseProps } from "./close" +export type { AlertDialogDescriptionProps } from "./description" +export type { AlertDialogPopupProps } from "./popup" +export type { AlertDialogPortalProps } from "./portal" +export type { AlertDialogTitleProps } from "./title" +export type { AlertDialogTriggerProps } from "./trigger" +export type { AlertDialogViewportProps } from "./viewport" +export type { AlertDialogContentProps } from "./content" diff --git a/src/components/ui/alert-dialog/popup.tsx b/src/components/ui/alert-dialog/popup.tsx new file mode 100644 index 0000000..2030d70 --- /dev/null +++ b/src/components/ui/alert-dialog/popup.tsx @@ -0,0 +1,27 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogPopup = BaseAlertDialog.Popup as React.ElementType + +export const AlertDialogPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogPopup.displayName = "AlertDialogPopup" diff --git a/src/components/ui/alert-dialog/portal.tsx b/src/components/ui/alert-dialog/portal.tsx new file mode 100644 index 0000000..fff4f4a --- /dev/null +++ b/src/components/ui/alert-dialog/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type AlertDialogPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogPortal = BaseAlertDialog.Portal as React.ElementType + +export const AlertDialogPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +AlertDialogPortal.displayName = "AlertDialogPortal" diff --git a/src/components/ui/alert-dialog/root.tsx b/src/components/ui/alert-dialog/root.tsx new file mode 100644 index 0000000..72c333a --- /dev/null +++ b/src/components/ui/alert-dialog/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogRoot = BaseAlertDialog.Root as React.ElementType + +export const AlertDialogRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogRoot.displayName = "AlertDialogRoot" diff --git a/src/components/ui/alert-dialog/title.tsx b/src/components/ui/alert-dialog/title.tsx new file mode 100644 index 0000000..b885b87 --- /dev/null +++ b/src/components/ui/alert-dialog/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogTitle = BaseAlertDialog.Title as React.ElementType + +export const AlertDialogTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogTitle.displayName = "AlertDialogTitle" diff --git a/src/components/ui/alert-dialog/trigger.tsx b/src/components/ui/alert-dialog/trigger.tsx new file mode 100644 index 0000000..adddb00 --- /dev/null +++ b/src/components/ui/alert-dialog/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogTrigger = BaseAlertDialog.Trigger as React.ElementType + +export const AlertDialogTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogTrigger.displayName = "AlertDialogTrigger" diff --git a/src/components/ui/alert-dialog/viewport.tsx b/src/components/ui/alert-dialog/viewport.tsx new file mode 100644 index 0000000..9dc9ef3 --- /dev/null +++ b/src/components/ui/alert-dialog/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog" +import { cn } from "@/lib/utils" + +export type AlertDialogViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAlertDialogViewport = BaseAlertDialog.Viewport as React.ElementType + +export const AlertDialogViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogViewport.displayName = "AlertDialogViewport" diff --git a/src/components/ui/autocomplete/arrow.tsx b/src/components/ui/autocomplete/arrow.tsx new file mode 100644 index 0000000..169c9e9 --- /dev/null +++ b/src/components/ui/autocomplete/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteArrow = BaseAutocomplete.Arrow as React.ElementType + +export const AutocompleteArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteArrow.displayName = "AutocompleteArrow" diff --git a/src/components/ui/autocomplete/backdrop.tsx b/src/components/ui/autocomplete/backdrop.tsx new file mode 100644 index 0000000..9d77373 --- /dev/null +++ b/src/components/ui/autocomplete/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteBackdrop = BaseAutocomplete.Backdrop as React.ElementType + +export const AutocompleteBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteBackdrop.displayName = "AutocompleteBackdrop" diff --git a/src/components/ui/autocomplete/clear.tsx b/src/components/ui/autocomplete/clear.tsx new file mode 100644 index 0000000..23339e1 --- /dev/null +++ b/src/components/ui/autocomplete/clear.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteClearProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteClear = BaseAutocomplete.Clear as React.ElementType + +export const AutocompleteClear = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteClear.displayName = "AutocompleteClear" diff --git a/src/components/ui/autocomplete/collection.tsx b/src/components/ui/autocomplete/collection.tsx new file mode 100644 index 0000000..515b75a --- /dev/null +++ b/src/components/ui/autocomplete/collection.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteCollectionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteCollection = BaseAutocomplete.Collection as React.ElementType + +export const AutocompleteCollection = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteCollection.displayName = "AutocompleteCollection" diff --git a/src/components/ui/autocomplete/empty.tsx b/src/components/ui/autocomplete/empty.tsx new file mode 100644 index 0000000..ddacea3 --- /dev/null +++ b/src/components/ui/autocomplete/empty.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteEmptyProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteEmpty = BaseAutocomplete.Empty as React.ElementType + +export const AutocompleteEmpty = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteEmpty.displayName = "AutocompleteEmpty" diff --git a/src/components/ui/autocomplete/group-label.tsx b/src/components/ui/autocomplete/group-label.tsx new file mode 100644 index 0000000..759aaf7 --- /dev/null +++ b/src/components/ui/autocomplete/group-label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteGroupLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteGroupLabel = BaseAutocomplete.GroupLabel as React.ElementType + +export const AutocompleteGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteGroupLabel.displayName = "AutocompleteGroupLabel" diff --git a/src/components/ui/autocomplete/group.tsx b/src/components/ui/autocomplete/group.tsx new file mode 100644 index 0000000..4553de7 --- /dev/null +++ b/src/components/ui/autocomplete/group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteGroup = BaseAutocomplete.Group as React.ElementType + +export const AutocompleteGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteGroup.displayName = "AutocompleteGroup" diff --git a/src/components/ui/autocomplete/icon.tsx b/src/components/ui/autocomplete/icon.tsx new file mode 100644 index 0000000..7cd0acb --- /dev/null +++ b/src/components/ui/autocomplete/icon.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteIconProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteIcon = BaseAutocomplete.Icon as React.ElementType + +export const AutocompleteIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteIcon.displayName = "AutocompleteIcon" diff --git a/src/components/ui/autocomplete/index.ts b/src/components/ui/autocomplete/index.ts new file mode 100644 index 0000000..9747a78 --- /dev/null +++ b/src/components/ui/autocomplete/index.ts @@ -0,0 +1,92 @@ +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { AutocompleteRoot } from "./root" +import { AutocompleteValue } from "./value" +import { AutocompleteTrigger } from "./trigger" +import { AutocompleteInput } from "./input" +import { AutocompleteInputGroup } from "./input-group" +import { AutocompleteIcon } from "./icon" +import { AutocompleteClear } from "./clear" +import { AutocompleteList } from "./list" +import { AutocompletePortal } from "./portal" +import { AutocompleteBackdrop } from "./backdrop" +import { AutocompletePositioner } from "./positioner" +import { AutocompletePopup } from "./popup" +import { AutocompleteArrow } from "./arrow" +import { AutocompleteGroup } from "./group" +import { AutocompleteGroupLabel } from "./group-label" +import { AutocompleteItem } from "./item" +import { AutocompleteRow } from "./row" +import { AutocompleteCollection } from "./collection" +import { AutocompleteEmpty } from "./empty" + +const AutocompletePrimitive = { + Root: AutocompleteRoot, + Value: AutocompleteValue, + Trigger: AutocompleteTrigger, + Input: AutocompleteInput, + InputGroup: AutocompleteInputGroup, + Icon: AutocompleteIcon, + Clear: AutocompleteClear, + List: AutocompleteList, + Portal: AutocompletePortal, + Backdrop: AutocompleteBackdrop, + Positioner: AutocompletePositioner, + Popup: AutocompletePopup, + Arrow: AutocompleteArrow, + Group: AutocompleteGroup, + GroupLabel: AutocompleteGroupLabel, + Item: AutocompleteItem, + Row: AutocompleteRow, + Collection: AutocompleteCollection, + Empty: AutocompleteEmpty, + Separator: BaseAutocomplete.Separator, + Status: BaseAutocomplete.Status, + useFilter: BaseAutocomplete.useFilter, + useFilteredItems: BaseAutocomplete.useFilteredItems, +} + +export default AutocompletePrimitive + +export { + AutocompleteRoot as Autocomplete, + AutocompleteRoot, + AutocompleteValue, + AutocompleteTrigger, + AutocompleteInput, + AutocompleteInputGroup, + AutocompleteIcon, + AutocompleteClear, + AutocompleteList, + AutocompletePortal, + AutocompleteBackdrop, + AutocompletePositioner, + AutocompletePopup, + AutocompleteArrow, + AutocompleteGroup, + AutocompleteGroupLabel, + AutocompleteItem, + AutocompleteRow, + AutocompleteCollection, + AutocompleteEmpty, + BaseAutocomplete, +} + +export type { AutocompleteRootProps } from "./root" +export type { AutocompleteValueProps } from "./value" +export type { AutocompleteTriggerProps } from "./trigger" +export type { AutocompleteInputProps } from "./input" +export type { AutocompleteInputGroupProps } from "./input-group" +export type { AutocompleteIconProps } from "./icon" +export type { AutocompleteClearProps } from "./clear" +export type { AutocompleteListProps } from "./list" +export type { AutocompletePortalProps } from "./portal" +export type { AutocompleteBackdropProps } from "./backdrop" +export type { AutocompletePositionerProps } from "./positioner" +export type { AutocompletePopupProps } from "./popup" +export type { AutocompleteArrowProps } from "./arrow" +export type { AutocompleteGroupProps } from "./group" +export type { AutocompleteGroupLabelProps } from "./group-label" +export type { AutocompleteItemProps } from "./item" +export type { AutocompleteRowProps } from "./row" +export type { AutocompleteCollectionProps } from "./collection" +export type { AutocompleteEmptyProps } from "./empty" diff --git a/src/components/ui/autocomplete/input-group.tsx b/src/components/ui/autocomplete/input-group.tsx new file mode 100644 index 0000000..4f074d7 --- /dev/null +++ b/src/components/ui/autocomplete/input-group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteInputGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteInputGroup = BaseAutocomplete.InputGroup as React.ElementType + +export const AutocompleteInputGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteInputGroup.displayName = "AutocompleteInputGroup" diff --git a/src/components/ui/autocomplete/input.tsx b/src/components/ui/autocomplete/input.tsx new file mode 100644 index 0000000..12473c7 --- /dev/null +++ b/src/components/ui/autocomplete/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteInput = BaseAutocomplete.Input as React.ElementType + +export const AutocompleteInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteInput.displayName = "AutocompleteInput" diff --git a/src/components/ui/autocomplete/item.tsx b/src/components/ui/autocomplete/item.tsx new file mode 100644 index 0000000..eeb4cdc --- /dev/null +++ b/src/components/ui/autocomplete/item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteItem = BaseAutocomplete.Item as React.ElementType + +export const AutocompleteItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteItem.displayName = "AutocompleteItem" diff --git a/src/components/ui/autocomplete/list.tsx b/src/components/ui/autocomplete/list.tsx new file mode 100644 index 0000000..443e75c --- /dev/null +++ b/src/components/ui/autocomplete/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteList = BaseAutocomplete.List as React.ElementType + +export const AutocompleteList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteList.displayName = "AutocompleteList" diff --git a/src/components/ui/autocomplete/popup.tsx b/src/components/ui/autocomplete/popup.tsx new file mode 100644 index 0000000..e00e31d --- /dev/null +++ b/src/components/ui/autocomplete/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompletePopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompletePopup = BaseAutocomplete.Popup as React.ElementType +const defaultAutocompletePopupClassName = + "w-[var(--anchor-width)] max-w-[var(--available-width)] border border-neutral-950 bg-white text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const AutocompletePopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompletePopup.displayName = "AutocompletePopup" diff --git a/src/components/ui/autocomplete/portal.tsx b/src/components/ui/autocomplete/portal.tsx new file mode 100644 index 0000000..82a6806 --- /dev/null +++ b/src/components/ui/autocomplete/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompletePortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompletePortal = BaseAutocomplete.Portal as React.ElementType + +export const AutocompletePortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompletePortal.displayName = "AutocompletePortal" diff --git a/src/components/ui/autocomplete/positioner.tsx b/src/components/ui/autocomplete/positioner.tsx new file mode 100644 index 0000000..7bcd037 --- /dev/null +++ b/src/components/ui/autocomplete/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompletePositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompletePositioner = BaseAutocomplete.Positioner as React.ElementType + +export const AutocompletePositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompletePositioner.displayName = "AutocompletePositioner" diff --git a/src/components/ui/autocomplete/root.tsx b/src/components/ui/autocomplete/root.tsx new file mode 100644 index 0000000..b6a6cb1 --- /dev/null +++ b/src/components/ui/autocomplete/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteRoot = BaseAutocomplete.Root as React.ElementType + +export const AutocompleteRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteRoot.displayName = "AutocompleteRoot" diff --git a/src/components/ui/autocomplete/row.tsx b/src/components/ui/autocomplete/row.tsx new file mode 100644 index 0000000..53c52af --- /dev/null +++ b/src/components/ui/autocomplete/row.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteRowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteRow = BaseAutocomplete.Row as React.ElementType + +export const AutocompleteRow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteRow.displayName = "AutocompleteRow" diff --git a/src/components/ui/autocomplete/trigger.tsx b/src/components/ui/autocomplete/trigger.tsx new file mode 100644 index 0000000..b931608 --- /dev/null +++ b/src/components/ui/autocomplete/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteTrigger = BaseAutocomplete.Trigger as React.ElementType + +export const AutocompleteTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteTrigger.displayName = "AutocompleteTrigger" diff --git a/src/components/ui/autocomplete/value.tsx b/src/components/ui/autocomplete/value.tsx new file mode 100644 index 0000000..e6abe76 --- /dev/null +++ b/src/components/ui/autocomplete/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete" +import { cn } from "@/lib/utils" + +export type AutocompleteValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAutocompleteValue = BaseAutocomplete.Value as React.ElementType + +export const AutocompleteValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteValue.displayName = "AutocompleteValue" diff --git a/src/components/ui/avatar/fallback.tsx b/src/components/ui/avatar/fallback.tsx new file mode 100644 index 0000000..3dc783f --- /dev/null +++ b/src/components/ui/avatar/fallback.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Avatar as BaseAvatar } from "@base-ui/react/avatar" +import { cn } from "@/lib/utils" + +export type AvatarFallbackProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAvatarFallback = BaseAvatar.Fallback as React.ElementType + +export const AvatarFallback = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AvatarFallback.displayName = "AvatarFallback" diff --git a/src/components/ui/avatar/image.tsx b/src/components/ui/avatar/image.tsx new file mode 100644 index 0000000..450a933 --- /dev/null +++ b/src/components/ui/avatar/image.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Avatar as BaseAvatar } from "@base-ui/react/avatar" +import { cn } from "@/lib/utils" + +export type AvatarImageProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAvatarImage = BaseAvatar.Image as React.ElementType + +export const AvatarImage = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AvatarImage.displayName = "AvatarImage" diff --git a/src/components/ui/avatar/index.ts b/src/components/ui/avatar/index.ts new file mode 100644 index 0000000..7c19bef --- /dev/null +++ b/src/components/ui/avatar/index.ts @@ -0,0 +1,22 @@ +import { AvatarRoot } from "./root" +import { AvatarImage } from "./image" +import { AvatarFallback } from "./fallback" + +const AvatarPrimitive = { + Root: AvatarRoot, + Image: AvatarImage, + Fallback: AvatarFallback, +} + +export default AvatarPrimitive + +export { + AvatarRoot as Avatar, + AvatarRoot, + AvatarImage, + AvatarFallback, +} + +export type { AvatarRootProps } from "./root" +export type { AvatarImageProps } from "./image" +export type { AvatarFallbackProps } from "./fallback" diff --git a/src/components/ui/avatar/root.tsx b/src/components/ui/avatar/root.tsx new file mode 100644 index 0000000..42ea2aa --- /dev/null +++ b/src/components/ui/avatar/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Avatar as BaseAvatar } from "@base-ui/react/avatar" +import { cn } from "@/lib/utils" + +export type AvatarRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseAvatarRoot = BaseAvatar.Root as React.ElementType + +export const AvatarRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AvatarRoot.displayName = "AvatarRoot" diff --git a/src/components/ui/button/index.ts b/src/components/ui/button/index.ts new file mode 100644 index 0000000..2b5c37f --- /dev/null +++ b/src/components/ui/button/index.ts @@ -0,0 +1,4 @@ +import { Button } from "./root" + +export { Button, type ButtonProps } from "./root" +export default Button diff --git a/src/components/ui/button/root.tsx b/src/components/ui/button/root.tsx new file mode 100644 index 0000000..649e619 --- /dev/null +++ b/src/components/ui/button/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Button as BaseButton } from "@base-ui/react/button" +import { cn } from "@/lib/utils" + +export type ButtonProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseButtonElement = BaseButton as React.ElementType + +export const Button = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Button.displayName = "Button" diff --git a/src/components/ui/checkbox-group/index.ts b/src/components/ui/checkbox-group/index.ts new file mode 100644 index 0000000..3dd6db8 --- /dev/null +++ b/src/components/ui/checkbox-group/index.ts @@ -0,0 +1,4 @@ +import { CheckboxGroup } from "./root" + +export { CheckboxGroup, type CheckboxGroupProps } from "./root" +export default CheckboxGroup diff --git a/src/components/ui/checkbox-group/root.tsx b/src/components/ui/checkbox-group/root.tsx new file mode 100644 index 0000000..d202579 --- /dev/null +++ b/src/components/ui/checkbox-group/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { CheckboxGroup as BaseCheckboxGroup } from "@base-ui/react/checkbox-group" +import { cn } from "@/lib/utils" + +export type CheckboxGroupProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseCheckboxGroupElement = BaseCheckboxGroup as React.ElementType + +export const CheckboxGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CheckboxGroup.displayName = "CheckboxGroup" diff --git a/src/components/ui/checkbox/index.ts b/src/components/ui/checkbox/index.ts new file mode 100644 index 0000000..2f1bc73 --- /dev/null +++ b/src/components/ui/checkbox/index.ts @@ -0,0 +1,18 @@ +import { CheckboxRoot } from "./root" +import { CheckboxIndicator } from "./indicator" + +const CheckboxPrimitive = { + Root: CheckboxRoot, + Indicator: CheckboxIndicator, +} + +export default CheckboxPrimitive + +export { + CheckboxRoot as Checkbox, + CheckboxRoot, + CheckboxIndicator, +} + +export type { CheckboxRootProps } from "./root" +export type { CheckboxIndicatorProps } from "./indicator" diff --git a/src/components/ui/checkbox/indicator.tsx b/src/components/ui/checkbox/indicator.tsx new file mode 100644 index 0000000..395fcee --- /dev/null +++ b/src/components/ui/checkbox/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox" +import { cn } from "@/lib/utils" + +export type CheckboxIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseCheckboxIndicator = BaseCheckbox.Indicator as React.ElementType + +export const CheckboxIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CheckboxIndicator.displayName = "CheckboxIndicator" diff --git a/src/components/ui/checkbox/root.tsx b/src/components/ui/checkbox/root.tsx new file mode 100644 index 0000000..4697673 --- /dev/null +++ b/src/components/ui/checkbox/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox" +import { cn } from "@/lib/utils" + +export type CheckboxRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseCheckboxRoot = BaseCheckbox.Root as React.ElementType + +export const CheckboxRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CheckboxRoot.displayName = "CheckboxRoot" diff --git a/src/components/ui/collapsible/index.ts b/src/components/ui/collapsible/index.ts new file mode 100644 index 0000000..38b96dd --- /dev/null +++ b/src/components/ui/collapsible/index.ts @@ -0,0 +1,22 @@ +import { CollapsibleRoot } from "./root" +import { CollapsibleTrigger } from "./trigger" +import { CollapsiblePanel } from "./panel" + +const CollapsiblePrimitive = { + Root: CollapsibleRoot, + Trigger: CollapsibleTrigger, + Panel: CollapsiblePanel, +} + +export default CollapsiblePrimitive + +export { + CollapsibleRoot as Collapsible, + CollapsibleRoot, + CollapsibleTrigger, + CollapsiblePanel, +} + +export type { CollapsibleRootProps } from "./root" +export type { CollapsibleTriggerProps } from "./trigger" +export type { CollapsiblePanelProps } from "./panel" diff --git a/src/components/ui/collapsible/panel.tsx b/src/components/ui/collapsible/panel.tsx new file mode 100644 index 0000000..2cae774 --- /dev/null +++ b/src/components/ui/collapsible/panel.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Collapsible as BaseCollapsible } from "@base-ui/react/collapsible" +import { cn } from "@/lib/utils" + +export type CollapsiblePanelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseCollapsiblePanel = BaseCollapsible.Panel as React.ElementType + +export const CollapsiblePanel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CollapsiblePanel.displayName = "CollapsiblePanel" diff --git a/src/components/ui/collapsible/root.tsx b/src/components/ui/collapsible/root.tsx new file mode 100644 index 0000000..aa2d54f --- /dev/null +++ b/src/components/ui/collapsible/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Collapsible as BaseCollapsible } from "@base-ui/react/collapsible" +import { cn } from "@/lib/utils" + +export type CollapsibleRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseCollapsibleRoot = BaseCollapsible.Root as React.ElementType + +export const CollapsibleRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CollapsibleRoot.displayName = "CollapsibleRoot" diff --git a/src/components/ui/collapsible/trigger.tsx b/src/components/ui/collapsible/trigger.tsx new file mode 100644 index 0000000..58bdea0 --- /dev/null +++ b/src/components/ui/collapsible/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Collapsible as BaseCollapsible } from "@base-ui/react/collapsible" +import { cn } from "@/lib/utils" + +export type CollapsibleTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseCollapsibleTrigger = BaseCollapsible.Trigger as React.ElementType + +export const CollapsibleTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CollapsibleTrigger.displayName = "CollapsibleTrigger" diff --git a/src/components/ui/combobox/arrow.tsx b/src/components/ui/combobox/arrow.tsx new file mode 100644 index 0000000..6146148 --- /dev/null +++ b/src/components/ui/combobox/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxArrow = BaseCombobox.Arrow as React.ElementType + +export const ComboboxArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxArrow.displayName = "ComboboxArrow" diff --git a/src/components/ui/combobox/backdrop.tsx b/src/components/ui/combobox/backdrop.tsx new file mode 100644 index 0000000..ae50fb7 --- /dev/null +++ b/src/components/ui/combobox/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxBackdrop = BaseCombobox.Backdrop as React.ElementType + +export const ComboboxBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxBackdrop.displayName = "ComboboxBackdrop" diff --git a/src/components/ui/combobox/chip-remove.tsx b/src/components/ui/combobox/chip-remove.tsx new file mode 100644 index 0000000..9898131 --- /dev/null +++ b/src/components/ui/combobox/chip-remove.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxChipRemoveProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxChipRemove = BaseCombobox.ChipRemove as React.ElementType + +export const ComboboxChipRemove = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxChipRemove.displayName = "ComboboxChipRemove" diff --git a/src/components/ui/combobox/chip.tsx b/src/components/ui/combobox/chip.tsx new file mode 100644 index 0000000..bae7c42 --- /dev/null +++ b/src/components/ui/combobox/chip.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxChipProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxChip = BaseCombobox.Chip as React.ElementType + +export const ComboboxChip = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxChip.displayName = "ComboboxChip" diff --git a/src/components/ui/combobox/chips.tsx b/src/components/ui/combobox/chips.tsx new file mode 100644 index 0000000..8e9f3f2 --- /dev/null +++ b/src/components/ui/combobox/chips.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxChipsProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxChips = BaseCombobox.Chips as React.ElementType + +export const ComboboxChips = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxChips.displayName = "ComboboxChips" diff --git a/src/components/ui/combobox/clear.tsx b/src/components/ui/combobox/clear.tsx new file mode 100644 index 0000000..51026ee --- /dev/null +++ b/src/components/ui/combobox/clear.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxClearProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxClear = BaseCombobox.Clear as React.ElementType + +export const ComboboxClear = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxClear.displayName = "ComboboxClear" diff --git a/src/components/ui/combobox/collection.tsx b/src/components/ui/combobox/collection.tsx new file mode 100644 index 0000000..bd59b65 --- /dev/null +++ b/src/components/ui/combobox/collection.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxCollectionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxCollection = BaseCombobox.Collection as React.ElementType + +export const ComboboxCollection = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxCollection.displayName = "ComboboxCollection" diff --git a/src/components/ui/combobox/empty.tsx b/src/components/ui/combobox/empty.tsx new file mode 100644 index 0000000..66c57ac --- /dev/null +++ b/src/components/ui/combobox/empty.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxEmptyProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxEmpty = BaseCombobox.Empty as React.ElementType + +export const ComboboxEmpty = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxEmpty.displayName = "ComboboxEmpty" diff --git a/src/components/ui/combobox/group-label.tsx b/src/components/ui/combobox/group-label.tsx new file mode 100644 index 0000000..e954c81 --- /dev/null +++ b/src/components/ui/combobox/group-label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxGroupLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxGroupLabel = BaseCombobox.GroupLabel as React.ElementType + +export const ComboboxGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxGroupLabel.displayName = "ComboboxGroupLabel" diff --git a/src/components/ui/combobox/group.tsx b/src/components/ui/combobox/group.tsx new file mode 100644 index 0000000..08b0535 --- /dev/null +++ b/src/components/ui/combobox/group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxGroup = BaseCombobox.Group as React.ElementType + +export const ComboboxGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxGroup.displayName = "ComboboxGroup" diff --git a/src/components/ui/combobox/icon.tsx b/src/components/ui/combobox/icon.tsx new file mode 100644 index 0000000..16cf06d --- /dev/null +++ b/src/components/ui/combobox/icon.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxIconProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxIcon = BaseCombobox.Icon as React.ElementType + +export const ComboboxIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxIcon.displayName = "ComboboxIcon" diff --git a/src/components/ui/combobox/index.ts b/src/components/ui/combobox/index.ts new file mode 100644 index 0000000..6e577fb --- /dev/null +++ b/src/components/ui/combobox/index.ts @@ -0,0 +1,112 @@ +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { ComboboxRoot } from "./root" +import { ComboboxLabel } from "./label" +import { ComboboxValue } from "./value" +import { ComboboxInput } from "./input" +import { ComboboxInputGroup } from "./input-group" +import { ComboboxTrigger } from "./trigger" +import { ComboboxList } from "./list" +import { ComboboxPortal } from "./portal" +import { ComboboxBackdrop } from "./backdrop" +import { ComboboxPositioner } from "./positioner" +import { ComboboxPopup } from "./popup" +import { ComboboxArrow } from "./arrow" +import { ComboboxIcon } from "./icon" +import { ComboboxGroup } from "./group" +import { ComboboxGroupLabel } from "./group-label" +import { ComboboxItem } from "./item" +import { ComboboxItemIndicator } from "./item-indicator" +import { ComboboxChips } from "./chips" +import { ComboboxChip } from "./chip" +import { ComboboxChipRemove } from "./chip-remove" +import { ComboboxRow } from "./row" +import { ComboboxCollection } from "./collection" +import { ComboboxEmpty } from "./empty" +import { ComboboxClear } from "./clear" + +const ComboboxPrimitive = { + Root: ComboboxRoot, + Label: ComboboxLabel, + Value: ComboboxValue, + Input: ComboboxInput, + InputGroup: ComboboxInputGroup, + Trigger: ComboboxTrigger, + List: ComboboxList, + Portal: ComboboxPortal, + Backdrop: ComboboxBackdrop, + Positioner: ComboboxPositioner, + Popup: ComboboxPopup, + Arrow: ComboboxArrow, + Icon: ComboboxIcon, + Group: ComboboxGroup, + GroupLabel: ComboboxGroupLabel, + Item: ComboboxItem, + ItemIndicator: ComboboxItemIndicator, + Chips: ComboboxChips, + Chip: ComboboxChip, + ChipRemove: ComboboxChipRemove, + Row: ComboboxRow, + Collection: ComboboxCollection, + Empty: ComboboxEmpty, + Clear: ComboboxClear, + Separator: BaseCombobox.Separator, + Status: BaseCombobox.Status, + useFilter: BaseCombobox.useFilter, + useFilteredItems: BaseCombobox.useFilteredItems, +} + +export default ComboboxPrimitive + +export { + ComboboxRoot as Combobox, + ComboboxRoot, + ComboboxLabel, + ComboboxValue, + ComboboxInput, + ComboboxInputGroup, + ComboboxTrigger, + ComboboxList, + ComboboxPortal, + ComboboxBackdrop, + ComboboxPositioner, + ComboboxPopup, + ComboboxArrow, + ComboboxIcon, + ComboboxGroup, + ComboboxGroupLabel, + ComboboxItem, + ComboboxItemIndicator, + ComboboxChips, + ComboboxChip, + ComboboxChipRemove, + ComboboxRow, + ComboboxCollection, + ComboboxEmpty, + ComboboxClear, + BaseCombobox, +} + +export type { ComboboxRootProps } from "./root" +export type { ComboboxLabelProps } from "./label" +export type { ComboboxValueProps } from "./value" +export type { ComboboxInputProps } from "./input" +export type { ComboboxInputGroupProps } from "./input-group" +export type { ComboboxTriggerProps } from "./trigger" +export type { ComboboxListProps } from "./list" +export type { ComboboxPortalProps } from "./portal" +export type { ComboboxBackdropProps } from "./backdrop" +export type { ComboboxPositionerProps } from "./positioner" +export type { ComboboxPopupProps } from "./popup" +export type { ComboboxArrowProps } from "./arrow" +export type { ComboboxIconProps } from "./icon" +export type { ComboboxGroupProps } from "./group" +export type { ComboboxGroupLabelProps } from "./group-label" +export type { ComboboxItemProps } from "./item" +export type { ComboboxItemIndicatorProps } from "./item-indicator" +export type { ComboboxChipsProps } from "./chips" +export type { ComboboxChipProps } from "./chip" +export type { ComboboxChipRemoveProps } from "./chip-remove" +export type { ComboboxRowProps } from "./row" +export type { ComboboxCollectionProps } from "./collection" +export type { ComboboxEmptyProps } from "./empty" +export type { ComboboxClearProps } from "./clear" diff --git a/src/components/ui/combobox/input-group.tsx b/src/components/ui/combobox/input-group.tsx new file mode 100644 index 0000000..0454ef5 --- /dev/null +++ b/src/components/ui/combobox/input-group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxInputGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxInputGroup = BaseCombobox.InputGroup as React.ElementType + +export const ComboboxInputGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + input]:pr-10 has-[.combobox-clear]:[&>input]:pr-18", + className, + )} + {...props} + /> + ), +) + +ComboboxInputGroup.displayName = "ComboboxInputGroup" diff --git a/src/components/ui/combobox/input.tsx b/src/components/ui/combobox/input.tsx new file mode 100644 index 0000000..47fef59 --- /dev/null +++ b/src/components/ui/combobox/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxInput = BaseCombobox.Input as React.ElementType + +export const ComboboxInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxInput.displayName = "ComboboxInput" diff --git a/src/components/ui/combobox/item-indicator.tsx b/src/components/ui/combobox/item-indicator.tsx new file mode 100644 index 0000000..6a03412 --- /dev/null +++ b/src/components/ui/combobox/item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxItemIndicator = BaseCombobox.ItemIndicator as React.ElementType + +export const ComboboxItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxItemIndicator.displayName = "ComboboxItemIndicator" diff --git a/src/components/ui/combobox/item.tsx b/src/components/ui/combobox/item.tsx new file mode 100644 index 0000000..c096a96 --- /dev/null +++ b/src/components/ui/combobox/item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxItem = BaseCombobox.Item as React.ElementType + +export const ComboboxItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxItem.displayName = "ComboboxItem" diff --git a/src/components/ui/combobox/label.tsx b/src/components/ui/combobox/label.tsx new file mode 100644 index 0000000..f5e3830 --- /dev/null +++ b/src/components/ui/combobox/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxLabel = BaseCombobox.Label as React.ElementType + +export const ComboboxLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxLabel.displayName = "ComboboxLabel" diff --git a/src/components/ui/combobox/list.tsx b/src/components/ui/combobox/list.tsx new file mode 100644 index 0000000..4c21d2a --- /dev/null +++ b/src/components/ui/combobox/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxList = BaseCombobox.List as React.ElementType + +export const ComboboxList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxList.displayName = "ComboboxList" diff --git a/src/components/ui/combobox/popup.tsx b/src/components/ui/combobox/popup.tsx new file mode 100644 index 0000000..544d729 --- /dev/null +++ b/src/components/ui/combobox/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxPopup = BaseCombobox.Popup as React.ElementType +const defaultComboboxPopupClassName = + "w-[var(--anchor-width)] max-w-[var(--available-width)] origin-[var(--transform-origin)] border border-neutral-950 bg-white text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] transition-[transform,opacity] duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:duration-150 data-ending-style:ease-out data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const ComboboxPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxPopup.displayName = "ComboboxPopup" diff --git a/src/components/ui/combobox/portal.tsx b/src/components/ui/combobox/portal.tsx new file mode 100644 index 0000000..3c2be7c --- /dev/null +++ b/src/components/ui/combobox/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxPortal = BaseCombobox.Portal as React.ElementType + +export const ComboboxPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxPortal.displayName = "ComboboxPortal" diff --git a/src/components/ui/combobox/positioner.tsx b/src/components/ui/combobox/positioner.tsx new file mode 100644 index 0000000..e873002 --- /dev/null +++ b/src/components/ui/combobox/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxPositioner = BaseCombobox.Positioner as React.ElementType + +export const ComboboxPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxPositioner.displayName = "ComboboxPositioner" diff --git a/src/components/ui/combobox/root.tsx b/src/components/ui/combobox/root.tsx new file mode 100644 index 0000000..ed2bde2 --- /dev/null +++ b/src/components/ui/combobox/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxRoot = BaseCombobox.Root as React.ElementType + +export const ComboboxRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxRoot.displayName = "ComboboxRoot" diff --git a/src/components/ui/combobox/row.tsx b/src/components/ui/combobox/row.tsx new file mode 100644 index 0000000..dfcce0b --- /dev/null +++ b/src/components/ui/combobox/row.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxRowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxRow = BaseCombobox.Row as React.ElementType + +export const ComboboxRow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxRow.displayName = "ComboboxRow" diff --git a/src/components/ui/combobox/trigger.tsx b/src/components/ui/combobox/trigger.tsx new file mode 100644 index 0000000..3a68cee --- /dev/null +++ b/src/components/ui/combobox/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxTrigger = BaseCombobox.Trigger as React.ElementType + +export const ComboboxTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxTrigger.displayName = "ComboboxTrigger" diff --git a/src/components/ui/combobox/value.tsx b/src/components/ui/combobox/value.tsx new file mode 100644 index 0000000..d8366e2 --- /dev/null +++ b/src/components/ui/combobox/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Combobox as BaseCombobox } from "@base-ui/react/combobox" +import { cn } from "@/lib/utils" + +export type ComboboxValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseComboboxValue = BaseCombobox.Value as React.ElementType + +export const ComboboxValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxValue.displayName = "ComboboxValue" diff --git a/src/components/ui/context-menu/arrow.tsx b/src/components/ui/context-menu/arrow.tsx new file mode 100644 index 0000000..90ae4c6 --- /dev/null +++ b/src/components/ui/context-menu/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuArrow = BaseContextMenu.Arrow as React.ElementType + +export const ContextMenuArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuArrow.displayName = "ContextMenuArrow" diff --git a/src/components/ui/context-menu/backdrop.tsx b/src/components/ui/context-menu/backdrop.tsx new file mode 100644 index 0000000..1a0e138 --- /dev/null +++ b/src/components/ui/context-menu/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuBackdrop = BaseContextMenu.Backdrop as React.ElementType + +export const ContextMenuBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuBackdrop.displayName = "ContextMenuBackdrop" diff --git a/src/components/ui/context-menu/checkbox-item-indicator.tsx b/src/components/ui/context-menu/checkbox-item-indicator.tsx new file mode 100644 index 0000000..dcf8f20 --- /dev/null +++ b/src/components/ui/context-menu/checkbox-item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuCheckboxItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuCheckboxItemIndicator = BaseContextMenu.CheckboxItemIndicator as React.ElementType + +export const ContextMenuCheckboxItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuCheckboxItemIndicator.displayName = "ContextMenuCheckboxItemIndicator" diff --git a/src/components/ui/context-menu/checkbox-item.tsx b/src/components/ui/context-menu/checkbox-item.tsx new file mode 100644 index 0000000..7e37aa5 --- /dev/null +++ b/src/components/ui/context-menu/checkbox-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuCheckboxItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuCheckboxItem = BaseContextMenu.CheckboxItem as React.ElementType + +export const ContextMenuCheckboxItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuCheckboxItem.displayName = "ContextMenuCheckboxItem" diff --git a/src/components/ui/context-menu/group-label.tsx b/src/components/ui/context-menu/group-label.tsx new file mode 100644 index 0000000..46ef892 --- /dev/null +++ b/src/components/ui/context-menu/group-label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuGroupLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuGroupLabel = BaseContextMenu.GroupLabel as React.ElementType + +export const ContextMenuGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuGroupLabel.displayName = "ContextMenuGroupLabel" diff --git a/src/components/ui/context-menu/group.tsx b/src/components/ui/context-menu/group.tsx new file mode 100644 index 0000000..06eeabf --- /dev/null +++ b/src/components/ui/context-menu/group.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuGroup = BaseContextMenu.Group as React.ElementType + +export const ContextMenuGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuGroup.displayName = "ContextMenuGroup" diff --git a/src/components/ui/context-menu/index.ts b/src/components/ui/context-menu/index.ts new file mode 100644 index 0000000..921f562 --- /dev/null +++ b/src/components/ui/context-menu/index.ts @@ -0,0 +1,85 @@ +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { ContextMenuRoot } from "./root" +import { ContextMenuTrigger } from "./trigger" +import { ContextMenuBackdrop } from "./backdrop" +import { ContextMenuPortal } from "./portal" +import { ContextMenuPositioner } from "./positioner" +import { ContextMenuPopup } from "./popup" +import { ContextMenuArrow } from "./arrow" +import { ContextMenuGroup } from "./group" +import { ContextMenuGroupLabel } from "./group-label" +import { ContextMenuItem } from "./item" +import { ContextMenuCheckboxItem } from "./checkbox-item" +import { ContextMenuCheckboxItemIndicator } from "./checkbox-item-indicator" +import { ContextMenuLinkItem } from "./link-item" +import { ContextMenuRadioGroup } from "./radio-group" +import { ContextMenuRadioItem } from "./radio-item" +import { ContextMenuRadioItemIndicator } from "./radio-item-indicator" +import { ContextMenuSubmenuRoot } from "./submenu-root" +import { ContextMenuSubmenuTrigger } from "./submenu-trigger" + +const ContextMenuPrimitive = { + Root: ContextMenuRoot, + Trigger: ContextMenuTrigger, + Backdrop: ContextMenuBackdrop, + Portal: ContextMenuPortal, + Positioner: ContextMenuPositioner, + Popup: ContextMenuPopup, + Arrow: ContextMenuArrow, + Group: ContextMenuGroup, + GroupLabel: ContextMenuGroupLabel, + Item: ContextMenuItem, + CheckboxItem: ContextMenuCheckboxItem, + CheckboxItemIndicator: ContextMenuCheckboxItemIndicator, + LinkItem: ContextMenuLinkItem, + RadioGroup: ContextMenuRadioGroup, + RadioItem: ContextMenuRadioItem, + RadioItemIndicator: ContextMenuRadioItemIndicator, + SubmenuRoot: ContextMenuSubmenuRoot, + SubmenuTrigger: ContextMenuSubmenuTrigger, + Separator: BaseContextMenu.Separator, +} + +export default ContextMenuPrimitive + +export { + ContextMenuRoot as ContextMenu, + ContextMenuRoot, + ContextMenuTrigger, + ContextMenuBackdrop, + ContextMenuPortal, + ContextMenuPositioner, + ContextMenuPopup, + ContextMenuArrow, + ContextMenuGroup, + ContextMenuGroupLabel, + ContextMenuItem, + ContextMenuCheckboxItem, + ContextMenuCheckboxItemIndicator, + ContextMenuLinkItem, + ContextMenuRadioGroup, + ContextMenuRadioItem, + ContextMenuRadioItemIndicator, + ContextMenuSubmenuRoot, + ContextMenuSubmenuTrigger, + BaseContextMenu, +} + +export type { ContextMenuRootProps } from "./root" +export type { ContextMenuTriggerProps } from "./trigger" +export type { ContextMenuBackdropProps } from "./backdrop" +export type { ContextMenuPortalProps } from "./portal" +export type { ContextMenuPositionerProps } from "./positioner" +export type { ContextMenuPopupProps } from "./popup" +export type { ContextMenuArrowProps } from "./arrow" +export type { ContextMenuGroupProps } from "./group" +export type { ContextMenuGroupLabelProps } from "./group-label" +export type { ContextMenuItemProps } from "./item" +export type { ContextMenuCheckboxItemProps } from "./checkbox-item" +export type { ContextMenuCheckboxItemIndicatorProps } from "./checkbox-item-indicator" +export type { ContextMenuLinkItemProps } from "./link-item" +export type { ContextMenuRadioGroupProps } from "./radio-group" +export type { ContextMenuRadioItemProps } from "./radio-item" +export type { ContextMenuRadioItemIndicatorProps } from "./radio-item-indicator" +export type { ContextMenuSubmenuRootProps } from "./submenu-root" +export type { ContextMenuSubmenuTriggerProps } from "./submenu-trigger" diff --git a/src/components/ui/context-menu/item.tsx b/src/components/ui/context-menu/item.tsx new file mode 100644 index 0000000..4ab899b --- /dev/null +++ b/src/components/ui/context-menu/item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuItem = BaseContextMenu.Item as React.ElementType + +export const ContextMenuItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuItem.displayName = "ContextMenuItem" diff --git a/src/components/ui/context-menu/link-item.tsx b/src/components/ui/context-menu/link-item.tsx new file mode 100644 index 0000000..efc98a0 --- /dev/null +++ b/src/components/ui/context-menu/link-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuLinkItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuLinkItem = BaseContextMenu.LinkItem as React.ElementType + +export const ContextMenuLinkItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuLinkItem.displayName = "ContextMenuLinkItem" diff --git a/src/components/ui/context-menu/popup.tsx b/src/components/ui/context-menu/popup.tsx new file mode 100644 index 0000000..542fb0a --- /dev/null +++ b/src/components/ui/context-menu/popup.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuPopup = BaseContextMenu.Popup as React.ElementType + +export const ContextMenuPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuPopup.displayName = "ContextMenuPopup" diff --git a/src/components/ui/context-menu/portal.tsx b/src/components/ui/context-menu/portal.tsx new file mode 100644 index 0000000..dd8890b --- /dev/null +++ b/src/components/ui/context-menu/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuPortal = BaseContextMenu.Portal as React.ElementType + +export const ContextMenuPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuPortal.displayName = "ContextMenuPortal" diff --git a/src/components/ui/context-menu/positioner.tsx b/src/components/ui/context-menu/positioner.tsx new file mode 100644 index 0000000..248eee8 --- /dev/null +++ b/src/components/ui/context-menu/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuPositioner = BaseContextMenu.Positioner as React.ElementType + +export const ContextMenuPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuPositioner.displayName = "ContextMenuPositioner" diff --git a/src/components/ui/context-menu/radio-group.tsx b/src/components/ui/context-menu/radio-group.tsx new file mode 100644 index 0000000..0506bda --- /dev/null +++ b/src/components/ui/context-menu/radio-group.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuRadioGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuRadioGroup = BaseContextMenu.RadioGroup as React.ElementType + +export const ContextMenuRadioGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRadioGroup.displayName = "ContextMenuRadioGroup" diff --git a/src/components/ui/context-menu/radio-item-indicator.tsx b/src/components/ui/context-menu/radio-item-indicator.tsx new file mode 100644 index 0000000..5054013 --- /dev/null +++ b/src/components/ui/context-menu/radio-item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuRadioItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuRadioItemIndicator = BaseContextMenu.RadioItemIndicator as React.ElementType + +export const ContextMenuRadioItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRadioItemIndicator.displayName = "ContextMenuRadioItemIndicator" diff --git a/src/components/ui/context-menu/radio-item.tsx b/src/components/ui/context-menu/radio-item.tsx new file mode 100644 index 0000000..bf587ae --- /dev/null +++ b/src/components/ui/context-menu/radio-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuRadioItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuRadioItem = BaseContextMenu.RadioItem as React.ElementType + +export const ContextMenuRadioItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRadioItem.displayName = "ContextMenuRadioItem" diff --git a/src/components/ui/context-menu/root.tsx b/src/components/ui/context-menu/root.tsx new file mode 100644 index 0000000..9d9b584 --- /dev/null +++ b/src/components/ui/context-menu/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuRoot = BaseContextMenu.Root as React.ElementType + +export const ContextMenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRoot.displayName = "ContextMenuRoot" diff --git a/src/components/ui/context-menu/submenu-root.tsx b/src/components/ui/context-menu/submenu-root.tsx new file mode 100644 index 0000000..1ac3bfc --- /dev/null +++ b/src/components/ui/context-menu/submenu-root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuSubmenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuSubmenuRoot = BaseContextMenu.SubmenuRoot as React.ElementType + +export const ContextMenuSubmenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuSubmenuRoot.displayName = "ContextMenuSubmenuRoot" diff --git a/src/components/ui/context-menu/submenu-trigger.tsx b/src/components/ui/context-menu/submenu-trigger.tsx new file mode 100644 index 0000000..13f7dc4 --- /dev/null +++ b/src/components/ui/context-menu/submenu-trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuSubmenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuSubmenuTrigger = BaseContextMenu.SubmenuTrigger as React.ElementType + +export const ContextMenuSubmenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuSubmenuTrigger.displayName = "ContextMenuSubmenuTrigger" diff --git a/src/components/ui/context-menu/trigger.tsx b/src/components/ui/context-menu/trigger.tsx new file mode 100644 index 0000000..f3b5af9 --- /dev/null +++ b/src/components/ui/context-menu/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu" +import { cn } from "@/lib/utils" + +export type ContextMenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuTrigger = BaseContextMenu.Trigger as React.ElementType + +export const ContextMenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuTrigger.displayName = "ContextMenuTrigger" diff --git a/src/components/ui/dialog/backdrop.tsx b/src/components/ui/dialog/backdrop.tsx new file mode 100644 index 0000000..a7eddaa --- /dev/null +++ b/src/components/ui/dialog/backdrop.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogBackdrop = BaseDialog.Backdrop as React.ElementType +const defaultDialogBackdropClassName = + "fixed inset-0 min-h-dvh bg-black opacity-20 transition-opacity duration-[350ms] ease-out data-ending-style:duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:opacity-50 supports-[-webkit-touch-callout:none]:absolute" + +export const DialogBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogBackdrop.displayName = "DialogBackdrop" diff --git a/src/components/ui/dialog/close.tsx b/src/components/ui/dialog/close.tsx new file mode 100644 index 0000000..d39f221 --- /dev/null +++ b/src/components/ui/dialog/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogClose = BaseDialog.Close as React.ElementType + +export const DialogClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogClose.displayName = "DialogClose" diff --git a/src/components/ui/dialog/content.tsx b/src/components/ui/dialog/content.tsx new file mode 100644 index 0000000..cb144d2 --- /dev/null +++ b/src/components/ui/dialog/content.tsx @@ -0,0 +1,20 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { DialogBackdrop } from "./backdrop" +import { DialogPortal } from "./portal" +import { DialogPopup, type DialogPopupProps } from "./popup" + +export type DialogContentProps = DialogPopupProps + +export const DialogContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + ), +) + +DialogContent.displayName = "DialogContent" diff --git a/src/components/ui/dialog/description.tsx b/src/components/ui/dialog/description.tsx new file mode 100644 index 0000000..505c77a --- /dev/null +++ b/src/components/ui/dialog/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogDescription = BaseDialog.Description as React.ElementType + +export const DialogDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogDescription.displayName = "DialogDescription" diff --git a/src/components/ui/dialog/index.ts b/src/components/ui/dialog/index.ts new file mode 100644 index 0000000..f93c2fe --- /dev/null +++ b/src/components/ui/dialog/index.ts @@ -0,0 +1,52 @@ +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { DialogBackdrop } from "./backdrop" +import { DialogClose } from "./close" +import { DialogDescription } from "./description" +import { DialogPopup } from "./popup" +import { DialogPortal } from "./portal" +import { DialogRoot } from "./root" +import { DialogViewport } from "./viewport" +import { DialogTitle } from "./title" +import { DialogTrigger } from "./trigger" +import { DialogContent } from "./content" + +const DialogPrimitive = { + Backdrop: DialogBackdrop, + Close: DialogClose, + Description: DialogDescription, + Popup: DialogPopup, + Portal: DialogPortal, + Root: DialogRoot, + Viewport: DialogViewport, + Title: DialogTitle, + Trigger: DialogTrigger, + createHandle: BaseDialog.createHandle, +} + +export default DialogPrimitive + +export { + DialogRoot as Dialog, + DialogBackdrop, + DialogClose, + DialogDescription, + DialogPopup, + DialogPortal, + DialogRoot, + DialogViewport, + DialogTitle, + DialogTrigger, + DialogContent, + BaseDialog, +} + +export type { DialogBackdropProps } from "./backdrop" +export type { DialogCloseProps } from "./close" +export type { DialogDescriptionProps } from "./description" +export type { DialogPopupProps } from "./popup" +export type { DialogPortalProps } from "./portal" +export type { DialogRootProps } from "./root" +export type { DialogViewportProps } from "./viewport" +export type { DialogTitleProps } from "./title" +export type { DialogTriggerProps } from "./trigger" +export type { DialogContentProps } from "./content" diff --git a/src/components/ui/dialog/popup.tsx b/src/components/ui/dialog/popup.tsx new file mode 100644 index 0000000..d46005a --- /dev/null +++ b/src/components/ui/dialog/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogPopup = BaseDialog.Popup as React.ElementType +const defaultDialogPopupClassName = + "fixed top-1/2 left-1/2 -mt-8 flex w-96 max-w-[calc(100vw-3rem)] -translate-x-1/2 -translate-y-1/2 flex-col gap-4 bg-white dark:bg-neutral-950 p-4 text-neutral-950 dark:text-white border border-neutral-950 dark:border-white shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] dark:shadow-none transition-[transform,opacity] duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:duration-150 data-ending-style:ease-out data-ending-style:scale-[0.98] data-ending-style:opacity-0 data-starting-style:scale-[0.98] data-starting-style:opacity-0" + +export const DialogPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogPopup.displayName = "DialogPopup" diff --git a/src/components/ui/dialog/portal.tsx b/src/components/ui/dialog/portal.tsx new file mode 100644 index 0000000..685e6c3 --- /dev/null +++ b/src/components/ui/dialog/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type DialogPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogPortal = BaseDialog.Portal as React.ElementType + +export const DialogPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +DialogPortal.displayName = "DialogPortal" diff --git a/src/components/ui/dialog/root.tsx b/src/components/ui/dialog/root.tsx new file mode 100644 index 0000000..d32d6b6 --- /dev/null +++ b/src/components/ui/dialog/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogRoot = BaseDialog.Root as React.ElementType + +export const DialogRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogRoot.displayName = "DialogRoot" diff --git a/src/components/ui/dialog/title.tsx b/src/components/ui/dialog/title.tsx new file mode 100644 index 0000000..1b2a70a --- /dev/null +++ b/src/components/ui/dialog/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogTitle = BaseDialog.Title as React.ElementType + +export const DialogTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogTitle.displayName = "DialogTitle" diff --git a/src/components/ui/dialog/trigger.tsx b/src/components/ui/dialog/trigger.tsx new file mode 100644 index 0000000..d9c092e --- /dev/null +++ b/src/components/ui/dialog/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogTrigger = BaseDialog.Trigger as React.ElementType + +export const DialogTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogTrigger.displayName = "DialogTrigger" diff --git a/src/components/ui/dialog/viewport.tsx b/src/components/ui/dialog/viewport.tsx new file mode 100644 index 0000000..8cda9cb --- /dev/null +++ b/src/components/ui/dialog/viewport.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogViewport = BaseDialog.Viewport as React.ElementType +const defaultDialogViewportClassName = + "fixed inset-0 flex items-center justify-center overflow-hidden py-6 [@media(min-height:600px)]:pb-12 [@media(min-height:600px)]:pt-8" + +export const DialogViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogViewport.displayName = "DialogViewport" diff --git a/src/components/ui/drawer/backdrop.tsx b/src/components/ui/drawer/backdrop.tsx new file mode 100644 index 0000000..6380865 --- /dev/null +++ b/src/components/ui/drawer/backdrop.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerBackdrop = BaseDrawer.Backdrop as React.ElementType +const defaultDrawerBackdropClassName = + "[--backdrop-opacity:0.2] [--bleed:3rem] dark:[--backdrop-opacity:0.7] fixed inset-0 min-h-dvh bg-black opacity-[calc(var(--backdrop-opacity)*(1-var(--drawer-swipe-progress)))] transition-opacity duration-[450ms] ease-[cubic-bezier(0.32,0.72,0,1)] data-swiping:duration-0 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0 data-[ending-style]:duration-[calc(var(--drawer-swipe-strength)*400ms)] supports-[-webkit-touch-callout:none]:absolute" + +export const DrawerBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerBackdrop.displayName = "DrawerBackdrop" diff --git a/src/components/ui/drawer/close.tsx b/src/components/ui/drawer/close.tsx new file mode 100644 index 0000000..83563b6 --- /dev/null +++ b/src/components/ui/drawer/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerClose = BaseDrawer.Close as React.ElementType + +export const DrawerClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerClose.displayName = "DrawerClose" diff --git a/src/components/ui/drawer/content.tsx b/src/components/ui/drawer/content.tsx new file mode 100644 index 0000000..8754ad2 --- /dev/null +++ b/src/components/ui/drawer/content.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerContent = BaseDrawer.Content as React.ElementType + +export const DrawerContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerContent.displayName = "DrawerContent" diff --git a/src/components/ui/drawer/description.tsx b/src/components/ui/drawer/description.tsx new file mode 100644 index 0000000..df642ed --- /dev/null +++ b/src/components/ui/drawer/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerDescription = BaseDrawer.Description as React.ElementType + +export const DrawerDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerDescription.displayName = "DrawerDescription" diff --git a/src/components/ui/drawer/indent-background.tsx b/src/components/ui/drawer/indent-background.tsx new file mode 100644 index 0000000..2ca9ee5 --- /dev/null +++ b/src/components/ui/drawer/indent-background.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerIndentBackgroundProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerIndentBackground = BaseDrawer.IndentBackground as React.ElementType + +export const DrawerIndentBackground = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerIndentBackground.displayName = "DrawerIndentBackground" diff --git a/src/components/ui/drawer/indent.tsx b/src/components/ui/drawer/indent.tsx new file mode 100644 index 0000000..56f3e7f --- /dev/null +++ b/src/components/ui/drawer/indent.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerIndentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerIndent = BaseDrawer.Indent as React.ElementType + +export const DrawerIndent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerIndent.displayName = "DrawerIndent" diff --git a/src/components/ui/drawer/index.ts b/src/components/ui/drawer/index.ts new file mode 100644 index 0000000..9934c4e --- /dev/null +++ b/src/components/ui/drawer/index.ts @@ -0,0 +1,70 @@ +import { DrawerBackdrop } from "./backdrop" +import { DrawerClose } from "./close" +import { DrawerContent } from "./content" +import { DrawerDescription } from "./description" +import { DrawerIndent } from "./indent" +import { DrawerIndentBackground } from "./indent-background" +import { DrawerPopup } from "./popup" +import { DrawerPortal } from "./portal" +import { DrawerProvider } from "./provider" +import { DrawerRoot } from "./root" +import { DrawerSwipeArea } from "./swipe-area" +import { DrawerTitle } from "./title" +import { DrawerTrigger } from "./trigger" +import { DrawerViewport } from "./viewport" +import { DrawerVirtualKeyboardProvider } from "./virtual-keyboard-provider" + +const DrawerPrimitive = { + Backdrop: DrawerBackdrop, + Close: DrawerClose, + Content: DrawerContent, + Description: DrawerDescription, + Indent: DrawerIndent, + IndentBackground: DrawerIndentBackground, + Popup: DrawerPopup, + Portal: DrawerPortal, + Provider: DrawerProvider, + Root: DrawerRoot, + SwipeArea: DrawerSwipeArea, + Title: DrawerTitle, + Trigger: DrawerTrigger, + Viewport: DrawerViewport, + VirtualKeyboardProvider: DrawerVirtualKeyboardProvider, +} + +export default DrawerPrimitive + +export { + DrawerRoot as Drawer, + DrawerBackdrop, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerIndent, + DrawerIndentBackground, + DrawerPopup, + DrawerPortal, + DrawerProvider, + DrawerRoot, + DrawerSwipeArea, + DrawerTitle, + DrawerTrigger, + DrawerViewport, + DrawerVirtualKeyboardProvider, +} + +export type { DrawerBackdropProps } from "./backdrop" +export type { DrawerCloseProps } from "./close" +export type { DrawerContentProps } from "./content" +export type { DrawerDescriptionProps } from "./description" +export type { DrawerIndentProps } from "./indent" +export type { DrawerIndentBackgroundProps } from "./indent-background" +export type { DrawerPopupProps } from "./popup" +export type { DrawerPortalProps } from "./portal" +export type { DrawerProviderProps } from "./provider" +export type { DrawerRootProps } from "./root" +export type { DrawerSwipeAreaProps } from "./swipe-area" +export type { DrawerTitleProps } from "./title" +export type { DrawerTriggerProps } from "./trigger" +export type { DrawerViewportProps } from "./viewport" +export type { DrawerVirtualKeyboardProviderProps } from "./virtual-keyboard-provider" diff --git a/src/components/ui/drawer/popup.tsx b/src/components/ui/drawer/popup.tsx new file mode 100644 index 0000000..b833a79 --- /dev/null +++ b/src/components/ui/drawer/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerPopup = BaseDrawer.Popup as React.ElementType +const defaultDrawerPopupClassName = + "[--bleed:3rem] supports-[-webkit-touch-callout:none]:[--bleed:0px] h-full w-[calc(20rem+3rem)] max-w-[calc(100vw-3rem+3rem)] -mr-[3rem] border-l border-neutral-950 bg-white p-6 pr-[calc(1.5rem+3rem)] text-neutral-950 outline-none shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] overflow-y-auto overscroll-contain touch-auto [transform:translateX(var(--drawer-swipe-movement-x))] transition-transform duration-[450ms] ease-[cubic-bezier(0.32,0.72,0,1)] data-swiping:select-none data-[ending-style]:[transform:translateX(calc(100%-var(--bleed)+var(--viewport-padding)+2px))] data-[starting-style]:[transform:translateX(calc(100%-var(--bleed)+var(--viewport-padding)+2px))] data-[ending-style]:duration-[calc(var(--drawer-swipe-strength)*400ms)] supports-[-webkit-touch-callout:none]:mr-0 supports-[-webkit-touch-callout:none]:w-[20rem] supports-[-webkit-touch-callout:none]:max-w-[calc(100vw-3rem)] supports-[-webkit-touch-callout:none]:border supports-[-webkit-touch-callout:none]:pr-6 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const DrawerPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerPopup.displayName = "DrawerPopup" diff --git a/src/components/ui/drawer/portal.tsx b/src/components/ui/drawer/portal.tsx new file mode 100644 index 0000000..c028900 --- /dev/null +++ b/src/components/ui/drawer/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type DrawerPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerPortal = BaseDrawer.Portal as React.ElementType + +export const DrawerPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +DrawerPortal.displayName = "DrawerPortal" diff --git a/src/components/ui/drawer/provider.tsx b/src/components/ui/drawer/provider.tsx new file mode 100644 index 0000000..764b496 --- /dev/null +++ b/src/components/ui/drawer/provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerProvider = BaseDrawer.Provider as React.ElementType + +export const DrawerProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerProvider.displayName = "DrawerProvider" diff --git a/src/components/ui/drawer/root.tsx b/src/components/ui/drawer/root.tsx new file mode 100644 index 0000000..c6ee019 --- /dev/null +++ b/src/components/ui/drawer/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerRoot = BaseDrawer.Root as React.ElementType + +export const DrawerRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerRoot.displayName = "DrawerRoot" diff --git a/src/components/ui/drawer/swipe-area.tsx b/src/components/ui/drawer/swipe-area.tsx new file mode 100644 index 0000000..2f49967 --- /dev/null +++ b/src/components/ui/drawer/swipe-area.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerSwipeAreaProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerSwipeArea = BaseDrawer.SwipeArea as React.ElementType + +export const DrawerSwipeArea = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerSwipeArea.displayName = "DrawerSwipeArea" diff --git a/src/components/ui/drawer/title.tsx b/src/components/ui/drawer/title.tsx new file mode 100644 index 0000000..ffdd9af --- /dev/null +++ b/src/components/ui/drawer/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerTitle = BaseDrawer.Title as React.ElementType + +export const DrawerTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerTitle.displayName = "DrawerTitle" diff --git a/src/components/ui/drawer/trigger.tsx b/src/components/ui/drawer/trigger.tsx new file mode 100644 index 0000000..70ae68f --- /dev/null +++ b/src/components/ui/drawer/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerTrigger = BaseDrawer.Trigger as React.ElementType + +export const DrawerTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerTrigger.displayName = "DrawerTrigger" diff --git a/src/components/ui/drawer/viewport.tsx b/src/components/ui/drawer/viewport.tsx new file mode 100644 index 0000000..2519e08 --- /dev/null +++ b/src/components/ui/drawer/viewport.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerViewport = BaseDrawer.Viewport as React.ElementType +const defaultDrawerViewportClassName = + "[--viewport-padding:0px] supports-[-webkit-touch-callout:none]:[--viewport-padding:0.625rem] fixed inset-0 flex items-stretch justify-end p-(--viewport-padding)" + +export const DrawerViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerViewport.displayName = "DrawerViewport" diff --git a/src/components/ui/drawer/virtual-keyboard-provider.tsx b/src/components/ui/drawer/virtual-keyboard-provider.tsx new file mode 100644 index 0000000..fa2dffc --- /dev/null +++ b/src/components/ui/drawer/virtual-keyboard-provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerVirtualKeyboardProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerVirtualKeyboardProvider = BaseDrawer.VirtualKeyboardProvider as React.ElementType + +export const DrawerVirtualKeyboardProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerVirtualKeyboardProvider.displayName = "DrawerVirtualKeyboardProvider" diff --git a/src/components/ui/field/control.tsx b/src/components/ui/field/control.tsx new file mode 100644 index 0000000..ed6a284 --- /dev/null +++ b/src/components/ui/field/control.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldControlProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldControl = BaseField.Control as React.ElementType + +export const FieldControl = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldControl.displayName = "FieldControl" diff --git a/src/components/ui/field/description.tsx b/src/components/ui/field/description.tsx new file mode 100644 index 0000000..0f626ad --- /dev/null +++ b/src/components/ui/field/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldDescription = BaseField.Description as React.ElementType + +export const FieldDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldDescription.displayName = "FieldDescription" diff --git a/src/components/ui/field/error.tsx b/src/components/ui/field/error.tsx new file mode 100644 index 0000000..7aefc48 --- /dev/null +++ b/src/components/ui/field/error.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldErrorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldError = BaseField.Error as React.ElementType + +export const FieldError = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldError.displayName = "FieldError" diff --git a/src/components/ui/field/index.ts b/src/components/ui/field/index.ts new file mode 100644 index 0000000..a116b3c --- /dev/null +++ b/src/components/ui/field/index.ts @@ -0,0 +1,38 @@ +import { FieldRoot } from "./root" +import { FieldLabel } from "./label" +import { FieldError } from "./error" +import { FieldDescription } from "./description" +import { FieldControl } from "./control" +import { FieldValidity } from "./validity" +import { FieldItem } from "./item" + +const FieldPrimitive = { + Root: FieldRoot, + Label: FieldLabel, + Error: FieldError, + Description: FieldDescription, + Control: FieldControl, + Validity: FieldValidity, + Item: FieldItem, +} + +export default FieldPrimitive + +export { + FieldRoot as Field, + FieldRoot, + FieldLabel, + FieldError, + FieldDescription, + FieldControl, + FieldValidity, + FieldItem, +} + +export type { FieldRootProps } from "./root" +export type { FieldLabelProps } from "./label" +export type { FieldErrorProps } from "./error" +export type { FieldDescriptionProps } from "./description" +export type { FieldControlProps } from "./control" +export type { FieldValidityProps } from "./validity" +export type { FieldItemProps } from "./item" diff --git a/src/components/ui/field/item.tsx b/src/components/ui/field/item.tsx new file mode 100644 index 0000000..1cef4b5 --- /dev/null +++ b/src/components/ui/field/item.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldItem = BaseField.Item as React.ElementType + +export const FieldItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldItem.displayName = "FieldItem" diff --git a/src/components/ui/field/label.tsx b/src/components/ui/field/label.tsx new file mode 100644 index 0000000..d9897bd --- /dev/null +++ b/src/components/ui/field/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldLabel = BaseField.Label as React.ElementType + +export const FieldLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldLabel.displayName = "FieldLabel" diff --git a/src/components/ui/field/root.tsx b/src/components/ui/field/root.tsx new file mode 100644 index 0000000..a8210f8 --- /dev/null +++ b/src/components/ui/field/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldRoot = BaseField.Root as React.ElementType + +export const FieldRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldRoot.displayName = "FieldRoot" diff --git a/src/components/ui/field/validity.tsx b/src/components/ui/field/validity.tsx new file mode 100644 index 0000000..8f0b4ab --- /dev/null +++ b/src/components/ui/field/validity.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldValidityProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldValidity = BaseField.Validity as React.ElementType + +export const FieldValidity = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldValidity.displayName = "FieldValidity" diff --git a/src/components/ui/fieldset/index.ts b/src/components/ui/fieldset/index.ts new file mode 100644 index 0000000..2a1ede7 --- /dev/null +++ b/src/components/ui/fieldset/index.ts @@ -0,0 +1,18 @@ +import { FieldsetRoot } from "./root" +import { FieldsetLegend } from "./legend" + +const FieldsetPrimitive = { + Root: FieldsetRoot, + Legend: FieldsetLegend, +} + +export default FieldsetPrimitive + +export { + FieldsetRoot as Fieldset, + FieldsetRoot, + FieldsetLegend, +} + +export type { FieldsetRootProps } from "./root" +export type { FieldsetLegendProps } from "./legend" diff --git a/src/components/ui/fieldset/legend.tsx b/src/components/ui/fieldset/legend.tsx new file mode 100644 index 0000000..5b11855 --- /dev/null +++ b/src/components/ui/fieldset/legend.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Fieldset as BaseFieldset } from "@base-ui/react/fieldset" +import { cn } from "@/lib/utils" + +export type FieldsetLegendProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldsetLegend = BaseFieldset.Legend as React.ElementType + +export const FieldsetLegend = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldsetLegend.displayName = "FieldsetLegend" diff --git a/src/components/ui/fieldset/root.tsx b/src/components/ui/fieldset/root.tsx new file mode 100644 index 0000000..8011aa0 --- /dev/null +++ b/src/components/ui/fieldset/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Fieldset as BaseFieldset } from "@base-ui/react/fieldset" +import { cn } from "@/lib/utils" + +export type FieldsetRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldsetRoot = BaseFieldset.Root as React.ElementType + +export const FieldsetRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldsetRoot.displayName = "FieldsetRoot" diff --git a/src/components/ui/form/index.ts b/src/components/ui/form/index.ts new file mode 100644 index 0000000..fa5ece3 --- /dev/null +++ b/src/components/ui/form/index.ts @@ -0,0 +1,4 @@ +import { Form } from "./root" + +export { Form, type FormProps } from "./root" +export default Form diff --git a/src/components/ui/form/root.tsx b/src/components/ui/form/root.tsx new file mode 100644 index 0000000..c18f298 --- /dev/null +++ b/src/components/ui/form/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Form as BaseForm } from "@base-ui/react/form" +import { cn } from "@/lib/utils" + +export type FormProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseFormElement = BaseForm as React.ElementType + +export const Form = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Form.displayName = "Form" diff --git a/src/components/ui/input/index.ts b/src/components/ui/input/index.ts new file mode 100644 index 0000000..1161ce5 --- /dev/null +++ b/src/components/ui/input/index.ts @@ -0,0 +1,4 @@ +import { Input } from "./root" + +export { Input, type InputProps } from "./root" +export default Input diff --git a/src/components/ui/input/root.tsx b/src/components/ui/input/root.tsx new file mode 100644 index 0000000..ab996d0 --- /dev/null +++ b/src/components/ui/input/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Input as BaseInput } from "@base-ui/react/input" +import { cn } from "@/lib/utils" + +export type InputProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseInputElement = BaseInput as React.ElementType + +export const Input = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Input.displayName = "Input" diff --git a/src/components/ui/menu/arrow.tsx b/src/components/ui/menu/arrow.tsx new file mode 100644 index 0000000..356a66b --- /dev/null +++ b/src/components/ui/menu/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuArrow = BaseMenu.Arrow as React.ElementType + +export const MenuArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuArrow.displayName = "MenuArrow" diff --git a/src/components/ui/menu/backdrop.tsx b/src/components/ui/menu/backdrop.tsx new file mode 100644 index 0000000..12ced99 --- /dev/null +++ b/src/components/ui/menu/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuBackdrop = BaseMenu.Backdrop as React.ElementType + +export const MenuBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuBackdrop.displayName = "MenuBackdrop" diff --git a/src/components/ui/menu/checkbox-item-indicator.tsx b/src/components/ui/menu/checkbox-item-indicator.tsx new file mode 100644 index 0000000..5cb1b23 --- /dev/null +++ b/src/components/ui/menu/checkbox-item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuCheckboxItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuCheckboxItemIndicator = BaseMenu.CheckboxItemIndicator as React.ElementType + +export const MenuCheckboxItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuCheckboxItemIndicator.displayName = "MenuCheckboxItemIndicator" diff --git a/src/components/ui/menu/checkbox-item.tsx b/src/components/ui/menu/checkbox-item.tsx new file mode 100644 index 0000000..bc0cdc9 --- /dev/null +++ b/src/components/ui/menu/checkbox-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuCheckboxItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuCheckboxItem = BaseMenu.CheckboxItem as React.ElementType + +export const MenuCheckboxItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuCheckboxItem.displayName = "MenuCheckboxItem" diff --git a/src/components/ui/menu/group-label.tsx b/src/components/ui/menu/group-label.tsx new file mode 100644 index 0000000..45ea521 --- /dev/null +++ b/src/components/ui/menu/group-label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuGroupLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuGroupLabel = BaseMenu.GroupLabel as React.ElementType + +export const MenuGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuGroupLabel.displayName = "MenuGroupLabel" diff --git a/src/components/ui/menu/group.tsx b/src/components/ui/menu/group.tsx new file mode 100644 index 0000000..4516fb2 --- /dev/null +++ b/src/components/ui/menu/group.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuGroup = BaseMenu.Group as React.ElementType + +export const MenuGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuGroup.displayName = "MenuGroup" diff --git a/src/components/ui/menu/index.ts b/src/components/ui/menu/index.ts new file mode 100644 index 0000000..fa5ecde --- /dev/null +++ b/src/components/ui/menu/index.ts @@ -0,0 +1,90 @@ +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { MenuArrow } from "./arrow" +import { MenuBackdrop } from "./backdrop" +import { MenuCheckboxItem } from "./checkbox-item" +import { MenuCheckboxItemIndicator } from "./checkbox-item-indicator" +import { MenuGroup } from "./group" +import { MenuGroupLabel } from "./group-label" +import { MenuItem } from "./item" +import { MenuLinkItem } from "./link-item" +import { MenuPopup } from "./popup" +import { MenuPortal } from "./portal" +import { MenuPositioner } from "./positioner" +import { MenuRadioGroup } from "./radio-group" +import { MenuRadioItem } from "./radio-item" +import { MenuRadioItemIndicator } from "./radio-item-indicator" +import { MenuRoot } from "./root" +import { MenuSubmenuRoot } from "./submenu-root" +import { MenuTrigger } from "./trigger" +import { MenuViewport } from "./viewport" +import { MenuSubmenuTrigger } from "./submenu-trigger" + +const MenuPrimitive = { + Arrow: MenuArrow, + Backdrop: MenuBackdrop, + CheckboxItem: MenuCheckboxItem, + CheckboxItemIndicator: MenuCheckboxItemIndicator, + Group: MenuGroup, + GroupLabel: MenuGroupLabel, + Item: MenuItem, + LinkItem: MenuLinkItem, + Popup: MenuPopup, + Portal: MenuPortal, + Positioner: MenuPositioner, + RadioGroup: MenuRadioGroup, + RadioItem: MenuRadioItem, + RadioItemIndicator: MenuRadioItemIndicator, + Root: MenuRoot, + SubmenuRoot: MenuSubmenuRoot, + Trigger: MenuTrigger, + Viewport: MenuViewport, + SubmenuTrigger: MenuSubmenuTrigger, + Separator: BaseMenu.Separator, + createHandle: BaseMenu.createHandle, +} + +export default MenuPrimitive + +export { + MenuRoot as Menu, + MenuArrow, + MenuBackdrop, + MenuCheckboxItem, + MenuCheckboxItemIndicator, + MenuGroup, + MenuGroupLabel, + MenuItem, + MenuLinkItem, + MenuPopup, + MenuPortal, + MenuPositioner, + MenuRadioGroup, + MenuRadioItem, + MenuRadioItemIndicator, + MenuRoot, + MenuSubmenuRoot, + MenuTrigger, + MenuViewport, + MenuSubmenuTrigger, + BaseMenu, +} + +export type { MenuArrowProps } from "./arrow" +export type { MenuBackdropProps } from "./backdrop" +export type { MenuCheckboxItemProps } from "./checkbox-item" +export type { MenuCheckboxItemIndicatorProps } from "./checkbox-item-indicator" +export type { MenuGroupProps } from "./group" +export type { MenuGroupLabelProps } from "./group-label" +export type { MenuItemProps } from "./item" +export type { MenuLinkItemProps } from "./link-item" +export type { MenuPopupProps } from "./popup" +export type { MenuPortalProps } from "./portal" +export type { MenuPositionerProps } from "./positioner" +export type { MenuRadioGroupProps } from "./radio-group" +export type { MenuRadioItemProps } from "./radio-item" +export type { MenuRadioItemIndicatorProps } from "./radio-item-indicator" +export type { MenuRootProps } from "./root" +export type { MenuSubmenuRootProps } from "./submenu-root" +export type { MenuTriggerProps } from "./trigger" +export type { MenuViewportProps } from "./viewport" +export type { MenuSubmenuTriggerProps } from "./submenu-trigger" diff --git a/src/components/ui/menu/item.tsx b/src/components/ui/menu/item.tsx new file mode 100644 index 0000000..9b01969 --- /dev/null +++ b/src/components/ui/menu/item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuItem = BaseMenu.Item as React.ElementType + +export const MenuItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuItem.displayName = "MenuItem" diff --git a/src/components/ui/menu/link-item.tsx b/src/components/ui/menu/link-item.tsx new file mode 100644 index 0000000..2dc83ed --- /dev/null +++ b/src/components/ui/menu/link-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuLinkItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuLinkItem = BaseMenu.LinkItem as React.ElementType + +export const MenuLinkItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuLinkItem.displayName = "MenuLinkItem" diff --git a/src/components/ui/menu/popup.tsx b/src/components/ui/menu/popup.tsx new file mode 100644 index 0000000..275a288 --- /dev/null +++ b/src/components/ui/menu/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuPopup = BaseMenu.Popup as React.ElementType +const defaultMenuPopupClassName = + "relative origin-[var(--transform-origin)] border border-neutral-950 bg-white py-1 text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] outline-none transition-[transform,opacity] duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:duration-150 data-ending-style:ease-out data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const MenuPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuPopup.displayName = "MenuPopup" diff --git a/src/components/ui/menu/portal.tsx b/src/components/ui/menu/portal.tsx new file mode 100644 index 0000000..2591405 --- /dev/null +++ b/src/components/ui/menu/portal.tsx @@ -0,0 +1,30 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type MenuPortalProps = React.ComponentPropsWithoutRef & { + className?: string + container?: HTMLElement | ShadowRoot | React.RefObject | null +} + +const BaseMenuPortal = BaseMenu.Portal as React.ElementType + +export const MenuPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +MenuPortal.displayName = "MenuPortal" diff --git a/src/components/ui/menu/positioner.tsx b/src/components/ui/menu/positioner.tsx new file mode 100644 index 0000000..e9db49f --- /dev/null +++ b/src/components/ui/menu/positioner.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuPositioner = BaseMenu.Positioner as React.ElementType +const defaultMenuPositionerClassName = "outline-none" + +export const MenuPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuPositioner.displayName = "MenuPositioner" diff --git a/src/components/ui/menu/radio-group.tsx b/src/components/ui/menu/radio-group.tsx new file mode 100644 index 0000000..f21c244 --- /dev/null +++ b/src/components/ui/menu/radio-group.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRadioGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRadioGroup = BaseMenu.RadioGroup as React.ElementType + +export const MenuRadioGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRadioGroup.displayName = "MenuRadioGroup" diff --git a/src/components/ui/menu/radio-item-indicator.tsx b/src/components/ui/menu/radio-item-indicator.tsx new file mode 100644 index 0000000..5b03bee --- /dev/null +++ b/src/components/ui/menu/radio-item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRadioItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRadioItemIndicator = BaseMenu.RadioItemIndicator as React.ElementType + +export const MenuRadioItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRadioItemIndicator.displayName = "MenuRadioItemIndicator" diff --git a/src/components/ui/menu/radio-item.tsx b/src/components/ui/menu/radio-item.tsx new file mode 100644 index 0000000..ac6eda1 --- /dev/null +++ b/src/components/ui/menu/radio-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRadioItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRadioItem = BaseMenu.RadioItem as React.ElementType + +export const MenuRadioItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRadioItem.displayName = "MenuRadioItem" diff --git a/src/components/ui/menu/root.tsx b/src/components/ui/menu/root.tsx new file mode 100644 index 0000000..47f6666 --- /dev/null +++ b/src/components/ui/menu/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRoot = BaseMenu.Root as React.ElementType + +export const MenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRoot.displayName = "MenuRoot" diff --git a/src/components/ui/menu/submenu-root.tsx b/src/components/ui/menu/submenu-root.tsx new file mode 100644 index 0000000..d3cb2c0 --- /dev/null +++ b/src/components/ui/menu/submenu-root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuSubmenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuSubmenuRoot = BaseMenu.SubmenuRoot as React.ElementType + +export const MenuSubmenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuSubmenuRoot.displayName = "MenuSubmenuRoot" diff --git a/src/components/ui/menu/submenu-trigger.tsx b/src/components/ui/menu/submenu-trigger.tsx new file mode 100644 index 0000000..812e9fc --- /dev/null +++ b/src/components/ui/menu/submenu-trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuSubmenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuSubmenuTrigger = BaseMenu.SubmenuTrigger as React.ElementType + +export const MenuSubmenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuSubmenuTrigger.displayName = "MenuSubmenuTrigger" diff --git a/src/components/ui/menu/trigger.tsx b/src/components/ui/menu/trigger.tsx new file mode 100644 index 0000000..5ad8586 --- /dev/null +++ b/src/components/ui/menu/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuTrigger = BaseMenu.Trigger as React.ElementType + +export const MenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuTrigger.displayName = "MenuTrigger" diff --git a/src/components/ui/menu/viewport.tsx b/src/components/ui/menu/viewport.tsx new file mode 100644 index 0000000..870ffc9 --- /dev/null +++ b/src/components/ui/menu/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuViewport = BaseMenu.Viewport as React.ElementType + +export const MenuViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuViewport.displayName = "MenuViewport" diff --git a/src/components/ui/menubar/index.ts b/src/components/ui/menubar/index.ts new file mode 100644 index 0000000..c2efebc --- /dev/null +++ b/src/components/ui/menubar/index.ts @@ -0,0 +1,4 @@ +import { Menubar } from "./root" + +export { Menubar, type MenubarProps } from "./root" +export default Menubar diff --git a/src/components/ui/menubar/root.tsx b/src/components/ui/menubar/root.tsx new file mode 100644 index 0000000..ad5a303 --- /dev/null +++ b/src/components/ui/menubar/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Menubar as BaseMenubar } from "@base-ui/react/menubar" +import { cn } from "@/lib/utils" + +export type MenubarProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseMenubarElement = BaseMenubar as React.ElementType + +export const Menubar = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Menubar.displayName = "Menubar" diff --git a/src/components/ui/meter/index.ts b/src/components/ui/meter/index.ts new file mode 100644 index 0000000..18e398c --- /dev/null +++ b/src/components/ui/meter/index.ts @@ -0,0 +1,30 @@ +import { MeterRoot } from "./root" +import { MeterTrack } from "./track" +import { MeterIndicator } from "./indicator" +import { MeterValue } from "./value" +import { MeterLabel } from "./label" + +const MeterPrimitive = { + Root: MeterRoot, + Track: MeterTrack, + Indicator: MeterIndicator, + Value: MeterValue, + Label: MeterLabel, +} + +export default MeterPrimitive + +export { + MeterRoot as Meter, + MeterRoot, + MeterTrack, + MeterIndicator, + MeterValue, + MeterLabel, +} + +export type { MeterRootProps } from "./root" +export type { MeterTrackProps } from "./track" +export type { MeterIndicatorProps } from "./indicator" +export type { MeterValueProps } from "./value" +export type { MeterLabelProps } from "./label" diff --git a/src/components/ui/meter/indicator.tsx b/src/components/ui/meter/indicator.tsx new file mode 100644 index 0000000..4087380 --- /dev/null +++ b/src/components/ui/meter/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterIndicator = BaseMeter.Indicator as React.ElementType + +export const MeterIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterIndicator.displayName = "MeterIndicator" diff --git a/src/components/ui/meter/label.tsx b/src/components/ui/meter/label.tsx new file mode 100644 index 0000000..fc01c6b --- /dev/null +++ b/src/components/ui/meter/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterLabel = BaseMeter.Label as React.ElementType + +export const MeterLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterLabel.displayName = "MeterLabel" diff --git a/src/components/ui/meter/root.tsx b/src/components/ui/meter/root.tsx new file mode 100644 index 0000000..10e53d3 --- /dev/null +++ b/src/components/ui/meter/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterRoot = BaseMeter.Root as React.ElementType + +export const MeterRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterRoot.displayName = "MeterRoot" diff --git a/src/components/ui/meter/track.tsx b/src/components/ui/meter/track.tsx new file mode 100644 index 0000000..a520288 --- /dev/null +++ b/src/components/ui/meter/track.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterTrackProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterTrack = BaseMeter.Track as React.ElementType + +export const MeterTrack = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterTrack.displayName = "MeterTrack" diff --git a/src/components/ui/meter/value.tsx b/src/components/ui/meter/value.tsx new file mode 100644 index 0000000..3b2b6b3 --- /dev/null +++ b/src/components/ui/meter/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterValue = BaseMeter.Value as React.ElementType + +export const MeterValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterValue.displayName = "MeterValue" diff --git a/src/components/ui/navigation-menu/arrow.tsx b/src/components/ui/navigation-menu/arrow.tsx new file mode 100644 index 0000000..37576bd --- /dev/null +++ b/src/components/ui/navigation-menu/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuArrow = BaseNavigationMenu.Arrow as React.ElementType + +export const NavigationMenuArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuArrow.displayName = "NavigationMenuArrow" diff --git a/src/components/ui/navigation-menu/backdrop.tsx b/src/components/ui/navigation-menu/backdrop.tsx new file mode 100644 index 0000000..09c6665 --- /dev/null +++ b/src/components/ui/navigation-menu/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuBackdrop = BaseNavigationMenu.Backdrop as React.ElementType + +export const NavigationMenuBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuBackdrop.displayName = "NavigationMenuBackdrop" diff --git a/src/components/ui/navigation-menu/content.tsx b/src/components/ui/navigation-menu/content.tsx new file mode 100644 index 0000000..3cd30ba --- /dev/null +++ b/src/components/ui/navigation-menu/content.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuContent = BaseNavigationMenu.Content as React.ElementType + +export const NavigationMenuContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuContent.displayName = "NavigationMenuContent" diff --git a/src/components/ui/navigation-menu/icon.tsx b/src/components/ui/navigation-menu/icon.tsx new file mode 100644 index 0000000..2701a9c --- /dev/null +++ b/src/components/ui/navigation-menu/icon.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuIconProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuIcon = BaseNavigationMenu.Icon as React.ElementType + +export const NavigationMenuIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuIcon.displayName = "NavigationMenuIcon" diff --git a/src/components/ui/navigation-menu/index.ts b/src/components/ui/navigation-menu/index.ts new file mode 100644 index 0000000..61e6ac6 --- /dev/null +++ b/src/components/ui/navigation-menu/index.ts @@ -0,0 +1,62 @@ +import { NavigationMenuRoot } from "./root" +import { NavigationMenuList } from "./list" +import { NavigationMenuItem } from "./item" +import { NavigationMenuContent } from "./content" +import { NavigationMenuTrigger } from "./trigger" +import { NavigationMenuPortal } from "./portal" +import { NavigationMenuPositioner } from "./positioner" +import { NavigationMenuViewport } from "./viewport" +import { NavigationMenuBackdrop } from "./backdrop" +import { NavigationMenuPopup } from "./popup" +import { NavigationMenuArrow } from "./arrow" +import { NavigationMenuLink } from "./link" +import { NavigationMenuIcon } from "./icon" + +const NavigationMenuPrimitive = { + Root: NavigationMenuRoot, + List: NavigationMenuList, + Item: NavigationMenuItem, + Content: NavigationMenuContent, + Trigger: NavigationMenuTrigger, + Portal: NavigationMenuPortal, + Positioner: NavigationMenuPositioner, + Viewport: NavigationMenuViewport, + Backdrop: NavigationMenuBackdrop, + Popup: NavigationMenuPopup, + Arrow: NavigationMenuArrow, + Link: NavigationMenuLink, + Icon: NavigationMenuIcon, +} + +export default NavigationMenuPrimitive + +export { + NavigationMenuRoot as NavigationMenu, + NavigationMenuRoot, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuPortal, + NavigationMenuPositioner, + NavigationMenuViewport, + NavigationMenuBackdrop, + NavigationMenuPopup, + NavigationMenuArrow, + NavigationMenuLink, + NavigationMenuIcon, +} + +export type { NavigationMenuRootProps } from "./root" +export type { NavigationMenuListProps } from "./list" +export type { NavigationMenuItemProps } from "./item" +export type { NavigationMenuContentProps } from "./content" +export type { NavigationMenuTriggerProps } from "./trigger" +export type { NavigationMenuPortalProps } from "./portal" +export type { NavigationMenuPositionerProps } from "./positioner" +export type { NavigationMenuViewportProps } from "./viewport" +export type { NavigationMenuBackdropProps } from "./backdrop" +export type { NavigationMenuPopupProps } from "./popup" +export type { NavigationMenuArrowProps } from "./arrow" +export type { NavigationMenuLinkProps } from "./link" +export type { NavigationMenuIconProps } from "./icon" diff --git a/src/components/ui/navigation-menu/item.tsx b/src/components/ui/navigation-menu/item.tsx new file mode 100644 index 0000000..51fa2bf --- /dev/null +++ b/src/components/ui/navigation-menu/item.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuItem = BaseNavigationMenu.Item as React.ElementType + +export const NavigationMenuItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuItem.displayName = "NavigationMenuItem" diff --git a/src/components/ui/navigation-menu/link.tsx b/src/components/ui/navigation-menu/link.tsx new file mode 100644 index 0000000..ca4b674 --- /dev/null +++ b/src/components/ui/navigation-menu/link.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuLinkProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuLink = BaseNavigationMenu.Link as React.ElementType + +export const NavigationMenuLink = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuLink.displayName = "NavigationMenuLink" diff --git a/src/components/ui/navigation-menu/list.tsx b/src/components/ui/navigation-menu/list.tsx new file mode 100644 index 0000000..d7c119c --- /dev/null +++ b/src/components/ui/navigation-menu/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuList = BaseNavigationMenu.List as React.ElementType + +export const NavigationMenuList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuList.displayName = "NavigationMenuList" diff --git a/src/components/ui/navigation-menu/popup.tsx b/src/components/ui/navigation-menu/popup.tsx new file mode 100644 index 0000000..77d4a2d --- /dev/null +++ b/src/components/ui/navigation-menu/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuPopup = BaseNavigationMenu.Popup as React.ElementType +const defaultNavigationMenuPopupClassName = + "relative h-[var(--popup-height)] w-[var(--popup-width)] origin-[var(--transform-origin)] border border-neutral-950 bg-white text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] outline-none transition-[opacity,transform,width,height,scale] duration-[var(--duration)] ease-[var(--easing)] data-[ending-style]:scale-90 data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[ending-style]:ease-[ease] data-[starting-style]:scale-90 data-[starting-style]:opacity-0 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const NavigationMenuPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuPopup.displayName = "NavigationMenuPopup" diff --git a/src/components/ui/navigation-menu/portal.tsx b/src/components/ui/navigation-menu/portal.tsx new file mode 100644 index 0000000..fcdb017 --- /dev/null +++ b/src/components/ui/navigation-menu/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type NavigationMenuPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuPortal = BaseNavigationMenu.Portal as React.ElementType + +export const NavigationMenuPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +NavigationMenuPortal.displayName = "NavigationMenuPortal" diff --git a/src/components/ui/navigation-menu/positioner.tsx b/src/components/ui/navigation-menu/positioner.tsx new file mode 100644 index 0000000..1e5a182 --- /dev/null +++ b/src/components/ui/navigation-menu/positioner.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuPositioner = BaseNavigationMenu.Positioner as React.ElementType +const defaultNavigationMenuPositionerClassName = + "h-[var(--positioner-height)] w-[var(--positioner-width)] max-w-[var(--available-width)] transition-[top,left,right,bottom] duration-[var(--duration)] ease-[var(--easing)] before:absolute before:content-[''] data-instant:transition-none data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0 data-[side=bottom]:before:h-2.5 data-[side=left]:before:top-0 data-[side=left]:before:right-[-10px] data-[side=left]:before:bottom-0 data-[side=left]:before:w-2.5 data-[side=right]:before:top-0 data-[side=right]:before:bottom-0 data-[side=right]:before:left-[-10px] data-[side=right]:before:w-2.5 data-[side=top]:before:right-0 data-[side=top]:before:bottom-[-10px] data-[side=top]:before:left-0 data-[side=top]:before:h-2.5" + +export const NavigationMenuPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuPositioner.displayName = "NavigationMenuPositioner" diff --git a/src/components/ui/navigation-menu/root.tsx b/src/components/ui/navigation-menu/root.tsx new file mode 100644 index 0000000..b8abb55 --- /dev/null +++ b/src/components/ui/navigation-menu/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuRoot = BaseNavigationMenu.Root as React.ElementType + +export const NavigationMenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuRoot.displayName = "NavigationMenuRoot" diff --git a/src/components/ui/navigation-menu/trigger.tsx b/src/components/ui/navigation-menu/trigger.tsx new file mode 100644 index 0000000..bd2e0c0 --- /dev/null +++ b/src/components/ui/navigation-menu/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuTrigger = BaseNavigationMenu.Trigger as React.ElementType + +export const NavigationMenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuTrigger.displayName = "NavigationMenuTrigger" diff --git a/src/components/ui/navigation-menu/viewport.tsx b/src/components/ui/navigation-menu/viewport.tsx new file mode 100644 index 0000000..0afd15f --- /dev/null +++ b/src/components/ui/navigation-menu/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuViewport = BaseNavigationMenu.Viewport as React.ElementType + +export const NavigationMenuViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuViewport.displayName = "NavigationMenuViewport" diff --git a/src/components/ui/number-field/decrement.tsx b/src/components/ui/number-field/decrement.tsx new file mode 100644 index 0000000..3a171aa --- /dev/null +++ b/src/components/ui/number-field/decrement.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldDecrementProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldDecrement = BaseNumberField.Decrement as React.ElementType + +export const NumberFieldDecrement = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldDecrement.displayName = "NumberFieldDecrement" diff --git a/src/components/ui/number-field/group.tsx b/src/components/ui/number-field/group.tsx new file mode 100644 index 0000000..5347851 --- /dev/null +++ b/src/components/ui/number-field/group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldGroup = BaseNumberField.Group as React.ElementType + +export const NumberFieldGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldGroup.displayName = "NumberFieldGroup" diff --git a/src/components/ui/number-field/increment.tsx b/src/components/ui/number-field/increment.tsx new file mode 100644 index 0000000..eacd6c8 --- /dev/null +++ b/src/components/ui/number-field/increment.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldIncrementProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldIncrement = BaseNumberField.Increment as React.ElementType + +export const NumberFieldIncrement = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldIncrement.displayName = "NumberFieldIncrement" diff --git a/src/components/ui/number-field/index.ts b/src/components/ui/number-field/index.ts new file mode 100644 index 0000000..d517351 --- /dev/null +++ b/src/components/ui/number-field/index.ts @@ -0,0 +1,38 @@ +import { NumberFieldRoot } from "./root" +import { NumberFieldGroup } from "./group" +import { NumberFieldIncrement } from "./increment" +import { NumberFieldDecrement } from "./decrement" +import { NumberFieldInput } from "./input" +import { NumberFieldScrubArea } from "./scrub-area" +import { NumberFieldScrubAreaCursor } from "./scrub-area-cursor" + +const NumberFieldPrimitive = { + Root: NumberFieldRoot, + Group: NumberFieldGroup, + Increment: NumberFieldIncrement, + Decrement: NumberFieldDecrement, + Input: NumberFieldInput, + ScrubArea: NumberFieldScrubArea, + ScrubAreaCursor: NumberFieldScrubAreaCursor, +} + +export default NumberFieldPrimitive + +export { + NumberFieldRoot as NumberField, + NumberFieldRoot, + NumberFieldGroup, + NumberFieldIncrement, + NumberFieldDecrement, + NumberFieldInput, + NumberFieldScrubArea, + NumberFieldScrubAreaCursor, +} + +export type { NumberFieldRootProps } from "./root" +export type { NumberFieldGroupProps } from "./group" +export type { NumberFieldIncrementProps } from "./increment" +export type { NumberFieldDecrementProps } from "./decrement" +export type { NumberFieldInputProps } from "./input" +export type { NumberFieldScrubAreaProps } from "./scrub-area" +export type { NumberFieldScrubAreaCursorProps } from "./scrub-area-cursor" diff --git a/src/components/ui/number-field/input.tsx b/src/components/ui/number-field/input.tsx new file mode 100644 index 0000000..5f8efaa --- /dev/null +++ b/src/components/ui/number-field/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldInput = BaseNumberField.Input as React.ElementType + +export const NumberFieldInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldInput.displayName = "NumberFieldInput" diff --git a/src/components/ui/number-field/root.tsx b/src/components/ui/number-field/root.tsx new file mode 100644 index 0000000..8d9b989 --- /dev/null +++ b/src/components/ui/number-field/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldRoot = BaseNumberField.Root as React.ElementType + +export const NumberFieldRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldRoot.displayName = "NumberFieldRoot" diff --git a/src/components/ui/number-field/scrub-area-cursor.tsx b/src/components/ui/number-field/scrub-area-cursor.tsx new file mode 100644 index 0000000..235bb98 --- /dev/null +++ b/src/components/ui/number-field/scrub-area-cursor.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldScrubAreaCursorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldScrubAreaCursor = BaseNumberField.ScrubAreaCursor as React.ElementType + +export const NumberFieldScrubAreaCursor = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldScrubAreaCursor.displayName = "NumberFieldScrubAreaCursor" diff --git a/src/components/ui/number-field/scrub-area.tsx b/src/components/ui/number-field/scrub-area.tsx new file mode 100644 index 0000000..945badb --- /dev/null +++ b/src/components/ui/number-field/scrub-area.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldScrubAreaProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldScrubArea = BaseNumberField.ScrubArea as React.ElementType + +export const NumberFieldScrubArea = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldScrubArea.displayName = "NumberFieldScrubArea" diff --git a/src/components/ui/otp-field/index.ts b/src/components/ui/otp-field/index.ts new file mode 100644 index 0000000..7e4882b --- /dev/null +++ b/src/components/ui/otp-field/index.ts @@ -0,0 +1,21 @@ +import { OTPField as BaseOTPField } from "@base-ui/react/otp-field" +import { OTPFieldRoot } from "./root" +import { OTPFieldInput } from "./input" + +const OTPFieldPrimitive = { + Root: OTPFieldRoot, + Input: OTPFieldInput, + Separator: BaseOTPField.Separator, +} + +export default OTPFieldPrimitive + +export { + OTPFieldRoot as OTPField, + OTPFieldRoot, + OTPFieldInput, + BaseOTPField, +} + +export type { OTPFieldRootProps } from "./root" +export type { OTPFieldInputProps } from "./input" diff --git a/src/components/ui/otp-field/input.tsx b/src/components/ui/otp-field/input.tsx new file mode 100644 index 0000000..504bf2e --- /dev/null +++ b/src/components/ui/otp-field/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { OTPField as BaseOTPField } from "@base-ui/react/otp-field" +import { cn } from "@/lib/utils" + +export type OTPFieldInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseOTPFieldInput = BaseOTPField.Input as React.ElementType + +export const OTPFieldInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +OTPFieldInput.displayName = "OTPFieldInput" diff --git a/src/components/ui/otp-field/root.tsx b/src/components/ui/otp-field/root.tsx new file mode 100644 index 0000000..27836cf --- /dev/null +++ b/src/components/ui/otp-field/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { OTPField as BaseOTPField } from "@base-ui/react/otp-field" +import { cn } from "@/lib/utils" + +export type OTPFieldRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseOTPFieldRoot = BaseOTPField.Root as React.ElementType + +export const OTPFieldRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +OTPFieldRoot.displayName = "OTPFieldRoot" diff --git a/src/components/ui/popover/arrow.tsx b/src/components/ui/popover/arrow.tsx new file mode 100644 index 0000000..5ed2a80 --- /dev/null +++ b/src/components/ui/popover/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverArrow = BasePopover.Arrow as React.ElementType + +export const PopoverArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverArrow.displayName = "PopoverArrow" diff --git a/src/components/ui/popover/backdrop.tsx b/src/components/ui/popover/backdrop.tsx new file mode 100644 index 0000000..12de54e --- /dev/null +++ b/src/components/ui/popover/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverBackdrop = BasePopover.Backdrop as React.ElementType + +export const PopoverBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverBackdrop.displayName = "PopoverBackdrop" diff --git a/src/components/ui/popover/close.tsx b/src/components/ui/popover/close.tsx new file mode 100644 index 0000000..4c96758 --- /dev/null +++ b/src/components/ui/popover/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverClose = BasePopover.Close as React.ElementType + +export const PopoverClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverClose.displayName = "PopoverClose" diff --git a/src/components/ui/popover/content.tsx b/src/components/ui/popover/content.tsx new file mode 100644 index 0000000..9e8e224 --- /dev/null +++ b/src/components/ui/popover/content.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { PopoverBackdrop } from "./backdrop" +import { PopoverPortal } from "./portal" +import { PopoverPositioner } from "./positioner" +import { PopoverPopup, type PopoverPopupProps } from "./popup" + +export type PopoverContentProps = PopoverPopupProps + +export const PopoverContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + + + ), +) + +PopoverContent.displayName = "PopoverContent" diff --git a/src/components/ui/popover/description.tsx b/src/components/ui/popover/description.tsx new file mode 100644 index 0000000..e88c3db --- /dev/null +++ b/src/components/ui/popover/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverDescription = BasePopover.Description as React.ElementType + +export const PopoverDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverDescription.displayName = "PopoverDescription" diff --git a/src/components/ui/popover/index.ts b/src/components/ui/popover/index.ts new file mode 100644 index 0000000..c6766ce --- /dev/null +++ b/src/components/ui/popover/index.ts @@ -0,0 +1,60 @@ +import { Popover as BasePopover } from "@base-ui/react/popover" +import { PopoverRoot } from "./root" +import { PopoverTrigger } from "./trigger" +import { PopoverPortal } from "./portal" +import { PopoverPositioner } from "./positioner" +import { PopoverPopup } from "./popup" +import { PopoverArrow } from "./arrow" +import { PopoverBackdrop } from "./backdrop" +import { PopoverTitle } from "./title" +import { PopoverDescription } from "./description" +import { PopoverClose } from "./close" +import { PopoverViewport } from "./viewport" +import { PopoverContent } from "./content" + +const PopoverPrimitive = { + Root: PopoverRoot, + Trigger: PopoverTrigger, + Portal: PopoverPortal, + Positioner: PopoverPositioner, + Popup: PopoverPopup, + Arrow: PopoverArrow, + Backdrop: PopoverBackdrop, + Title: PopoverTitle, + Description: PopoverDescription, + Close: PopoverClose, + Viewport: PopoverViewport, + createHandle: BasePopover.createHandle, +} + +export default PopoverPrimitive + +export { + PopoverRoot as Popover, + PopoverRoot, + PopoverTrigger, + PopoverPortal, + PopoverPositioner, + PopoverPopup, + PopoverArrow, + PopoverBackdrop, + PopoverTitle, + PopoverDescription, + PopoverClose, + PopoverViewport, + PopoverContent, + BasePopover, +} + +export type { PopoverRootProps } from "./root" +export type { PopoverTriggerProps } from "./trigger" +export type { PopoverPortalProps } from "./portal" +export type { PopoverPositionerProps } from "./positioner" +export type { PopoverPopupProps } from "./popup" +export type { PopoverArrowProps } from "./arrow" +export type { PopoverBackdropProps } from "./backdrop" +export type { PopoverTitleProps } from "./title" +export type { PopoverDescriptionProps } from "./description" +export type { PopoverCloseProps } from "./close" +export type { PopoverViewportProps } from "./viewport" +export type { PopoverContentProps } from "./content" diff --git a/src/components/ui/popover/popup.tsx b/src/components/ui/popover/popup.tsx new file mode 100644 index 0000000..75be69d --- /dev/null +++ b/src/components/ui/popover/popup.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverPopup = BasePopover.Popup as React.ElementType + +export const PopoverPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverPopup.displayName = "PopoverPopup" diff --git a/src/components/ui/popover/portal.tsx b/src/components/ui/popover/portal.tsx new file mode 100644 index 0000000..b7047d8 --- /dev/null +++ b/src/components/ui/popover/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverPortal = BasePopover.Portal as React.ElementType + +export const PopoverPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverPortal.displayName = "PopoverPortal" diff --git a/src/components/ui/popover/positioner.tsx b/src/components/ui/popover/positioner.tsx new file mode 100644 index 0000000..a49387a --- /dev/null +++ b/src/components/ui/popover/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverPositioner = BasePopover.Positioner as React.ElementType + +export const PopoverPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverPositioner.displayName = "PopoverPositioner" diff --git a/src/components/ui/popover/root.tsx b/src/components/ui/popover/root.tsx new file mode 100644 index 0000000..5497c35 --- /dev/null +++ b/src/components/ui/popover/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverRoot = BasePopover.Root as React.ElementType + +export const PopoverRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverRoot.displayName = "PopoverRoot" diff --git a/src/components/ui/popover/title.tsx b/src/components/ui/popover/title.tsx new file mode 100644 index 0000000..fcd4972 --- /dev/null +++ b/src/components/ui/popover/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverTitle = BasePopover.Title as React.ElementType + +export const PopoverTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverTitle.displayName = "PopoverTitle" diff --git a/src/components/ui/popover/trigger.tsx b/src/components/ui/popover/trigger.tsx new file mode 100644 index 0000000..e150581 --- /dev/null +++ b/src/components/ui/popover/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverTrigger = BasePopover.Trigger as React.ElementType + +export const PopoverTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverTrigger.displayName = "PopoverTrigger" diff --git a/src/components/ui/popover/viewport.tsx b/src/components/ui/popover/viewport.tsx new file mode 100644 index 0000000..0e0675a --- /dev/null +++ b/src/components/ui/popover/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverViewport = BasePopover.Viewport as React.ElementType + +export const PopoverViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverViewport.displayName = "PopoverViewport" diff --git a/src/components/ui/preview-card/arrow.tsx b/src/components/ui/preview-card/arrow.tsx new file mode 100644 index 0000000..87b892c --- /dev/null +++ b/src/components/ui/preview-card/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardArrow = BasePreviewCard.Arrow as React.ElementType + +export const PreviewCardArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardArrow.displayName = "PreviewCardArrow" diff --git a/src/components/ui/preview-card/backdrop.tsx b/src/components/ui/preview-card/backdrop.tsx new file mode 100644 index 0000000..b528129 --- /dev/null +++ b/src/components/ui/preview-card/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardBackdrop = BasePreviewCard.Backdrop as React.ElementType + +export const PreviewCardBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardBackdrop.displayName = "PreviewCardBackdrop" diff --git a/src/components/ui/preview-card/content.tsx b/src/components/ui/preview-card/content.tsx new file mode 100644 index 0000000..e044ad5 --- /dev/null +++ b/src/components/ui/preview-card/content.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { PreviewCardBackdrop } from "./backdrop" +import { PreviewCardPortal } from "./portal" +import { PreviewCardPositioner } from "./positioner" +import { PreviewCardPopup, type PreviewCardPopupProps } from "./popup" + +export type PreviewCardContentProps = PreviewCardPopupProps + +export const PreviewCardContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + + + ), +) + +PreviewCardContent.displayName = "PreviewCardContent" diff --git a/src/components/ui/preview-card/index.ts b/src/components/ui/preview-card/index.ts new file mode 100644 index 0000000..fb8b51d --- /dev/null +++ b/src/components/ui/preview-card/index.ts @@ -0,0 +1,48 @@ +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { PreviewCardRoot } from "./root" +import { PreviewCardPortal } from "./portal" +import { PreviewCardTrigger } from "./trigger" +import { PreviewCardPositioner } from "./positioner" +import { PreviewCardPopup } from "./popup" +import { PreviewCardArrow } from "./arrow" +import { PreviewCardBackdrop } from "./backdrop" +import { PreviewCardViewport } from "./viewport" +import { PreviewCardContent } from "./content" + +const PreviewCardPrimitive = { + Root: PreviewCardRoot, + Portal: PreviewCardPortal, + Trigger: PreviewCardTrigger, + Positioner: PreviewCardPositioner, + Popup: PreviewCardPopup, + Arrow: PreviewCardArrow, + Backdrop: PreviewCardBackdrop, + Viewport: PreviewCardViewport, + createHandle: BasePreviewCard.createHandle, +} + +export default PreviewCardPrimitive + +export { + PreviewCardRoot as PreviewCard, + PreviewCardRoot, + PreviewCardPortal, + PreviewCardTrigger, + PreviewCardPositioner, + PreviewCardPopup, + PreviewCardArrow, + PreviewCardBackdrop, + PreviewCardViewport, + PreviewCardContent, + BasePreviewCard, +} + +export type { PreviewCardRootProps } from "./root" +export type { PreviewCardPortalProps } from "./portal" +export type { PreviewCardTriggerProps } from "./trigger" +export type { PreviewCardPositionerProps } from "./positioner" +export type { PreviewCardPopupProps } from "./popup" +export type { PreviewCardArrowProps } from "./arrow" +export type { PreviewCardBackdropProps } from "./backdrop" +export type { PreviewCardViewportProps } from "./viewport" +export type { PreviewCardContentProps } from "./content" diff --git a/src/components/ui/preview-card/popup.tsx b/src/components/ui/preview-card/popup.tsx new file mode 100644 index 0000000..d8ae9db --- /dev/null +++ b/src/components/ui/preview-card/popup.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardPopup = BasePreviewCard.Popup as React.ElementType + +export const PreviewCardPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardPopup.displayName = "PreviewCardPopup" diff --git a/src/components/ui/preview-card/portal.tsx b/src/components/ui/preview-card/portal.tsx new file mode 100644 index 0000000..7d0ebeb --- /dev/null +++ b/src/components/ui/preview-card/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardPortal = BasePreviewCard.Portal as React.ElementType + +export const PreviewCardPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardPortal.displayName = "PreviewCardPortal" diff --git a/src/components/ui/preview-card/positioner.tsx b/src/components/ui/preview-card/positioner.tsx new file mode 100644 index 0000000..aa9b075 --- /dev/null +++ b/src/components/ui/preview-card/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardPositioner = BasePreviewCard.Positioner as React.ElementType + +export const PreviewCardPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardPositioner.displayName = "PreviewCardPositioner" diff --git a/src/components/ui/preview-card/root.tsx b/src/components/ui/preview-card/root.tsx new file mode 100644 index 0000000..be9ac46 --- /dev/null +++ b/src/components/ui/preview-card/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardRoot = BasePreviewCard.Root as React.ElementType + +export const PreviewCardRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardRoot.displayName = "PreviewCardRoot" diff --git a/src/components/ui/preview-card/trigger.tsx b/src/components/ui/preview-card/trigger.tsx new file mode 100644 index 0000000..b7139c2 --- /dev/null +++ b/src/components/ui/preview-card/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardTrigger = BasePreviewCard.Trigger as React.ElementType + +export const PreviewCardTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardTrigger.displayName = "PreviewCardTrigger" diff --git a/src/components/ui/preview-card/viewport.tsx b/src/components/ui/preview-card/viewport.tsx new file mode 100644 index 0000000..47d63e4 --- /dev/null +++ b/src/components/ui/preview-card/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardViewport = BasePreviewCard.Viewport as React.ElementType + +export const PreviewCardViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardViewport.displayName = "PreviewCardViewport" diff --git a/src/components/ui/progress/index.ts b/src/components/ui/progress/index.ts new file mode 100644 index 0000000..cd0662d --- /dev/null +++ b/src/components/ui/progress/index.ts @@ -0,0 +1,30 @@ +import { ProgressRoot } from "./root" +import { ProgressTrack } from "./track" +import { ProgressIndicator } from "./indicator" +import { ProgressValue } from "./value" +import { ProgressLabel } from "./label" + +const ProgressPrimitive = { + Root: ProgressRoot, + Track: ProgressTrack, + Indicator: ProgressIndicator, + Value: ProgressValue, + Label: ProgressLabel, +} + +export default ProgressPrimitive + +export { + ProgressRoot as Progress, + ProgressRoot, + ProgressTrack, + ProgressIndicator, + ProgressValue, + ProgressLabel, +} + +export type { ProgressRootProps } from "./root" +export type { ProgressTrackProps } from "./track" +export type { ProgressIndicatorProps } from "./indicator" +export type { ProgressValueProps } from "./value" +export type { ProgressLabelProps } from "./label" diff --git a/src/components/ui/progress/indicator.tsx b/src/components/ui/progress/indicator.tsx new file mode 100644 index 0000000..a044e92 --- /dev/null +++ b/src/components/ui/progress/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressIndicator = BaseProgress.Indicator as React.ElementType + +export const ProgressIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressIndicator.displayName = "ProgressIndicator" diff --git a/src/components/ui/progress/label.tsx b/src/components/ui/progress/label.tsx new file mode 100644 index 0000000..bc8befa --- /dev/null +++ b/src/components/ui/progress/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressLabel = BaseProgress.Label as React.ElementType + +export const ProgressLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressLabel.displayName = "ProgressLabel" diff --git a/src/components/ui/progress/root.tsx b/src/components/ui/progress/root.tsx new file mode 100644 index 0000000..eaf9991 --- /dev/null +++ b/src/components/ui/progress/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressRoot = BaseProgress.Root as React.ElementType + +export const ProgressRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressRoot.displayName = "ProgressRoot" diff --git a/src/components/ui/progress/track.tsx b/src/components/ui/progress/track.tsx new file mode 100644 index 0000000..2494a12 --- /dev/null +++ b/src/components/ui/progress/track.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressTrackProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressTrack = BaseProgress.Track as React.ElementType + +export const ProgressTrack = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressTrack.displayName = "ProgressTrack" diff --git a/src/components/ui/progress/value.tsx b/src/components/ui/progress/value.tsx new file mode 100644 index 0000000..b8ee5a6 --- /dev/null +++ b/src/components/ui/progress/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressValue = BaseProgress.Value as React.ElementType + +export const ProgressValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressValue.displayName = "ProgressValue" diff --git a/src/components/ui/radio/index.ts b/src/components/ui/radio/index.ts new file mode 100644 index 0000000..974fb9d --- /dev/null +++ b/src/components/ui/radio/index.ts @@ -0,0 +1,18 @@ +import { RadioRoot } from "./root" +import { RadioIndicator } from "./indicator" + +const RadioPrimitive = { + Root: RadioRoot, + Indicator: RadioIndicator, +} + +export default RadioPrimitive + +export { + RadioRoot as Radio, + RadioRoot, + RadioIndicator, +} + +export type { RadioRootProps } from "./root" +export type { RadioIndicatorProps } from "./indicator" diff --git a/src/components/ui/radio/indicator.tsx b/src/components/ui/radio/indicator.tsx new file mode 100644 index 0000000..27c7ef0 --- /dev/null +++ b/src/components/ui/radio/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Radio as BaseRadio } from "@base-ui/react/radio" +import { cn } from "@/lib/utils" + +export type RadioIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseRadioIndicator = BaseRadio.Indicator as React.ElementType + +export const RadioIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +RadioIndicator.displayName = "RadioIndicator" diff --git a/src/components/ui/radio/root.tsx b/src/components/ui/radio/root.tsx new file mode 100644 index 0000000..88c6623 --- /dev/null +++ b/src/components/ui/radio/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Radio as BaseRadio } from "@base-ui/react/radio" +import { cn } from "@/lib/utils" + +export type RadioRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseRadioRoot = BaseRadio.Root as React.ElementType + +export const RadioRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +RadioRoot.displayName = "RadioRoot" diff --git a/src/components/ui/scroll-area/content.tsx b/src/components/ui/scroll-area/content.tsx new file mode 100644 index 0000000..1469bd4 --- /dev/null +++ b/src/components/ui/scroll-area/content.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaContent = BaseScrollArea.Content as React.ElementType +const defaultScrollAreaContentClassName = + "flex flex-col gap-4 py-2 pr-5 pl-3 text-sm leading-[1.375rem] text-neutral-950 dark:text-white" + +export const ScrollAreaContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaContent.displayName = "ScrollAreaContent" diff --git a/src/components/ui/scroll-area/corner.tsx b/src/components/ui/scroll-area/corner.tsx new file mode 100644 index 0000000..b05ff73 --- /dev/null +++ b/src/components/ui/scroll-area/corner.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaCornerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaCorner = BaseScrollArea.Corner as React.ElementType +const defaultScrollAreaCornerClassName = "bg-neutral-100 dark:bg-neutral-900" + +export const ScrollAreaCorner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaCorner.displayName = "ScrollAreaCorner" diff --git a/src/components/ui/scroll-area/index.ts b/src/components/ui/scroll-area/index.ts new file mode 100644 index 0000000..e79238d --- /dev/null +++ b/src/components/ui/scroll-area/index.ts @@ -0,0 +1,34 @@ +import { ScrollAreaRoot } from "./root" +import { ScrollAreaViewport } from "./viewport" +import { ScrollAreaScrollbar } from "./scrollbar" +import { ScrollAreaContent } from "./content" +import { ScrollAreaThumb } from "./thumb" +import { ScrollAreaCorner } from "./corner" + +const ScrollAreaPrimitive = { + Root: ScrollAreaRoot, + Viewport: ScrollAreaViewport, + Scrollbar: ScrollAreaScrollbar, + Content: ScrollAreaContent, + Thumb: ScrollAreaThumb, + Corner: ScrollAreaCorner, +} + +export default ScrollAreaPrimitive + +export { + ScrollAreaRoot as ScrollArea, + ScrollAreaRoot, + ScrollAreaViewport, + ScrollAreaScrollbar, + ScrollAreaContent, + ScrollAreaThumb, + ScrollAreaCorner, +} + +export type { ScrollAreaRootProps } from "./root" +export type { ScrollAreaViewportProps } from "./viewport" +export type { ScrollAreaScrollbarProps } from "./scrollbar" +export type { ScrollAreaContentProps } from "./content" +export type { ScrollAreaThumbProps } from "./thumb" +export type { ScrollAreaCornerProps } from "./corner" diff --git a/src/components/ui/scroll-area/root.tsx b/src/components/ui/scroll-area/root.tsx new file mode 100644 index 0000000..bcf9057 --- /dev/null +++ b/src/components/ui/scroll-area/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaRoot = BaseScrollArea.Root as React.ElementType +const defaultScrollAreaRootClassName = + "group/scroll-area h-[8.5rem] w-96 max-w-[calc(100vw-8rem)] bg-white dark:bg-neutral-950" + +export const ScrollAreaRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaRoot.displayName = "ScrollAreaRoot" diff --git a/src/components/ui/scroll-area/scrollbar.tsx b/src/components/ui/scroll-area/scrollbar.tsx new file mode 100644 index 0000000..66c85a6 --- /dev/null +++ b/src/components/ui/scroll-area/scrollbar.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaScrollbarProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaScrollbar = BaseScrollArea.Scrollbar as React.ElementType +const defaultScrollAreaScrollbarClassName = + "m-px flex bg-black/[.12] opacity-0 transition-opacity pointer-events-none data-[orientation=vertical]:w-4 data-[orientation=horizontal]:h-4 data-hovering:opacity-100 data-hovering:pointer-events-auto data-scrolling:opacity-100 data-scrolling:duration-0 data-scrolling:pointer-events-auto group-hover/scroll-area:opacity-100 group-hover/scroll-area:pointer-events-auto dark:bg-white/[.12]" + +export const ScrollAreaScrollbar = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaScrollbar.displayName = "ScrollAreaScrollbar" diff --git a/src/components/ui/scroll-area/thumb.tsx b/src/components/ui/scroll-area/thumb.tsx new file mode 100644 index 0000000..d4e3f48 --- /dev/null +++ b/src/components/ui/scroll-area/thumb.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaThumbProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaThumb = BaseScrollArea.Thumb as React.ElementType + +export const ScrollAreaThumb = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaThumb.displayName = "ScrollAreaThumb" diff --git a/src/components/ui/scroll-area/viewport.tsx b/src/components/ui/scroll-area/viewport.tsx new file mode 100644 index 0000000..b3b3355 --- /dev/null +++ b/src/components/ui/scroll-area/viewport.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaViewport = BaseScrollArea.Viewport as React.ElementType +const defaultScrollAreaViewportClassName = + "h-full border border-neutral-950 dark:border-white focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const ScrollAreaViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaViewport.displayName = "ScrollAreaViewport" diff --git a/src/components/ui/select/arrow.tsx b/src/components/ui/select/arrow.tsx new file mode 100644 index 0000000..ebc6c01 --- /dev/null +++ b/src/components/ui/select/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectArrow = BaseSelect.Arrow as React.ElementType + +export const SelectArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectArrow.displayName = "SelectArrow" diff --git a/src/components/ui/select/backdrop.tsx b/src/components/ui/select/backdrop.tsx new file mode 100644 index 0000000..d26f8ad --- /dev/null +++ b/src/components/ui/select/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectBackdrop = BaseSelect.Backdrop as React.ElementType + +export const SelectBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectBackdrop.displayName = "SelectBackdrop" diff --git a/src/components/ui/select/group-label.tsx b/src/components/ui/select/group-label.tsx new file mode 100644 index 0000000..990495b --- /dev/null +++ b/src/components/ui/select/group-label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectGroupLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectGroupLabel = BaseSelect.GroupLabel as React.ElementType + +export const SelectGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectGroupLabel.displayName = "SelectGroupLabel" diff --git a/src/components/ui/select/group.tsx b/src/components/ui/select/group.tsx new file mode 100644 index 0000000..3698e9b --- /dev/null +++ b/src/components/ui/select/group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectGroup = BaseSelect.Group as React.ElementType + +export const SelectGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectGroup.displayName = "SelectGroup" diff --git a/src/components/ui/select/icon.tsx b/src/components/ui/select/icon.tsx new file mode 100644 index 0000000..45b90fa --- /dev/null +++ b/src/components/ui/select/icon.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectIconProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectIcon = BaseSelect.Icon as React.ElementType + +export const SelectIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectIcon.displayName = "SelectIcon" diff --git a/src/components/ui/select/index.ts b/src/components/ui/select/index.ts new file mode 100644 index 0000000..88aa533 --- /dev/null +++ b/src/components/ui/select/index.ts @@ -0,0 +1,88 @@ +import { Select as BaseSelect } from "@base-ui/react/select" +import { SelectRoot } from "./root" +import { SelectLabel } from "./label" +import { SelectTrigger } from "./trigger" +import { SelectValue } from "./value" +import { SelectIcon } from "./icon" +import { SelectPortal } from "./portal" +import { SelectBackdrop } from "./backdrop" +import { SelectPositioner } from "./positioner" +import { SelectPopup } from "./popup" +import { SelectList } from "./list" +import { SelectItem } from "./item" +import { SelectItemIndicator } from "./item-indicator" +import { SelectItemText } from "./item-text" +import { SelectArrow } from "./arrow" +import { SelectScrollDownArrow } from "./scroll-down-arrow" +import { SelectScrollUpArrow } from "./scroll-up-arrow" +import { SelectGroup } from "./group" +import { SelectGroupLabel } from "./group-label" +import { SelectSeparator } from "./separator" + +const SelectPrimitive = { + Root: SelectRoot, + Label: SelectLabel, + Trigger: SelectTrigger, + Value: SelectValue, + Icon: SelectIcon, + Portal: SelectPortal, + Backdrop: SelectBackdrop, + Positioner: SelectPositioner, + Popup: SelectPopup, + List: SelectList, + Item: SelectItem, + ItemIndicator: SelectItemIndicator, + ItemText: SelectItemText, + Arrow: SelectArrow, + ScrollDownArrow: SelectScrollDownArrow, + ScrollUpArrow: SelectScrollUpArrow, + Group: SelectGroup, + GroupLabel: SelectGroupLabel, + Separator: SelectSeparator, +} + +export default SelectPrimitive + +export { + SelectRoot as Select, + SelectRoot, + SelectLabel, + SelectTrigger, + SelectValue, + SelectIcon, + SelectPortal, + SelectBackdrop, + SelectPositioner, + SelectPopup, + SelectList, + SelectItem, + SelectItemIndicator, + SelectItemText, + SelectArrow, + SelectScrollDownArrow, + SelectScrollUpArrow, + SelectGroup, + SelectGroupLabel, + SelectSeparator, + BaseSelect, +} + +export type { SelectRootProps } from "./root" +export type { SelectLabelProps } from "./label" +export type { SelectTriggerProps } from "./trigger" +export type { SelectValueProps } from "./value" +export type { SelectIconProps } from "./icon" +export type { SelectPortalProps } from "./portal" +export type { SelectBackdropProps } from "./backdrop" +export type { SelectPositionerProps } from "./positioner" +export type { SelectPopupProps } from "./popup" +export type { SelectListProps } from "./list" +export type { SelectItemProps } from "./item" +export type { SelectItemIndicatorProps } from "./item-indicator" +export type { SelectItemTextProps } from "./item-text" +export type { SelectArrowProps } from "./arrow" +export type { SelectScrollDownArrowProps } from "./scroll-down-arrow" +export type { SelectScrollUpArrowProps } from "./scroll-up-arrow" +export type { SelectGroupProps } from "./group" +export type { SelectGroupLabelProps } from "./group-label" +export type { SelectSeparatorProps } from "./separator" diff --git a/src/components/ui/select/item-indicator.tsx b/src/components/ui/select/item-indicator.tsx new file mode 100644 index 0000000..3592963 --- /dev/null +++ b/src/components/ui/select/item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectItemIndicator = BaseSelect.ItemIndicator as React.ElementType + +export const SelectItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectItemIndicator.displayName = "SelectItemIndicator" diff --git a/src/components/ui/select/item-text.tsx b/src/components/ui/select/item-text.tsx new file mode 100644 index 0000000..a076da8 --- /dev/null +++ b/src/components/ui/select/item-text.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectItemTextProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectItemText = BaseSelect.ItemText as React.ElementType + +export const SelectItemText = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectItemText.displayName = "SelectItemText" diff --git a/src/components/ui/select/item.tsx b/src/components/ui/select/item.tsx new file mode 100644 index 0000000..31dd089 --- /dev/null +++ b/src/components/ui/select/item.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectItem = BaseSelect.Item as React.ElementType +const defaultSelectItemClassName = + "grid cursor-default grid-cols-[1rem_1fr] items-center gap-2 py-1.5 pr-4 pl-2.5 text-sm outline-none select-none data-[highlighted]:bg-neutral-950 data-[highlighted]:text-white pointer-coarse:py-2.5 dark:data-[highlighted]:bg-white dark:data-[highlighted]:text-neutral-950" + +export const SelectItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectItem.displayName = "SelectItem" diff --git a/src/components/ui/select/label.tsx b/src/components/ui/select/label.tsx new file mode 100644 index 0000000..0460002 --- /dev/null +++ b/src/components/ui/select/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectLabel = BaseSelect.Label as React.ElementType + +export const SelectLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectLabel.displayName = "SelectLabel" diff --git a/src/components/ui/select/list.tsx b/src/components/ui/select/list.tsx new file mode 100644 index 0000000..8702dad --- /dev/null +++ b/src/components/ui/select/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectList = BaseSelect.List as React.ElementType + +export const SelectList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectList.displayName = "SelectList" diff --git a/src/components/ui/select/popup.tsx b/src/components/ui/select/popup.tsx new file mode 100644 index 0000000..1dda4e8 --- /dev/null +++ b/src/components/ui/select/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectPopup = BaseSelect.Popup as React.ElementType +const defaultSelectPopupClassName = + "group min-w-[var(--anchor-width)] origin-[var(--transform-origin)] bg-clip-padding border border-neutral-950 bg-white text-neutral-950 outline-none shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] transition-[transform,opacity] duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:duration-150 data-ending-style:ease-out data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[side=none]:translate-y-px data-[side=none]:min-w-[calc(var(--anchor-width)+1.75rem)] data-[side=none]:data-[ending-style]:transition-none data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0 data-[side=none]:data-[starting-style]:scale-100 data-[side=none]:data-[starting-style]:opacity-100 data-[side=none]:data-[starting-style]:transition-none dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const SelectPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectPopup.displayName = "SelectPopup" diff --git a/src/components/ui/select/portal.tsx b/src/components/ui/select/portal.tsx new file mode 100644 index 0000000..2fec9e7 --- /dev/null +++ b/src/components/ui/select/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type SelectPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectPortal = BaseSelect.Portal as React.ElementType + +export const SelectPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +SelectPortal.displayName = "SelectPortal" diff --git a/src/components/ui/select/positioner.tsx b/src/components/ui/select/positioner.tsx new file mode 100644 index 0000000..32cd4cf --- /dev/null +++ b/src/components/ui/select/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectPositioner = BaseSelect.Positioner as React.ElementType + +export const SelectPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectPositioner.displayName = "SelectPositioner" diff --git a/src/components/ui/select/root.tsx b/src/components/ui/select/root.tsx new file mode 100644 index 0000000..a625eb3 --- /dev/null +++ b/src/components/ui/select/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectRoot = BaseSelect.Root as React.ElementType + +export const SelectRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectRoot.displayName = "SelectRoot" diff --git a/src/components/ui/select/scroll-down-arrow.tsx b/src/components/ui/select/scroll-down-arrow.tsx new file mode 100644 index 0000000..1411162 --- /dev/null +++ b/src/components/ui/select/scroll-down-arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectScrollDownArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectScrollDownArrow = BaseSelect.ScrollDownArrow as React.ElementType + +export const SelectScrollDownArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectScrollDownArrow.displayName = "SelectScrollDownArrow" diff --git a/src/components/ui/select/scroll-up-arrow.tsx b/src/components/ui/select/scroll-up-arrow.tsx new file mode 100644 index 0000000..1a721d5 --- /dev/null +++ b/src/components/ui/select/scroll-up-arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectScrollUpArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectScrollUpArrow = BaseSelect.ScrollUpArrow as React.ElementType + +export const SelectScrollUpArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectScrollUpArrow.displayName = "SelectScrollUpArrow" diff --git a/src/components/ui/select/separator.tsx b/src/components/ui/select/separator.tsx new file mode 100644 index 0000000..6cd35ae --- /dev/null +++ b/src/components/ui/select/separator.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectSeparatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectSeparator = BaseSelect.Separator as React.ElementType +const defaultSelectSeparatorClassName = "mx-4 my-1 h-px bg-neutral-950 dark:bg-white" + +export const SelectSeparator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectSeparator.displayName = "SelectSeparator" diff --git a/src/components/ui/select/trigger.tsx b/src/components/ui/select/trigger.tsx new file mode 100644 index 0000000..f646feb --- /dev/null +++ b/src/components/ui/select/trigger.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectTrigger = BaseSelect.Trigger as React.ElementType +const defaultSelectTriggerClassName = + "flex h-8 min-w-40 items-center justify-between gap-3 pl-2 pr-1 text-sm leading-none whitespace-nowrap border border-neutral-950 dark:border-white bg-white dark:bg-neutral-950 text-neutral-950 dark:text-white select-none [&:not([data-disabled]):hover]:bg-neutral-100 dark:[&:not([data-disabled]):hover]:bg-neutral-800 [&:not([data-disabled]):active]:bg-neutral-200 dark:[&:not([data-disabled]):active]:bg-neutral-700 data-[disabled]:border-neutral-500 data-[disabled]:text-neutral-500 disabled:border-neutral-500 disabled:text-neutral-500 dark:data-[disabled]:border-neutral-400 dark:data-[disabled]:text-neutral-400 data-[popup-open]:bg-neutral-100 dark:data-[popup-open]:bg-neutral-800 font-normal focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const SelectTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectTrigger.displayName = "SelectTrigger" diff --git a/src/components/ui/select/value.tsx b/src/components/ui/select/value.tsx new file mode 100644 index 0000000..a1fdcfd --- /dev/null +++ b/src/components/ui/select/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectValue = BaseSelect.Value as React.ElementType + +export const SelectValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectValue.displayName = "SelectValue" diff --git a/src/components/ui/separator/index.ts b/src/components/ui/separator/index.ts new file mode 100644 index 0000000..e273624 --- /dev/null +++ b/src/components/ui/separator/index.ts @@ -0,0 +1,4 @@ +import { Separator } from "./root" + +export { Separator, type SeparatorProps } from "./root" +export default Separator diff --git a/src/components/ui/separator/root.tsx b/src/components/ui/separator/root.tsx new file mode 100644 index 0000000..c71b287 --- /dev/null +++ b/src/components/ui/separator/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Separator as BaseSeparator } from "@base-ui/react/separator" +import { cn } from "@/lib/utils" + +export type SeparatorProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseSeparatorElement = BaseSeparator as React.ElementType + +export const Separator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Separator.displayName = "Separator" diff --git a/src/components/ui/slider/control.tsx b/src/components/ui/slider/control.tsx new file mode 100644 index 0000000..2808b83 --- /dev/null +++ b/src/components/ui/slider/control.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderControlProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderControl = BaseSlider.Control as React.ElementType + +export const SliderControl = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderControl.displayName = "SliderControl" diff --git a/src/components/ui/slider/index.ts b/src/components/ui/slider/index.ts new file mode 100644 index 0000000..9a380fb --- /dev/null +++ b/src/components/ui/slider/index.ts @@ -0,0 +1,38 @@ +import { SliderRoot } from "./root" +import { SliderLabel } from "./label" +import { SliderValue } from "./value" +import { SliderControl } from "./control" +import { SliderTrack } from "./track" +import { SliderThumb } from "./thumb" +import { SliderIndicator } from "./indicator" + +const SliderPrimitive = { + Root: SliderRoot, + Label: SliderLabel, + Value: SliderValue, + Control: SliderControl, + Track: SliderTrack, + Thumb: SliderThumb, + Indicator: SliderIndicator, +} + +export default SliderPrimitive + +export { + SliderRoot as Slider, + SliderRoot, + SliderLabel, + SliderValue, + SliderControl, + SliderTrack, + SliderThumb, + SliderIndicator, +} + +export type { SliderRootProps } from "./root" +export type { SliderLabelProps } from "./label" +export type { SliderValueProps } from "./value" +export type { SliderControlProps } from "./control" +export type { SliderTrackProps } from "./track" +export type { SliderThumbProps } from "./thumb" +export type { SliderIndicatorProps } from "./indicator" diff --git a/src/components/ui/slider/indicator.tsx b/src/components/ui/slider/indicator.tsx new file mode 100644 index 0000000..0d64683 --- /dev/null +++ b/src/components/ui/slider/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderIndicator = BaseSlider.Indicator as React.ElementType + +export const SliderIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderIndicator.displayName = "SliderIndicator" diff --git a/src/components/ui/slider/label.tsx b/src/components/ui/slider/label.tsx new file mode 100644 index 0000000..d02f94d --- /dev/null +++ b/src/components/ui/slider/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderLabel = BaseSlider.Label as React.ElementType + +export const SliderLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderLabel.displayName = "SliderLabel" diff --git a/src/components/ui/slider/root.tsx b/src/components/ui/slider/root.tsx new file mode 100644 index 0000000..d598e97 --- /dev/null +++ b/src/components/ui/slider/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderRoot = BaseSlider.Root as React.ElementType + +export const SliderRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderRoot.displayName = "SliderRoot" diff --git a/src/components/ui/slider/thumb.tsx b/src/components/ui/slider/thumb.tsx new file mode 100644 index 0000000..805643d --- /dev/null +++ b/src/components/ui/slider/thumb.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderThumbProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderThumb = BaseSlider.Thumb as React.ElementType + +export const SliderThumb = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderThumb.displayName = "SliderThumb" diff --git a/src/components/ui/slider/track.tsx b/src/components/ui/slider/track.tsx new file mode 100644 index 0000000..c6fe448 --- /dev/null +++ b/src/components/ui/slider/track.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderTrackProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderTrack = BaseSlider.Track as React.ElementType + +export const SliderTrack = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderTrack.displayName = "SliderTrack" diff --git a/src/components/ui/slider/value.tsx b/src/components/ui/slider/value.tsx new file mode 100644 index 0000000..0daaebb --- /dev/null +++ b/src/components/ui/slider/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderValue = BaseSlider.Value as React.ElementType + +export const SliderValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderValue.displayName = "SliderValue" diff --git a/src/components/ui/switch/index.ts b/src/components/ui/switch/index.ts new file mode 100644 index 0000000..56a8f1b --- /dev/null +++ b/src/components/ui/switch/index.ts @@ -0,0 +1,18 @@ +import { SwitchRoot } from "./root" +import { SwitchThumb } from "./thumb" + +const SwitchPrimitive = { + Root: SwitchRoot, + Thumb: SwitchThumb, +} + +export default SwitchPrimitive + +export { + SwitchRoot as Switch, + SwitchRoot, + SwitchThumb, +} + +export type { SwitchRootProps } from "./root" +export type { SwitchThumbProps } from "./thumb" diff --git a/src/components/ui/switch/root.tsx b/src/components/ui/switch/root.tsx new file mode 100644 index 0000000..b683827 --- /dev/null +++ b/src/components/ui/switch/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Switch as BaseSwitch } from "@base-ui/react/switch" +import { cn } from "@/lib/utils" + +export type SwitchRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSwitchRoot = BaseSwitch.Root as React.ElementType +const defaultSwitchRootClassName = + "flex h-5 w-9 shrink-0 border border-neutral-950 bg-white p-0.5 transition-colors duration-150 ease-[ease] data-[checked]:bg-neutral-950 focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:outline-offset-2 focus-visible:outline-neutral-950 dark:border-white dark:bg-neutral-950 dark:data-[checked]:bg-white dark:focus-visible:outline-white" + +export const SwitchRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SwitchRoot.displayName = "SwitchRoot" diff --git a/src/components/ui/switch/thumb.tsx b/src/components/ui/switch/thumb.tsx new file mode 100644 index 0000000..565963a --- /dev/null +++ b/src/components/ui/switch/thumb.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Switch as BaseSwitch } from "@base-ui/react/switch" +import { cn } from "@/lib/utils" + +export type SwitchThumbProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSwitchThumb = BaseSwitch.Thumb as React.ElementType +const defaultSwitchThumbClassName = + "size-3.5 bg-neutral-950 transition-[translate,background-color] duration-150 ease-[ease] data-checked:translate-x-4 data-checked:bg-white dark:bg-white dark:data-checked:bg-neutral-950" + +export const SwitchThumb = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SwitchThumb.displayName = "SwitchThumb" diff --git a/src/components/ui/tabs/index.ts b/src/components/ui/tabs/index.ts new file mode 100644 index 0000000..ca93104 --- /dev/null +++ b/src/components/ui/tabs/index.ts @@ -0,0 +1,30 @@ +import { TabsRoot } from "./root" +import { TabsTab } from "./tab" +import { TabsIndicator } from "./indicator" +import { TabsPanel } from "./panel" +import { TabsList } from "./list" + +const TabsPrimitive = { + Root: TabsRoot, + Tab: TabsTab, + Indicator: TabsIndicator, + Panel: TabsPanel, + List: TabsList, +} + +export default TabsPrimitive + +export { + TabsRoot as Tabs, + TabsRoot, + TabsTab, + TabsIndicator, + TabsPanel, + TabsList, +} + +export type { TabsRootProps } from "./root" +export type { TabsTabProps } from "./tab" +export type { TabsIndicatorProps } from "./indicator" +export type { TabsPanelProps } from "./panel" +export type { TabsListProps } from "./list" diff --git a/src/components/ui/tabs/indicator.tsx b/src/components/ui/tabs/indicator.tsx new file mode 100644 index 0000000..f9f10b9 --- /dev/null +++ b/src/components/ui/tabs/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsIndicator = BaseTabs.Indicator as React.ElementType + +export const TabsIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsIndicator.displayName = "TabsIndicator" diff --git a/src/components/ui/tabs/list.tsx b/src/components/ui/tabs/list.tsx new file mode 100644 index 0000000..ed2f537 --- /dev/null +++ b/src/components/ui/tabs/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsList = BaseTabs.List as React.ElementType + +export const TabsList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsList.displayName = "TabsList" diff --git a/src/components/ui/tabs/panel.tsx b/src/components/ui/tabs/panel.tsx new file mode 100644 index 0000000..d0690f1 --- /dev/null +++ b/src/components/ui/tabs/panel.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsPanelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsPanel = BaseTabs.Panel as React.ElementType + +export const TabsPanel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsPanel.displayName = "TabsPanel" diff --git a/src/components/ui/tabs/root.tsx b/src/components/ui/tabs/root.tsx new file mode 100644 index 0000000..82eaee8 --- /dev/null +++ b/src/components/ui/tabs/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsRoot = BaseTabs.Root as React.ElementType + +export const TabsRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsRoot.displayName = "TabsRoot" diff --git a/src/components/ui/tabs/tab.tsx b/src/components/ui/tabs/tab.tsx new file mode 100644 index 0000000..53e68a1 --- /dev/null +++ b/src/components/ui/tabs/tab.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsTabProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsTab = BaseTabs.Tab as React.ElementType + +export const TabsTab = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsTab.displayName = "TabsTab" diff --git a/src/components/ui/toast/action.tsx b/src/components/ui/toast/action.tsx new file mode 100644 index 0000000..f10e1a6 --- /dev/null +++ b/src/components/ui/toast/action.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastActionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastAction = BaseToast.Action as React.ElementType + +export const ToastAction = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastAction.displayName = "ToastAction" diff --git a/src/components/ui/toast/arrow.tsx b/src/components/ui/toast/arrow.tsx new file mode 100644 index 0000000..5e8830c --- /dev/null +++ b/src/components/ui/toast/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastArrow = BaseToast.Arrow as React.ElementType + +export const ToastArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastArrow.displayName = "ToastArrow" diff --git a/src/components/ui/toast/close.tsx b/src/components/ui/toast/close.tsx new file mode 100644 index 0000000..ac6549b --- /dev/null +++ b/src/components/ui/toast/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastClose = BaseToast.Close as React.ElementType + +export const ToastClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastClose.displayName = "ToastClose" diff --git a/src/components/ui/toast/content.tsx b/src/components/ui/toast/content.tsx new file mode 100644 index 0000000..dcbff13 --- /dev/null +++ b/src/components/ui/toast/content.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastContent = BaseToast.Content as React.ElementType + +export const ToastContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastContent.displayName = "ToastContent" diff --git a/src/components/ui/toast/description.tsx b/src/components/ui/toast/description.tsx new file mode 100644 index 0000000..2532df1 --- /dev/null +++ b/src/components/ui/toast/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastDescription = BaseToast.Description as React.ElementType + +export const ToastDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastDescription.displayName = "ToastDescription" diff --git a/src/components/ui/toast/index.ts b/src/components/ui/toast/index.ts new file mode 100644 index 0000000..f44784c --- /dev/null +++ b/src/components/ui/toast/index.ts @@ -0,0 +1,62 @@ +import { Toast as BaseToast } from "@base-ui/react/toast" +import { ToastProvider } from "./provider" +import { ToastViewport } from "./viewport" +import { ToastRoot } from "./root" +import { ToastContent } from "./content" +import { ToastDescription } from "./description" +import { ToastTitle } from "./title" +import { ToastClose } from "./close" +import { ToastAction } from "./action" +import { ToastPortal } from "./portal" +import { ToastPositioner } from "./positioner" +import { ToastArrow } from "./arrow" + +const useToastManager = BaseToast.useToastManager +const createToastManager = BaseToast.createToastManager + +const ToastPrimitive = { + Provider: ToastProvider, + Viewport: ToastViewport, + Root: ToastRoot, + Content: ToastContent, + Description: ToastDescription, + Title: ToastTitle, + Close: ToastClose, + Action: ToastAction, + Portal: ToastPortal, + Positioner: ToastPositioner, + Arrow: ToastArrow, + useToastManager: BaseToast.useToastManager, + createToastManager: BaseToast.createToastManager, +} + +export default ToastPrimitive + +export { + ToastRoot as Toast, + ToastProvider, + ToastViewport, + ToastRoot, + ToastContent, + ToastDescription, + ToastTitle, + ToastClose, + ToastAction, + ToastPortal, + ToastPositioner, + ToastArrow, + useToastManager, + createToastManager, +} + +export type { ToastProviderProps } from "./provider" +export type { ToastViewportProps } from "./viewport" +export type { ToastRootProps } from "./root" +export type { ToastContentProps } from "./content" +export type { ToastDescriptionProps } from "./description" +export type { ToastTitleProps } from "./title" +export type { ToastCloseProps } from "./close" +export type { ToastActionProps } from "./action" +export type { ToastPortalProps } from "./portal" +export type { ToastPositionerProps } from "./positioner" +export type { ToastArrowProps } from "./arrow" diff --git a/src/components/ui/toast/portal.tsx b/src/components/ui/toast/portal.tsx new file mode 100644 index 0000000..3f1c549 --- /dev/null +++ b/src/components/ui/toast/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type ToastPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastPortal = BaseToast.Portal as React.ElementType + +export const ToastPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +ToastPortal.displayName = "ToastPortal" diff --git a/src/components/ui/toast/positioner.tsx b/src/components/ui/toast/positioner.tsx new file mode 100644 index 0000000..0d694ba --- /dev/null +++ b/src/components/ui/toast/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastPositioner = BaseToast.Positioner as React.ElementType + +export const ToastPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastPositioner.displayName = "ToastPositioner" diff --git a/src/components/ui/toast/provider.tsx b/src/components/ui/toast/provider.tsx new file mode 100644 index 0000000..f7faf36 --- /dev/null +++ b/src/components/ui/toast/provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastProvider = BaseToast.Provider as React.ElementType + +export const ToastProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastProvider.displayName = "ToastProvider" diff --git a/src/components/ui/toast/root.tsx b/src/components/ui/toast/root.tsx new file mode 100644 index 0000000..5deb2f0 --- /dev/null +++ b/src/components/ui/toast/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastRoot = BaseToast.Root as React.ElementType +const defaultToastRootClassName = + "border border-neutral-950 bg-white text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] select-none focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const ToastRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastRoot.displayName = "ToastRoot" diff --git a/src/components/ui/toast/title.tsx b/src/components/ui/toast/title.tsx new file mode 100644 index 0000000..2eca064 --- /dev/null +++ b/src/components/ui/toast/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastTitle = BaseToast.Title as React.ElementType + +export const ToastTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastTitle.displayName = "ToastTitle" diff --git a/src/components/ui/toast/viewport.tsx b/src/components/ui/toast/viewport.tsx new file mode 100644 index 0000000..fc967c7 --- /dev/null +++ b/src/components/ui/toast/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastViewport = BaseToast.Viewport as React.ElementType + +export const ToastViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastViewport.displayName = "ToastViewport" diff --git a/src/components/ui/toggle-group/index.ts b/src/components/ui/toggle-group/index.ts new file mode 100644 index 0000000..053002a --- /dev/null +++ b/src/components/ui/toggle-group/index.ts @@ -0,0 +1,4 @@ +import { ToggleGroup } from "./root" + +export { ToggleGroup, type ToggleGroupProps } from "./root" +export default ToggleGroup diff --git a/src/components/ui/toggle-group/root.tsx b/src/components/ui/toggle-group/root.tsx new file mode 100644 index 0000000..db285d5 --- /dev/null +++ b/src/components/ui/toggle-group/root.tsx @@ -0,0 +1,22 @@ +"use client" + +import * as React from "react" +import { ToggleGroup as BaseToggleGroup } from "@base-ui/react/toggle-group" +import { cn } from "@/lib/utils" + +export type ToggleGroupProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseToggleGroupElement = BaseToggleGroup as React.ElementType +const defaultToggleGroupClassName = "flex gap-px border border-neutral-950 p-px dark:border-white" + +export const ToggleGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToggleGroup.displayName = "ToggleGroup" diff --git a/src/components/ui/toggle/index.ts b/src/components/ui/toggle/index.ts new file mode 100644 index 0000000..de64e1d --- /dev/null +++ b/src/components/ui/toggle/index.ts @@ -0,0 +1,4 @@ +import { Toggle } from "./root" + +export { Toggle, type ToggleProps } from "./root" +export default Toggle diff --git a/src/components/ui/toggle/root.tsx b/src/components/ui/toggle/root.tsx new file mode 100644 index 0000000..b9a0a4f --- /dev/null +++ b/src/components/ui/toggle/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toggle as BaseToggle } from "@base-ui/react/toggle" +import { cn } from "@/lib/utils" + +export type ToggleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToggleElement = BaseToggle as React.ElementType +const defaultToggleClassName = + "flex size-8 items-center justify-center border-none rounded-none bg-transparent text-neutral-950 dark:text-white select-none [&:not([data-disabled]):hover]:bg-neutral-100 dark:[&:not([data-disabled]):hover]:bg-neutral-800 [&:not([data-disabled]):not([data-pressed]):active]:bg-neutral-200 dark:[&:not([data-disabled]):not([data-pressed]):active]:bg-neutral-700 data-[pressed]:bg-neutral-950 data-[pressed]:text-white dark:data-[pressed]:bg-white dark:data-[pressed]:text-neutral-950 data-[pressed]:hover:bg-neutral-950 data-[pressed]:hover:text-white dark:data-[pressed]:hover:bg-white dark:data-[pressed]:hover:text-neutral-950 focus-visible:relative focus-visible:z-1 focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const Toggle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Toggle.displayName = "Toggle" diff --git a/src/components/ui/toolbar/button.tsx b/src/components/ui/toolbar/button.tsx new file mode 100644 index 0000000..49555e9 --- /dev/null +++ b/src/components/ui/toolbar/button.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarButtonProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarButton = BaseToolbar.Button as React.ElementType +const defaultToolbarButtonClassName = + "flex h-8 min-w-8 items-center justify-center gap-2 border-0 bg-transparent font-[inherit] text-sm leading-none whitespace-nowrap font-normal text-neutral-950 select-none [&:not([data-disabled]):hover]:bg-neutral-100 [&:not([data-disabled]):not([data-pressed]):active]:bg-neutral-200 data-[pressed]:bg-neutral-950 data-[pressed]:text-white data-[pressed]:[&:not([data-disabled]):hover]:bg-neutral-950 data-[pressed]:[&:not([data-disabled]):hover]:text-white data-[popup-open]:!bg-neutral-100 data-[popup-open]:!text-neutral-950 dark:text-white dark:[&:not([data-disabled]):hover]:bg-neutral-800 dark:[&:not([data-disabled]):not([data-pressed]):active]:bg-neutral-700 dark:data-[pressed]:bg-white dark:data-[pressed]:text-neutral-950 dark:data-[pressed]:[&:not([data-disabled]):hover]:bg-white dark:data-[pressed]:[&:not([data-disabled]):hover]:text-neutral-950 dark:data-[popup-open]:!bg-neutral-800 dark:data-[popup-open]:!text-white focus-visible:bg-transparent focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const ToolbarButton = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarButton.displayName = "ToolbarButton" diff --git a/src/components/ui/toolbar/group.tsx b/src/components/ui/toolbar/group.tsx new file mode 100644 index 0000000..c6f0993 --- /dev/null +++ b/src/components/ui/toolbar/group.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarGroup = BaseToolbar.Group as React.ElementType +const defaultToolbarGroupClassName = "flex gap-px" + +export const ToolbarGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarGroup.displayName = "ToolbarGroup" diff --git a/src/components/ui/toolbar/index.ts b/src/components/ui/toolbar/index.ts new file mode 100644 index 0000000..3ec94f7 --- /dev/null +++ b/src/components/ui/toolbar/index.ts @@ -0,0 +1,34 @@ +import { ToolbarSeparator } from "./separator" +import { ToolbarRoot } from "./root" +import { ToolbarGroup } from "./group" +import { ToolbarButton } from "./button" +import { ToolbarLink } from "./link" +import { ToolbarInput } from "./input" + +const ToolbarPrimitive = { + Separator: ToolbarSeparator, + Root: ToolbarRoot, + Group: ToolbarGroup, + Button: ToolbarButton, + Link: ToolbarLink, + Input: ToolbarInput, +} + +export default ToolbarPrimitive + +export { + ToolbarRoot as Toolbar, + ToolbarSeparator, + ToolbarRoot, + ToolbarGroup, + ToolbarButton, + ToolbarLink, + ToolbarInput, +} + +export type { ToolbarSeparatorProps } from "./separator" +export type { ToolbarRootProps } from "./root" +export type { ToolbarGroupProps } from "./group" +export type { ToolbarButtonProps } from "./button" +export type { ToolbarLinkProps } from "./link" +export type { ToolbarInputProps } from "./input" diff --git a/src/components/ui/toolbar/input.tsx b/src/components/ui/toolbar/input.tsx new file mode 100644 index 0000000..bbfcb4c --- /dev/null +++ b/src/components/ui/toolbar/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarInput = BaseToolbar.Input as React.ElementType + +export const ToolbarInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarInput.displayName = "ToolbarInput" diff --git a/src/components/ui/toolbar/link.tsx b/src/components/ui/toolbar/link.tsx new file mode 100644 index 0000000..a458854 --- /dev/null +++ b/src/components/ui/toolbar/link.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarLinkProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarLink = BaseToolbar.Link as React.ElementType +const defaultToolbarLinkClassName = + "mr-[0.875rem] ml-auto flex-none self-center font-[inherit] text-sm text-neutral-500 no-underline hover:text-blue-700 dark:text-neutral-400 dark:hover:text-blue-500 focus-visible:outline-2 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const ToolbarLink = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarLink.displayName = "ToolbarLink" diff --git a/src/components/ui/toolbar/root.tsx b/src/components/ui/toolbar/root.tsx new file mode 100644 index 0000000..40ee4c0 --- /dev/null +++ b/src/components/ui/toolbar/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarRoot = BaseToolbar.Root as React.ElementType +const defaultToolbarRootClassName = + "flex w-[37.5rem] items-center gap-px border border-neutral-950 bg-white p-px dark:border-white dark:bg-neutral-950" + +export const ToolbarRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarRoot.displayName = "ToolbarRoot" diff --git a/src/components/ui/toolbar/separator.tsx b/src/components/ui/toolbar/separator.tsx new file mode 100644 index 0000000..76a5c61 --- /dev/null +++ b/src/components/ui/toolbar/separator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarSeparatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarSeparator = BaseToolbar.Separator as React.ElementType + +export const ToolbarSeparator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarSeparator.displayName = "ToolbarSeparator" diff --git a/src/components/ui/tooltip/arrow.tsx b/src/components/ui/tooltip/arrow.tsx new file mode 100644 index 0000000..79e6cb0 --- /dev/null +++ b/src/components/ui/tooltip/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipArrow = BaseTooltip.Arrow as React.ElementType + +export const TooltipArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipArrow.displayName = "TooltipArrow" diff --git a/src/components/ui/tooltip/content.tsx b/src/components/ui/tooltip/content.tsx new file mode 100644 index 0000000..1248cbc --- /dev/null +++ b/src/components/ui/tooltip/content.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { TooltipPortal } from "./portal" +import { TooltipPositioner } from "./positioner" +import { TooltipPopup, type TooltipPopupProps } from "./popup" + +export type TooltipContentProps = TooltipPopupProps + +export const TooltipContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + + ), +) + +TooltipContent.displayName = "TooltipContent" diff --git a/src/components/ui/tooltip/index.ts b/src/components/ui/tooltip/index.ts new file mode 100644 index 0000000..5f94b79 --- /dev/null +++ b/src/components/ui/tooltip/index.ts @@ -0,0 +1,48 @@ +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { TooltipRoot } from "./root" +import { TooltipTrigger } from "./trigger" +import { TooltipPortal } from "./portal" +import { TooltipPositioner } from "./positioner" +import { TooltipPopup } from "./popup" +import { TooltipArrow } from "./arrow" +import { TooltipProvider } from "./provider" +import { TooltipViewport } from "./viewport" +import { TooltipContent } from "./content" + +const TooltipPrimitive = { + Root: TooltipRoot, + Trigger: TooltipTrigger, + Portal: TooltipPortal, + Positioner: TooltipPositioner, + Popup: TooltipPopup, + Arrow: TooltipArrow, + Provider: TooltipProvider, + Viewport: TooltipViewport, + createHandle: BaseTooltip.createHandle, +} + +export default TooltipPrimitive + +export { + TooltipRoot as Tooltip, + TooltipRoot, + TooltipTrigger, + TooltipPortal, + TooltipPositioner, + TooltipPopup, + TooltipArrow, + TooltipProvider, + TooltipViewport, + TooltipContent, + BaseTooltip, +} + +export type { TooltipRootProps } from "./root" +export type { TooltipTriggerProps } from "./trigger" +export type { TooltipPortalProps } from "./portal" +export type { TooltipPositionerProps } from "./positioner" +export type { TooltipPopupProps } from "./popup" +export type { TooltipArrowProps } from "./arrow" +export type { TooltipProviderProps } from "./provider" +export type { TooltipViewportProps } from "./viewport" +export type { TooltipContentProps } from "./content" diff --git a/src/components/ui/tooltip/popup.tsx b/src/components/ui/tooltip/popup.tsx new file mode 100644 index 0000000..75b58a0 --- /dev/null +++ b/src/components/ui/tooltip/popup.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipPopup = BaseTooltip.Popup as React.ElementType + +export const TooltipPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipPopup.displayName = "TooltipPopup" diff --git a/src/components/ui/tooltip/portal.tsx b/src/components/ui/tooltip/portal.tsx new file mode 100644 index 0000000..41f7e1e --- /dev/null +++ b/src/components/ui/tooltip/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipPortal = BaseTooltip.Portal as React.ElementType + +export const TooltipPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipPortal.displayName = "TooltipPortal" diff --git a/src/components/ui/tooltip/positioner.tsx b/src/components/ui/tooltip/positioner.tsx new file mode 100644 index 0000000..4de534e --- /dev/null +++ b/src/components/ui/tooltip/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipPositioner = BaseTooltip.Positioner as React.ElementType + +export const TooltipPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipPositioner.displayName = "TooltipPositioner" diff --git a/src/components/ui/tooltip/provider.tsx b/src/components/ui/tooltip/provider.tsx new file mode 100644 index 0000000..3ff755b --- /dev/null +++ b/src/components/ui/tooltip/provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipProvider = BaseTooltip.Provider as React.ElementType + +export const TooltipProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipProvider.displayName = "TooltipProvider" diff --git a/src/components/ui/tooltip/root.tsx b/src/components/ui/tooltip/root.tsx new file mode 100644 index 0000000..df9e528 --- /dev/null +++ b/src/components/ui/tooltip/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipRoot = BaseTooltip.Root as React.ElementType + +export const TooltipRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipRoot.displayName = "TooltipRoot" diff --git a/src/components/ui/tooltip/trigger.tsx b/src/components/ui/tooltip/trigger.tsx new file mode 100644 index 0000000..5b61d5b --- /dev/null +++ b/src/components/ui/tooltip/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipTrigger = BaseTooltip.Trigger as React.ElementType + +export const TooltipTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipTrigger.displayName = "TooltipTrigger" diff --git a/src/components/ui/tooltip/viewport.tsx b/src/components/ui/tooltip/viewport.tsx new file mode 100644 index 0000000..2c89f63 --- /dev/null +++ b/src/components/ui/tooltip/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipViewport = BaseTooltip.Viewport as React.ElementType + +export const TooltipViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipViewport.displayName = "TooltipViewport" diff --git a/src/lib/portal-container.tsx b/src/lib/portal-container.tsx new file mode 100644 index 0000000..6295e50 --- /dev/null +++ b/src/lib/portal-container.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" + +type PortalContainer = React.RefObject + +const PortalContainerContext = React.createContext(null) + +export function PortalContainerProvider({ + children, + container, +}: { + children: React.ReactNode + container: PortalContainer +}) { + return ( + + {children} + + ) +} + +export function usePortalContainer() { + return React.useContext(PortalContainerContext) +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/src/styles/globals.css b/src/styles/globals.css new file mode 100644 index 0000000..96865d3 --- /dev/null +++ b/src/styles/globals.css @@ -0,0 +1,98 @@ +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +@utility no-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; + + &::-webkit-scrollbar { + display: none; + } +} + +@custom-variant data-open { + &:where([data-state="open"]), + &:where([data-open]:not([data-open="false"])) { + @slot; + } +} + +@custom-variant data-closed { + &:where([data-state="closed"]), + &:where([data-closed]:not([data-closed="false"])) { + @slot; + } +} + +@custom-variant data-checked { + &:where([data-state="checked"]), + &:where([data-checked]:not([data-checked="false"])) { + @slot; + } +} + +@custom-variant data-unchecked { + &:where([data-state="unchecked"]), + &:where([data-unchecked]:not([data-unchecked="false"])) { + @slot; + } +} + +@custom-variant data-selected { + &:where([data-selected="true"]) { + @slot; + } +} + +@custom-variant data-disabled { + &:where([data-disabled="true"]), + &:where([data-disabled]:not([data-disabled="false"])) { + @slot; + } +} + +@custom-variant data-active { + &:where([data-state="active"]), + &:where([data-active]:not([data-active="false"])) { + @slot; + } +} + +@custom-variant data-horizontal { + &:where([data-orientation="horizontal"]) { + @slot; + } +} + +@custom-variant data-vertical { + &:where([data-orientation="vertical"]) { + @slot; + } +} + +@theme inline { + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); +} + +:root { + --radius: 0.625rem; +} + +.dark {} + +@layer base { + /** { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + }*/ +}