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