@glyphui/ui 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -12
- package/dist/chart.d.ts +14 -202
- package/dist/chart.js +14 -456
- package/dist/components/accordion/accordion.d.ts +15 -0
- package/dist/components/accordion/accordion.js +69 -0
- package/dist/components/accordion/accordion.styles.d.ts +65 -0
- package/dist/components/accordion/accordion.styles.js +30 -0
- package/dist/components/accordion/index.d.ts +3 -0
- package/dist/components/alert/alert-icons.js +62 -0
- package/dist/components/alert/alert.d.ts +19 -0
- package/dist/components/alert/alert.js +64 -0
- package/dist/components/alert/alert.styles.d.ts +107 -0
- package/dist/components/alert/alert.styles.js +86 -0
- package/dist/components/alert/index.d.ts +3 -0
- package/dist/components/alert-dialog/alert-dialog.d.ts +29 -0
- package/dist/components/alert-dialog/alert-dialog.js +89 -0
- package/dist/components/alert-dialog/alert-dialog.styles.d.ts +63 -0
- package/dist/components/alert-dialog/alert-dialog.styles.js +19 -0
- package/dist/components/alert-dialog/confirm-dialog.js +22 -0
- package/dist/components/alert-dialog/confirm.d.ts +30 -0
- package/dist/components/alert-dialog/confirm.js +62 -0
- package/dist/components/alert-dialog/index.d.ts +4 -0
- package/dist/components/aspect-ratio/aspect-ratio.d.ts +55 -0
- package/dist/components/aspect-ratio/aspect-ratio.js +28 -0
- package/dist/components/aspect-ratio/index.d.ts +2 -0
- package/dist/components/avatar/avatar.d.ts +13 -0
- package/dist/components/avatar/avatar.js +50 -0
- package/dist/components/avatar/avatar.styles.d.ts +77 -0
- package/dist/components/avatar/avatar.styles.js +32 -0
- package/dist/components/avatar/index.d.ts +3 -0
- package/dist/components/badge/badge.d.ts +10 -0
- package/dist/components/badge/badge.js +28 -0
- package/dist/components/badge/badge.styles.d.ts +62 -0
- package/dist/components/badge/badge.styles.js +72 -0
- package/dist/components/badge/index.d.ts +3 -0
- package/dist/components/banner/banner.d.ts +17 -0
- package/dist/components/banner/banner.js +71 -0
- package/dist/components/banner/banner.styles.d.ts +98 -0
- package/dist/components/banner/banner.styles.js +27 -0
- package/dist/components/banner/index.d.ts +3 -0
- package/dist/components/blockquote/blockquote.d.ts +72 -0
- package/dist/components/blockquote/blockquote.js +47 -0
- package/dist/components/blockquote/index.d.ts +2 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +28 -0
- package/dist/components/breadcrumb/breadcrumb.js +85 -0
- package/dist/components/breadcrumb/breadcrumb.styles.d.ts +63 -0
- package/dist/components/breadcrumb/breadcrumb.styles.js +18 -0
- package/dist/components/breadcrumb/index.d.ts +3 -0
- package/dist/components/button/button.d.ts +20 -0
- package/dist/components/button/button.js +52 -0
- package/dist/components/button/button.styles.d.ts +146 -0
- package/dist/components/button/button.styles.js +64 -0
- package/dist/components/button/index.d.ts +3 -0
- package/dist/components/calendar/calendar.d.ts +9 -0
- package/dist/components/calendar/calendar.js +75 -0
- package/dist/components/calendar/calendar.styles.d.ts +171 -0
- package/dist/components/calendar/calendar.styles.js +42 -0
- package/dist/components/calendar/index.d.ts +4 -0
- package/dist/components/card/card.d.ts +17 -0
- package/dist/components/card/card.js +79 -0
- package/dist/components/card/card.styles.d.ts +113 -0
- package/dist/components/card/card.styles.js +38 -0
- package/dist/components/card/index.d.ts +3 -0
- package/dist/components/carousel/carousel.d.ts +37 -0
- package/dist/components/carousel/carousel.js +190 -0
- package/dist/components/carousel/carousel.styles.d.ts +74 -0
- package/dist/components/carousel/carousel.styles.js +35 -0
- package/dist/components/carousel/index.d.ts +3 -0
- package/dist/components/checkbox/checkbox.d.ts +37 -0
- package/dist/components/checkbox/checkbox.js +44 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/code/code.d.ts +18 -0
- package/dist/components/code/code.js +75 -0
- package/dist/components/code/code.styles.d.ts +76 -0
- package/dist/components/code/code.styles.js +18 -0
- package/dist/components/code/index.d.ts +3 -0
- package/dist/components/collapsible/collapsible.d.ts +56 -0
- package/dist/components/collapsible/collapsible.js +43 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/combobox/combobox.d.ts +50 -0
- package/dist/components/combobox/combobox.js +141 -0
- package/dist/components/combobox/combobox.styles.d.ts +110 -0
- package/dist/components/combobox/combobox.styles.js +42 -0
- package/dist/components/combobox/index.d.ts +3 -0
- package/dist/components/command-menu/command-menu.d.ts +40 -0
- package/dist/components/command-menu/command-menu.js +148 -0
- package/dist/components/command-menu/command-menu.styles.d.ts +105 -0
- package/dist/components/command-menu/command-menu.styles.js +30 -0
- package/dist/components/command-menu/index.d.ts +3 -0
- package/dist/components/container/container.d.ts +34 -0
- package/dist/components/container/container.js +30 -0
- package/dist/components/container/index.d.ts +2 -0
- package/dist/components/context-menu/context-menu.d.ts +34 -0
- package/dist/components/context-menu/context-menu.js +157 -0
- package/dist/components/context-menu/context-menu.styles.d.ts +135 -0
- package/dist/components/context-menu/context-menu.styles.js +14 -0
- package/dist/components/context-menu/index.d.ts +3 -0
- package/dist/components/copy-button/copy-button.d.ts +61 -0
- package/dist/components/copy-button/copy-button.js +79 -0
- package/dist/components/copy-button/index.d.ts +2 -0
- package/dist/components/date-picker/date-picker.d.ts +51 -0
- package/dist/components/date-picker/date-picker.js +235 -0
- package/dist/components/date-picker/date-picker.styles.d.ts +77 -0
- package/dist/components/date-picker/date-picker.styles.js +31 -0
- package/dist/components/date-picker/index.d.ts +3 -0
- package/dist/components/description-list/description-list.d.ts +15 -0
- package/dist/components/description-list/description-list.js +51 -0
- package/dist/components/description-list/description-list.styles.d.ts +74 -0
- package/dist/components/description-list/description-list.styles.js +35 -0
- package/dist/components/description-list/index.d.ts +3 -0
- package/dist/components/dialog/close-icon.js +22 -0
- package/dist/components/dialog/dialog.d.ts +21 -0
- package/dist/components/dialog/dialog.js +79 -0
- package/dist/components/dialog/dialog.styles.d.ts +83 -0
- package/dist/components/dialog/dialog.styles.js +34 -0
- package/dist/components/dialog/index.d.ts +3 -0
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +34 -0
- package/dist/components/dropdown-menu/dropdown-menu.js +160 -0
- package/dist/components/dropdown-menu/dropdown-menu.styles.d.ts +83 -0
- package/dist/components/dropdown-menu/dropdown-menu.styles.js +38 -0
- package/dist/components/dropdown-menu/index.d.ts +3 -0
- package/dist/components/eyebrow/eyebrow.d.ts +9 -0
- package/dist/components/eyebrow/eyebrow.js +20 -0
- package/dist/components/eyebrow/eyebrow.styles.d.ts +38 -0
- package/dist/components/eyebrow/eyebrow.styles.js +13 -0
- package/dist/components/eyebrow/index.d.ts +3 -0
- package/dist/components/field/field-context.d.ts +25 -0
- package/dist/components/field/field-context.js +27 -0
- package/dist/components/field/field.d.ts +28 -0
- package/dist/{field-CWZ_FdkD.js → components/field/field.js} +20 -34
- package/dist/components/field/field.styles.d.ts +53 -0
- package/dist/components/field/field.styles.js +22 -0
- package/dist/components/field/index.d.ts +4 -0
- package/dist/components/file-upload/file-upload.d.ts +52 -0
- package/dist/components/file-upload/file-upload.js +266 -0
- package/dist/components/file-upload/file-upload.styles.d.ts +123 -0
- package/dist/components/file-upload/file-upload.styles.js +32 -0
- package/dist/components/file-upload/index.d.ts +3 -0
- package/dist/components/grid/grid.d.ts +168 -0
- package/dist/components/grid/grid.js +126 -0
- package/dist/components/grid/index.d.ts +2 -0
- package/dist/components/heading/heading.d.ts +12 -0
- package/dist/components/heading/heading.js +28 -0
- package/dist/components/heading/heading.styles.d.ts +65 -0
- package/dist/components/heading/heading.styles.js +15 -0
- package/dist/components/heading/index.d.ts +3 -0
- package/dist/components/hover-card/hover-card.d.ts +43 -0
- package/dist/components/hover-card/hover-card.js +27 -0
- package/dist/components/hover-card/index.d.ts +2 -0
- package/dist/components/input/index.d.ts +3 -0
- package/dist/components/input/input.d.ts +13 -0
- package/dist/components/input/input.js +33 -0
- package/dist/components/input/input.styles.d.ts +55 -0
- package/dist/components/input/input.styles.js +33 -0
- package/dist/components/input-otp/index.d.ts +4 -0
- package/dist/components/input-otp/index.js +5 -0
- package/dist/components/input-otp/input-otp.d.ts +23 -0
- package/dist/components/input-otp/input-otp.js +86 -0
- package/dist/components/input-otp/input-otp.styles.d.ts +71 -0
- package/dist/components/input-otp/input-otp.styles.js +30 -0
- package/dist/components/kbd/index.d.ts +2 -0
- package/dist/components/kbd/kbd.d.ts +30 -0
- package/dist/components/kbd/kbd.js +17 -0
- package/dist/components/label/index.d.ts +2 -0
- package/dist/components/label/label.d.ts +31 -0
- package/dist/components/label/label.js +17 -0
- package/dist/components/link/index.d.ts +3 -0
- package/dist/components/link/link.d.ts +14 -0
- package/dist/components/link/link.js +57 -0
- package/dist/components/link/link.styles.d.ts +89 -0
- package/dist/components/link/link.styles.js +33 -0
- package/dist/components/modal/index.d.ts +3 -0
- package/dist/components/modal/modal.d.ts +33 -0
- package/dist/components/modal/modal.js +56 -0
- package/dist/components/modal/modal.styles.d.ts +61 -0
- package/dist/components/modal/modal.styles.js +14 -0
- package/dist/components/navigation-menu/index.d.ts +3 -0
- package/dist/components/navigation-menu/navigation-menu.d.ts +37 -0
- package/dist/components/navigation-menu/navigation-menu.js +138 -0
- package/dist/components/navigation-menu/navigation-menu.styles.d.ts +111 -0
- package/dist/components/navigation-menu/navigation-menu.styles.js +39 -0
- package/dist/components/number-input/index.d.ts +3 -0
- package/dist/components/number-input/number-input.d.ts +30 -0
- package/dist/components/number-input/number-input.js +151 -0
- package/dist/components/number-input/number-input.styles.d.ts +68 -0
- package/dist/components/number-input/number-input.styles.js +35 -0
- package/dist/components/pagination/index.d.ts +4 -0
- package/dist/components/pagination/pagination-range.d.ts +11 -0
- package/dist/components/pagination/pagination-range.js +42 -0
- package/dist/components/pagination/pagination.d.ts +18 -0
- package/dist/components/pagination/pagination.js +94 -0
- package/dist/components/pagination/pagination.styles.d.ts +65 -0
- package/dist/components/pagination/pagination.styles.js +35 -0
- package/dist/components/password-input/index.d.ts +3 -0
- package/dist/components/password-input/password-input.d.ts +20 -0
- package/dist/components/password-input/password-input.js +106 -0
- package/dist/components/password-input/password-input.styles.d.ts +66 -0
- package/dist/components/password-input/password-input.styles.js +21 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/popover.d.ts +52 -0
- package/dist/components/popover/popover.js +35 -0
- package/dist/components/progress/index.d.ts +3 -0
- package/dist/components/progress/progress.d.ts +29 -0
- package/dist/components/progress/progress.js +108 -0
- package/dist/components/progress/progress.styles.d.ts +236 -0
- package/dist/components/progress/progress.styles.js +69 -0
- package/dist/components/prose/index.d.ts +2 -0
- package/dist/components/prose/prose.d.ts +90 -0
- package/dist/components/prose/prose.js +67 -0
- package/dist/components/radio-group/index.d.ts +3 -0
- package/dist/components/radio-group/radio-group.d.ts +26 -0
- package/dist/components/radio-group/radio-group.js +102 -0
- package/dist/components/radio-group/radio-group.styles.d.ts +80 -0
- package/dist/components/radio-group/radio-group.styles.js +56 -0
- package/dist/components/resizable/index.d.ts +3 -0
- package/dist/components/resizable/resizable.d.ts +17 -0
- package/dist/components/resizable/resizable.js +81 -0
- package/dist/components/resizable/resizable.styles.d.ts +53 -0
- package/dist/components/resizable/resizable.styles.js +19 -0
- package/dist/components/scroll-area/index.d.ts +2 -0
- package/dist/components/scroll-area/scroll-area.d.ts +70 -0
- package/dist/components/scroll-area/scroll-area.js +70 -0
- package/dist/components/section/index.d.ts +2 -0
- package/dist/components/section/section.d.ts +52 -0
- package/dist/components/section/section.js +41 -0
- package/dist/components/segmented-control/index.d.ts +2 -0
- package/dist/components/segmented-control/segmented-control.d.ts +92 -0
- package/dist/components/segmented-control/segmented-control.js +86 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/select.d.ts +85 -0
- package/dist/components/select/select.js +81 -0
- package/dist/components/separator/index.d.ts +2 -0
- package/dist/components/separator/separator.d.ts +40 -0
- package/dist/components/separator/separator.js +27 -0
- package/dist/components/sheet/index.d.ts +3 -0
- package/dist/components/sheet/sheet.d.ts +20 -0
- package/dist/components/sheet/sheet.js +83 -0
- package/dist/components/sheet/sheet.styles.d.ts +101 -0
- package/dist/components/sheet/sheet.styles.js +62 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/skeleton.d.ts +30 -0
- package/dist/components/skeleton/skeleton.js +18 -0
- package/dist/components/slider/index.d.ts +3 -0
- package/dist/components/slider/slider.d.ts +38 -0
- package/dist/components/slider/slider.js +68 -0
- package/dist/components/slider/slider.styles.d.ts +56 -0
- package/dist/components/slider/slider.styles.js +23 -0
- package/dist/components/spinner/index.d.ts +3 -0
- package/dist/components/spinner/spinner.d.ts +9 -0
- package/dist/components/spinner/spinner.js +36 -0
- package/dist/components/spinner/spinner.styles.d.ts +53 -0
- package/dist/components/spinner/spinner.styles.js +18 -0
- package/dist/components/stack/index.d.ts +2 -0
- package/dist/components/stack/stack.d.ts +109 -0
- package/dist/components/stack/stack.js +62 -0
- package/dist/components/stat-card/index.d.ts +3 -0
- package/dist/components/stat-card/stat-card.d.ts +22 -0
- package/dist/components/stat-card/stat-card.js +82 -0
- package/dist/components/stat-card/stat-card.styles.d.ts +83 -0
- package/dist/components/stat-card/stat-card.styles.js +16 -0
- package/dist/components/stepper/index.d.ts +3 -0
- package/dist/components/stepper/stepper.d.ts +20 -0
- package/dist/components/stepper/stepper.js +100 -0
- package/dist/components/stepper/stepper.styles.d.ts +170 -0
- package/dist/components/stepper/stepper.styles.js +67 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/switch.d.ts +51 -0
- package/dist/components/switch/switch.js +43 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/table.d.ts +78 -0
- package/dist/components/table/table.js +82 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/tabs.d.ts +73 -0
- package/dist/components/tabs/tabs.js +103 -0
- package/dist/components/tag-input/index.d.ts +3 -0
- package/dist/components/tag-input/tag-input.d.ts +30 -0
- package/dist/components/tag-input/tag-input.js +149 -0
- package/dist/components/tag-input/tag-input.styles.d.ts +71 -0
- package/dist/components/tag-input/tag-input.styles.js +29 -0
- package/dist/components/text/index.d.ts +3 -0
- package/dist/components/text/text.d.ts +9 -0
- package/dist/components/text/text.js +25 -0
- package/dist/components/text/text.styles.d.ts +188 -0
- package/dist/components/text/text.styles.js +36 -0
- package/dist/components/textarea/index.d.ts +2 -0
- package/dist/components/textarea/textarea.d.ts +29 -0
- package/dist/components/textarea/textarea.js +23 -0
- package/dist/components/timeline/index.d.ts +3 -0
- package/dist/components/timeline/timeline.d.ts +28 -0
- package/dist/components/timeline/timeline.js +61 -0
- package/dist/components/timeline/timeline.styles.d.ts +110 -0
- package/dist/components/timeline/timeline.styles.js +30 -0
- package/dist/components/toast/index.d.ts +2 -0
- package/dist/components/toast/toast.d.ts +119 -0
- package/dist/components/toast/toast.js +75 -0
- package/dist/components/toggle/index.d.ts +3 -0
- package/dist/components/toggle/toggle.d.ts +20 -0
- package/dist/components/toggle/toggle.js +58 -0
- package/dist/components/toggle/toggle.styles.d.ts +80 -0
- package/dist/components/toggle/toggle.styles.js +34 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/tooltip.d.ts +39 -0
- package/dist/components/tooltip/tooltip.js +29 -0
- package/dist/components/tree-view/index.d.ts +3 -0
- package/dist/components/tree-view/tree-view.d.ts +31 -0
- package/dist/components/tree-view/tree-view.js +192 -0
- package/dist/components/tree-view/tree-view.styles.d.ts +59 -0
- package/dist/components/tree-view/tree-view.styles.js +32 -0
- package/dist/components/visually-hidden/index.d.ts +2 -0
- package/dist/components/visually-hidden/visually-hidden.d.ts +10 -0
- package/dist/components/visually-hidden/visually-hidden.js +16 -0
- package/dist/data-table.d.ts +3 -110
- package/dist/data-table.js +2 -224
- package/dist/form.d.ts +2 -79
- package/dist/form.js +1 -83
- package/dist/hooks/index.d.ts +5 -0
- package/dist/hooks/use-component-config.d.ts +13 -0
- package/dist/hooks/use-component-config.js +22 -0
- package/dist/hooks/use-controllable-state.d.ts +9 -0
- package/dist/hooks/use-controllable-state.js +18 -0
- package/dist/hooks/use-media-query.d.ts +4 -0
- package/dist/hooks/use-media-query.js +13 -0
- package/dist/hooks/use-scrolled.d.ts +4 -0
- package/dist/hooks/use-scrolled.js +17 -0
- package/dist/index.d.ts +223 -6849
- package/dist/index.js +148 -6718
- package/dist/internal/dev.js +12 -0
- package/dist/internal/icons.js +91 -0
- package/dist/motion/active-indicator.d.ts +12 -0
- package/dist/motion/active-indicator.js +26 -0
- package/dist/motion/animated-number.d.ts +21 -0
- package/dist/motion/animated-number.js +88 -0
- package/dist/motion/features.js +10 -0
- package/dist/motion/index.d.ts +10 -0
- package/dist/motion/index.js +10 -0
- package/dist/motion/motion-root.js +48 -0
- package/dist/motion/page-transition.d.ts +16 -0
- package/dist/motion/page-transition.js +23 -0
- package/dist/motion/presence-list.js +46 -0
- package/dist/motion/presence.d.ts +11 -0
- package/dist/motion/presence.js +17 -0
- package/dist/motion/reveal.d.ts +18 -0
- package/dist/motion/reveal.js +37 -0
- package/dist/motion/stagger.d.ts +29 -0
- package/dist/motion/stagger.js +52 -0
- package/dist/motion/use-motion-settings.d.ts +25 -0
- package/dist/motion/use-motion-settings.js +47 -0
- package/dist/motion/use-reveal.d.ts +11 -0
- package/dist/motion/use-reveal.js +41 -0
- package/dist/patterns/app-shell/app-shell-context.d.ts +14 -0
- package/dist/patterns/app-shell/app-shell-context.js +16 -0
- package/dist/patterns/app-shell/app-shell.d.ts +21 -0
- package/dist/patterns/app-shell/app-shell.js +82 -0
- package/dist/patterns/app-shell/app-shell.styles.d.ts +302 -0
- package/dist/patterns/app-shell/app-shell.styles.js +106 -0
- package/dist/patterns/app-shell/index.d.ts +7 -0
- package/dist/patterns/app-shell/navbar.d.ts +29 -0
- package/dist/patterns/app-shell/navbar.js +116 -0
- package/dist/patterns/app-shell/page-header.d.ts +12 -0
- package/dist/patterns/app-shell/page-header.js +38 -0
- package/dist/patterns/app-shell/sidebar.d.ts +31 -0
- package/dist/patterns/app-shell/sidebar.js +141 -0
- package/dist/patterns/async/async.d.ts +40 -0
- package/dist/patterns/async/async.js +61 -0
- package/dist/patterns/async/index.d.ts +3 -0
- package/dist/patterns/async/states.d.ts +68 -0
- package/dist/patterns/async/states.js +116 -0
- package/dist/patterns/chart/cartesian.d.ts +128 -0
- package/dist/patterns/chart/cartesian.js +552 -0
- package/dist/patterns/chart/chart-card.d.ts +39 -0
- package/dist/patterns/chart/chart-card.js +103 -0
- package/dist/patterns/chart/chart-parts.d.ts +53 -0
- package/dist/patterns/chart/chart-parts.js +282 -0
- package/dist/patterns/chart/chart.styles.d.ts +200 -0
- package/dist/patterns/chart/chart.styles.js +43 -0
- package/dist/patterns/chart/export.d.ts +45 -0
- package/dist/patterns/chart/export.js +293 -0
- package/dist/patterns/chart/funnel.d.ts +23 -0
- package/dist/patterns/chart/funnel.js +129 -0
- package/dist/patterns/chart/heatmap.d.ts +37 -0
- package/dist/patterns/chart/heatmap.js +258 -0
- package/dist/patterns/chart/icons.js +39 -0
- package/dist/patterns/chart/pie.d.ts +36 -0
- package/dist/patterns/chart/pie.js +120 -0
- package/dist/patterns/chart/radial.d.ts +75 -0
- package/dist/patterns/chart/radial.js +282 -0
- package/dist/patterns/chart/sankey.d.ts +29 -0
- package/dist/patterns/chart/sankey.js +136 -0
- package/dist/patterns/chart/scatter.d.ts +42 -0
- package/dist/patterns/chart/scatter.js +203 -0
- package/dist/patterns/chart/sparkline.d.ts +20 -0
- package/dist/patterns/chart/sparkline.js +102 -0
- package/dist/patterns/chart/treemap.d.ts +25 -0
- package/dist/patterns/chart/treemap.js +128 -0
- package/dist/patterns/chart/use-element-width.js +23 -0
- package/dist/patterns/data-table/data-table.d.ts +109 -0
- package/dist/patterns/data-table/data-table.js +233 -0
- package/dist/patterns/form/form.d.ts +89 -0
- package/dist/patterns/form/form.js +111 -0
- package/dist/provider/color-mode-script.d.ts +15 -0
- package/dist/provider/color-mode-script.js +13 -0
- package/dist/provider/color-mode.d.ts +24 -0
- package/dist/provider/color-mode.js +87 -0
- package/dist/provider/glyph-context.d.ts +51 -0
- package/dist/provider/glyph-context.js +28 -0
- package/dist/provider/glyph-provider.d.ts +37 -0
- package/dist/provider/glyph-provider.js +48 -0
- package/dist/provider/index.d.ts +6 -0
- package/dist/provider/theme-scope.d.ts +12 -0
- package/dist/provider/theme-scope.js +42 -0
- package/dist/provider/theme-style.js +15 -0
- package/dist/react-router.d.ts +18 -0
- package/dist/react-router.js +44 -0
- package/dist/register.d.ts +57 -0
- package/dist/themes.d.ts +22 -0
- package/dist/themes.js +49 -0
- package/dist/utils/cn.d.ts +6 -0
- package/dist/utils/cn.js +12 -0
- package/dist/utils/compose-refs.js +11 -0
- package/dist/{registry-BGSJoiLq.d.ts → utils/registry.d.ts} +2 -3
- package/dist/utils/styles.js +20 -0
- package/dist/{tv-DuMh7UH2.d.ts → utils/tv.d.ts} +2 -2
- package/dist/utils/tv.js +8 -0
- package/dist/utils/tw-merge-config.js +13 -0
- package/dist/vite.d.ts +27 -0
- package/dist/vite.js +29 -0
- package/fonts.css +10 -0
- package/package.json +33 -5
- package/src/components/accordion/accordion.styles.ts +1 -1
- package/src/components/alert/alert.styles.ts +1 -1
- package/src/components/alert-dialog/alert-dialog.styles.ts +5 -4
- package/src/components/alert-dialog/confirm-dialog.tsx +42 -0
- package/src/components/alert-dialog/confirm.tsx +12 -31
- package/src/components/aspect-ratio/aspect-ratio.tsx +1 -1
- package/src/components/avatar/avatar.styles.ts +1 -1
- package/src/components/badge/badge.styles.ts +12 -17
- package/src/components/banner/banner.styles.ts +5 -5
- package/src/components/blockquote/blockquote.tsx +1 -1
- package/src/components/breadcrumb/breadcrumb.styles.ts +1 -1
- package/src/components/button/button.styles.ts +6 -2
- package/src/components/calendar/calendar.styles.ts +4 -3
- package/src/components/card/card.styles.ts +1 -1
- package/src/components/carousel/carousel.styles.ts +1 -1
- package/src/components/checkbox/checkbox.tsx +20 -5
- package/src/components/code/code.styles.ts +2 -2
- package/src/components/collapsible/collapsible.tsx +1 -1
- package/src/components/combobox/combobox.styles.ts +5 -2
- package/src/components/command-menu/command-menu.styles.ts +6 -4
- package/src/components/container/container.tsx +1 -1
- package/src/components/context-menu/context-menu.styles.ts +4 -2
- package/src/components/copy-button/copy-button.tsx +1 -1
- package/src/components/date-picker/date-picker.styles.ts +2 -2
- package/src/components/description-list/description-list.styles.ts +1 -1
- package/src/components/dialog/dialog.styles.ts +11 -4
- package/src/components/dropdown-menu/dropdown-menu.styles.ts +5 -5
- package/src/components/eyebrow/eyebrow.styles.ts +2 -2
- package/src/components/field/field-context.ts +2 -0
- package/src/components/field/field.styles.ts +5 -3
- package/src/components/field/field.tsx +25 -4
- package/src/components/file-upload/file-upload.styles.ts +4 -4
- package/src/components/file-upload/file-upload.tsx +51 -48
- package/src/components/grid/grid.tsx +1 -1
- package/src/components/heading/heading.styles.ts +1 -1
- package/src/components/hover-card/hover-card.tsx +5 -2
- package/src/components/input/input.styles.ts +1 -1
- package/src/components/input-otp/input-otp.styles.ts +1 -1
- package/src/components/kbd/kbd.tsx +1 -1
- package/src/components/label/label.tsx +1 -1
- package/src/components/link/link.styles.ts +2 -2
- package/src/components/modal/modal.styles.ts +3 -1
- package/src/components/modal/modal.tsx +30 -5
- package/src/components/navigation-menu/navigation-menu.styles.ts +2 -2
- package/src/components/navigation-menu/navigation-menu.tsx +14 -4
- package/src/components/number-input/number-input.styles.ts +1 -1
- package/src/components/pagination/pagination.styles.ts +6 -4
- package/src/components/pagination/pagination.tsx +14 -1
- package/src/components/password-input/password-input.styles.ts +4 -4
- package/src/components/popover/popover.tsx +1 -1
- package/src/components/progress/progress.styles.ts +2 -2
- package/src/components/prose/prose.tsx +2 -2
- package/src/components/radio-group/radio-group.styles.ts +1 -1
- package/src/components/resizable/resizable.styles.ts +1 -1
- package/src/components/scroll-area/scroll-area.tsx +24 -2
- package/src/components/section/section.tsx +1 -1
- package/src/components/segmented-control/segmented-control.tsx +40 -9
- package/src/components/select/select.tsx +2 -2
- package/src/components/separator/separator.tsx +1 -1
- package/src/components/sheet/sheet.styles.ts +1 -1
- package/src/components/skeleton/skeleton.tsx +1 -1
- package/src/components/slider/slider.styles.ts +1 -1
- package/src/components/slider/slider.tsx +9 -2
- package/src/components/spinner/spinner.styles.ts +1 -1
- package/src/components/stack/stack.tsx +1 -1
- package/src/components/stat-card/stat-card.styles.ts +1 -1
- package/src/components/stepper/stepper.styles.ts +3 -3
- package/src/components/switch/switch.tsx +2 -2
- package/src/components/table/table.tsx +1 -1
- package/src/components/tabs/tabs.tsx +46 -15
- package/src/components/tag-input/tag-input.styles.ts +2 -2
- package/src/components/tag-input/tag-input.tsx +27 -18
- package/src/components/text/text.styles.ts +5 -5
- package/src/components/textarea/textarea.tsx +1 -1
- package/src/components/timeline/timeline.styles.ts +1 -1
- package/src/components/toast/toast.tsx +1 -1
- package/src/components/toggle/toggle.styles.ts +1 -1
- package/src/components/tooltip/tooltip.tsx +6 -3
- package/src/components/tree-view/tree-view.styles.ts +1 -1
- package/src/index.ts +3 -0
- package/src/integrations/react-router.tsx +39 -0
- package/src/integrations/vite.test-d.ts +6 -0
- package/src/integrations/vite.test.ts +28 -0
- package/src/integrations/vite.ts +33 -0
- package/src/internal/dev.ts +12 -0
- package/src/motion/active-indicator.tsx +26 -0
- package/src/motion/animated-number.tsx +113 -0
- package/src/motion/features.ts +7 -0
- package/src/motion/index.ts +9 -0
- package/src/motion/motion-root.tsx +46 -0
- package/src/motion/page-transition.tsx +30 -0
- package/src/motion/presence-list.tsx +42 -0
- package/src/motion/presence.tsx +13 -0
- package/src/motion/reveal.tsx +50 -0
- package/src/motion/stagger.tsx +81 -0
- package/src/motion/use-motion-settings.ts +52 -0
- package/src/motion/use-reveal.ts +54 -0
- package/src/patterns/app-shell/app-shell.styles.ts +19 -12
- package/src/patterns/app-shell/navbar.tsx +34 -16
- package/src/patterns/app-shell/sidebar.tsx +35 -9
- package/src/patterns/async/states.tsx +1 -1
- package/src/patterns/chart/cartesian.tsx +755 -0
- package/src/patterns/chart/chart-card.tsx +148 -0
- package/src/patterns/chart/chart-parts.tsx +330 -57
- package/src/patterns/chart/chart.styles.ts +29 -3
- package/src/patterns/chart/export.ts +334 -0
- package/src/patterns/chart/funnel.tsx +171 -0
- package/src/patterns/chart/heatmap.tsx +339 -0
- package/src/patterns/chart/icons.tsx +44 -0
- package/src/patterns/chart/index.ts +52 -7
- package/src/patterns/chart/pie.tsx +169 -0
- package/src/patterns/chart/radial.tsx +361 -0
- package/src/patterns/chart/sankey.tsx +197 -0
- package/src/patterns/chart/scatter.tsx +254 -0
- package/src/patterns/chart/sparkline.tsx +111 -0
- package/src/patterns/chart/test-utils.tsx +35 -0
- package/src/patterns/chart/treemap.tsx +198 -0
- package/src/patterns/chart/use-element-width.ts +20 -0
- package/src/patterns/data-table/data-table.tsx +1 -1
- package/src/patterns/form/form.tsx +49 -7
- package/src/patterns/form/index.ts +1 -0
- package/src/provider/color-mode-script.ts +28 -0
- package/src/provider/color-mode.tsx +14 -20
- package/src/provider/glyph-context.ts +41 -1
- package/src/provider/glyph-provider.tsx +45 -14
- package/src/provider/index.ts +4 -0
- package/src/provider/theme-scope.tsx +20 -11
- package/src/themes.ts +3 -3
- package/src/utils/styles.ts +17 -3
- package/styles.css +194 -3
- package/dist/field-context-anGPYXbW.js +0 -267
- package/dist/index-BWK4czIG.d.ts +0 -233
- package/dist/states-DR-OoDT-.js +0 -288
- package/dist/tv-DBAGlgXJ.js +0 -58
- package/src/patterns/chart/chart.tsx +0 -369
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ButtonProps } from "../../components/button/button.js";
|
|
2
|
+
import "../../components/button/index.js";
|
|
3
|
+
import { FieldProps } from "../../components/field/field.js";
|
|
4
|
+
import "../../components/field/index.js";
|
|
5
|
+
import { ComponentProps, ReactNode } from "react";
|
|
6
|
+
import { Control, ControllerRenderProps, FieldPath, FieldValues, UseFormProps, UseFormReturn } from "react-hook-form";
|
|
7
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
8
|
+
//#region src/patterns/form/form.d.ts
|
|
9
|
+
type AnySchema = StandardSchemaV1<FieldValues, FieldValues>;
|
|
10
|
+
type InputOf<S extends AnySchema> = StandardSchemaV1.InferInput<S>;
|
|
11
|
+
type OutputOf<S extends AnySchema> = StandardSchemaV1.InferOutput<S>;
|
|
12
|
+
export interface UseFormOptions<S extends AnySchema> extends Omit<UseFormProps<InputOf<S>, unknown, OutputOf<S>>, 'resolver'> {
|
|
13
|
+
/** Any Standard Schema validator: zod, valibot, arktype, ... */
|
|
14
|
+
schema: S;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* react-hook-form's `useForm`, validated by a schema. Field names and submitted values are
|
|
18
|
+
* typed from the schema.
|
|
19
|
+
*/
|
|
20
|
+
declare function useForm$1<S extends AnySchema>({ schema, ...options }: UseFormOptions<S>): UseFormReturn<InputOf<S>, unknown, OutputOf<S>>;
|
|
21
|
+
/** Field-level errors from the server, keyed by field name. `root` shows above the form. */
|
|
22
|
+
export type FormErrors<TInput extends FieldValues> = Partial<Record<FieldPath<TInput> | 'root', string>>;
|
|
23
|
+
export type SubmitResult<TInput extends FieldValues> = void | {
|
|
24
|
+
errors: FormErrors<TInput>;
|
|
25
|
+
};
|
|
26
|
+
export interface FormProps<TInput extends FieldValues, TOutput> extends Omit<ComponentProps<'form'>, 'onSubmit'> {
|
|
27
|
+
form: UseFormReturn<TInput, unknown, TOutput>;
|
|
28
|
+
/**
|
|
29
|
+
* Receives validated values. Return `{ errors }` to show server-side field errors, or throw
|
|
30
|
+
* to show a form-level error. The submit button shows a spinner until this settles.
|
|
31
|
+
*/
|
|
32
|
+
onSubmit: (values: TOutput) => SubmitResult<TInput> | Promise<SubmitResult<TInput>>;
|
|
33
|
+
}
|
|
34
|
+
export declare function Form<TInput extends FieldValues, TOutput>({ form, onSubmit, children, ref, ...props }: FormProps<TInput, TOutput>): import("react").JSX.Element;
|
|
35
|
+
export interface FormFieldProps<TInput extends FieldValues, TName extends FieldPath<TInput>> extends Omit<FieldProps, 'children' | 'error'> {
|
|
36
|
+
control: Control<TInput, unknown, any>;
|
|
37
|
+
/** Typed from the schema: a misspelled name is a compile error. */
|
|
38
|
+
name: TName;
|
|
39
|
+
/** Render the control and spread `field` onto it: `{(field) => <Input {...field} />}`. */
|
|
40
|
+
children: (field: ControllerRenderProps<TInput, TName>) => ReactNode;
|
|
41
|
+
}
|
|
42
|
+
/** One schema field: label, control, description and validation message, all wired. */
|
|
43
|
+
export declare function FormField<TInput extends FieldValues, TName extends FieldPath<TInput>>({ control, name, children, ...fieldProps }: FormFieldProps<TInput, TName>): import("react").JSX.Element;
|
|
44
|
+
export interface FormSubmitProps extends Omit<ButtonProps, 'type' | 'form'> {
|
|
45
|
+
/**
|
|
46
|
+
* The form to submit, for a button outside `<Form>` such as a Modal footer:
|
|
47
|
+
* `<FormSubmit form={form}>`. Not needed inside `<Form>`.
|
|
48
|
+
*/
|
|
49
|
+
form?: UseFormReturn<any, any, any>;
|
|
50
|
+
}
|
|
51
|
+
/** Submit button that shows progress while the form submits. */
|
|
52
|
+
export declare function FormSubmit({ form, onClick, ...props }: FormSubmitProps): import("react").JSX.Element;
|
|
53
|
+
export declare const formErrorStyles: import("tailwind-variants").TVReturnType<{
|
|
54
|
+
[key: string]: {
|
|
55
|
+
[key: string]: import("tailwind-variants").ClassValue | {
|
|
56
|
+
base?: import("tailwind-variants").ClassValue;
|
|
57
|
+
icon?: import("tailwind-variants").ClassValue;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
[x: string]: {
|
|
62
|
+
[x: string]: import("tailwind-variants").ClassValue | {
|
|
63
|
+
base?: import("tailwind-variants").ClassValue;
|
|
64
|
+
icon?: import("tailwind-variants").ClassValue;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
} | {}, {
|
|
68
|
+
base: string;
|
|
69
|
+
icon: string;
|
|
70
|
+
}, undefined, {
|
|
71
|
+
[key: string]: {
|
|
72
|
+
[key: string]: import("tailwind-variants").ClassValue | {
|
|
73
|
+
base?: import("tailwind-variants").ClassValue;
|
|
74
|
+
icon?: import("tailwind-variants").ClassValue;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
} | {}, {
|
|
78
|
+
base: string;
|
|
79
|
+
icon: string;
|
|
80
|
+
}, import("tailwind-variants").TVReturnTypeLike<unknown, {
|
|
81
|
+
base: string;
|
|
82
|
+
icon: string;
|
|
83
|
+
}>>;
|
|
84
|
+
/** Form-level error (thrown from `onSubmit` or returned as `errors.root`). */
|
|
85
|
+
export declare function FormError({ className }: {
|
|
86
|
+
className?: string;
|
|
87
|
+
}): import("react").JSX.Element | null;
|
|
88
|
+
//#endregion
|
|
89
|
+
export { useForm$1 as useForm };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { AlertIcon } from "../../internal/icons.js";
|
|
3
|
+
import { tv } from "../../utils/tv.js";
|
|
4
|
+
import { Button } from "../../components/button/button.js";
|
|
5
|
+
import { Field } from "../../components/field/field.js";
|
|
6
|
+
import { useCallback } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
|
9
|
+
import { Controller, FormProvider, useForm, useFormContext, useFormState } from "react-hook-form";
|
|
10
|
+
//#region src/patterns/form/form.tsx
|
|
11
|
+
/**
|
|
12
|
+
* react-hook-form's `useForm`, validated by a schema. Field names and submitted values are
|
|
13
|
+
* typed from the schema.
|
|
14
|
+
*/
|
|
15
|
+
function useForm$1({ schema, ...options }) {
|
|
16
|
+
return useForm({
|
|
17
|
+
mode: "onTouched",
|
|
18
|
+
...options,
|
|
19
|
+
resolver: standardSchemaResolver(schema)
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** The rendered `<form>` of each form, so a FormSubmit outside it can submit it. */
|
|
23
|
+
const formElements = /* @__PURE__ */ new WeakMap();
|
|
24
|
+
function Form({ form, onSubmit, children, ref, ...props }) {
|
|
25
|
+
const control = form.control;
|
|
26
|
+
const registerElement = useCallback((element) => {
|
|
27
|
+
if (element) formElements.set(control, element);
|
|
28
|
+
else formElements.delete(control);
|
|
29
|
+
if (typeof ref === "function") ref(element);
|
|
30
|
+
else if (ref) ref.current = element;
|
|
31
|
+
}, [control, ref]);
|
|
32
|
+
const submit = form.handleSubmit(async (values) => {
|
|
33
|
+
try {
|
|
34
|
+
const result = await onSubmit(values);
|
|
35
|
+
if (!result?.errors) return;
|
|
36
|
+
for (const [name, message] of Object.entries(result.errors)) if (message) form.setError(name, {
|
|
37
|
+
type: "server",
|
|
38
|
+
message
|
|
39
|
+
});
|
|
40
|
+
} catch (error) {
|
|
41
|
+
form.setError("root", {
|
|
42
|
+
type: "server",
|
|
43
|
+
message: error instanceof Error ? error.message : "Something went wrong. Try again."
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return /* @__PURE__ */ jsx(FormProvider, {
|
|
48
|
+
...form,
|
|
49
|
+
children: /* @__PURE__ */ jsx("form", {
|
|
50
|
+
noValidate: true,
|
|
51
|
+
onSubmit: submit,
|
|
52
|
+
ref: registerElement,
|
|
53
|
+
...props,
|
|
54
|
+
children
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/** One schema field: label, control, description and validation message, all wired. */
|
|
59
|
+
function FormField({ control, name, children, ...fieldProps }) {
|
|
60
|
+
return /* @__PURE__ */ jsx(Controller, {
|
|
61
|
+
control,
|
|
62
|
+
name,
|
|
63
|
+
render: ({ field, fieldState }) => /* @__PURE__ */ jsx(Field, {
|
|
64
|
+
...fieldProps,
|
|
65
|
+
error: fieldState.error?.message,
|
|
66
|
+
children: children(field)
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** Submit button that shows progress while the form submits. */
|
|
71
|
+
function FormSubmit({ form, onClick, ...props }) {
|
|
72
|
+
const context = useFormContext();
|
|
73
|
+
const control = (form ?? context)?.control;
|
|
74
|
+
if (!control) throw new Error("FormSubmit must be inside <Form> or receive form={form}, e.g. <FormSubmit form={form}> in a Modal footer.");
|
|
75
|
+
const { isSubmitting } = useFormState({ control });
|
|
76
|
+
if (!form) return /* @__PURE__ */ jsx(Button, {
|
|
77
|
+
type: "submit",
|
|
78
|
+
loading: isSubmitting,
|
|
79
|
+
onClick,
|
|
80
|
+
...props
|
|
81
|
+
});
|
|
82
|
+
const submitOutside = (event) => {
|
|
83
|
+
onClick?.(event);
|
|
84
|
+
if (!event.defaultPrevented) formElements.get(control)?.requestSubmit();
|
|
85
|
+
};
|
|
86
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
87
|
+
type: "button",
|
|
88
|
+
loading: isSubmitting,
|
|
89
|
+
onClick: submitOutside,
|
|
90
|
+
...props
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const formErrorStyles = /* @__PURE__ */ tv({ slots: {
|
|
94
|
+
base: "flex items-start gap-2 rounded-md border border-danger/30 bg-danger/8 px-3 py-2.5 text-small text-danger-text",
|
|
95
|
+
icon: "mt-0.5 size-4 shrink-0"
|
|
96
|
+
} });
|
|
97
|
+
/** Form-level error (thrown from `onSubmit` or returned as `errors.root`). */
|
|
98
|
+
function FormError({ className }) {
|
|
99
|
+
const { errors } = useFormState();
|
|
100
|
+
const message = errors.root?.message;
|
|
101
|
+
if (!message) return null;
|
|
102
|
+
const s = formErrorStyles();
|
|
103
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
104
|
+
role: "alert",
|
|
105
|
+
"data-slot": "form-error",
|
|
106
|
+
className: s.base({ class: className }),
|
|
107
|
+
children: [/* @__PURE__ */ jsx(AlertIcon, { className: s.icon() }), /* @__PURE__ */ jsx("span", { children: message })]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { Form, FormError, FormField, FormSubmit, formErrorStyles, useForm$1 as useForm };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ColorMode } from "@glyphui/tokens";
|
|
2
|
+
//#region src/provider/color-mode-script.d.ts
|
|
3
|
+
export type ColorModePreference = ColorMode | 'system';
|
|
4
|
+
export interface ColorModeOptions {
|
|
5
|
+
/** Used when nothing is stored yet. */
|
|
6
|
+
defaultMode?: ColorModePreference;
|
|
7
|
+
/** localStorage key. Set to `null` to disable persistence. */
|
|
8
|
+
storageKey?: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A tiny inline script that sets `data-mode` on `<html>` before first paint, so dark-mode
|
|
12
|
+
* visitors never see a light flash. Use the same options as `GlyphProvider`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getColorModeScript({ defaultMode, storageKey }?: ColorModeOptions): string;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region src/provider/color-mode-script.ts
|
|
3
|
+
const DARK_QUERY = "(prefers-color-scheme: dark)";
|
|
4
|
+
const DEFAULT_STORAGE_KEY = "glyph-mode";
|
|
5
|
+
/**
|
|
6
|
+
* A tiny inline script that sets `data-mode` on `<html>` before first paint, so dark-mode
|
|
7
|
+
* visitors never see a light flash. Use the same options as `GlyphProvider`.
|
|
8
|
+
*/
|
|
9
|
+
function getColorModeScript({ defaultMode = "system", storageKey = DEFAULT_STORAGE_KEY } = {}) {
|
|
10
|
+
return `(function(){try{var d=${JSON.stringify(defaultMode)},m=null;${storageKey ? `m=localStorage.getItem(${JSON.stringify(storageKey)});` : ""}if(m!=='light'&&m!=='dark'&&m!=='system')m=d;if(m==='system')m=matchMedia('${DARK_QUERY}').matches?'dark':'light';var r=document.documentElement;r.dataset.mode=m;r.style.colorScheme=m}catch(e){}})()`;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { DARK_QUERY, DEFAULT_STORAGE_KEY, getColorModeScript };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ColorModeOptions, ColorModePreference, getColorModeScript } from "./color-mode-script.js";
|
|
2
|
+
import { ColorMode } from "@glyphui/tokens";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
//#region src/provider/color-mode.d.ts
|
|
5
|
+
export interface ColorModeContextValue {
|
|
6
|
+
/** What the user chose. */
|
|
7
|
+
mode: ColorModePreference;
|
|
8
|
+
/** What is shown: `system` resolved against the OS setting. */
|
|
9
|
+
resolvedMode: ColorMode;
|
|
10
|
+
setMode: (mode: ColorModePreference) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function ColorModeProvider({ children, defaultMode, storageKey }: ColorModeOptions & {
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}): import("react").JSX.Element;
|
|
15
|
+
/** Read and change the color mode. */
|
|
16
|
+
export declare function useColorMode(): ColorModeContextValue;
|
|
17
|
+
/**
|
|
18
|
+
* Inline script that sets `data-mode` on `<html>` before first paint, so a dark-mode
|
|
19
|
+
* visitor never sees a light flash. Put it in `<head>`.
|
|
20
|
+
*/
|
|
21
|
+
/** `<script>` element version of `getColorModeScript` for SSR frameworks. */
|
|
22
|
+
export declare function ColorModeScript(props: ColorModeOptions): import("react").JSX.Element;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { type ColorModeOptions, type ColorModePreference, getColorModeScript };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DARK_QUERY, DEFAULT_STORAGE_KEY, getColorModeScript } from "./color-mode-script.js";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/provider/color-mode.tsx
|
|
6
|
+
const ColorModeContext = createContext(null);
|
|
7
|
+
const isBrowser = typeof window !== "undefined";
|
|
8
|
+
function readStoredMode(storageKey) {
|
|
9
|
+
if (!isBrowser || !storageKey) return null;
|
|
10
|
+
try {
|
|
11
|
+
const value = window.localStorage.getItem(storageKey);
|
|
12
|
+
return value === "light" || value === "dark" || value === "system" ? value : null;
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function systemMode() {
|
|
18
|
+
return isBrowser && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
19
|
+
}
|
|
20
|
+
/** Disables transitions for one frame so a mode switch doesn't animate every color. */
|
|
21
|
+
function suppressTransitions() {
|
|
22
|
+
const style = document.createElement("style");
|
|
23
|
+
style.textContent = "*,*::before,*::after{transition:none!important}";
|
|
24
|
+
document.head.appendChild(style);
|
|
25
|
+
return () => {
|
|
26
|
+
window.getComputedStyle(document.body);
|
|
27
|
+
requestAnimationFrame(() => style.remove());
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function ColorModeProvider({ children, defaultMode = "system", storageKey = DEFAULT_STORAGE_KEY }) {
|
|
31
|
+
const [mode, setModeState] = useState(() => readStoredMode(storageKey) ?? defaultMode);
|
|
32
|
+
const [system, setSystem] = useState(systemMode);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const query = window.matchMedia(DARK_QUERY);
|
|
35
|
+
const onChange = () => setSystem(query.matches ? "dark" : "light");
|
|
36
|
+
query.addEventListener("change", onChange);
|
|
37
|
+
return () => query.removeEventListener("change", onChange);
|
|
38
|
+
}, []);
|
|
39
|
+
const resolvedMode = mode === "system" ? system : mode;
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const root = document.documentElement;
|
|
42
|
+
if (root.dataset.mode === resolvedMode) return;
|
|
43
|
+
const restore = suppressTransitions();
|
|
44
|
+
root.dataset.mode = resolvedMode;
|
|
45
|
+
root.style.colorScheme = resolvedMode;
|
|
46
|
+
restore();
|
|
47
|
+
}, [resolvedMode]);
|
|
48
|
+
const setMode = useCallback((next) => {
|
|
49
|
+
setModeState(next);
|
|
50
|
+
if (!storageKey) return;
|
|
51
|
+
try {
|
|
52
|
+
window.localStorage.setItem(storageKey, next);
|
|
53
|
+
} catch {}
|
|
54
|
+
}, [storageKey]);
|
|
55
|
+
const value = useMemo(() => ({
|
|
56
|
+
mode,
|
|
57
|
+
resolvedMode,
|
|
58
|
+
setMode
|
|
59
|
+
}), [
|
|
60
|
+
mode,
|
|
61
|
+
resolvedMode,
|
|
62
|
+
setMode
|
|
63
|
+
]);
|
|
64
|
+
return /* @__PURE__ */ jsx(ColorModeContext.Provider, {
|
|
65
|
+
value,
|
|
66
|
+
children
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Read and change the color mode. */
|
|
70
|
+
function useColorMode() {
|
|
71
|
+
const value = useContext(ColorModeContext);
|
|
72
|
+
if (!value) throw new Error("useColorMode must be used inside <GlyphProvider>.");
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Inline script that sets `data-mode` on `<html>` before first paint, so a dark-mode
|
|
77
|
+
* visitor never sees a light flash. Put it in `<head>`.
|
|
78
|
+
*/
|
|
79
|
+
/** `<script>` element version of `getColorModeScript` for SSR frameworks. */
|
|
80
|
+
function ColorModeScript(props) {
|
|
81
|
+
return /* @__PURE__ */ jsx("script", {
|
|
82
|
+
dangerouslySetInnerHTML: { __html: getColorModeScript(props) },
|
|
83
|
+
suppressHydrationWarning: true
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { ColorModeProvider, ColorModeScript, getColorModeScript, useColorMode };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { MotionLevel, Theme } from "@glyphui/tokens";
|
|
2
|
+
import { ElementType, MouseEventHandler, ReactNode } from "react";
|
|
3
|
+
//#region src/provider/glyph-context.d.ts
|
|
4
|
+
/** Props Glyph passes to your router's link component. */
|
|
5
|
+
export interface LinkComponentProps {
|
|
6
|
+
href: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
onClick?: MouseEventHandler<HTMLAnchorElement>;
|
|
10
|
+
'aria-current'?: 'page' | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Any component that renders a link from these props. Plain `'a'` by default.
|
|
14
|
+
* React Router: `({ href, ...props }) => <Link to={href} {...props} />`
|
|
15
|
+
*/
|
|
16
|
+
export type LinkComponent = ElementType<LinkComponentProps>;
|
|
17
|
+
export interface IsActiveOptions {
|
|
18
|
+
/** Match only this exact path, not its children. Default false. */
|
|
19
|
+
end?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A hook that reports whether `href` is the current location. Glyph calls it once per
|
|
23
|
+
* navigation item on every render, so it must follow the rules of hooks.
|
|
24
|
+
*/
|
|
25
|
+
export type UseIsActive = (href: string, options?: IsActiveOptions) => boolean;
|
|
26
|
+
/** Connects Glyph's navigation components to your router. */
|
|
27
|
+
export interface GlyphRouter {
|
|
28
|
+
/** Renders links client-side. */
|
|
29
|
+
Link: LinkComponent;
|
|
30
|
+
/** Marks Sidebar, Navbar and NavigationMenu items active automatically. */
|
|
31
|
+
useIsActive?: UseIsActive;
|
|
32
|
+
}
|
|
33
|
+
export interface GlyphContextValue {
|
|
34
|
+
theme: Theme;
|
|
35
|
+
linkComponent: LinkComponent;
|
|
36
|
+
useIsActive: UseIsActive;
|
|
37
|
+
/** Overrides the theme's motion level for the whole app. */
|
|
38
|
+
motion?: MotionLevel | undefined;
|
|
39
|
+
}
|
|
40
|
+
/** The active theme and app-level settings. Must be used under `GlyphProvider`. */
|
|
41
|
+
export declare function useGlyph(): GlyphContextValue;
|
|
42
|
+
/** The router-aware link component configured on `GlyphProvider`. */
|
|
43
|
+
export declare function useLinkComponent(): LinkComponent;
|
|
44
|
+
/**
|
|
45
|
+
* Whether `href` is the current page, using the router passed to `GlyphProvider`.
|
|
46
|
+
* Returns `explicit` when it is set, so an `active` prop always wins.
|
|
47
|
+
*/
|
|
48
|
+
export declare function useIsActive(href: string | undefined, options?: IsActiveOptions & {
|
|
49
|
+
explicit?: boolean | undefined;
|
|
50
|
+
}): boolean;
|
|
51
|
+
//#endregion
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
//#region src/provider/glyph-context.ts
|
|
4
|
+
const GlyphContext = createContext(null);
|
|
5
|
+
/** The active theme and app-level settings. Must be used under `GlyphProvider`. */
|
|
6
|
+
function useGlyph() {
|
|
7
|
+
const value = useContext(GlyphContext);
|
|
8
|
+
if (!value) throw new Error("useGlyph must be used inside <GlyphProvider>.");
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
/** The router-aware link component configured on `GlyphProvider`. */
|
|
12
|
+
function useLinkComponent() {
|
|
13
|
+
return useContext(GlyphContext)?.linkComponent ?? "a";
|
|
14
|
+
}
|
|
15
|
+
const neverActive = () => false;
|
|
16
|
+
/**
|
|
17
|
+
* Whether `href` is the current page, using the router passed to `GlyphProvider`.
|
|
18
|
+
* Returns `explicit` when it is set, so an `active` prop always wins.
|
|
19
|
+
*/
|
|
20
|
+
function useIsActive(href, options) {
|
|
21
|
+
const isActive = useContext(GlyphContext)?.useIsActive ?? neverActive;
|
|
22
|
+
const { explicit, ...matchOptions } = options ?? {};
|
|
23
|
+
const matched = isActive(href ?? "", matchOptions);
|
|
24
|
+
if (explicit !== void 0) return explicit;
|
|
25
|
+
return href ? matched : false;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { GlyphContext, neverActive, useGlyph, useIsActive, useLinkComponent };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ToasterProps } from "../components/toast/toast.js";
|
|
2
|
+
import { ColorModePreference } from "./color-mode-script.js";
|
|
3
|
+
import "./color-mode.js";
|
|
4
|
+
import { GlyphRouter, LinkComponent } from "./glyph-context.js";
|
|
5
|
+
import { MotionLevel, Theme } from "@glyphui/tokens";
|
|
6
|
+
import { ReactNode } from "react";
|
|
7
|
+
//#region src/provider/glyph-provider.d.ts
|
|
8
|
+
export interface GlyphProviderProps {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
/** The theme for the whole app. Defaults to the `glyph` preset. */
|
|
11
|
+
theme?: Theme;
|
|
12
|
+
/** Color mode used until the user picks one. */
|
|
13
|
+
defaultMode?: ColorModePreference;
|
|
14
|
+
/** localStorage key for the user's color mode. `null` disables persistence. */
|
|
15
|
+
storageKey?: string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Your router: its link component, plus an optional `useIsActive` hook that marks the
|
|
18
|
+
* current page in Sidebar, Navbar and NavigationMenu. React Router:
|
|
19
|
+
* `import { reactRouter } from '@glyphui/ui/react-router'`.
|
|
20
|
+
*/
|
|
21
|
+
router?: GlyphRouter;
|
|
22
|
+
/** Your router's link only. Prefer `router`, which also handles active items. */
|
|
23
|
+
linkComponent?: LinkComponent;
|
|
24
|
+
/**
|
|
25
|
+
* Mounts a themed `<Toaster />` so `toast()` works anywhere. `true` for defaults, or pass
|
|
26
|
+
* Toaster props (e.g. `{ position: 'top-center' }`). Off by default.
|
|
27
|
+
*/
|
|
28
|
+
toaster?: boolean | ToasterProps;
|
|
29
|
+
/**
|
|
30
|
+
* Overrides the theme's motion level everywhere, e.g. `"none"` in tests or for a user
|
|
31
|
+
* setting. Visitors who ask for reduced motion never get animation either way.
|
|
32
|
+
*/
|
|
33
|
+
motion?: MotionLevel;
|
|
34
|
+
}
|
|
35
|
+
/** Provides the theme, color mode, tooltips, `useConfirm()` and (optionally) toasts. Render once at the root. */
|
|
36
|
+
export declare function GlyphProvider({ children, theme, defaultMode, storageKey, router, linkComponent, toaster, motion }: GlyphProviderProps): import("react").JSX.Element;
|
|
37
|
+
//#endregion
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { GlyphContext, neverActive } from "./glyph-context.js";
|
|
3
|
+
import { ConfirmProvider } from "../components/alert-dialog/confirm.js";
|
|
4
|
+
import { ColorModeProvider } from "./color-mode.js";
|
|
5
|
+
import { MotionRootAttribute, MotionScope } from "../motion/motion-root.js";
|
|
6
|
+
import { glyph } from "../themes.js";
|
|
7
|
+
import { ThemeStyle } from "./theme-style.js";
|
|
8
|
+
import { Tooltip } from "radix-ui";
|
|
9
|
+
import { Suspense, lazy, useMemo } from "react";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
//#region src/provider/glyph-provider.tsx
|
|
12
|
+
const Toaster = lazy(() => import("../components/toast/toast.js").then((m) => ({ default: m.Toaster })));
|
|
13
|
+
/** Provides the theme, color mode, tooltips, `useConfirm()` and (optionally) toasts. Render once at the root. */
|
|
14
|
+
function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, router, linkComponent, toaster = false, motion }) {
|
|
15
|
+
const Link = router?.Link ?? linkComponent ?? "a";
|
|
16
|
+
const useIsActive = router?.useIsActive ?? neverActive;
|
|
17
|
+
const value = useMemo(() => ({
|
|
18
|
+
theme,
|
|
19
|
+
linkComponent: Link,
|
|
20
|
+
useIsActive,
|
|
21
|
+
motion
|
|
22
|
+
}), [
|
|
23
|
+
theme,
|
|
24
|
+
Link,
|
|
25
|
+
useIsActive,
|
|
26
|
+
motion
|
|
27
|
+
]);
|
|
28
|
+
return /* @__PURE__ */ jsx(ColorModeProvider, {
|
|
29
|
+
...defaultMode !== void 0 && { defaultMode },
|
|
30
|
+
...storageKey !== void 0 && { storageKey },
|
|
31
|
+
children: /* @__PURE__ */ jsxs(GlyphContext.Provider, {
|
|
32
|
+
value,
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ jsx(ThemeStyle, { theme }),
|
|
35
|
+
/* @__PURE__ */ jsx(MotionRootAttribute, {}),
|
|
36
|
+
/* @__PURE__ */ jsx(MotionScope, { children: /* @__PURE__ */ jsx(Tooltip.Provider, {
|
|
37
|
+
delayDuration: 300,
|
|
38
|
+
children: /* @__PURE__ */ jsxs(ConfirmProvider, { children: [children, toaster && /* @__PURE__ */ jsx(Suspense, {
|
|
39
|
+
fallback: null,
|
|
40
|
+
children: /* @__PURE__ */ jsx(Toaster, { ...toaster === true ? {} : toaster })
|
|
41
|
+
})] })
|
|
42
|
+
}) })
|
|
43
|
+
]
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { GlyphProvider };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ColorModeOptions, ColorModePreference, getColorModeScript } from "./color-mode-script.js";
|
|
2
|
+
import { ColorModeContextValue, ColorModeProvider, ColorModeScript, useColorMode } from "./color-mode.js";
|
|
3
|
+
import { GlyphContextValue, GlyphRouter, IsActiveOptions, LinkComponent, LinkComponentProps, UseIsActive, useGlyph, useIsActive, useLinkComponent } from "./glyph-context.js";
|
|
4
|
+
import { GlyphProvider, GlyphProviderProps } from "./glyph-provider.js";
|
|
5
|
+
import { ThemeScope, ThemeScopeProps } from "./theme-scope.js";
|
|
6
|
+
export { type ColorModeContextValue, type ColorModeOptions, type ColorModePreference, ColorModeProvider, ColorModeScript, type GlyphContextValue, GlyphProvider, type GlyphProviderProps, type GlyphRouter, type IsActiveOptions, type LinkComponent, type LinkComponentProps, ThemeScope, type ThemeScopeProps, type UseIsActive, getColorModeScript, useColorMode, useGlyph, useIsActive, useLinkComponent };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ColorMode, Theme } from "@glyphui/tokens";
|
|
2
|
+
import { ComponentProps } from "react";
|
|
3
|
+
//#region src/provider/theme-scope.d.ts
|
|
4
|
+
export interface ThemeScopeProps extends ComponentProps<'div'> {
|
|
5
|
+
theme: Theme;
|
|
6
|
+
/** Force a color mode for this subtree. Follows the page by default. */
|
|
7
|
+
mode?: ColorMode;
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Renders a subtree with a different theme, e.g. to compare themes side by side. */
|
|
11
|
+
export declare function ThemeScope({ theme, mode, asChild, children, ...props }: ThemeScopeProps): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { GlyphContext, neverActive } from "./glyph-context.js";
|
|
3
|
+
import { cn } from "../utils/cn.js";
|
|
4
|
+
import { ScopedMotionConfig } from "../motion/motion-root.js";
|
|
5
|
+
import { ThemeStyle } from "./theme-style.js";
|
|
6
|
+
import { scopeSelector } from "@glyphui/tokens";
|
|
7
|
+
import { Slot } from "radix-ui";
|
|
8
|
+
import { useContext, useMemo } from "react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
//#region src/provider/theme-scope.tsx
|
|
11
|
+
/** Renders a subtree with a different theme, e.g. to compare themes side by side. */
|
|
12
|
+
function ThemeScope({ theme, mode, asChild, children, ...props }) {
|
|
13
|
+
const parent = useContext(GlyphContext);
|
|
14
|
+
const value = useMemo(() => ({
|
|
15
|
+
theme,
|
|
16
|
+
linkComponent: parent?.linkComponent ?? "a",
|
|
17
|
+
useIsActive: parent?.useIsActive ?? neverActive,
|
|
18
|
+
motion: parent?.motion
|
|
19
|
+
}), [
|
|
20
|
+
theme,
|
|
21
|
+
parent?.linkComponent,
|
|
22
|
+
parent?.useIsActive,
|
|
23
|
+
parent?.motion
|
|
24
|
+
]);
|
|
25
|
+
const Comp = asChild ? Slot.Root : "div";
|
|
26
|
+
return /* @__PURE__ */ jsxs(GlyphContext.Provider, {
|
|
27
|
+
value,
|
|
28
|
+
children: [/* @__PURE__ */ jsx(ThemeStyle, {
|
|
29
|
+
theme,
|
|
30
|
+
selector: scopeSelector(theme)
|
|
31
|
+
}), /* @__PURE__ */ jsx(ScopedMotionConfig, { children: /* @__PURE__ */ jsx(Comp, {
|
|
32
|
+
"data-glyph-theme": theme.name,
|
|
33
|
+
"data-mode": mode,
|
|
34
|
+
"data-motion": parent?.motion ?? theme.motion.level ?? "subtle",
|
|
35
|
+
...props,
|
|
36
|
+
className: cn("bg-background font-sans text-foreground", props.className),
|
|
37
|
+
children
|
|
38
|
+
}) })]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { ThemeScope };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { themeToCss } from "@glyphui/tokens";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/provider/theme-style.tsx
|
|
6
|
+
/** Renders a theme's CSS variables. Re-renders replace the previous rules in place. */
|
|
7
|
+
function ThemeStyle({ theme, selector }) {
|
|
8
|
+
const css = useMemo(() => themeToCss(theme, selector ? { selector } : {}), [theme, selector]);
|
|
9
|
+
return /* @__PURE__ */ jsx("style", {
|
|
10
|
+
"data-glyph-theme-style": theme.name,
|
|
11
|
+
dangerouslySetInnerHTML: { __html: css }
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ThemeStyle };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GlyphRouter, IsActiveOptions, LinkComponentProps } from "./provider/glyph-context.js";
|
|
2
|
+
//#region src/integrations/react-router.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* React Router's `Link`, taking Glyph's `href` prop. Hash links, external URLs and `mailto:`
|
|
5
|
+
* stay plain anchors, so in-page anchors scroll and external links leave the app.
|
|
6
|
+
*/
|
|
7
|
+
export declare function RouterLink({ href, ...props }: LinkComponentProps): import("react").JSX.Element;
|
|
8
|
+
/** Whether an in-app `href` matches a pathname, with React Router's `NavLink` semantics. */
|
|
9
|
+
export declare function matchPath(href: string, pathname: string, { end }?: IsActiveOptions): boolean;
|
|
10
|
+
/** Marks a link active when the current location matches it, like React Router's `NavLink`. */
|
|
11
|
+
export declare function useRouterIsActive(href: string, options?: IsActiveOptions): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Connects Glyph's navigation to React Router (v7 or later):
|
|
14
|
+
* `<GlyphProvider router={reactRouter}>`. Links render client-side, and Sidebar, Navbar
|
|
15
|
+
* and NavigationMenu items mark the current page automatically. Must render inside a router.
|
|
16
|
+
*/
|
|
17
|
+
export declare const reactRouter: GlyphRouter;
|
|
18
|
+
//#endregion
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Link, useLocation } from "react-router";
|
|
4
|
+
//#region src/integrations/react-router.tsx
|
|
5
|
+
const isOutsideApp = (href) => href.startsWith("#") || href.startsWith("//") || /^[a-z][a-z\d+.-]*:/i.test(href);
|
|
6
|
+
/**
|
|
7
|
+
* React Router's `Link`, taking Glyph's `href` prop. Hash links, external URLs and `mailto:`
|
|
8
|
+
* stay plain anchors, so in-page anchors scroll and external links leave the app.
|
|
9
|
+
*/
|
|
10
|
+
function RouterLink({ href, ...props }) {
|
|
11
|
+
if (isOutsideApp(href)) return /* @__PURE__ */ jsx("a", {
|
|
12
|
+
href,
|
|
13
|
+
...props
|
|
14
|
+
});
|
|
15
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
16
|
+
to: href,
|
|
17
|
+
...props
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
const trimSlash = (path) => path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
21
|
+
/** Whether an in-app `href` matches a pathname, with React Router's `NavLink` semantics. */
|
|
22
|
+
function matchPath(href, pathname, { end = false } = {}) {
|
|
23
|
+
if (!href || isOutsideApp(href)) return false;
|
|
24
|
+
const target = trimSlash(new URL(href, "http://glyph.local").pathname);
|
|
25
|
+
const current = trimSlash(pathname);
|
|
26
|
+
if (end || target === "/") return current === target;
|
|
27
|
+
return current === target || current.startsWith(`${target}/`);
|
|
28
|
+
}
|
|
29
|
+
/** Marks a link active when the current location matches it, like React Router's `NavLink`. */
|
|
30
|
+
function useRouterIsActive(href, options) {
|
|
31
|
+
const { pathname } = useLocation();
|
|
32
|
+
return matchPath(href, pathname, options);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Connects Glyph's navigation to React Router (v7 or later):
|
|
36
|
+
* `<GlyphProvider router={reactRouter}>`. Links render client-side, and Sidebar, Navbar
|
|
37
|
+
* and NavigationMenu items mark the current page automatically. Must render inside a router.
|
|
38
|
+
*/
|
|
39
|
+
const reactRouter = {
|
|
40
|
+
Link: RouterLink,
|
|
41
|
+
useIsActive: useRouterIsActive
|
|
42
|
+
};
|
|
43
|
+
//#endregion
|
|
44
|
+
export { RouterLink, matchPath, reactRouter, useRouterIsActive };
|