@arolariu/components 0.5.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{changelog.md → CHANGELOG.md} +82 -0
- package/CONTRIBUTING.md +344 -265
- package/DEBUGGING.md +185 -103
- package/EXAMPLES.md +2976 -341
- package/{readme.md → README.md} +306 -203
- package/dist/components/ui/accordion.d.ts +157 -5
- package/dist/components/ui/accordion.d.ts.map +1 -1
- package/dist/components/ui/accordion.js +100 -22
- package/dist/components/ui/accordion.js.map +1 -1
- package/dist/components/ui/accordion.module.js +12 -0
- package/dist/components/ui/accordion.module.js.map +1 -0
- package/dist/components/ui/accordion_module.css +72 -0
- package/dist/components/ui/accordion_module.css.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +309 -18
- package/dist/components/ui/alert-dialog.d.ts.map +1 -1
- package/dist/components/ui/alert-dialog.js +149 -52
- package/dist/components/ui/alert-dialog.js.map +1 -1
- package/dist/components/ui/alert-dialog.module.js +13 -0
- package/dist/components/ui/alert-dialog.module.js.map +1 -0
- package/dist/components/ui/alert-dialog_module.css +89 -0
- package/dist/components/ui/alert-dialog_module.css.map +1 -0
- package/dist/components/ui/alert.d.ts +109 -6
- package/dist/components/ui/alert.d.ts.map +1 -1
- package/dist/components/ui/alert.js +12 -21
- package/dist/components/ui/alert.js.map +1 -1
- package/dist/components/ui/alert.module.js +11 -0
- package/dist/components/ui/alert.module.js.map +1 -0
- package/dist/components/ui/alert_module.css +59 -0
- package/dist/components/ui/alert_module.css.map +1 -0
- package/dist/components/ui/aspect-ratio.d.ts +24 -2
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -1
- package/dist/components/ui/aspect-ratio.js +14 -3
- package/dist/components/ui/aspect-ratio.js.map +1 -1
- package/dist/components/ui/aspect-ratio.module.js +7 -0
- package/dist/components/ui/aspect-ratio.module.js.map +1 -0
- package/dist/components/ui/aspect-ratio_module.css +10 -0
- package/dist/components/ui/aspect-ratio_module.css.map +1 -0
- package/dist/components/ui/async-boundary.js +17 -0
- package/dist/components/ui/async-boundary.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +88 -4
- package/dist/components/ui/avatar.d.ts.map +1 -1
- package/dist/components/ui/avatar.js +52 -20
- package/dist/components/ui/avatar.js.map +1 -1
- package/dist/components/ui/avatar.module.js +9 -0
- package/dist/components/ui/avatar.module.js.map +1 -0
- package/dist/components/ui/avatar_module.css +35 -0
- package/dist/components/ui/avatar_module.css.map +1 -0
- package/dist/components/ui/background-beams.d.ts +21 -3
- package/dist/components/ui/background-beams.d.ts.map +1 -1
- package/dist/components/ui/background-beams.js +22 -11
- package/dist/components/ui/background-beams.js.map +1 -1
- package/dist/components/ui/background-beams.module.js +8 -0
- package/dist/components/ui/background-beams.module.js.map +1 -0
- package/dist/components/ui/background-beams_module.css +22 -0
- package/dist/components/ui/background-beams_module.css.map +1 -0
- package/dist/components/ui/badge.d.ts +79 -6
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/badge.js +19 -23
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/badge.module.js +11 -0
- package/dist/components/ui/badge.module.js.map +1 -0
- package/dist/components/ui/badge_module.css +63 -0
- package/dist/components/ui/badge_module.css.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +158 -13
- package/dist/components/ui/breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb.js +39 -30
- package/dist/components/ui/breadcrumb.js.map +1 -1
- package/dist/components/ui/breadcrumb.module.js +14 -0
- package/dist/components/ui/breadcrumb.module.js.map +1 -0
- package/dist/components/ui/breadcrumb_module.css +90 -0
- package/dist/components/ui/breadcrumb_module.css.map +1 -0
- package/dist/components/ui/bubble-background.d.ts +38 -10
- package/dist/components/ui/bubble-background.d.ts.map +1 -1
- package/dist/components/ui/bubble-background.js +33 -35
- package/dist/components/ui/bubble-background.js.map +1 -1
- package/dist/components/ui/bubble-background.module.js +20 -0
- package/dist/components/ui/bubble-background.module.js.map +1 -0
- package/dist/components/ui/bubble-background_module.css +99 -0
- package/dist/components/ui/bubble-background_module.css.map +1 -0
- package/dist/components/ui/button-group.d.ts +88 -8
- package/dist/components/ui/button-group.d.ts.map +1 -1
- package/dist/components/ui/button-group.js +35 -32
- package/dist/components/ui/button-group.js.map +1 -1
- package/dist/components/ui/button-group.module.js +11 -0
- package/dist/components/ui/button-group.module.js.map +1 -0
- package/dist/components/ui/button-group_module.css +79 -0
- package/dist/components/ui/button-group_module.css.map +1 -0
- package/dist/components/ui/button.d.ts +82 -7
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/button.js +69 -34
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/button.module.js +17 -0
- package/dist/components/ui/button.module.js.map +1 -0
- package/dist/components/ui/button_module.css +137 -0
- package/dist/components/ui/button_module.css.map +1 -0
- package/dist/components/ui/calendar.d.ts +36 -5
- package/dist/components/ui/calendar.d.ts.map +1 -1
- package/dist/components/ui/calendar.js +75 -64
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/components/ui/calendar.module.js +35 -0
- package/dist/components/ui/calendar.module.js.map +1 -0
- package/dist/components/ui/calendar_module.css +245 -0
- package/dist/components/ui/calendar_module.css.map +1 -0
- package/dist/components/ui/card-skeleton.js +41 -0
- package/dist/components/ui/card-skeleton.js.map +1 -0
- package/dist/components/ui/card-skeleton.module.js +15 -0
- package/dist/components/ui/card-skeleton.module.js.map +1 -0
- package/dist/components/ui/card-skeleton_module.css +54 -0
- package/dist/components/ui/card-skeleton_module.css.map +1 -0
- package/dist/components/ui/card.d.ts +162 -7
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/card.js +13 -13
- package/dist/components/ui/card.js.map +1 -1
- package/dist/components/ui/card.module.js +13 -0
- package/dist/components/ui/card.module.js.map +1 -0
- package/dist/components/ui/card_module.css +43 -0
- package/dist/components/ui/card_module.css.map +1 -0
- package/dist/components/ui/carousel.d.ts +127 -3
- package/dist/components/ui/carousel.d.ts.map +1 -1
- package/dist/components/ui/carousel.js +63 -36
- package/dist/components/ui/carousel.js.map +1 -1
- package/dist/components/ui/carousel.module.js +17 -0
- package/dist/components/ui/carousel.module.js.map +1 -0
- package/dist/components/ui/carousel_module.css +82 -0
- package/dist/components/ui/carousel_module.css.map +1 -0
- package/dist/components/ui/chart.d.ts +323 -13
- package/dist/components/ui/chart.d.ts.map +1 -1
- package/dist/components/ui/chart.js +224 -53
- package/dist/components/ui/chart.js.map +1 -1
- package/dist/components/ui/chart.module.js +27 -0
- package/dist/components/ui/chart.module.js.map +1 -0
- package/dist/components/ui/chart_module.css +159 -0
- package/dist/components/ui/chart_module.css.map +1 -0
- package/dist/components/ui/checkbox-group.d.ts +27 -0
- package/dist/components/ui/checkbox-group.d.ts.map +1 -0
- package/dist/components/ui/checkbox-group.js +26 -0
- package/dist/components/ui/checkbox-group.js.map +1 -0
- package/dist/components/ui/checkbox-group.module.js +7 -0
- package/dist/components/ui/checkbox-group.module.js.map +1 -0
- package/dist/components/ui/checkbox-group_module.css +11 -0
- package/dist/components/ui/checkbox-group_module.css.map +1 -0
- package/dist/components/ui/checkbox.d.ts +35 -2
- package/dist/components/ui/checkbox.d.ts.map +1 -1
- package/dist/components/ui/checkbox.js +40 -12
- package/dist/components/ui/checkbox.js.map +1 -1
- package/dist/components/ui/checkbox.module.js +8 -0
- package/dist/components/ui/checkbox.module.js.map +1 -0
- package/dist/components/ui/checkbox_module.css +45 -0
- package/dist/components/ui/checkbox_module.css.map +1 -0
- package/dist/components/ui/collapsible.d.ts +87 -3
- package/dist/components/ui/collapsible.d.ts.map +1 -1
- package/dist/components/ui/collapsible.js +46 -32
- package/dist/components/ui/collapsible.js.map +1 -1
- package/dist/components/ui/collapsible.module.js +8 -0
- package/dist/components/ui/collapsible.module.js.map +1 -0
- package/dist/components/ui/collapsible_module.css +26 -0
- package/dist/components/ui/collapsible_module.css.map +1 -0
- package/dist/components/ui/combobox.d.ts +335 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/combobox.js +206 -0
- package/dist/components/ui/combobox.js.map +1 -0
- package/dist/components/ui/combobox.module.js +23 -0
- package/dist/components/ui/combobox.module.js.map +1 -0
- package/dist/components/ui/combobox_module.css +142 -0
- package/dist/components/ui/combobox_module.css.map +1 -0
- package/dist/components/ui/command.d.ts +284 -51
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/command.js +396 -51
- package/dist/components/ui/command.js.map +1 -1
- package/dist/components/ui/command.module.js +20 -0
- package/dist/components/ui/command.module.js.map +1 -0
- package/dist/components/ui/command_module.css +194 -0
- package/dist/components/ui/command_module.css.map +1 -0
- package/dist/components/ui/context-menu.d.ts +414 -21
- package/dist/components/ui/context-menu.d.ts.map +1 -1
- package/dist/components/ui/context-menu.js +190 -68
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/components/ui/context-menu.module.js +19 -0
- package/dist/components/ui/context-menu.module.js.map +1 -0
- package/dist/components/ui/context-menu_module.css +114 -0
- package/dist/components/ui/context-menu_module.css.map +1 -0
- package/dist/components/ui/copy-button.d.ts +41 -0
- package/dist/components/ui/copy-button.d.ts.map +1 -0
- package/dist/components/ui/copy-button.js +51 -0
- package/dist/components/ui/copy-button.js.map +1 -0
- package/dist/components/ui/copy-button.module.js +8 -0
- package/dist/components/ui/copy-button.module.js.map +1 -0
- package/dist/components/ui/copy-button_module.css +37 -0
- package/dist/components/ui/copy-button_module.css.map +1 -0
- package/dist/components/ui/counting-number.d.ts +28 -2
- package/dist/components/ui/counting-number.d.ts.map +1 -1
- package/dist/components/ui/counting-number.js +31 -27
- package/dist/components/ui/counting-number.js.map +1 -1
- package/dist/components/ui/counting-number.module.js +7 -0
- package/dist/components/ui/counting-number.module.js.map +1 -0
- package/dist/components/ui/counting-number_module.css +7 -0
- package/dist/components/ui/counting-number_module.css.map +1 -0
- package/dist/components/ui/dialog.d.ts +287 -17
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog.js +129 -52
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/dialog.module.js +13 -0
- package/dist/components/ui/dialog.module.js.map +1 -0
- package/dist/components/ui/dialog_module.css +114 -0
- package/dist/components/ui/dialog_module.css.map +1 -0
- package/dist/components/ui/dot-background.d.ts +25 -35
- package/dist/components/ui/dot-background.d.ts.map +1 -1
- package/dist/components/ui/dot-background.js +31 -22
- package/dist/components/ui/dot-background.js.map +1 -1
- package/dist/components/ui/dot-background.module.js +8 -0
- package/dist/components/ui/dot-background.module.js.map +1 -0
- package/dist/components/ui/dot-background_module.css +15 -0
- package/dist/components/ui/dot-background_module.css.map +1 -0
- package/dist/components/ui/drawer.d.ts +287 -18
- package/dist/components/ui/drawer.d.ts.map +1 -1
- package/dist/components/ui/drawer.js +117 -40
- package/dist/components/ui/drawer.js.map +1 -1
- package/dist/components/ui/drawer.module.js +14 -0
- package/dist/components/ui/drawer.module.js.map +1 -0
- package/dist/components/ui/drawer_module.css +86 -0
- package/dist/components/ui/drawer_module.css.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +414 -21
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.js +189 -68
- package/dist/components/ui/dropdown-menu.js.map +1 -1
- package/dist/components/ui/dropdown-menu.module.js +19 -0
- package/dist/components/ui/dropdown-menu.module.js.map +1 -0
- package/dist/components/ui/dropdown-menu_module.css +114 -0
- package/dist/components/ui/dropdown-menu_module.css.map +1 -0
- package/dist/components/ui/dropdrawer.d.ts +307 -17
- package/dist/components/ui/dropdrawer.d.ts.map +1 -1
- package/dist/components/ui/dropdrawer.js +438 -166
- package/dist/components/ui/dropdrawer.js.map +1 -1
- package/dist/components/ui/dropdrawer.module.js +43 -0
- package/dist/components/ui/dropdrawer.module.js.map +1 -0
- package/dist/components/ui/dropdrawer_module.css +307 -0
- package/dist/components/ui/dropdrawer_module.css.map +1 -0
- package/dist/components/ui/empty.d.ts +129 -10
- package/dist/components/ui/empty.d.ts.map +1 -1
- package/dist/components/ui/empty.js +32 -47
- package/dist/components/ui/empty.js.map +1 -1
- package/dist/components/ui/empty.module.js +13 -0
- package/dist/components/ui/empty.module.js.map +1 -0
- package/dist/components/ui/empty_module.css +85 -0
- package/dist/components/ui/empty_module.css.map +1 -0
- package/dist/components/ui/error-boundary.js +61 -0
- package/dist/components/ui/error-boundary.js.map +1 -0
- package/dist/components/ui/error-boundary.module.js +10 -0
- package/dist/components/ui/error-boundary.module.js.map +1 -0
- package/dist/components/ui/error-boundary_module.css +41 -0
- package/dist/components/ui/error-boundary_module.css.map +1 -0
- package/dist/components/ui/field.d.ts +222 -23
- package/dist/components/ui/field.d.ts.map +1 -1
- package/dist/components/ui/field.js +76 -86
- package/dist/components/ui/field.js.map +1 -1
- package/dist/components/ui/field.module.js +24 -0
- package/dist/components/ui/field.module.js.map +1 -0
- package/dist/components/ui/field_module.css +185 -0
- package/dist/components/ui/field_module.css.map +1 -0
- package/dist/components/ui/fireworks-background.d.ts +27 -3
- package/dist/components/ui/fireworks-background.d.ts.map +1 -1
- package/dist/components/ui/fireworks-background.js +36 -35
- package/dist/components/ui/fireworks-background.js.map +1 -1
- package/dist/components/ui/fireworks-background.module.js +8 -0
- package/dist/components/ui/fireworks-background.module.js.map +1 -0
- package/dist/components/ui/fireworks-background_module.css +17 -0
- package/dist/components/ui/fireworks-background_module.css.map +1 -0
- package/dist/components/ui/flip-button.d.ts +27 -3
- package/dist/components/ui/flip-button.d.ts.map +1 -1
- package/dist/components/ui/flip-button.js +27 -17
- package/dist/components/ui/flip-button.js.map +1 -1
- package/dist/components/ui/flip-button.module.js +11 -0
- package/dist/components/ui/flip-button.module.js.map +1 -0
- package/dist/components/ui/flip-button_module.css +47 -0
- package/dist/components/ui/flip-button_module.css.map +1 -0
- package/dist/components/ui/focus-scope.js +70 -0
- package/dist/components/ui/focus-scope.js.map +1 -0
- package/dist/components/ui/focus-scope.module.js +7 -0
- package/dist/components/ui/focus-scope.module.js.map +1 -0
- package/dist/components/ui/focus-scope_module.css +6 -0
- package/dist/components/ui/focus-scope_module.css.map +1 -0
- package/dist/components/ui/form-skeleton.js +32 -0
- package/dist/components/ui/form-skeleton.js.map +1 -0
- package/dist/components/ui/form-skeleton.module.js +11 -0
- package/dist/components/ui/form-skeleton.module.js.map +1 -0
- package/dist/components/ui/form-skeleton_module.css +30 -0
- package/dist/components/ui/form-skeleton_module.css.map +1 -0
- package/dist/components/ui/form.d.ts +143 -13
- package/dist/components/ui/form.d.ts.map +1 -1
- package/dist/components/ui/form.js +55 -21
- package/dist/components/ui/form.js.map +1 -1
- package/dist/components/ui/form.module.js +10 -0
- package/dist/components/ui/form.module.js.map +1 -0
- package/dist/components/ui/form_module.css +22 -0
- package/dist/components/ui/form_module.css.map +1 -0
- package/dist/components/ui/gradient-background.d.ts +21 -3
- package/dist/components/ui/gradient-background.d.ts.map +1 -1
- package/dist/components/ui/gradient-background.js +8 -4
- package/dist/components/ui/gradient-background.js.map +1 -1
- package/dist/components/ui/gradient-background.module.js +7 -0
- package/dist/components/ui/gradient-background.module.js.map +1 -0
- package/dist/components/ui/gradient-background_module.css +9 -0
- package/dist/components/ui/gradient-background_module.css.map +1 -0
- package/dist/components/ui/gradient-text.d.ts +23 -2
- package/dist/components/ui/gradient-text.d.ts.map +1 -1
- package/dist/components/ui/gradient-text.js +8 -6
- package/dist/components/ui/gradient-text.js.map +1 -1
- package/dist/components/ui/gradient-text.module.js +9 -0
- package/dist/components/ui/gradient-text.module.js.map +1 -0
- package/dist/components/ui/gradient-text_module.css +24 -0
- package/dist/components/ui/gradient-text_module.css.map +1 -0
- package/dist/components/ui/highlight-text.d.ts +24 -2
- package/dist/components/ui/highlight-text.d.ts.map +1 -1
- package/dist/components/ui/highlight-text.js +7 -10
- package/dist/components/ui/highlight-text.js.map +1 -1
- package/dist/components/ui/highlight-text.module.js +7 -0
- package/dist/components/ui/highlight-text.module.js.map +1 -0
- package/dist/components/ui/highlight-text_module.css +16 -0
- package/dist/components/ui/highlight-text_module.css.map +1 -0
- package/dist/components/ui/hole-background.d.ts +23 -2
- package/dist/components/ui/hole-background.d.ts.map +1 -1
- package/dist/components/ui/hole-background.js +155 -118
- package/dist/components/ui/hole-background.js.map +1 -1
- package/dist/components/ui/hole-background.module.js +10 -0
- package/dist/components/ui/hole-background.module.js.map +1 -0
- package/dist/components/ui/hole-background_module.css +85 -0
- package/dist/components/ui/hole-background_module.css.map +1 -0
- package/dist/components/ui/hover-card.d.ts +85 -4
- package/dist/components/ui/hover-card.d.ts.map +1 -1
- package/dist/components/ui/hover-card.js +52 -10
- package/dist/components/ui/hover-card.js.map +1 -1
- package/dist/components/ui/hover-card.module.js +8 -0
- package/dist/components/ui/hover-card.module.js.map +1 -0
- package/dist/components/ui/hover-card_module.css +23 -0
- package/dist/components/ui/hover-card_module.css.map +1 -0
- package/dist/components/ui/input-group.d.ts +132 -13
- package/dist/components/ui/input-group.d.ts.map +1 -1
- package/dist/components/ui/input-group.js +62 -66
- package/dist/components/ui/input-group.js.map +1 -1
- package/dist/components/ui/input-group.module.js +20 -0
- package/dist/components/ui/input-group.module.js.map +1 -0
- package/dist/components/ui/input-group_module.css +150 -0
- package/dist/components/ui/input-group_module.css.map +1 -0
- package/dist/components/ui/input-otp.d.ts +110 -30
- package/dist/components/ui/input-otp.d.ts.map +1 -1
- package/dist/components/ui/input-otp.js +24 -15
- package/dist/components/ui/input-otp.js.map +1 -1
- package/dist/components/ui/input-otp.module.js +17 -0
- package/dist/components/ui/input-otp.module.js.map +1 -0
- package/dist/components/ui/input-otp_module.css +89 -0
- package/dist/components/ui/input-otp_module.css.map +1 -0
- package/dist/components/ui/input.d.ts +31 -1
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/input.js +21 -8
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/input.module.js +7 -0
- package/dist/components/ui/input.module.js.map +1 -0
- package/dist/components/ui/input_module.css +40 -0
- package/dist/components/ui/input_module.css.map +1 -0
- package/dist/components/ui/item.d.ts +221 -19
- package/dist/components/ui/item.d.ts.map +1 -1
- package/dist/components/ui/item.js +66 -90
- package/dist/components/ui/item.js.map +1 -1
- package/dist/components/ui/item.module.js +22 -0
- package/dist/components/ui/item.module.js.map +1 -0
- package/dist/components/ui/item_module.css +143 -0
- package/dist/components/ui/item_module.css.map +1 -0
- package/dist/components/ui/kbd.d.ts +43 -2
- package/dist/components/ui/kbd.d.ts.map +1 -1
- package/dist/components/ui/kbd.js +12 -12
- package/dist/components/ui/kbd.js.map +1 -1
- package/dist/components/ui/kbd.module.js +8 -0
- package/dist/components/ui/kbd.module.js.map +1 -0
- package/dist/components/ui/kbd_module.css +35 -0
- package/dist/components/ui/kbd_module.css.map +1 -0
- package/dist/components/ui/label.d.ts +30 -3
- package/dist/components/ui/label.d.ts.map +1 -1
- package/dist/components/ui/label.js +7 -8
- package/dist/components/ui/label.js.map +1 -1
- package/dist/components/ui/label.module.js +7 -0
- package/dist/components/ui/label.module.js.map +1 -0
- package/dist/components/ui/label_module.css +17 -0
- package/dist/components/ui/label_module.css.map +1 -0
- package/dist/components/ui/list-skeleton.js +35 -0
- package/dist/components/ui/list-skeleton.js.map +1 -0
- package/dist/components/ui/list-skeleton.module.js +12 -0
- package/dist/components/ui/list-skeleton.module.js.map +1 -0
- package/dist/components/ui/list-skeleton_module.css +39 -0
- package/dist/components/ui/list-skeleton_module.css.map +1 -0
- package/dist/components/ui/loading-overlay.js +21 -0
- package/dist/components/ui/loading-overlay.js.map +1 -0
- package/dist/components/ui/loading-overlay.module.js +9 -0
- package/dist/components/ui/loading-overlay.module.js.map +1 -0
- package/dist/components/ui/loading-overlay_module.css +22 -0
- package/dist/components/ui/loading-overlay_module.css.map +1 -0
- package/dist/components/ui/menubar.d.ts +420 -22
- package/dist/components/ui/menubar.d.ts.map +1 -1
- package/dist/components/ui/menubar.js +199 -100
- package/dist/components/ui/menubar.js.map +1 -1
- package/dist/components/ui/menubar.module.js +21 -0
- package/dist/components/ui/menubar.module.js.map +1 -0
- package/dist/components/ui/menubar_module.css +145 -0
- package/dist/components/ui/menubar_module.css.map +1 -0
- package/dist/components/ui/meter.d.ts +85 -0
- package/dist/components/ui/meter.d.ts.map +1 -0
- package/dist/components/ui/meter.js +75 -0
- package/dist/components/ui/meter.js.map +1 -0
- package/dist/components/ui/meter.module.js +10 -0
- package/dist/components/ui/meter.module.js.map +1 -0
- package/dist/components/ui/meter_module.css +31 -0
- package/dist/components/ui/meter_module.css.map +1 -0
- package/dist/components/ui/navigation-menu.d.ts +233 -11
- package/dist/components/ui/navigation-menu.d.ts.map +1 -1
- package/dist/components/ui/navigation-menu.js +138 -49
- package/dist/components/ui/navigation-menu.js.map +1 -1
- package/dist/components/ui/navigation-menu.module.js +18 -0
- package/dist/components/ui/navigation-menu.module.js.map +1 -0
- package/dist/components/ui/navigation-menu_module.css +112 -0
- package/dist/components/ui/navigation-menu_module.css.map +1 -0
- package/dist/components/ui/number-field.d.ts +138 -0
- package/dist/components/ui/number-field.d.ts.map +1 -0
- package/dist/components/ui/number-field.js +111 -0
- package/dist/components/ui/number-field.js.map +1 -0
- package/dist/components/ui/number-field.module.js +15 -0
- package/dist/components/ui/number-field.module.js.map +1 -0
- package/dist/components/ui/number-field_module.css +125 -0
- package/dist/components/ui/number-field_module.css.map +1 -0
- package/dist/components/ui/pagination.d.ts +150 -24
- package/dist/components/ui/pagination.d.ts.map +1 -1
- package/dist/components/ui/pagination.js +41 -38
- package/dist/components/ui/pagination.js.map +1 -1
- package/dist/components/ui/pagination.module.js +14 -0
- package/dist/components/ui/pagination.module.js.map +1 -0
- package/dist/components/ui/pagination_module.css +66 -0
- package/dist/components/ui/pagination_module.css.map +1 -0
- package/dist/components/ui/popover.d.ts +133 -5
- package/dist/components/ui/popover.d.ts.map +1 -1
- package/dist/components/ui/popover.js +68 -14
- package/dist/components/ui/popover.js.map +1 -1
- package/dist/components/ui/popover.module.js +9 -0
- package/dist/components/ui/popover.module.js.map +1 -0
- package/dist/components/ui/popover_module.css +28 -0
- package/dist/components/ui/popover_module.css.map +1 -0
- package/dist/components/ui/progress.d.ts +31 -2
- package/dist/components/ui/progress.d.ts.map +1 -1
- package/dist/components/ui/progress.js +22 -13
- package/dist/components/ui/progress.js.map +1 -1
- package/dist/components/ui/progress.module.js +8 -0
- package/dist/components/ui/progress.module.js.map +1 -0
- package/dist/components/ui/progress_module.css +20 -0
- package/dist/components/ui/progress_module.css.map +1 -0
- package/dist/components/ui/radio-group.d.ts +42 -3
- package/dist/components/ui/radio-group.d.ts.map +1 -1
- package/dist/components/ui/radio-group.js +38 -16
- package/dist/components/ui/radio-group.js.map +1 -1
- package/dist/components/ui/radio-group.module.js +10 -0
- package/dist/components/ui/radio-group.module.js.map +1 -0
- package/dist/components/ui/radio-group_module.css +44 -0
- package/dist/components/ui/radio-group_module.css.map +1 -0
- package/dist/components/ui/resizable.d.ts +78 -5
- package/dist/components/ui/resizable.d.ts.map +1 -1
- package/dist/components/ui/resizable.js +23 -13
- package/dist/components/ui/resizable.js.map +1 -1
- package/dist/components/ui/resizable.module.js +10 -0
- package/dist/components/ui/resizable.module.js.map +1 -0
- package/dist/components/ui/resizable_module.css +70 -0
- package/dist/components/ui/resizable_module.css.map +1 -0
- package/dist/components/ui/ripple-button.d.ts +23 -2
- package/dist/components/ui/ripple-button.d.ts.map +1 -1
- package/dist/components/ui/ripple-button.js +26 -11
- package/dist/components/ui/ripple-button.js.map +1 -1
- package/dist/components/ui/ripple-button.module.js +9 -0
- package/dist/components/ui/ripple-button.module.js.map +1 -0
- package/dist/components/ui/ripple-button_module.css +38 -0
- package/dist/components/ui/ripple-button_module.css.map +1 -0
- package/dist/components/ui/scratcher.d.ts +26 -3
- package/dist/components/ui/scratcher.d.ts.map +1 -1
- package/dist/components/ui/scratcher.js +89 -90
- package/dist/components/ui/scratcher.js.map +1 -1
- package/dist/components/ui/scratcher.module.js +8 -0
- package/dist/components/ui/scratcher.module.js.map +1 -0
- package/dist/components/ui/scratcher_module.css +13 -0
- package/dist/components/ui/scratcher_module.css.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +44 -3
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.js +44 -19
- package/dist/components/ui/scroll-area.js.map +1 -1
- package/dist/components/ui/scroll-area.module.js +14 -0
- package/dist/components/ui/scroll-area.module.js.map +1 -0
- package/dist/components/ui/scroll-area_module.css +51 -0
- package/dist/components/ui/scroll-area_module.css.map +1 -0
- package/dist/components/ui/select.d.ts +269 -11
- package/dist/components/ui/select.d.ts.map +1 -1
- package/dist/components/ui/select.js +152 -67
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/select.module.js +20 -0
- package/dist/components/ui/select.module.js.map +1 -0
- package/dist/components/ui/select_module.css +134 -0
- package/dist/components/ui/select_module.css.map +1 -0
- package/dist/components/ui/separator.d.ts +33 -2
- package/dist/components/ui/separator.d.ts.map +1 -1
- package/dist/components/ui/separator.js +20 -9
- package/dist/components/ui/separator.js.map +1 -1
- package/dist/components/ui/separator.module.js +9 -0
- package/dist/components/ui/separator.module.js.map +1 -0
- package/dist/components/ui/separator_module.css +17 -0
- package/dist/components/ui/separator_module.css.map +1 -0
- package/dist/components/ui/sheet.d.ts +297 -23
- package/dist/components/ui/sheet.d.ts.map +1 -1
- package/dist/components/ui/sheet.js +121 -63
- package/dist/components/ui/sheet.js.map +1 -1
- package/dist/components/ui/sheet.module.js +18 -0
- package/dist/components/ui/sheet.module.js.map +1 -0
- package/dist/components/ui/sheet_module.css +136 -0
- package/dist/components/ui/sheet_module.css.map +1 -0
- package/dist/components/ui/sidebar.d.ts +491 -23
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/sidebar.js +214 -143
- package/dist/components/ui/sidebar.js.map +1 -1
- package/dist/components/ui/sidebar.module.js +50 -0
- package/dist/components/ui/sidebar.module.js.map +1 -0
- package/dist/components/ui/sidebar_module.css +569 -0
- package/dist/components/ui/sidebar_module.css.map +1 -0
- package/dist/components/ui/skeleton.d.ts +30 -1
- package/dist/components/ui/skeleton.d.ts.map +1 -1
- package/dist/components/ui/skeleton.js +7 -7
- package/dist/components/ui/skeleton.js.map +1 -1
- package/dist/components/ui/skeleton.module.js +8 -0
- package/dist/components/ui/skeleton.module.js.map +1 -0
- package/dist/components/ui/skeleton_module.css +18 -0
- package/dist/components/ui/skeleton_module.css.map +1 -0
- package/dist/components/ui/slider.d.ts +48 -2
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/slider.js +44 -17
- package/dist/components/ui/slider.js.map +1 -1
- package/dist/components/ui/slider.module.js +11 -0
- package/dist/components/ui/slider.module.js.map +1 -0
- package/dist/components/ui/slider_module.css +55 -0
- package/dist/components/ui/slider_module.css.map +1 -0
- package/dist/components/ui/sonner.d.ts +138 -4
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/sonner.js +450 -17
- package/dist/components/ui/sonner.js.map +1 -1
- package/dist/components/ui/sonner.module.js +34 -0
- package/dist/components/ui/sonner.module.js.map +1 -0
- package/dist/components/ui/sonner_module.css +233 -0
- package/dist/components/ui/sonner_module.css.map +1 -0
- package/dist/components/ui/spinner.d.ts +20 -1
- package/dist/components/ui/spinner.d.ts.map +1 -1
- package/dist/components/ui/spinner.js +29 -11
- package/dist/components/ui/spinner.js.map +1 -1
- package/dist/components/ui/spinner.module.js +10 -0
- package/dist/components/ui/spinner.module.js.map +1 -0
- package/dist/components/ui/spinner_module.css +28 -0
- package/dist/components/ui/spinner_module.css.map +1 -0
- package/dist/components/ui/stepper.d.ts +48 -0
- package/dist/components/ui/stepper.d.ts.map +1 -0
- package/dist/components/ui/stepper.js +41 -0
- package/dist/components/ui/stepper.js.map +1 -0
- package/dist/components/ui/stepper.module.js +12 -0
- package/dist/components/ui/stepper.module.js.map +1 -0
- package/dist/components/ui/stepper_module.css +75 -0
- package/dist/components/ui/stepper_module.css.map +1 -0
- package/dist/components/ui/switch.d.ts +29 -2
- package/dist/components/ui/switch.d.ts.map +1 -1
- package/dist/components/ui/switch.js +21 -9
- package/dist/components/ui/switch.js.map +1 -1
- package/dist/components/ui/switch.module.js +8 -0
- package/dist/components/ui/switch.module.js.map +1 -0
- package/dist/components/ui/switch_module.css +45 -0
- package/dist/components/ui/switch_module.css.map +1 -0
- package/dist/components/ui/table-skeleton.js +34 -0
- package/dist/components/ui/table-skeleton.js.map +1 -0
- package/dist/components/ui/table-skeleton.module.js +11 -0
- package/dist/components/ui/table-skeleton.module.js.map +1 -0
- package/dist/components/ui/table-skeleton_module.css +32 -0
- package/dist/components/ui/table-skeleton_module.css.map +1 -0
- package/dist/components/ui/table.d.ts +170 -8
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/table.js +17 -17
- package/dist/components/ui/table.js.map +1 -1
- package/dist/components/ui/table.module.js +15 -0
- package/dist/components/ui/table.module.js.map +1 -0
- package/dist/components/ui/table_module.css +71 -0
- package/dist/components/ui/table_module.css.map +1 -0
- package/dist/components/ui/tabs.d.ts +114 -5
- package/dist/components/ui/tabs.d.ts.map +1 -1
- package/dist/components/ui/tabs.js +71 -20
- package/dist/components/ui/tabs.js.map +1 -1
- package/dist/components/ui/tabs.module.js +10 -0
- package/dist/components/ui/tabs.module.js.map +1 -0
- package/dist/components/ui/tabs_module.css +89 -0
- package/dist/components/ui/tabs_module.css.map +1 -0
- package/dist/components/ui/textarea.d.ts +24 -1
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/textarea.js +2 -2
- package/dist/components/ui/textarea.js.map +1 -1
- package/dist/components/ui/textarea.module.js +7 -0
- package/dist/components/ui/textarea.module.js.map +1 -0
- package/dist/components/ui/textarea_module.css +33 -0
- package/dist/components/ui/textarea_module.css.map +1 -0
- package/dist/components/ui/timeline.d.ts +111 -0
- package/dist/components/ui/timeline.d.ts.map +1 -0
- package/dist/components/ui/timeline.js +34 -0
- package/dist/components/ui/timeline.js.map +1 -0
- package/dist/components/ui/timeline.module.js +10 -0
- package/dist/components/ui/timeline.module.js.map +1 -0
- package/dist/components/ui/timeline_module.css +47 -0
- package/dist/components/ui/timeline_module.css.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +75 -10
- package/dist/components/ui/toggle-group.d.ts.map +1 -1
- package/dist/components/ui/toggle-group.js +32 -21
- package/dist/components/ui/toggle-group.js.map +1 -1
- package/dist/components/ui/toggle-group.module.js +7 -0
- package/dist/components/ui/toggle-group.module.js.map +1 -0
- package/dist/components/ui/toggle-group_module.css +8 -0
- package/dist/components/ui/toggle-group_module.css.map +1 -0
- package/dist/components/ui/toggle.d.ts +60 -11
- package/dist/components/ui/toggle.d.ts.map +1 -1
- package/dist/components/ui/toggle.js +29 -29
- package/dist/components/ui/toggle.js.map +1 -1
- package/dist/components/ui/toggle.module.js +12 -0
- package/dist/components/ui/toggle.module.js.map +1 -0
- package/dist/components/ui/toggle_module.css +62 -0
- package/dist/components/ui/toggle_module.css.map +1 -0
- package/dist/components/ui/toolbar.d.ts +107 -0
- package/dist/components/ui/toolbar.d.ts.map +1 -0
- package/dist/components/ui/toolbar.js +90 -0
- package/dist/components/ui/toolbar.js.map +1 -0
- package/dist/components/ui/toolbar.module.js +12 -0
- package/dist/components/ui/toolbar.module.js.map +1 -0
- package/dist/components/ui/toolbar_module.css +115 -0
- package/dist/components/ui/toolbar_module.css.map +1 -0
- package/dist/components/ui/tooltip.d.ts +119 -5
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/tooltip.js +48 -13
- package/dist/components/ui/tooltip.js.map +1 -1
- package/dist/components/ui/tooltip.module.js +9 -0
- package/dist/components/ui/tooltip.module.js.map +1 -0
- package/dist/components/ui/tooltip_module.css +35 -0
- package/dist/components/ui/tooltip_module.css.map +1 -0
- package/dist/components/ui/typewriter.d.ts +48 -13
- package/dist/components/ui/typewriter.d.ts.map +1 -1
- package/dist/components/ui/typewriter.js +46 -49
- package/dist/components/ui/typewriter.js.map +1 -1
- package/dist/components/ui/typewriter.module.js +16 -0
- package/dist/components/ui/typewriter.module.js.map +1 -0
- package/dist/components/ui/typewriter_module.css +102 -0
- package/dist/components/ui/typewriter_module.css.map +1 -0
- package/dist/components/ui/visually-hidden.d.ts +38 -0
- package/dist/components/ui/visually-hidden.d.ts.map +1 -0
- package/dist/components/ui/visually-hidden.js +13 -0
- package/dist/components/ui/visually-hidden.js.map +1 -0
- package/dist/components/ui/visually-hidden.module.js +7 -0
- package/dist/components/ui/visually-hidden.module.js.map +1 -0
- package/dist/components/ui/visually-hidden_module.css +14 -0
- package/dist/components/ui/visually-hidden_module.css.map +1 -0
- package/dist/hooks/useAnnounce.js +46 -0
- package/dist/hooks/useAnnounce.js.map +1 -0
- package/dist/hooks/useBreakpoint.d.ts +17 -0
- package/dist/hooks/useBreakpoint.d.ts.map +1 -0
- package/dist/hooks/useBreakpoint.js +16 -0
- package/dist/hooks/useBreakpoint.js.map +1 -0
- package/dist/hooks/useClipboard.d.ts +77 -0
- package/dist/hooks/useClipboard.d.ts.map +1 -0
- package/dist/hooks/useClipboard.js +42 -0
- package/dist/hooks/useClipboard.js.map +1 -0
- package/dist/hooks/useColorScheme.d.ts +14 -0
- package/dist/hooks/useColorScheme.d.ts.map +1 -0
- package/dist/hooks/useColorScheme.js +9 -0
- package/dist/hooks/useColorScheme.js.map +1 -0
- package/dist/hooks/useControllableState.d.ts +54 -0
- package/dist/hooks/useControllableState.d.ts.map +1 -0
- package/dist/hooks/useControllableState.js +29 -0
- package/dist/hooks/useControllableState.js.map +1 -0
- package/dist/hooks/useDebounce.d.ts +33 -0
- package/dist/hooks/useDebounce.d.ts.map +1 -0
- package/dist/hooks/useDebounce.js +20 -0
- package/dist/hooks/useDebounce.js.map +1 -0
- package/dist/hooks/useEventCallback.d.ts +34 -0
- package/dist/hooks/useEventCallback.d.ts.map +1 -0
- package/dist/hooks/useEventCallback.js +12 -0
- package/dist/hooks/useEventCallback.js.map +1 -0
- package/dist/hooks/useFocusManager.js +51 -0
- package/dist/hooks/useFocusManager.js.map +1 -0
- package/dist/hooks/useFocusVisible.d.ts +50 -0
- package/dist/hooks/useFocusVisible.d.ts.map +1 -0
- package/dist/hooks/useFocusVisible.js +35 -0
- package/dist/hooks/useFocusVisible.js.map +1 -0
- package/dist/hooks/useId.d.ts +30 -0
- package/dist/hooks/useId.d.ts.map +1 -0
- package/dist/hooks/useId.js +9 -0
- package/dist/hooks/useId.js.map +1 -0
- package/dist/hooks/useIntersectionObserver.d.ts +51 -0
- package/dist/hooks/useIntersectionObserver.d.ts.map +1 -0
- package/dist/hooks/useIntersectionObserver.js +25 -0
- package/dist/hooks/useIntersectionObserver.js.map +1 -0
- package/dist/hooks/useInterval.d.ts +55 -0
- package/dist/hooks/useInterval.d.ts.map +1 -0
- package/dist/hooks/useInterval.js +24 -0
- package/dist/hooks/useInterval.js.map +1 -0
- package/dist/hooks/useIsMobile.d.ts +5 -11
- package/dist/hooks/useIsMobile.d.ts.map +1 -1
- package/dist/hooks/useIsMobile.js +2 -13
- package/dist/hooks/useIsMobile.js.map +1 -1
- package/dist/hooks/useLocalStorage.d.ts +43 -0
- package/dist/hooks/useLocalStorage.d.ts.map +1 -0
- package/dist/hooks/useLocalStorage.js +53 -0
- package/dist/hooks/useLocalStorage.js.map +1 -0
- package/dist/hooks/useMediaQuery.d.ts +14 -0
- package/dist/hooks/useMediaQuery.d.ts.map +1 -0
- package/dist/hooks/useMediaQuery.js +20 -0
- package/dist/hooks/useMediaQuery.js.map +1 -0
- package/dist/hooks/useMergedRefs.d.ts +27 -0
- package/dist/hooks/useMergedRefs.d.ts.map +1 -0
- package/dist/hooks/useMergedRefs.js +11 -0
- package/dist/hooks/useMergedRefs.js.map +1 -0
- package/dist/hooks/useOnClickOutside.d.ts +32 -0
- package/dist/hooks/useOnClickOutside.d.ts.map +1 -0
- package/dist/hooks/useOnClickOutside.js +23 -0
- package/dist/hooks/useOnClickOutside.js.map +1 -0
- package/dist/hooks/usePrefersContrast.d.ts +19 -0
- package/dist/hooks/usePrefersContrast.d.ts.map +1 -0
- package/dist/hooks/usePrefersContrast.js +8 -0
- package/dist/hooks/usePrefersContrast.js.map +1 -0
- package/dist/hooks/usePrevious.d.ts +33 -0
- package/dist/hooks/usePrevious.d.ts.map +1 -0
- package/dist/hooks/usePrevious.js +14 -0
- package/dist/hooks/usePrevious.js.map +1 -0
- package/dist/hooks/useReducedMotion.d.ts +19 -0
- package/dist/hooks/useReducedMotion.d.ts.map +1 -0
- package/dist/hooks/useReducedMotion.js +2 -0
- package/dist/hooks/useThrottle.d.ts +37 -0
- package/dist/hooks/useThrottle.d.ts.map +1 -0
- package/dist/hooks/useThrottle.js +34 -0
- package/dist/hooks/useThrottle.js.map +1 -0
- package/dist/hooks/useTimeout.d.ts +28 -0
- package/dist/hooks/useTimeout.d.ts.map +1 -0
- package/dist/hooks/useTimeout.js +24 -0
- package/dist/hooks/useTimeout.js.map +1 -0
- package/dist/index.css +104 -5363
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +52 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +103 -72
- package/dist/lib/utilities.d.ts +5 -5
- package/dist/lib/utilities.d.ts.map +1 -1
- package/dist/lib/utilities.js +1 -2
- package/dist/lib/utilities.js.map +1 -1
- package/dist/motion/Collapse.js +19 -0
- package/dist/motion/Collapse.js.map +1 -0
- package/dist/motion/Collapse.module.js +8 -0
- package/dist/motion/Collapse.module.js.map +1 -0
- package/dist/motion/Collapse_module.css +25 -0
- package/dist/motion/Collapse_module.css.map +1 -0
- package/dist/motion/Presence.js +14 -0
- package/dist/motion/Presence.js.map +1 -0
- package/dist/motion/index.js +5 -0
- package/dist/motion/presets.js +117 -0
- package/dist/motion/presets.js.map +1 -0
- package/dist/motion/tokens.js +41 -0
- package/dist/motion/tokens.js.map +1 -0
- package/dist/rslib-runtime.js +39 -0
- package/dist/rslib-runtime.js.map +1 -0
- package/package.json +233 -67
- package/src/components/ui/accordion.module.css +70 -0
- package/src/components/ui/accordion.tsx +278 -44
- package/src/components/ui/alert-dialog.module.css +87 -0
- package/src/components/ui/alert-dialog.tsx +481 -99
- package/src/components/ui/alert.module.css +57 -0
- package/src/components/ui/alert.tsx +136 -43
- package/src/components/ui/aspect-ratio.module.css +7 -0
- package/src/components/ui/aspect-ratio.tsx +38 -3
- package/src/components/ui/async-boundary.tsx +56 -0
- package/src/components/ui/avatar.module.css +31 -0
- package/src/components/ui/avatar.tsx +149 -36
- package/src/components/ui/background-beams.module.css +20 -0
- package/src/components/ui/background-beams.tsx +173 -134
- package/src/components/ui/badge.module.css +60 -0
- package/src/components/ui/badge.tsx +100 -32
- package/src/components/ui/breadcrumb.module.css +87 -0
- package/src/components/ui/breadcrumb.tsx +256 -74
- package/src/components/ui/bubble-background.module.css +97 -0
- package/src/components/ui/bubble-background.tsx +92 -52
- package/src/components/ui/button-group.module.css +76 -0
- package/src/components/ui/button-group.tsx +135 -46
- package/src/components/ui/button.module.css +138 -0
- package/src/components/ui/button.tsx +159 -41
- package/src/components/ui/calendar.module.css +250 -0
- package/src/components/ui/calendar.tsx +135 -111
- package/src/components/ui/card-skeleton.module.css +50 -0
- package/src/components/ui/card-skeleton.tsx +69 -0
- package/src/components/ui/card.module.css +41 -0
- package/src/components/ui/card.tsx +175 -22
- package/src/components/ui/carousel.module.css +80 -0
- package/src/components/ui/carousel.tsx +186 -43
- package/src/components/ui/chart.module.css +164 -0
- package/src/components/ui/chart.tsx +447 -102
- package/src/components/ui/checkbox-group.module.css +8 -0
- package/src/components/ui/checkbox-group.tsx +53 -0
- package/src/components/ui/checkbox.module.css +43 -0
- package/src/components/ui/checkbox.tsx +81 -19
- package/src/components/ui/collapsible.module.css +24 -0
- package/src/components/ui/collapsible.tsx +140 -3
- package/src/components/ui/combobox.module.css +158 -0
- package/src/components/ui/combobox.tsx +569 -0
- package/src/components/ui/command.module.css +193 -0
- package/src/components/ui/command.tsx +893 -114
- package/src/components/ui/context-menu.module.css +113 -0
- package/src/components/ui/context-menu.tsx +619 -157
- package/src/components/ui/copy-button.module.css +34 -0
- package/src/components/ui/copy-button.tsx +116 -0
- package/src/components/ui/counting-number.module.css +4 -0
- package/src/components/ui/counting-number.tsx +69 -31
- package/src/components/ui/dialog.module.css +113 -0
- package/src/components/ui/dialog.tsx +427 -81
- package/src/components/ui/dot-background.module.css +12 -0
- package/src/components/ui/dot-background.tsx +134 -126
- package/src/components/ui/drawer.module.css +85 -0
- package/src/components/ui/drawer.tsx +410 -80
- package/src/components/ui/dropdown-menu.module.css +113 -0
- package/src/components/ui/dropdown-menu.tsx +619 -159
- package/src/components/ui/dropdrawer.module.css +322 -0
- package/src/components/ui/dropdrawer.tsx +870 -400
- package/src/components/ui/empty.module.css +84 -0
- package/src/components/ui/empty.tsx +176 -52
- package/src/components/ui/error-boundary.module.css +36 -0
- package/src/components/ui/error-boundary.tsx +127 -0
- package/src/components/ui/field.module.css +179 -0
- package/src/components/ui/field.tsx +345 -139
- package/src/components/ui/fireworks-background.module.css +13 -0
- package/src/components/ui/fireworks-background.tsx +89 -51
- package/src/components/ui/flip-button.module.css +44 -0
- package/src/components/ui/flip-button.tsx +59 -28
- package/src/components/ui/focus-scope.module.css +3 -0
- package/src/components/ui/focus-scope.tsx +160 -0
- package/src/components/ui/form-skeleton.module.css +28 -0
- package/src/components/ui/form-skeleton.tsx +62 -0
- package/src/components/ui/form.module.css +20 -0
- package/src/components/ui/form.tsx +244 -33
- package/src/components/ui/gradient-background.module.css +6 -0
- package/src/components/ui/gradient-background.tsx +27 -5
- package/src/components/ui/gradient-text.module.css +23 -0
- package/src/components/ui/gradient-text.tsx +36 -9
- package/src/components/ui/highlight-text.module.css +14 -0
- package/src/components/ui/highlight-text.tsx +37 -15
- package/src/components/ui/hole-background.module.css +84 -0
- package/src/components/ui/hole-background.tsx +290 -162
- package/src/components/ui/hover-card.module.css +21 -0
- package/src/components/ui/hover-card.tsx +142 -21
- package/src/components/ui/input-group.module.css +148 -0
- package/src/components/ui/input-group.tsx +222 -98
- package/src/components/ui/input-otp.module.css +92 -0
- package/src/components/ui/input-otp.tsx +159 -33
- package/src/components/ui/input.module.css +37 -0
- package/src/components/ui/input.tsx +56 -14
- package/src/components/ui/item.module.css +143 -0
- package/src/components/ui/item.tsx +331 -104
- package/src/components/ui/kbd.module.css +31 -0
- package/src/components/ui/kbd.tsx +60 -17
- package/src/components/ui/label.module.css +13 -0
- package/src/components/ui/label.tsx +38 -14
- package/src/components/ui/list-skeleton.module.css +35 -0
- package/src/components/ui/list-skeleton.tsx +70 -0
- package/src/components/ui/loading-overlay.module.css +19 -0
- package/src/components/ui/loading-overlay.tsx +72 -0
- package/src/components/ui/menubar.module.css +144 -0
- package/src/components/ui/menubar.tsx +604 -192
- package/src/components/ui/meter.module.css +32 -0
- package/src/components/ui/meter.tsx +169 -0
- package/src/components/ui/navigation-menu.module.css +110 -0
- package/src/components/ui/navigation-menu.tsx +381 -99
- package/src/components/ui/number-field.module.css +126 -0
- package/src/components/ui/number-field.tsx +247 -0
- package/src/components/ui/pagination.module.css +64 -0
- package/src/components/ui/pagination.tsx +250 -72
- package/src/components/ui/popover.module.css +26 -0
- package/src/components/ui/popover.tsx +207 -25
- package/src/components/ui/progress.module.css +15 -0
- package/src/components/ui/progress.tsx +54 -16
- package/src/components/ui/radio-group.module.css +41 -0
- package/src/components/ui/radio-group.tsx +88 -34
- package/src/components/ui/resizable.module.css +67 -0
- package/src/components/ui/resizable.tsx +106 -26
- package/src/components/ui/ripple-button.module.css +35 -0
- package/src/components/ui/ripple-button.tsx +55 -21
- package/src/components/ui/scratcher.module.css +9 -0
- package/src/components/ui/scratcher.tsx +134 -108
- package/src/components/ui/scroll-area.module.css +47 -0
- package/src/components/ui/scroll-area.tsx +93 -34
- package/src/components/ui/select.module.css +131 -0
- package/src/components/ui/select.tsx +435 -124
- package/src/components/ui/separator.module.css +14 -0
- package/src/components/ui/separator.tsx +60 -18
- package/src/components/ui/sheet.module.css +138 -0
- package/src/components/ui/sheet.tsx +427 -95
- package/src/components/ui/sidebar.module.css +594 -0
- package/src/components/ui/sidebar.tsx +900 -425
- package/src/components/ui/skeleton.module.css +14 -0
- package/src/components/ui/skeleton.tsx +39 -9
- package/src/components/ui/slider.module.css +48 -0
- package/src/components/ui/slider.tsx +89 -16
- package/src/components/ui/sonner.module.css +246 -0
- package/src/components/ui/sonner.tsx +777 -25
- package/src/components/ui/spinner.module.css +25 -0
- package/src/components/ui/spinner.tsx +51 -12
- package/src/components/ui/stepper.module.css +72 -0
- package/src/components/ui/stepper.tsx +95 -0
- package/src/components/ui/switch.module.css +42 -0
- package/src/components/ui/switch.tsx +53 -20
- package/src/components/ui/table-skeleton.module.css +29 -0
- package/src/components/ui/table-skeleton.tsx +79 -0
- package/src/components/ui/table.module.css +66 -0
- package/src/components/ui/table.tsx +235 -61
- package/src/components/ui/tabs.module.css +89 -0
- package/src/components/ui/tabs.tsx +192 -45
- package/src/components/ui/textarea.module.css +30 -0
- package/src/components/ui/textarea.tsx +30 -10
- package/src/components/ui/timeline.module.css +43 -0
- package/src/components/ui/timeline.tsx +153 -0
- package/src/components/ui/toggle-group.module.css +5 -0
- package/src/components/ui/toggle-group.tsx +115 -32
- package/src/components/ui/toggle.module.css +57 -0
- package/src/components/ui/toggle.tsx +89 -33
- package/src/components/ui/toolbar.module.css +112 -0
- package/src/components/ui/toolbar.tsx +209 -0
- package/src/components/ui/tooltip.module.css +39 -0
- package/src/components/ui/tooltip.tsx +181 -24
- package/src/components/ui/typewriter.module.css +101 -0
- package/src/components/ui/typewriter.tsx +130 -128
- package/src/components/ui/visually-hidden.module.css +11 -0
- package/src/components/ui/visually-hidden.tsx +50 -0
- package/src/css-modules.d.ts +9 -0
- package/src/hooks/useAnnounce.tsx +73 -0
- package/src/hooks/useBreakpoint.tsx +41 -0
- package/src/hooks/useClipboard.tsx +137 -0
- package/src/hooks/useColorScheme.tsx +23 -0
- package/src/hooks/useControllableState.tsx +81 -0
- package/src/hooks/useDebounce.tsx +50 -0
- package/src/hooks/useEventCallback.tsx +47 -0
- package/src/hooks/useFocusManager.tsx +89 -0
- package/src/hooks/useFocusVisible.tsx +88 -0
- package/src/hooks/useId.tsx +36 -0
- package/src/hooks/useIntersectionObserver.tsx +81 -0
- package/src/hooks/useInterval.tsx +80 -0
- package/src/hooks/useIsMobile.tsx +7 -28
- package/src/hooks/useLocalStorage.tsx +111 -0
- package/src/hooks/useMediaQuery.tsx +34 -0
- package/src/hooks/useMergedRefs.tsx +48 -0
- package/src/hooks/useOnClickOutside.tsx +55 -0
- package/src/hooks/usePrefersContrast.tsx +24 -0
- package/src/hooks/usePrevious.tsx +44 -0
- package/src/hooks/useReducedMotion.tsx +20 -0
- package/src/hooks/useThrottle.tsx +78 -0
- package/src/hooks/useTimeout.tsx +51 -0
- package/src/index.css +127 -65
- package/src/index.ts +219 -18
- package/src/lib/utilities.ts +8 -7
- package/src/motion/Collapse.module.css +22 -0
- package/src/motion/Collapse.tsx +52 -0
- package/src/motion/Presence.tsx +44 -0
- package/src/motion/index.ts +13 -0
- package/src/motion/presets.ts +77 -0
- package/src/motion/tokens.ts +37 -0
- package/src/stories/DesignPrinciples.mdx +48 -0
- package/src/stories/GettingStarted.mdx +92 -0
- package/src/stories/Welcome.mdx +44 -0
- package/src/hooks/useIsMobile.test.tsx +0 -96
- package/src/hooks/useWindowSize.test.tsx +0 -57
- package/src/index.test.ts +0 -537
- package/src/lib/color-conversion-utilities.test.ts +0 -225
- package/src/lib/utilities.test.ts +0 -37
|
@@ -1,205 +1,569 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
/* eslint-disable */
|
|
3
|
+
/* eslint-disable react/no-children-prop, react-x/no-children-for-each, react-x/no-children-map, react-x/no-children-to-array, react-x/no-clone-element, sonarjs/function-return-type, sonarjs/no-identical-functions, sonarjs/no-unused-vars, max-lines, unicorn/no-array-callback-reference, unicorn/no-useless-undefined, unicorn/prefer-at, unicorn/prefer-dom-node-dataset, jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
|
|
4
4
|
|
|
5
|
+
import {Drawer as BaseDrawer} from "@base-ui/react/drawer";
|
|
6
|
+
import {Menu as BaseMenu} from "@base-ui/react/menu";
|
|
7
|
+
import {mergeProps} from "@base-ui/react/merge-props";
|
|
8
|
+
import {useRender} from "@base-ui/react/use-render";
|
|
5
9
|
import {ChevronLeftIcon, ChevronRightIcon} from "lucide-react";
|
|
6
|
-
import {AnimatePresence, motion, Transition} from "motion/react";
|
|
10
|
+
import {AnimatePresence, motion, type Transition} from "motion/react";
|
|
7
11
|
import * as React from "react";
|
|
8
12
|
|
|
9
|
-
import {Drawer, DrawerClose, DrawerContent, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger} from "@/components/ui/drawer";
|
|
10
|
-
import {
|
|
11
|
-
DropdownMenu,
|
|
12
|
-
DropdownMenuContent,
|
|
13
|
-
DropdownMenuItem,
|
|
14
|
-
DropdownMenuLabel,
|
|
15
|
-
DropdownMenuSeparator,
|
|
16
|
-
DropdownMenuSub,
|
|
17
|
-
DropdownMenuSubContent,
|
|
18
|
-
DropdownMenuSubTrigger,
|
|
19
|
-
DropdownMenuTrigger,
|
|
20
|
-
} from "@/components/ui/dropdown-menu";
|
|
21
13
|
import {useIsMobile} from "@/hooks/useIsMobile";
|
|
22
14
|
import {cn} from "@/lib/utilities";
|
|
15
|
+
import styles from "./dropdrawer.module.css";
|
|
23
16
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
const MOBILE_MENU_TITLE = "Menu";
|
|
18
|
+
const MOBILE_SUBMENU_TITLE = "Submenu";
|
|
19
|
+
const MOBILE_BACK_LABEL = "Go back";
|
|
20
|
+
|
|
21
|
+
interface DropDrawerContextValue {
|
|
22
|
+
isMobile: boolean;
|
|
23
|
+
}
|
|
27
24
|
|
|
28
|
-
const
|
|
25
|
+
const DropDrawerContext = React.createContext<DropDrawerContextValue | null>(null);
|
|
26
|
+
|
|
27
|
+
const useDropDrawerContext = (): DropDrawerContextValue => {
|
|
29
28
|
const context = React.useContext(DropDrawerContext);
|
|
30
|
-
|
|
29
|
+
|
|
30
|
+
if (context === null) {
|
|
31
31
|
throw new Error("DropDrawer components cannot be rendered outside the Context");
|
|
32
32
|
}
|
|
33
|
+
|
|
33
34
|
return context;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
const Drawer = BaseDrawer.Root;
|
|
38
|
+
const DrawerPortal = BaseDrawer.Portal;
|
|
39
|
+
|
|
40
|
+
const DrawerTrigger = React.forwardRef<HTMLButtonElement, React.ComponentPropsWithRef<typeof BaseDrawer.Trigger> & {asChild?: boolean}>(
|
|
41
|
+
function DrawerTrigger(props, forwardedRef) {
|
|
42
|
+
const {asChild = false, children, className, render, ...otherProps} = props;
|
|
43
|
+
const renderProp = asChild && React.isValidElement(children) ? children : render;
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<BaseDrawer.Trigger
|
|
47
|
+
{...otherProps}
|
|
48
|
+
ref={forwardedRef}
|
|
49
|
+
render={useRender({
|
|
50
|
+
defaultTagName: "button",
|
|
51
|
+
render: renderProp as never,
|
|
52
|
+
props: mergeProps({className}, {}),
|
|
53
|
+
})}>
|
|
54
|
+
{renderProp ? undefined : children}
|
|
55
|
+
</BaseDrawer.Trigger>
|
|
56
|
+
);
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
function DrawerOverlay(props: Readonly<React.ComponentPropsWithRef<typeof BaseDrawer.Backdrop>>): React.ReactElement {
|
|
61
|
+
const {className, render, ...otherProps} = props;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<BaseDrawer.Backdrop
|
|
65
|
+
{...otherProps}
|
|
66
|
+
render={useRender({
|
|
67
|
+
defaultTagName: "div",
|
|
68
|
+
render: render as never,
|
|
69
|
+
props: mergeProps({className: cn(styles.drawerOverlay, className)}, {}),
|
|
70
|
+
})}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const DrawerContent = React.forwardRef<HTMLDivElement, React.ComponentPropsWithRef<typeof BaseDrawer.Popup> & {children?: React.ReactNode}>(
|
|
76
|
+
function DrawerContent(props, forwardedRef) {
|
|
77
|
+
const {className, children, render, ...otherProps} = props;
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<DrawerPortal>
|
|
81
|
+
<DrawerOverlay />
|
|
82
|
+
<BaseDrawer.Viewport className={styles.drawerViewport}>
|
|
83
|
+
<BaseDrawer.Popup
|
|
84
|
+
{...otherProps}
|
|
85
|
+
ref={forwardedRef}
|
|
86
|
+
render={useRender({
|
|
87
|
+
defaultTagName: "div",
|
|
88
|
+
render: render as never,
|
|
89
|
+
props: mergeProps({className: cn(styles.drawerContent, className)}, {}),
|
|
90
|
+
})}>
|
|
91
|
+
<div className={styles.drawerHandle} />
|
|
92
|
+
<BaseDrawer.Content className={styles.drawerInnerContent}>{children}</BaseDrawer.Content>
|
|
93
|
+
</BaseDrawer.Popup>
|
|
94
|
+
</BaseDrawer.Viewport>
|
|
95
|
+
</DrawerPortal>
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
function DrawerHeader(
|
|
101
|
+
props: Readonly<React.ComponentPropsWithRef<"div"> & {render?: useRender.RenderProp<Record<string, never>>}>,
|
|
102
|
+
): React.ReactElement {
|
|
103
|
+
const {className, children, render, ...otherProps} = props;
|
|
104
|
+
|
|
105
|
+
return useRender({
|
|
106
|
+
defaultTagName: "div",
|
|
107
|
+
render: render as never,
|
|
108
|
+
props: mergeProps({className: cn(styles.drawerHeader, className)}, otherProps, {children}),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function DrawerFooter(
|
|
113
|
+
props: Readonly<React.ComponentPropsWithRef<"div"> & {render?: useRender.RenderProp<Record<string, never>>}>,
|
|
114
|
+
): React.ReactElement {
|
|
115
|
+
const {className, children, render, ...otherProps} = props;
|
|
116
|
+
|
|
117
|
+
return useRender({
|
|
118
|
+
defaultTagName: "div",
|
|
119
|
+
render: render as never,
|
|
120
|
+
props: mergeProps({className: cn(styles.drawerFooter, className)}, otherProps, {children}),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function DrawerTitle(props: Readonly<React.ComponentPropsWithRef<typeof BaseDrawer.Title>>): React.ReactElement {
|
|
125
|
+
const {className, children, render, ...otherProps} = props;
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<BaseDrawer.Title
|
|
129
|
+
{...otherProps}
|
|
130
|
+
render={useRender({
|
|
131
|
+
defaultTagName: "h2",
|
|
132
|
+
render: render as never,
|
|
133
|
+
props: mergeProps({className: cn(styles.drawerTitle, className)}, {}),
|
|
134
|
+
})}>
|
|
135
|
+
{children}
|
|
136
|
+
</BaseDrawer.Title>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const DropdownMenu = BaseMenu.Root;
|
|
141
|
+
const DropdownMenuSub = BaseMenu.SubmenuRoot;
|
|
142
|
+
|
|
143
|
+
const DropdownMenuTrigger = React.forwardRef<HTMLButtonElement, React.ComponentPropsWithRef<typeof BaseMenu.Trigger> & {asChild?: boolean}>(
|
|
144
|
+
function DropdownMenuTrigger(props, forwardedRef) {
|
|
145
|
+
const {asChild = false, children, className, render, ...otherProps} = props;
|
|
146
|
+
const renderProp = asChild && React.isValidElement(children) ? children : render;
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<BaseMenu.Trigger
|
|
150
|
+
{...otherProps}
|
|
151
|
+
ref={forwardedRef}
|
|
152
|
+
render={useRender({
|
|
153
|
+
defaultTagName: "button",
|
|
154
|
+
render: renderProp as never,
|
|
155
|
+
props: mergeProps({className}, {}),
|
|
156
|
+
})}>
|
|
157
|
+
{renderProp ? undefined : children}
|
|
158
|
+
</BaseMenu.Trigger>
|
|
159
|
+
);
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const DropdownMenuContent = React.forwardRef<
|
|
164
|
+
HTMLDivElement,
|
|
165
|
+
React.ComponentPropsWithRef<typeof BaseMenu.Positioner> & {children?: React.ReactNode}
|
|
166
|
+
>(function DropdownMenuContent(props, forwardedRef) {
|
|
167
|
+
const {className, children, render, ...otherProps} = props;
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<BaseMenu.Portal>
|
|
171
|
+
<BaseMenu.Positioner
|
|
172
|
+
{...otherProps}
|
|
173
|
+
ref={forwardedRef}
|
|
174
|
+
render={useRender({
|
|
175
|
+
defaultTagName: "div",
|
|
176
|
+
props: mergeProps({className: styles.dropdownPositioner}, {}),
|
|
177
|
+
})}>
|
|
178
|
+
<BaseMenu.Popup
|
|
179
|
+
render={useRender({
|
|
180
|
+
defaultTagName: "div",
|
|
181
|
+
render: render as never,
|
|
182
|
+
props: mergeProps({className: cn(styles.dropdownContent, className)}, {}),
|
|
183
|
+
})}>
|
|
184
|
+
{children}
|
|
185
|
+
</BaseMenu.Popup>
|
|
186
|
+
</BaseMenu.Positioner>
|
|
187
|
+
</BaseMenu.Portal>
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
interface DropdownMenuItemProps extends React.ComponentPropsWithRef<typeof BaseMenu.Item> {
|
|
192
|
+
/** @deprecated Prefer Base UI's `render` prop. */
|
|
193
|
+
asChild?: boolean;
|
|
194
|
+
/**
|
|
195
|
+
* Whether to apply inset spacing to align with grouped menu content.
|
|
196
|
+
* @default false
|
|
197
|
+
*/
|
|
198
|
+
inset?: boolean;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function DropdownMenuItem(props: Readonly<DropdownMenuItemProps>): React.ReactElement {
|
|
202
|
+
// eslint-disable-next-line sonarjs/deprecation -- backward-compatible asChild API
|
|
203
|
+
const {asChild = false, children, className, inset = false, render, ...otherProps} = props;
|
|
204
|
+
const renderProp = asChild && React.isValidElement(children) ? children : render;
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<BaseMenu.Item
|
|
208
|
+
{...otherProps}
|
|
209
|
+
render={useRender({
|
|
210
|
+
defaultTagName: "div",
|
|
211
|
+
render: renderProp as never,
|
|
212
|
+
props: mergeProps({className: cn(styles.desktopItem, inset && styles.inset, className)}, {}),
|
|
213
|
+
})}>
|
|
214
|
+
{renderProp ? undefined : children}
|
|
215
|
+
</BaseMenu.Item>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function DropdownMenuLabel(props: Readonly<React.ComponentPropsWithRef<typeof BaseMenu.GroupLabel>>): React.ReactElement {
|
|
220
|
+
const {className, children, render, ...otherProps} = props;
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<BaseMenu.GroupLabel
|
|
224
|
+
{...otherProps}
|
|
225
|
+
render={useRender({
|
|
226
|
+
defaultTagName: "div",
|
|
227
|
+
render: render as never,
|
|
228
|
+
props: mergeProps({className: cn(styles.desktopLabel, className)}, {}),
|
|
229
|
+
})}>
|
|
230
|
+
{children}
|
|
231
|
+
</BaseMenu.GroupLabel>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function DropdownMenuSeparator(props: Readonly<React.ComponentPropsWithRef<typeof BaseMenu.Separator>>): React.ReactElement {
|
|
236
|
+
const {className, render, ...otherProps} = props;
|
|
237
|
+
|
|
238
|
+
return (
|
|
239
|
+
<BaseMenu.Separator
|
|
240
|
+
{...otherProps}
|
|
241
|
+
render={useRender({
|
|
242
|
+
defaultTagName: "div",
|
|
243
|
+
render: render as never,
|
|
244
|
+
props: mergeProps({className: cn(styles.desktopSeparator, className)}, {}),
|
|
245
|
+
})}
|
|
246
|
+
/>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function DropdownMenuSubTrigger(
|
|
251
|
+
props: Readonly<React.ComponentPropsWithRef<typeof BaseMenu.SubmenuTrigger> & {inset?: boolean}>,
|
|
252
|
+
): React.ReactElement {
|
|
253
|
+
const {className, children, inset = false, render, ...otherProps} = props;
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<BaseMenu.SubmenuTrigger
|
|
257
|
+
{...otherProps}
|
|
258
|
+
render={useRender({
|
|
259
|
+
defaultTagName: "div",
|
|
260
|
+
render: render as never,
|
|
261
|
+
props: mergeProps({className: cn(styles.desktopSubTrigger, inset && styles.inset, className)}, {}),
|
|
262
|
+
})}>
|
|
263
|
+
{children}
|
|
264
|
+
<ChevronRightIcon className={styles.chevron} />
|
|
265
|
+
</BaseMenu.SubmenuTrigger>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function DropdownMenuSubContent(
|
|
270
|
+
props: Readonly<React.ComponentPropsWithRef<typeof BaseMenu.Positioner> & {children?: React.ReactNode}>,
|
|
271
|
+
): React.ReactElement {
|
|
272
|
+
const {className, children, render, ...otherProps} = props;
|
|
273
|
+
|
|
274
|
+
return (
|
|
275
|
+
<BaseMenu.Positioner
|
|
276
|
+
{...otherProps}
|
|
277
|
+
render={useRender({
|
|
278
|
+
defaultTagName: "div",
|
|
279
|
+
props: mergeProps({className: styles.dropdownPositioner}, {}),
|
|
280
|
+
})}>
|
|
281
|
+
<BaseMenu.Popup
|
|
282
|
+
render={useRender({
|
|
283
|
+
defaultTagName: "div",
|
|
284
|
+
render: render as never,
|
|
285
|
+
props: mergeProps({className: cn(styles.dropdownSubContent, className)}, {}),
|
|
286
|
+
})}>
|
|
287
|
+
{children}
|
|
288
|
+
</BaseMenu.Popup>
|
|
289
|
+
</BaseMenu.Positioner>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
type DropDrawerRootProps = React.ComponentProps<typeof Drawer> | React.ComponentProps<typeof DropdownMenu>;
|
|
294
|
+
type DropDrawerTriggerProps =
|
|
295
|
+
| React.ComponentPropsWithoutRef<typeof DrawerTrigger>
|
|
296
|
+
| React.ComponentPropsWithoutRef<typeof DropdownMenuTrigger>;
|
|
297
|
+
type DropDrawerContentProps =
|
|
298
|
+
| React.ComponentPropsWithoutRef<typeof DrawerContent>
|
|
299
|
+
| React.ComponentPropsWithoutRef<typeof DropdownMenuContent>;
|
|
300
|
+
|
|
301
|
+
interface MobileSubmenuDataAttributes {
|
|
302
|
+
"data-parent-submenu-id"?: string;
|
|
303
|
+
"data-parent-submenu"?: string;
|
|
304
|
+
"data-submenu-id"?: string;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
interface SharedDropDrawerItemProps
|
|
308
|
+
extends Omit<React.ComponentPropsWithoutRef<typeof BaseMenu.Item>, "children" | "onClick" | "onSelect">, MobileSubmenuDataAttributes {
|
|
309
|
+
/**
|
|
310
|
+
* Item contents.
|
|
311
|
+
* @default undefined
|
|
312
|
+
*/
|
|
313
|
+
children?: React.ReactNode;
|
|
314
|
+
/**
|
|
315
|
+
* Additional CSS classes merged with the item styles.
|
|
316
|
+
* @default undefined
|
|
317
|
+
*/
|
|
318
|
+
className?: string;
|
|
319
|
+
/**
|
|
320
|
+
* Whether the desktop dropdown should close after the item is activated.
|
|
321
|
+
* @default undefined
|
|
322
|
+
*/
|
|
323
|
+
closeOnClick?: boolean;
|
|
324
|
+
/**
|
|
325
|
+
* Optional trailing icon or affordance rendered alongside the item content.
|
|
326
|
+
* @default undefined
|
|
327
|
+
*/
|
|
328
|
+
icon?: React.ReactNode;
|
|
329
|
+
/**
|
|
330
|
+
* Whether to apply inset spacing to align the item with grouped content.
|
|
331
|
+
* @default undefined
|
|
332
|
+
*/
|
|
333
|
+
inset?: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Mouse click handler invoked when the item is activated.
|
|
336
|
+
* @default undefined
|
|
337
|
+
*/
|
|
338
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
339
|
+
/**
|
|
340
|
+
* Selection callback invoked with the native event when the item is activated.
|
|
341
|
+
* @default undefined
|
|
342
|
+
*/
|
|
343
|
+
onSelect?: (event: Event) => void;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
interface SubmenuContextType {
|
|
347
|
+
activeSubmenu: string | null;
|
|
348
|
+
navigateToSubmenu?: (id: string, title: string) => void;
|
|
349
|
+
registerSubmenuContent?: (id: string, content: ReadonlyArray<React.ReactNode>) => void;
|
|
350
|
+
setActiveSubmenu: (id: string | null) => void;
|
|
351
|
+
setSubmenuTitle: (title: string | null) => void;
|
|
352
|
+
submenuTitle: string | null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const SubmenuContext = React.createContext<SubmenuContextType>({
|
|
356
|
+
activeSubmenu: null,
|
|
357
|
+
navigateToSubmenu: undefined,
|
|
358
|
+
registerSubmenuContent: undefined,
|
|
359
|
+
setActiveSubmenu: () => undefined,
|
|
360
|
+
setSubmenuTitle: () => undefined,
|
|
361
|
+
submenuTitle: null,
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Provides a responsive dropdown-on-desktop, drawer-on-mobile navigation surface.
|
|
366
|
+
*
|
|
367
|
+
* @remarks
|
|
368
|
+
* - Renders either Base UI `Menu.Root` or `Drawer.Root` depending on viewport size
|
|
369
|
+
* - Built on Base UI Menu and Drawer primitives
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```tsx
|
|
373
|
+
* <DropDrawer>
|
|
374
|
+
* <DropDrawerTrigger>Open menu</DropDrawerTrigger>
|
|
375
|
+
* <DropDrawerContent>
|
|
376
|
+
* <DropDrawerItem>Profile</DropDrawerItem>
|
|
377
|
+
* </DropDrawerContent>
|
|
378
|
+
* </DropDrawer>
|
|
379
|
+
* ```
|
|
380
|
+
*
|
|
381
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
382
|
+
*/
|
|
383
|
+
function DropDrawer({children, ...props}: DropDrawerRootProps): React.JSX.Element {
|
|
37
384
|
const isMobile = useIsMobile();
|
|
38
|
-
const DropdownComponent = isMobile ? Drawer : DropdownMenu;
|
|
39
385
|
|
|
40
386
|
return (
|
|
41
387
|
<DropDrawerContext.Provider value={{isMobile}}>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
388
|
+
{isMobile ? (
|
|
389
|
+
<Drawer
|
|
390
|
+
data-slot='drop-drawer'
|
|
391
|
+
{...(props as React.ComponentProps<typeof Drawer>)}>
|
|
392
|
+
{children}
|
|
393
|
+
</Drawer>
|
|
394
|
+
) : (
|
|
395
|
+
<DropdownMenu
|
|
396
|
+
data-slot='drop-drawer'
|
|
397
|
+
{...(props as React.ComponentProps<typeof DropdownMenu>)}>
|
|
398
|
+
{children}
|
|
399
|
+
</DropdownMenu>
|
|
400
|
+
)}
|
|
48
401
|
</DropDrawerContext.Provider>
|
|
49
402
|
);
|
|
50
403
|
}
|
|
51
404
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
405
|
+
/**
|
|
406
|
+
* Renders the control that opens the dropdown or drawer surface.
|
|
407
|
+
*
|
|
408
|
+
* @remarks
|
|
409
|
+
* - Renders either a Base UI menu trigger or drawer trigger
|
|
410
|
+
* - Built on Base UI Menu and Drawer primitives
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```tsx
|
|
414
|
+
* <DropDrawerTrigger>Open menu</DropDrawerTrigger>
|
|
415
|
+
* ```
|
|
416
|
+
*
|
|
417
|
+
* @see {@link https://base-ui.com/react/components/drawer | Base UI Drawer Docs}
|
|
418
|
+
*/
|
|
419
|
+
const DropDrawerTrigger = React.forwardRef<HTMLButtonElement, DropDrawerTriggerProps>(function DropDrawerTrigger(
|
|
420
|
+
{className, children, ...props},
|
|
421
|
+
forwardedRef,
|
|
422
|
+
) {
|
|
57
423
|
const {isMobile} = useDropDrawerContext();
|
|
58
|
-
const TriggerComponent = isMobile ? DrawerTrigger : DropdownMenuTrigger;
|
|
59
424
|
|
|
60
|
-
return (
|
|
61
|
-
<
|
|
425
|
+
return isMobile ? (
|
|
426
|
+
<DrawerTrigger
|
|
427
|
+
ref={forwardedRef}
|
|
62
428
|
data-slot='drop-drawer-trigger'
|
|
63
429
|
className={className}
|
|
64
|
-
{...props}>
|
|
430
|
+
{...(props as React.ComponentProps<typeof DrawerTrigger>)}>
|
|
65
431
|
{children}
|
|
66
|
-
</
|
|
432
|
+
</DrawerTrigger>
|
|
433
|
+
) : (
|
|
434
|
+
<DropdownMenuTrigger
|
|
435
|
+
ref={forwardedRef}
|
|
436
|
+
data-slot='drop-drawer-trigger'
|
|
437
|
+
className={className}
|
|
438
|
+
{...(props as React.ComponentProps<typeof DropdownMenuTrigger>)}>
|
|
439
|
+
{children}
|
|
440
|
+
</DropdownMenuTrigger>
|
|
67
441
|
);
|
|
68
|
-
}
|
|
442
|
+
});
|
|
69
443
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
444
|
+
/**
|
|
445
|
+
* Renders the responsive dropdown or drawer content surface.
|
|
446
|
+
*
|
|
447
|
+
* @remarks
|
|
448
|
+
* - Renders a Base UI popup on desktop and drawer content on mobile
|
|
449
|
+
* - Built on Base UI Menu and Drawer primitives with animated mobile submenu navigation
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```tsx
|
|
453
|
+
* <DropDrawerContent>
|
|
454
|
+
* <DropDrawerItem>Settings</DropDrawerItem>
|
|
455
|
+
* </DropDrawerContent>
|
|
456
|
+
* ```
|
|
457
|
+
*
|
|
458
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
459
|
+
*/
|
|
460
|
+
const DropDrawerContent = React.forwardRef<HTMLDivElement, DropDrawerContentProps>(function DropDrawerContent(
|
|
461
|
+
{className, children, ...props},
|
|
462
|
+
forwardedRef,
|
|
463
|
+
) {
|
|
75
464
|
const {isMobile} = useDropDrawerContext();
|
|
76
465
|
const [activeSubmenu, setActiveSubmenu] = React.useState<string | null>(null);
|
|
77
466
|
const [submenuTitle, setSubmenuTitle] = React.useState<string | null>(null);
|
|
78
|
-
const [submenuStack, setSubmenuStack] = React.useState<{id: string; title: string}
|
|
79
|
-
// Add animation direction state
|
|
467
|
+
const [submenuStack, setSubmenuStack] = React.useState<ReadonlyArray<{id: string; title: string}>>([]);
|
|
80
468
|
const [animationDirection, setAnimationDirection] = React.useState<"forward" | "backward">("forward");
|
|
469
|
+
const submenuContentRef = React.useRef(new Map<string, ReadonlyArray<React.ReactNode>>());
|
|
81
470
|
|
|
82
|
-
|
|
83
|
-
|
|
471
|
+
React.useEffect(() => {
|
|
472
|
+
submenuContentRef.current.clear();
|
|
473
|
+
}, [children]);
|
|
84
474
|
|
|
85
|
-
|
|
86
|
-
const navigateToSubmenu = React.useCallback((id: string, title: string) => {
|
|
87
|
-
// Set animation direction to forward when navigating to a submenu
|
|
475
|
+
const navigateToSubmenu = React.useCallback((id: string, title: string): void => {
|
|
88
476
|
setAnimationDirection("forward");
|
|
89
477
|
setActiveSubmenu(id);
|
|
90
478
|
setSubmenuTitle(title);
|
|
91
|
-
setSubmenuStack((
|
|
479
|
+
setSubmenuStack((previousStack) => [...previousStack, {id, title}]);
|
|
92
480
|
}, []);
|
|
93
481
|
|
|
94
|
-
|
|
95
|
-
const goBack = React.useCallback(() => {
|
|
96
|
-
// Set animation direction to backward when going back
|
|
482
|
+
const goBack = React.useCallback((): void => {
|
|
97
483
|
setAnimationDirection("backward");
|
|
98
484
|
|
|
99
485
|
if (submenuStack.length <= 1) {
|
|
100
|
-
// If we're at the first level, go back to main menu
|
|
101
486
|
setActiveSubmenu(null);
|
|
102
487
|
setSubmenuTitle(null);
|
|
103
488
|
setSubmenuStack([]);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const newStack = [...submenuStack];
|
|
493
|
+
newStack.pop();
|
|
494
|
+
const previousSubmenu = newStack[newStack.length - 1];
|
|
495
|
+
|
|
496
|
+
if (!previousSubmenu) {
|
|
497
|
+
setActiveSubmenu(null);
|
|
498
|
+
setSubmenuTitle(null);
|
|
499
|
+
setSubmenuStack([]);
|
|
500
|
+
return;
|
|
112
501
|
}
|
|
502
|
+
|
|
503
|
+
setActiveSubmenu(previousSubmenu.id);
|
|
504
|
+
setSubmenuTitle(previousSubmenu.title);
|
|
505
|
+
setSubmenuStack(newStack);
|
|
113
506
|
}, [submenuStack]);
|
|
114
507
|
|
|
115
|
-
|
|
116
|
-
const registerSubmenuContent = React.useCallback((id: string, content: React.ReactNode[]) => {
|
|
508
|
+
const registerSubmenuContent = React.useCallback((id: string, content: ReadonlyArray<React.ReactNode>): void => {
|
|
117
509
|
submenuContentRef.current.set(id, content);
|
|
118
510
|
}, []);
|
|
119
511
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const result: React.ReactNode[] = [];
|
|
512
|
+
const extractSubmenuContent = React.useCallback((elements: React.ReactNode, targetId: string): ReadonlyArray<React.ReactNode> => {
|
|
513
|
+
const result: Array<React.ReactNode> = [];
|
|
123
514
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
515
|
+
const findSubmenuContent = (node: React.ReactNode): void => {
|
|
516
|
+
if (!React.isValidElement(node)) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
128
519
|
|
|
129
|
-
const element = node as React.ReactElement
|
|
130
|
-
// Use a more specific type to avoid 'any'
|
|
131
|
-
const props = element.props as {
|
|
132
|
-
id?: string;
|
|
520
|
+
const element = node as React.ReactElement<{
|
|
133
521
|
"data-submenu-id"?: string;
|
|
134
522
|
children?: React.ReactNode;
|
|
135
|
-
|
|
523
|
+
id?: string;
|
|
524
|
+
}>;
|
|
136
525
|
|
|
137
|
-
// Check if this is a DropDrawerSub
|
|
138
526
|
if (element.type === DropDrawerSub) {
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
const dataSubmenuId = props["data-submenu-id"];
|
|
527
|
+
const elementId = element.props.id;
|
|
528
|
+
const dataSubmenuId = element.props["data-submenu-id"];
|
|
142
529
|
|
|
143
|
-
// If this is the submenu we're looking for
|
|
144
530
|
if (elementId === targetId || dataSubmenuId === targetId) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
React.Children.forEach(props.children, (child) => {
|
|
531
|
+
if (element.props.children) {
|
|
532
|
+
React.Children.forEach(element.props.children, (child) => {
|
|
148
533
|
if (React.isValidElement(child) && child.type === DropDrawerSubContent) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
React.Children.forEach(subContentProps.children, (contentChild) => {
|
|
155
|
-
result.push(contentChild);
|
|
156
|
-
});
|
|
157
|
-
}
|
|
534
|
+
const subContentElement = child as React.ReactElement<{children?: React.ReactNode}>;
|
|
535
|
+
|
|
536
|
+
React.Children.forEach(subContentElement.props.children, (contentChild) => {
|
|
537
|
+
result.push(contentChild);
|
|
538
|
+
});
|
|
158
539
|
}
|
|
159
540
|
});
|
|
160
541
|
}
|
|
161
|
-
|
|
542
|
+
|
|
543
|
+
return;
|
|
162
544
|
}
|
|
163
545
|
}
|
|
164
546
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (Array.isArray(props.children)) {
|
|
168
|
-
props.children.forEach((child: React.ReactNode) => findSubmenuContent(child));
|
|
169
|
-
} else {
|
|
170
|
-
findSubmenuContent(props.children);
|
|
171
|
-
}
|
|
547
|
+
if (element.props.children) {
|
|
548
|
+
React.Children.forEach(element.props.children, findSubmenuContent);
|
|
172
549
|
}
|
|
173
550
|
};
|
|
174
551
|
|
|
175
|
-
|
|
176
|
-
if (Array.isArray(elements)) {
|
|
177
|
-
elements.forEach((child) => findSubmenuContent(child));
|
|
178
|
-
} else {
|
|
179
|
-
findSubmenuContent(elements);
|
|
180
|
-
}
|
|
181
|
-
|
|
552
|
+
React.Children.forEach(elements, findSubmenuContent);
|
|
182
553
|
return result;
|
|
183
554
|
}, []);
|
|
184
555
|
|
|
185
|
-
// Get submenu content (either from cache or extract it)
|
|
186
556
|
const getSubmenuContent = React.useCallback(
|
|
187
|
-
(id: string) => {
|
|
188
|
-
|
|
189
|
-
|
|
557
|
+
(id: string): ReadonlyArray<React.ReactNode> => {
|
|
558
|
+
const cachedContent = submenuContentRef.current.get(id);
|
|
559
|
+
|
|
190
560
|
if (cachedContent && cachedContent.length > 0) {
|
|
191
561
|
return cachedContent;
|
|
192
562
|
}
|
|
193
563
|
|
|
194
|
-
// If not in cache, extract it
|
|
195
564
|
const submenuContent = extractSubmenuContent(children, id);
|
|
196
565
|
|
|
197
|
-
if (submenuContent.length
|
|
198
|
-
return [];
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Store in cache for future use
|
|
202
|
-
if (id) {
|
|
566
|
+
if (submenuContent.length > 0) {
|
|
203
567
|
submenuContentRef.current.set(id, submenuContent);
|
|
204
568
|
}
|
|
205
569
|
|
|
@@ -208,26 +572,24 @@ function DropDrawerContent({
|
|
|
208
572
|
[children, extractSubmenuContent],
|
|
209
573
|
);
|
|
210
574
|
|
|
211
|
-
// Animation variants for Framer Motion
|
|
212
575
|
const variants = {
|
|
213
|
-
enter: (direction: "forward" | "backward") => ({
|
|
214
|
-
x: direction === "forward" ? "100%" : "-100%",
|
|
215
|
-
opacity: 0,
|
|
216
|
-
}),
|
|
217
576
|
center: {
|
|
218
|
-
x: 0,
|
|
219
577
|
opacity: 1,
|
|
578
|
+
x: 0,
|
|
220
579
|
},
|
|
580
|
+
enter: (direction: "forward" | "backward") => ({
|
|
581
|
+
opacity: 0,
|
|
582
|
+
x: direction === "forward" ? "100%" : "-100%",
|
|
583
|
+
}),
|
|
221
584
|
exit: (direction: "forward" | "backward") => ({
|
|
222
|
-
x: direction === "forward" ? "-100%" : "100%",
|
|
223
585
|
opacity: 0,
|
|
586
|
+
x: direction === "forward" ? "-100%" : "100%",
|
|
224
587
|
}),
|
|
225
588
|
};
|
|
226
589
|
|
|
227
|
-
// Animation transition
|
|
228
590
|
const transition = {
|
|
229
591
|
duration: 0.3,
|
|
230
|
-
ease: [0.25, 0.1, 0.25, 1
|
|
592
|
+
ease: [0.25, 0.1, 0.25, 1],
|
|
231
593
|
} satisfies Transition;
|
|
232
594
|
|
|
233
595
|
if (isMobile) {
|
|
@@ -235,6 +597,8 @@ function DropDrawerContent({
|
|
|
235
597
|
<SubmenuContext.Provider
|
|
236
598
|
value={{
|
|
237
599
|
activeSubmenu,
|
|
600
|
+
navigateToSubmenu,
|
|
601
|
+
registerSubmenuContent,
|
|
238
602
|
setActiveSubmenu: (id) => {
|
|
239
603
|
if (id === null) {
|
|
240
604
|
setActiveSubmenu(null);
|
|
@@ -242,53 +606,53 @@ function DropDrawerContent({
|
|
|
242
606
|
setSubmenuStack([]);
|
|
243
607
|
}
|
|
244
608
|
},
|
|
245
|
-
submenuTitle,
|
|
246
609
|
setSubmenuTitle,
|
|
247
|
-
|
|
248
|
-
registerSubmenuContent,
|
|
610
|
+
submenuTitle,
|
|
249
611
|
}}>
|
|
250
612
|
<DrawerContent
|
|
613
|
+
ref={forwardedRef}
|
|
251
614
|
data-slot='drop-drawer-content'
|
|
252
|
-
className={cn(
|
|
253
|
-
{...props}>
|
|
615
|
+
className={cn(styles.mobileContent, className)}
|
|
616
|
+
{...(props as React.ComponentProps<typeof DrawerContent>)}>
|
|
254
617
|
{activeSubmenu ? (
|
|
255
618
|
<>
|
|
256
619
|
<DrawerHeader>
|
|
257
|
-
<div className=
|
|
620
|
+
<div className={styles.mobileHeaderRow}>
|
|
258
621
|
<button
|
|
622
|
+
type='button'
|
|
623
|
+
aria-label={MOBILE_BACK_LABEL}
|
|
259
624
|
onClick={goBack}
|
|
260
|
-
className=
|
|
261
|
-
<ChevronLeftIcon className=
|
|
625
|
+
className={styles.backButton}>
|
|
626
|
+
<ChevronLeftIcon className={styles.chevron} />
|
|
262
627
|
</button>
|
|
263
|
-
<DrawerTitle>{submenuTitle ||
|
|
628
|
+
<DrawerTitle>{submenuTitle || MOBILE_SUBMENU_TITLE}</DrawerTitle>
|
|
264
629
|
</div>
|
|
265
630
|
</DrawerHeader>
|
|
266
|
-
<div className=
|
|
267
|
-
{/* Use AnimatePresence to handle exit animations */}
|
|
631
|
+
<div className={styles.mobileViewport}>
|
|
268
632
|
<AnimatePresence
|
|
269
633
|
initial={false}
|
|
270
634
|
mode='wait'
|
|
271
635
|
custom={animationDirection}>
|
|
272
636
|
<motion.div
|
|
273
|
-
key={activeSubmenu
|
|
637
|
+
key={activeSubmenu}
|
|
274
638
|
custom={animationDirection}
|
|
275
639
|
variants={variants}
|
|
276
640
|
initial='enter'
|
|
277
641
|
animate='center'
|
|
278
642
|
exit='exit'
|
|
279
643
|
transition={transition}
|
|
280
|
-
className=
|
|
281
|
-
{
|
|
644
|
+
className={styles.mobileMotionPanel}>
|
|
645
|
+
{getSubmenuContent(activeSubmenu)}
|
|
282
646
|
</motion.div>
|
|
283
647
|
</AnimatePresence>
|
|
284
648
|
</div>
|
|
285
649
|
</>
|
|
286
650
|
) : (
|
|
287
651
|
<>
|
|
288
|
-
<DrawerHeader className=
|
|
289
|
-
<DrawerTitle>
|
|
652
|
+
<DrawerHeader className={styles.screenReaderOnlyHeader}>
|
|
653
|
+
<DrawerTitle>{MOBILE_MENU_TITLE}</DrawerTitle>
|
|
290
654
|
</DrawerHeader>
|
|
291
|
-
<div className=
|
|
655
|
+
<div className={styles.mobileMainViewport}>
|
|
292
656
|
<AnimatePresence
|
|
293
657
|
initial={false}
|
|
294
658
|
mode='wait'
|
|
@@ -301,7 +665,7 @@ function DropDrawerContent({
|
|
|
301
665
|
animate='center'
|
|
302
666
|
exit='exit'
|
|
303
667
|
transition={transition}
|
|
304
|
-
className=
|
|
668
|
+
className={styles.mobileMotionPanel}>
|
|
305
669
|
{children}
|
|
306
670
|
</motion.div>
|
|
307
671
|
</AnimatePresence>
|
|
@@ -317,141 +681,203 @@ function DropDrawerContent({
|
|
|
317
681
|
<SubmenuContext.Provider
|
|
318
682
|
value={{
|
|
319
683
|
activeSubmenu,
|
|
684
|
+
registerSubmenuContent,
|
|
320
685
|
setActiveSubmenu,
|
|
321
|
-
submenuTitle,
|
|
322
686
|
setSubmenuTitle,
|
|
323
|
-
|
|
687
|
+
submenuTitle,
|
|
324
688
|
}}>
|
|
325
689
|
<DropdownMenuContent
|
|
690
|
+
ref={forwardedRef}
|
|
326
691
|
data-slot='drop-drawer-content'
|
|
327
692
|
align='end'
|
|
328
693
|
sideOffset={4}
|
|
329
|
-
className={cn(
|
|
330
|
-
{...props}>
|
|
694
|
+
className={cn(styles.desktopContent, className)}
|
|
695
|
+
{...(props as React.ComponentProps<typeof DropdownMenuContent>)}>
|
|
331
696
|
{children}
|
|
332
697
|
</DropdownMenuContent>
|
|
333
698
|
</SubmenuContext.Provider>
|
|
334
699
|
);
|
|
335
|
-
}
|
|
700
|
+
});
|
|
336
701
|
|
|
702
|
+
/**
|
|
703
|
+
* Renders an actionable item inside the drop drawer surface.
|
|
704
|
+
*
|
|
705
|
+
* @remarks
|
|
706
|
+
* - Renders a Base UI menu item on desktop and a keyboard-accessible `<div>` on mobile
|
|
707
|
+
* - Built on Base UI Menu and Drawer close primitives
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```tsx
|
|
711
|
+
* <DropDrawerItem icon={<ChevronRightIcon />}>Account</DropDrawerItem>
|
|
712
|
+
* ```
|
|
713
|
+
*
|
|
714
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
715
|
+
*/
|
|
337
716
|
function DropDrawerItem({
|
|
338
717
|
className,
|
|
339
718
|
children,
|
|
340
|
-
|
|
341
|
-
|
|
719
|
+
closeOnClick,
|
|
720
|
+
disabled,
|
|
342
721
|
icon,
|
|
343
722
|
inset,
|
|
344
|
-
|
|
723
|
+
onClick,
|
|
724
|
+
onSelect,
|
|
345
725
|
...props
|
|
346
|
-
}: React.
|
|
347
|
-
icon?: React.ReactNode;
|
|
348
|
-
}) {
|
|
726
|
+
}: SharedDropDrawerItemProps): React.JSX.Element {
|
|
349
727
|
const {isMobile} = useDropDrawerContext();
|
|
350
728
|
|
|
351
|
-
// Define hooks outside of conditionals to follow React rules
|
|
352
|
-
// Check if this item is inside a group by looking at parent elements
|
|
353
729
|
const isInGroup = React.useCallback((element: HTMLElement | null): boolean => {
|
|
354
|
-
if (!element)
|
|
730
|
+
if (!element) {
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
355
733
|
|
|
356
|
-
// Check if any parent has a data-drop-drawer-group attribute
|
|
357
734
|
let parent = element.parentElement;
|
|
735
|
+
|
|
358
736
|
while (parent) {
|
|
359
737
|
if (parent.hasAttribute("data-drop-drawer-group")) {
|
|
360
738
|
return true;
|
|
361
739
|
}
|
|
740
|
+
|
|
362
741
|
parent = parent.parentElement;
|
|
363
742
|
}
|
|
743
|
+
|
|
364
744
|
return false;
|
|
365
745
|
}, []);
|
|
366
746
|
|
|
367
|
-
// Create a ref to check if the item is in a group
|
|
368
747
|
const itemRef = React.useRef<HTMLDivElement>(null);
|
|
369
748
|
const [isInsideGroup, setIsInsideGroup] = React.useState(false);
|
|
370
749
|
|
|
371
750
|
React.useEffect(() => {
|
|
372
|
-
|
|
373
|
-
|
|
751
|
+
if (!isMobile) {
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
374
754
|
|
|
375
|
-
|
|
376
|
-
const timer = setTimeout(() => {
|
|
755
|
+
const timer = globalThis.window.setTimeout(() => {
|
|
377
756
|
if (itemRef.current) {
|
|
378
757
|
setIsInsideGroup(isInGroup(itemRef.current));
|
|
379
758
|
}
|
|
380
759
|
}, 0);
|
|
381
760
|
|
|
382
|
-
return () => clearTimeout(timer);
|
|
761
|
+
return () => globalThis.window.clearTimeout(timer);
|
|
383
762
|
}, [isInGroup, isMobile]);
|
|
384
763
|
|
|
764
|
+
const handleSelect = React.useCallback(
|
|
765
|
+
(event: Event): void => {
|
|
766
|
+
if (!disabled) {
|
|
767
|
+
onSelect?.(event);
|
|
768
|
+
}
|
|
769
|
+
},
|
|
770
|
+
[disabled, onSelect],
|
|
771
|
+
);
|
|
772
|
+
|
|
385
773
|
if (isMobile) {
|
|
386
|
-
const handleClick
|
|
387
|
-
if (disabled)
|
|
388
|
-
|
|
389
|
-
|
|
774
|
+
const handleClick: React.MouseEventHandler<HTMLDivElement> = (event): void => {
|
|
775
|
+
if (disabled) {
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
onClick?.(event);
|
|
780
|
+
handleSelect(event.nativeEvent);
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
const handleKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event): void => {
|
|
784
|
+
if (event.key !== "Enter" && event.key !== " ") {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
event.preventDefault();
|
|
789
|
+
event.currentTarget.click();
|
|
390
790
|
};
|
|
391
791
|
|
|
392
|
-
// Only wrap in DrawerClose if it's not a submenu item
|
|
393
792
|
const content = (
|
|
394
793
|
<div
|
|
395
794
|
ref={itemRef}
|
|
396
795
|
data-slot='drop-drawer-item'
|
|
397
|
-
data-inset={inset}
|
|
398
796
|
data-disabled={disabled}
|
|
797
|
+
data-inset={inset}
|
|
798
|
+
role='menuitem'
|
|
799
|
+
tabIndex={disabled ? -1 : 0}
|
|
399
800
|
className={cn(
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
isInsideGroup && "bg-transparent py-4",
|
|
405
|
-
inset && "pl-8",
|
|
406
|
-
disabled && "pointer-events-none opacity-50",
|
|
801
|
+
styles.mobileItem,
|
|
802
|
+
!isInsideGroup && styles.mobileStandaloneItem,
|
|
803
|
+
isInsideGroup && styles.mobileGroupedItem,
|
|
804
|
+
inset && styles.inset,
|
|
407
805
|
className,
|
|
408
806
|
)}
|
|
409
807
|
onClick={handleClick}
|
|
808
|
+
onKeyDown={handleKeyDown}
|
|
410
809
|
aria-disabled={disabled}
|
|
411
810
|
{...props}>
|
|
412
|
-
<div className=
|
|
413
|
-
{icon
|
|
811
|
+
<div className={styles.itemChildren}>{children}</div>
|
|
812
|
+
{icon ? <div className={styles.itemIcon}>{icon}</div> : null}
|
|
414
813
|
</div>
|
|
415
814
|
);
|
|
416
815
|
|
|
417
|
-
|
|
418
|
-
const isInSubmenu =
|
|
419
|
-
(props as Record<string, unknown>)["data-parent-submenu-id"] || (props as Record<string, unknown>)["data-parent-submenu"];
|
|
816
|
+
const parentSubmenuId = props["data-parent-submenu-id"] ?? props["data-parent-submenu"];
|
|
420
817
|
|
|
421
|
-
if (
|
|
818
|
+
if (parentSubmenuId) {
|
|
422
819
|
return content;
|
|
423
820
|
}
|
|
424
821
|
|
|
425
|
-
return
|
|
822
|
+
return (
|
|
823
|
+
<BaseDrawer.Close
|
|
824
|
+
nativeButton={false}
|
|
825
|
+
render={content}
|
|
826
|
+
/>
|
|
827
|
+
);
|
|
426
828
|
}
|
|
427
829
|
|
|
830
|
+
const handleDesktopClick: React.MouseEventHandler<HTMLElement> = (event): void => {
|
|
831
|
+
if (disabled) {
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
onClick?.(event);
|
|
836
|
+
handleSelect(event.nativeEvent);
|
|
837
|
+
};
|
|
838
|
+
|
|
428
839
|
return (
|
|
429
840
|
<DropdownMenuItem
|
|
430
841
|
data-slot='drop-drawer-item'
|
|
431
842
|
data-inset={inset}
|
|
432
|
-
className={className}
|
|
433
|
-
|
|
434
|
-
onClick={onClick as React.MouseEventHandler<HTMLDivElement>}
|
|
435
|
-
inset={inset}
|
|
843
|
+
className={cn(styles.desktopItem, className)}
|
|
844
|
+
closeOnClick={closeOnClick}
|
|
436
845
|
disabled={disabled}
|
|
846
|
+
inset={inset}
|
|
847
|
+
onClick={handleDesktopClick}
|
|
437
848
|
{...props}>
|
|
438
|
-
<div className=
|
|
439
|
-
<div>{children}</div>
|
|
440
|
-
{icon
|
|
849
|
+
<div className={styles.itemRow}>
|
|
850
|
+
<div className={styles.itemChildren}>{children}</div>
|
|
851
|
+
{icon ? <div className={styles.itemIcon}>{icon}</div> : null}
|
|
441
852
|
</div>
|
|
442
853
|
</DropdownMenuItem>
|
|
443
854
|
);
|
|
444
855
|
}
|
|
445
856
|
|
|
446
|
-
|
|
857
|
+
/**
|
|
858
|
+
* Renders a visual separator between desktop drop drawer sections.
|
|
859
|
+
*
|
|
860
|
+
* @remarks
|
|
861
|
+
* - Renders a separator only in desktop dropdown mode
|
|
862
|
+
* - Built on Base UI Menu separator primitives
|
|
863
|
+
*
|
|
864
|
+
* @example
|
|
865
|
+
* ```tsx
|
|
866
|
+
* <DropDrawerSeparator />
|
|
867
|
+
* ```
|
|
868
|
+
*
|
|
869
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
870
|
+
*/
|
|
871
|
+
function DropDrawerSeparator({
|
|
872
|
+
className,
|
|
873
|
+
...props
|
|
874
|
+
}: React.ComponentPropsWithoutRef<typeof DropdownMenuSeparator>): React.JSX.Element | null {
|
|
447
875
|
const {isMobile} = useDropDrawerContext();
|
|
448
876
|
|
|
449
|
-
// For mobile, render a simple divider
|
|
450
877
|
if (isMobile) {
|
|
451
878
|
return null;
|
|
452
879
|
}
|
|
453
880
|
|
|
454
|
-
// For desktop, use the standard dropdown separator
|
|
455
881
|
return (
|
|
456
882
|
<DropdownMenuSeparator
|
|
457
883
|
data-slot='drop-drawer-separator'
|
|
@@ -461,210 +887,211 @@ function DropDrawerSeparator({className, ...props}: React.ComponentProps<typeof
|
|
|
461
887
|
);
|
|
462
888
|
}
|
|
463
889
|
|
|
890
|
+
/**
|
|
891
|
+
* Renders a section label for the drop drawer surface.
|
|
892
|
+
*
|
|
893
|
+
* @remarks
|
|
894
|
+
* - Renders a drawer title on mobile and a menu label on desktop
|
|
895
|
+
* - Built on Base UI Drawer and Menu primitives
|
|
896
|
+
*
|
|
897
|
+
* @example
|
|
898
|
+
* ```tsx
|
|
899
|
+
* <DropDrawerLabel>Actions</DropDrawerLabel>
|
|
900
|
+
* ```
|
|
901
|
+
*
|
|
902
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
903
|
+
*/
|
|
464
904
|
function DropDrawerLabel({
|
|
465
905
|
className,
|
|
466
906
|
children,
|
|
467
907
|
...props
|
|
468
|
-
}: React.ComponentProps<typeof DropdownMenuLabel> | React.ComponentProps<typeof DrawerTitle>) {
|
|
908
|
+
}: React.ComponentProps<typeof DropdownMenuLabel> | React.ComponentProps<typeof DrawerTitle>): React.JSX.Element {
|
|
469
909
|
const {isMobile} = useDropDrawerContext();
|
|
470
910
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
<
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return (
|
|
911
|
+
return isMobile ? (
|
|
912
|
+
<DrawerHeader className={styles.mobileLabelWrapper}>
|
|
913
|
+
<DrawerTitle
|
|
914
|
+
data-slot='drop-drawer-label'
|
|
915
|
+
className={cn(styles.mobileLabel, className)}
|
|
916
|
+
{...(props as React.ComponentProps<typeof DrawerTitle>)}>
|
|
917
|
+
{children}
|
|
918
|
+
</DrawerTitle>
|
|
919
|
+
</DrawerHeader>
|
|
920
|
+
) : (
|
|
485
921
|
<DropdownMenuLabel
|
|
486
922
|
data-slot='drop-drawer-label'
|
|
487
923
|
className={className}
|
|
488
|
-
{...props}>
|
|
924
|
+
{...(props as React.ComponentProps<typeof DropdownMenuLabel>)}>
|
|
489
925
|
{children}
|
|
490
926
|
</DropdownMenuLabel>
|
|
491
927
|
);
|
|
492
928
|
}
|
|
493
929
|
|
|
494
|
-
|
|
930
|
+
/**
|
|
931
|
+
* Renders footer content aligned to the bottom of the responsive surface.
|
|
932
|
+
*
|
|
933
|
+
* @remarks
|
|
934
|
+
* - Renders a drawer footer on mobile and a styled `<div>` on desktop
|
|
935
|
+
* - Built on Base UI Drawer primitives for mobile layouts
|
|
936
|
+
*
|
|
937
|
+
* @example
|
|
938
|
+
* ```tsx
|
|
939
|
+
* <DropDrawerFooter>Signed in as Alex</DropDrawerFooter>
|
|
940
|
+
* ```
|
|
941
|
+
*
|
|
942
|
+
* @see {@link https://base-ui.com/react/components/drawer | Base UI Drawer Docs}
|
|
943
|
+
*/
|
|
944
|
+
function DropDrawerFooter({
|
|
945
|
+
className,
|
|
946
|
+
children,
|
|
947
|
+
...props
|
|
948
|
+
}: React.ComponentProps<typeof DrawerFooter> | React.ComponentProps<"div">): React.JSX.Element {
|
|
495
949
|
const {isMobile} = useDropDrawerContext();
|
|
496
950
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// No direct equivalent in DropdownMenu, so we'll just render a div
|
|
509
|
-
return (
|
|
951
|
+
return isMobile ? (
|
|
952
|
+
<DrawerFooter
|
|
953
|
+
data-slot='drop-drawer-footer'
|
|
954
|
+
className={cn(styles.mobileFooter, className)}
|
|
955
|
+
{...(props as React.ComponentProps<typeof DrawerFooter>)}>
|
|
956
|
+
{children}
|
|
957
|
+
</DrawerFooter>
|
|
958
|
+
) : (
|
|
510
959
|
<div
|
|
511
960
|
data-slot='drop-drawer-footer'
|
|
512
|
-
className={cn(
|
|
961
|
+
className={cn(styles.desktopFooter, className)}
|
|
513
962
|
{...props}>
|
|
514
963
|
{children}
|
|
515
964
|
</div>
|
|
516
965
|
);
|
|
517
966
|
}
|
|
518
967
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
968
|
+
/**
|
|
969
|
+
* Renders a grouped collection of drop drawer items.
|
|
970
|
+
*
|
|
971
|
+
* @remarks
|
|
972
|
+
* - Renders a Base UI menu group on desktop and a `<div role="group">` on mobile
|
|
973
|
+
* - Inserts mobile-only separators between adjacent children
|
|
974
|
+
*
|
|
975
|
+
* @example
|
|
976
|
+
* ```tsx
|
|
977
|
+
* <DropDrawerGroup>
|
|
978
|
+
* <DropDrawerItem>Profile</DropDrawerItem>
|
|
979
|
+
* <DropDrawerItem>Billing</DropDrawerItem>
|
|
980
|
+
* </DropDrawerGroup>
|
|
981
|
+
* ```
|
|
982
|
+
*
|
|
983
|
+
* @see {@link https://developer.mozilla.org/docs/Web/Accessibility/ARIA/Roles/group_role | ARIA Group Role}
|
|
984
|
+
*/
|
|
985
|
+
function DropDrawerGroup({className, children, ...props}: React.ComponentProps<"div"> & {children: React.ReactNode}): React.JSX.Element {
|
|
526
986
|
const {isMobile} = useDropDrawerContext();
|
|
527
987
|
|
|
528
|
-
// Add separators between children on mobile
|
|
529
988
|
const childrenWithSeparators = React.useMemo(() => {
|
|
530
|
-
if (!isMobile)
|
|
989
|
+
if (!isMobile) {
|
|
990
|
+
return children;
|
|
991
|
+
}
|
|
531
992
|
|
|
532
993
|
const childArray = React.Children.toArray(children);
|
|
994
|
+
const filteredChildren = childArray.filter((child) => !(React.isValidElement(child) && child.type === DropDrawerSeparator));
|
|
533
995
|
|
|
534
|
-
// Filter out any existing separators
|
|
535
|
-
const filteredChildren = childArray.filter((child) => React.isValidElement(child) && child.type !== DropDrawerSeparator);
|
|
536
|
-
|
|
537
|
-
// Add separators between items
|
|
538
996
|
return filteredChildren.flatMap((child, index) => {
|
|
539
|
-
if (index === filteredChildren.length - 1)
|
|
997
|
+
if (index === filteredChildren.length - 1) {
|
|
998
|
+
return [child];
|
|
999
|
+
}
|
|
1000
|
+
|
|
540
1001
|
return [
|
|
541
1002
|
child,
|
|
542
1003
|
<div
|
|
543
1004
|
key={`separator-${index}`}
|
|
544
|
-
className=
|
|
1005
|
+
className={styles.mobileGroupSeparator}
|
|
545
1006
|
aria-hidden='true'
|
|
546
1007
|
/>,
|
|
547
1008
|
];
|
|
548
1009
|
});
|
|
549
1010
|
}, [children, isMobile]);
|
|
550
1011
|
|
|
551
|
-
|
|
552
|
-
return (
|
|
553
|
-
<div
|
|
554
|
-
data-drop-drawer-group
|
|
555
|
-
data-slot='drop-drawer-group'
|
|
556
|
-
role='group'
|
|
557
|
-
className={cn(
|
|
558
|
-
"mx-2 my-3 overflow-hidden rounded-xl bg-neutral-100 dark:bg-neutral-100 dark:bg-neutral-800 dark:dark:bg-neutral-800",
|
|
559
|
-
className,
|
|
560
|
-
)}
|
|
561
|
-
{...props}>
|
|
562
|
-
{childrenWithSeparators}
|
|
563
|
-
</div>
|
|
564
|
-
);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// On desktop, use a div with proper role and attributes
|
|
568
|
-
return (
|
|
1012
|
+
return isMobile ? (
|
|
569
1013
|
<div
|
|
570
1014
|
data-drop-drawer-group
|
|
571
1015
|
data-slot='drop-drawer-group'
|
|
572
1016
|
role='group'
|
|
573
|
-
className={className}
|
|
1017
|
+
className={cn(styles.mobileGroup, className)}
|
|
574
1018
|
{...props}>
|
|
575
|
-
{
|
|
1019
|
+
{childrenWithSeparators}
|
|
576
1020
|
</div>
|
|
1021
|
+
) : (
|
|
1022
|
+
<BaseMenu.Group
|
|
1023
|
+
data-drop-drawer-group
|
|
1024
|
+
data-slot='drop-drawer-group'
|
|
1025
|
+
className={className}
|
|
1026
|
+
{...(props as React.ComponentPropsWithoutRef<typeof BaseMenu.Group>)}>
|
|
1027
|
+
{children}
|
|
1028
|
+
</BaseMenu.Group>
|
|
577
1029
|
);
|
|
578
1030
|
}
|
|
579
1031
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// Submenu components
|
|
600
|
-
// Counter for generating simple numeric IDs
|
|
601
|
-
let submenuIdCounter = 0;
|
|
602
|
-
|
|
1032
|
+
/**
|
|
1033
|
+
* Renders a submenu root within the drop drawer surface.
|
|
1034
|
+
*
|
|
1035
|
+
* @remarks
|
|
1036
|
+
* - Renders a Base UI submenu on desktop and a mobile-aware container on small screens
|
|
1037
|
+
* - Registers submenu content for animated mobile drill-down navigation
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* ```tsx
|
|
1041
|
+
* <DropDrawerSub>
|
|
1042
|
+
* <DropDrawerSubTrigger>More</DropDrawerSubTrigger>
|
|
1043
|
+
* <DropDrawerSubContent>
|
|
1044
|
+
* <DropDrawerItem>Sub item</DropDrawerItem>
|
|
1045
|
+
* </DropDrawerSubContent>
|
|
1046
|
+
* </DropDrawerSub>
|
|
1047
|
+
* ```
|
|
1048
|
+
*
|
|
1049
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
1050
|
+
*/
|
|
603
1051
|
function DropDrawerSub({
|
|
604
1052
|
children,
|
|
605
1053
|
id,
|
|
606
1054
|
...props
|
|
607
|
-
}: React.
|
|
608
|
-
id?: string;
|
|
609
|
-
}) {
|
|
1055
|
+
}: React.ComponentPropsWithoutRef<typeof DropdownMenuSub> & {children?: React.ReactNode; id?: string}): React.JSX.Element {
|
|
610
1056
|
const {isMobile} = useDropDrawerContext();
|
|
611
1057
|
const {registerSubmenuContent} = React.useContext(SubmenuContext);
|
|
612
|
-
|
|
613
|
-
// Generate a simple numeric ID instead of using React.useId()
|
|
614
|
-
const [generatedId] = React.useState(() => `submenu-${submenuIdCounter++}`);
|
|
1058
|
+
const generatedId = React.useId();
|
|
615
1059
|
const submenuId = id || generatedId;
|
|
616
1060
|
|
|
617
|
-
// Extract submenu content to register with parent
|
|
618
1061
|
React.useEffect(() => {
|
|
619
|
-
if (!registerSubmenuContent)
|
|
1062
|
+
if (!registerSubmenuContent) {
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
const contentItems: Array<React.ReactNode> = [];
|
|
620
1067
|
|
|
621
|
-
// Find the SubContent within this Sub
|
|
622
|
-
const contentItems: React.ReactNode[] = [];
|
|
623
1068
|
React.Children.forEach(children, (child) => {
|
|
624
1069
|
if (React.isValidElement(child) && child.type === DropDrawerSubContent) {
|
|
625
|
-
|
|
626
|
-
|
|
1070
|
+
const childElement = child as React.ReactElement<{children?: React.ReactNode}>;
|
|
1071
|
+
|
|
1072
|
+
React.Children.forEach(childElement.props.children, (contentChild) => {
|
|
627
1073
|
contentItems.push(contentChild);
|
|
628
1074
|
});
|
|
629
1075
|
}
|
|
630
1076
|
});
|
|
631
1077
|
|
|
632
|
-
// Register the content with the parent
|
|
633
1078
|
if (contentItems.length > 0) {
|
|
634
1079
|
registerSubmenuContent(submenuId, contentItems);
|
|
635
1080
|
}
|
|
636
1081
|
}, [children, registerSubmenuContent, submenuId]);
|
|
637
1082
|
|
|
638
1083
|
if (isMobile) {
|
|
639
|
-
// For mobile, we'll use the context to manage submenu state
|
|
640
|
-
// Process children to pass the submenu ID to the trigger and content
|
|
641
1084
|
const processedChildren = React.Children.map(children, (child) => {
|
|
642
|
-
if (!React.isValidElement(child))
|
|
643
|
-
|
|
644
|
-
if (child.type === DropDrawerSubTrigger) {
|
|
645
|
-
return React.cloneElement(
|
|
646
|
-
child as React.ReactElement,
|
|
647
|
-
{
|
|
648
|
-
...(child.props as object),
|
|
649
|
-
"data-parent-submenu-id": submenuId,
|
|
650
|
-
"data-submenu-id": submenuId,
|
|
651
|
-
// Use only data attributes, not custom props
|
|
652
|
-
"data-parent-submenu": submenuId,
|
|
653
|
-
} as React.HTMLAttributes<HTMLElement>,
|
|
654
|
-
);
|
|
1085
|
+
if (!React.isValidElement(child)) {
|
|
1086
|
+
return child;
|
|
655
1087
|
}
|
|
656
1088
|
|
|
657
|
-
if (child.type === DropDrawerSubContent) {
|
|
658
|
-
return React.cloneElement(
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
"data-submenu-id": submenuId,
|
|
664
|
-
// Use only data attributes, not custom props
|
|
665
|
-
"data-parent-submenu": submenuId,
|
|
666
|
-
} as React.HTMLAttributes<HTMLElement>,
|
|
667
|
-
);
|
|
1089
|
+
if (child.type === DropDrawerSubTrigger || child.type === DropDrawerSubContent) {
|
|
1090
|
+
return React.cloneElement(child as React.ReactElement<MobileSubmenuDataAttributes>, {
|
|
1091
|
+
"data-parent-submenu": submenuId,
|
|
1092
|
+
"data-parent-submenu-id": submenuId,
|
|
1093
|
+
"data-submenu-id": submenuId,
|
|
1094
|
+
});
|
|
668
1095
|
}
|
|
669
1096
|
|
|
670
1097
|
return child;
|
|
@@ -680,137 +1107,151 @@ function DropDrawerSub({
|
|
|
680
1107
|
);
|
|
681
1108
|
}
|
|
682
1109
|
|
|
683
|
-
// For desktop, pass the generated ID to the DropdownMenuSub
|
|
684
1110
|
return (
|
|
685
1111
|
<DropdownMenuSub
|
|
686
1112
|
data-slot='drop-drawer-sub'
|
|
687
1113
|
data-submenu-id={submenuId}
|
|
688
|
-
// Don't pass id to DropdownMenuSub as it doesn't accept this prop
|
|
689
1114
|
{...props}>
|
|
690
1115
|
{children}
|
|
691
1116
|
</DropdownMenuSub>
|
|
692
1117
|
);
|
|
693
1118
|
}
|
|
694
1119
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
1120
|
+
interface DropDrawerSubTriggerProps
|
|
1121
|
+
extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuSubTrigger>, "children" | "onClick">, MobileSubmenuDataAttributes {
|
|
1122
|
+
/**
|
|
1123
|
+
* Trigger contents.
|
|
1124
|
+
* @default undefined
|
|
1125
|
+
*/
|
|
1126
|
+
children?: React.ReactNode;
|
|
1127
|
+
/**
|
|
1128
|
+
* Additional CSS classes merged with the trigger styles.
|
|
1129
|
+
* @default undefined
|
|
1130
|
+
*/
|
|
1131
|
+
className?: string;
|
|
1132
|
+
/**
|
|
1133
|
+
* Whether to apply inset spacing to align the trigger with grouped content.
|
|
1134
|
+
* @default undefined
|
|
1135
|
+
*/
|
|
1136
|
+
inset?: boolean;
|
|
1137
|
+
/**
|
|
1138
|
+
* Mouse click handler invoked before submenu navigation occurs.
|
|
1139
|
+
* @default undefined
|
|
1140
|
+
*/
|
|
1141
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* Renders the trigger that opens a nested submenu.
|
|
1146
|
+
*
|
|
1147
|
+
* @remarks
|
|
1148
|
+
* - Renders a Base UI submenu trigger on desktop and a keyboard-accessible `<div>` on mobile
|
|
1149
|
+
* - Built on Base UI Menu submenu primitives
|
|
1150
|
+
*
|
|
1151
|
+
* @example
|
|
1152
|
+
* ```tsx
|
|
1153
|
+
* <DropDrawerSubTrigger>Advanced</DropDrawerSubTrigger>
|
|
1154
|
+
* ```
|
|
1155
|
+
*
|
|
1156
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
1157
|
+
*/
|
|
1158
|
+
function DropDrawerSubTrigger({className, inset, children, onClick, ...props}: DropDrawerSubTriggerProps): React.JSX.Element {
|
|
703
1159
|
const {isMobile} = useDropDrawerContext();
|
|
704
1160
|
const {navigateToSubmenu} = React.useContext(SubmenuContext);
|
|
705
1161
|
|
|
706
|
-
// Define hooks outside of conditionals to follow React rules
|
|
707
|
-
// Check if this item is inside a group by looking at parent elements
|
|
708
1162
|
const isInGroup = React.useCallback((element: HTMLElement | null): boolean => {
|
|
709
|
-
if (!element)
|
|
1163
|
+
if (!element) {
|
|
1164
|
+
return false;
|
|
1165
|
+
}
|
|
710
1166
|
|
|
711
|
-
// Check if any parent has a data-drop-drawer-group attribute
|
|
712
1167
|
let parent = element.parentElement;
|
|
1168
|
+
|
|
713
1169
|
while (parent) {
|
|
714
1170
|
if (parent.hasAttribute("data-drop-drawer-group")) {
|
|
715
1171
|
return true;
|
|
716
1172
|
}
|
|
1173
|
+
|
|
717
1174
|
parent = parent.parentElement;
|
|
718
1175
|
}
|
|
1176
|
+
|
|
719
1177
|
return false;
|
|
720
1178
|
}, []);
|
|
721
1179
|
|
|
722
|
-
// Create a ref to check if the item is in a group
|
|
723
1180
|
const itemRef = React.useRef<HTMLDivElement>(null);
|
|
724
1181
|
const [isInsideGroup, setIsInsideGroup] = React.useState(false);
|
|
725
1182
|
|
|
726
1183
|
React.useEffect(() => {
|
|
727
|
-
|
|
728
|
-
|
|
1184
|
+
if (!isMobile) {
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
729
1187
|
|
|
730
|
-
|
|
731
|
-
const timer = setTimeout(() => {
|
|
1188
|
+
const timer = globalThis.window.setTimeout(() => {
|
|
732
1189
|
if (itemRef.current) {
|
|
733
1190
|
setIsInsideGroup(isInGroup(itemRef.current));
|
|
734
1191
|
}
|
|
735
1192
|
}, 0);
|
|
736
1193
|
|
|
737
|
-
return () => clearTimeout(timer);
|
|
1194
|
+
return () => globalThis.window.clearTimeout(timer);
|
|
738
1195
|
}, [isInGroup, isMobile]);
|
|
739
1196
|
|
|
740
1197
|
if (isMobile) {
|
|
741
|
-
|
|
742
|
-
const handleClick = (e: React.MouseEvent) => {
|
|
743
|
-
e.preventDefault();
|
|
744
|
-
e.stopPropagation();
|
|
745
|
-
|
|
746
|
-
// Get the closest parent with data-submenu-id attribute
|
|
747
|
-
const element = e.currentTarget as HTMLElement;
|
|
1198
|
+
const navigate = (eventTarget: HTMLElement): void => {
|
|
748
1199
|
let submenuId: string | null = null;
|
|
1200
|
+
const closestElement = eventTarget.closest("[data-submenu-id]");
|
|
1201
|
+
const closestId = closestElement?.getAttribute("data-submenu-id");
|
|
749
1202
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
const closestElement = element.closest("[data-submenu-id]");
|
|
753
|
-
const id = closestElement?.getAttribute("data-submenu-id");
|
|
754
|
-
if (id) {
|
|
755
|
-
submenuId = id;
|
|
756
|
-
}
|
|
1203
|
+
if (closestId) {
|
|
1204
|
+
submenuId = closestId;
|
|
757
1205
|
}
|
|
758
1206
|
|
|
759
|
-
// If not found, try props
|
|
760
1207
|
if (!submenuId) {
|
|
761
|
-
submenuId =
|
|
762
|
-
((props as Record<string, unknown>)["data-parent-submenu-id"] as string)
|
|
763
|
-
|| ((props as Record<string, unknown>)["data-parent-submenu"] as string);
|
|
1208
|
+
submenuId = props["data-parent-submenu-id"] ?? props["data-parent-submenu"] ?? null;
|
|
764
1209
|
}
|
|
765
1210
|
|
|
766
1211
|
if (!submenuId) {
|
|
767
1212
|
return;
|
|
768
1213
|
}
|
|
769
1214
|
|
|
770
|
-
|
|
771
|
-
|
|
1215
|
+
const title = typeof children === "string" ? children : MOBILE_SUBMENU_TITLE;
|
|
1216
|
+
navigateToSubmenu?.(submenuId, title);
|
|
1217
|
+
};
|
|
772
1218
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
1219
|
+
const handleClick: React.MouseEventHandler<HTMLDivElement> = (event): void => {
|
|
1220
|
+
event.preventDefault();
|
|
1221
|
+
event.stopPropagation();
|
|
1222
|
+
onClick?.(event);
|
|
1223
|
+
navigate(event.currentTarget);
|
|
777
1224
|
};
|
|
778
1225
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
const typedProps = props as Record<string, unknown>;
|
|
783
|
-
if (typedProps["onClick"]) {
|
|
784
|
-
const originalOnClick = typedProps["onClick"] as React.MouseEventHandler<HTMLDivElement>;
|
|
785
|
-
originalOnClick(e as React.MouseEvent<HTMLDivElement>);
|
|
1226
|
+
const handleKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event): void => {
|
|
1227
|
+
if (event.key !== "Enter" && event.key !== " ") {
|
|
1228
|
+
return;
|
|
786
1229
|
}
|
|
787
1230
|
|
|
788
|
-
|
|
789
|
-
|
|
1231
|
+
event.preventDefault();
|
|
1232
|
+
event.stopPropagation();
|
|
1233
|
+
event.currentTarget.click();
|
|
790
1234
|
};
|
|
791
1235
|
|
|
792
|
-
// Remove onClick from props to avoid duplicate handlers
|
|
793
|
-
const {...restProps} = props as Record<string, unknown>;
|
|
794
|
-
|
|
795
|
-
// Don't wrap in DrawerClose for submenu triggers
|
|
796
1236
|
return (
|
|
797
1237
|
<div
|
|
798
1238
|
ref={itemRef}
|
|
799
1239
|
data-slot='drop-drawer-sub-trigger'
|
|
800
1240
|
data-inset={inset}
|
|
1241
|
+
role='menuitem'
|
|
1242
|
+
tabIndex={0}
|
|
801
1243
|
className={cn(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
isInsideGroup && "bg-transparent py-4",
|
|
807
|
-
inset && "pl-8",
|
|
1244
|
+
styles.mobileItem,
|
|
1245
|
+
!isInsideGroup && styles.mobileStandaloneItem,
|
|
1246
|
+
isInsideGroup && styles.mobileGroupedItem,
|
|
1247
|
+
inset && styles.inset,
|
|
808
1248
|
className,
|
|
809
1249
|
)}
|
|
810
|
-
onClick={
|
|
811
|
-
{
|
|
812
|
-
|
|
813
|
-
<
|
|
1250
|
+
onClick={handleClick}
|
|
1251
|
+
onKeyDown={handleKeyDown}
|
|
1252
|
+
{...props}>
|
|
1253
|
+
<div className={styles.itemChildren}>{children}</div>
|
|
1254
|
+
<ChevronRightIcon className={styles.chevron} />
|
|
814
1255
|
</div>
|
|
815
1256
|
);
|
|
816
1257
|
}
|
|
@@ -821,18 +1262,38 @@ function DropDrawerSubTrigger({
|
|
|
821
1262
|
data-inset={inset}
|
|
822
1263
|
className={className}
|
|
823
1264
|
inset={inset}
|
|
1265
|
+
onClick={onClick}
|
|
824
1266
|
{...props}>
|
|
825
1267
|
{children}
|
|
826
1268
|
</DropdownMenuSubTrigger>
|
|
827
1269
|
);
|
|
828
1270
|
}
|
|
829
1271
|
|
|
830
|
-
|
|
1272
|
+
/**
|
|
1273
|
+
* Renders the content region for a nested submenu.
|
|
1274
|
+
*
|
|
1275
|
+
* @remarks
|
|
1276
|
+
* - Renders only in desktop dropdown mode
|
|
1277
|
+
* - Built on Base UI Menu submenu popup primitives
|
|
1278
|
+
*
|
|
1279
|
+
* @example
|
|
1280
|
+
* ```tsx
|
|
1281
|
+
* <DropDrawerSubContent>
|
|
1282
|
+
* <DropDrawerItem>Details</DropDrawerItem>
|
|
1283
|
+
* </DropDrawerSubContent>
|
|
1284
|
+
* ```
|
|
1285
|
+
*
|
|
1286
|
+
* @see {@link https://base-ui.com/react/components/menu | Base UI Menu Docs}
|
|
1287
|
+
*/
|
|
1288
|
+
function DropDrawerSubContent({
|
|
1289
|
+
className,
|
|
1290
|
+
sideOffset = 4,
|
|
1291
|
+
children,
|
|
1292
|
+
...props
|
|
1293
|
+
}: React.ComponentProps<typeof DropdownMenuSubContent>): React.JSX.Element | null {
|
|
831
1294
|
const {isMobile} = useDropDrawerContext();
|
|
832
1295
|
|
|
833
1296
|
if (isMobile) {
|
|
834
|
-
// For mobile, we don't render the content directly
|
|
835
|
-
// It will be rendered by the DropDrawerContent component when active
|
|
836
1297
|
return null;
|
|
837
1298
|
}
|
|
838
1299
|
|
|
@@ -840,16 +1301,25 @@ function DropDrawerSubContent({className, sideOffset = 4, children, ...props}: R
|
|
|
840
1301
|
<DropdownMenuSubContent
|
|
841
1302
|
data-slot='drop-drawer-sub-content'
|
|
842
1303
|
sideOffset={sideOffset}
|
|
843
|
-
className={cn(
|
|
844
|
-
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-neutral-200 p-1 shadow-lg dark:border-neutral-800",
|
|
845
|
-
className,
|
|
846
|
-
)}
|
|
1304
|
+
className={cn(styles.dropdownSubContent, className)}
|
|
847
1305
|
{...props}>
|
|
848
1306
|
{children}
|
|
849
1307
|
</DropdownMenuSubContent>
|
|
850
1308
|
);
|
|
851
1309
|
}
|
|
852
1310
|
|
|
1311
|
+
DropDrawer.displayName = "DropDrawer";
|
|
1312
|
+
DropDrawerTrigger.displayName = "DropDrawerTrigger";
|
|
1313
|
+
DropDrawerContent.displayName = "DropDrawerContent";
|
|
1314
|
+
DropDrawerItem.displayName = "DropDrawerItem";
|
|
1315
|
+
DropDrawerSeparator.displayName = "DropDrawerSeparator";
|
|
1316
|
+
DropDrawerLabel.displayName = "DropDrawerLabel";
|
|
1317
|
+
DropDrawerFooter.displayName = "DropDrawerFooter";
|
|
1318
|
+
DropDrawerGroup.displayName = "DropDrawerGroup";
|
|
1319
|
+
DropDrawerSub.displayName = "DropDrawerSub";
|
|
1320
|
+
DropDrawerSubTrigger.displayName = "DropDrawerSubTrigger";
|
|
1321
|
+
DropDrawerSubContent.displayName = "DropDrawerSubContent";
|
|
1322
|
+
|
|
853
1323
|
export {
|
|
854
1324
|
DropDrawer,
|
|
855
1325
|
DropDrawerContent,
|