@kortix/ui 0.0.0-bootstrap.0 → 0.14.3
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 +153 -2
- package/dist/_vendor/kortix-shared.js +341 -0
- package/dist/chat/agent-picker.d.ts +8 -0
- package/dist/chat/agent-picker.js +18 -0
- package/dist/chat/composer.d.ts +31 -0
- package/dist/chat/composer.js +114 -0
- package/dist/chat/index.d.ts +22 -0
- package/dist/chat/index.js +22 -0
- package/dist/chat/markdown.d.ts +10 -0
- package/dist/chat/markdown.js +36 -0
- package/dist/chat/message-list.d.ts +25 -0
- package/dist/chat/message-list.js +73 -0
- package/dist/chat/message-view.d.ts +17 -0
- package/dist/chat/message-view.js +86 -0
- package/dist/chat/model-picker.d.ts +10 -0
- package/dist/chat/model-picker.js +68 -0
- package/dist/chat/permission-prompt.d.ts +10 -0
- package/dist/chat/permission-prompt.js +40 -0
- package/dist/chat/question-prompt.d.ts +8 -0
- package/dist/chat/question-prompt.js +60 -0
- package/dist/chat/send-failure.d.ts +9 -0
- package/dist/chat/send-failure.js +21 -0
- package/dist/chat/session-thread.d.ts +28 -0
- package/dist/chat/session-thread.js +47 -0
- package/dist/chat/streaming-markdown.d.ts +21 -0
- package/dist/chat/streaming-markdown.js +59 -0
- package/dist/chat/tool-call.d.ts +4 -0
- package/dist/chat/tool-call.js +150 -0
- package/dist/chat/user-message-parts.d.ts +6 -0
- package/dist/chat/user-message-parts.js +11 -0
- package/dist/components/ui/accordion.d.ts +7 -0
- package/dist/components/ui/accordion.js +18 -0
- package/dist/components/ui/alert-dialog.d.ts +19 -0
- package/dist/components/ui/alert-dialog.js +48 -0
- package/dist/components/ui/alert.d.ts +13 -0
- package/dist/components/ui/alert.js +67 -0
- package/dist/components/ui/avatar.d.ts +11 -0
- package/dist/components/ui/avatar.js +23 -0
- package/dist/components/ui/back-pill.d.ts +13 -0
- package/dist/components/ui/back-pill.js +18 -0
- package/dist/components/ui/badge.d.ts +10 -0
- package/dist/components/ui/badge.js +42 -0
- package/dist/components/ui/breadcrumb.d.ts +11 -0
- package/dist/components/ui/breadcrumb.js +28 -0
- package/dist/components/ui/bubble.d.ts +20 -0
- package/dist/components/ui/bubble.js +38 -0
- package/dist/components/ui/button-group.d.ts +9 -0
- package/dist/components/ui/button-group.js +32 -0
- package/dist/components/ui/button.d.ts +13 -0
- package/dist/components/ui/button.js +67 -0
- package/dist/components/ui/calendar.d.ts +4 -0
- package/dist/components/ui/calendar.js +39 -0
- package/dist/components/ui/card.d.ts +96 -0
- package/dist/components/ui/card.js +291 -0
- package/dist/components/ui/chain-of-thought.d.ts +75 -0
- package/dist/components/ui/chain-of-thought.js +66 -0
- package/dist/components/ui/chart.d.ts +65 -0
- package/dist/components/ui/chart.js +118 -0
- package/dist/components/ui/checkbox-group.d.ts +19 -0
- package/dist/components/ui/checkbox-group.js +41 -0
- package/dist/components/ui/checkbox.d.ts +14 -0
- package/dist/components/ui/checkbox.js +27 -0
- package/dist/components/ui/collapsible.d.ts +5 -0
- package/dist/components/ui/collapsible.js +14 -0
- package/dist/components/ui/command.d.ts +58 -0
- package/dist/components/ui/command.js +135 -0
- package/dist/components/ui/confirm-dialog.d.ts +19 -0
- package/dist/components/ui/confirm-dialog.js +30 -0
- package/dist/components/ui/context-menu.d.ts +45 -0
- package/dist/components/ui/context-menu.js +93 -0
- package/dist/components/ui/count-badge.d.ts +26 -0
- package/dist/components/ui/count-badge.js +26 -0
- package/dist/components/ui/data-grid.d.ts +24 -0
- package/dist/components/ui/data-grid.js +107 -0
- package/dist/components/ui/date-range-picker.d.ts +119 -0
- package/dist/components/ui/date-range-picker.js +190 -0
- package/dist/components/ui/definition-list.d.ts +15 -0
- package/dist/components/ui/definition-list.js +26 -0
- package/dist/components/ui/dialog.d.ts +29 -0
- package/dist/components/ui/dialog.js +52 -0
- package/dist/components/ui/disclosure.d.ts +121 -0
- package/dist/components/ui/disclosure.js +138 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-10.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-10.js +29 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-12.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-12.js +19 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-13.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-13.js +19 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-15.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-15.js +22 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-16.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-16.js +5 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-18.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-18.js +5 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-19.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-19.js +5 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-2.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-2.js +3 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-20.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-20.js +5 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-21.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-21.js +5 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-3.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-3.js +3 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-4.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-4.js +3 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-5.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-5.js +3 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-6.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-6.js +19 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-7.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-7.js +19 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-8.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-8.js +19 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-9.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-3x3-9.js +23 -0
- package/dist/components/ui/dot-matrix/dotm-circular-1.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-1.js +28 -0
- package/dist/components/ui/dot-matrix/dotm-circular-10.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-10.js +40 -0
- package/dist/components/ui/dot-matrix/dotm-circular-11.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-11.js +37 -0
- package/dist/components/ui/dot-matrix/dotm-circular-12.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-12.js +42 -0
- package/dist/components/ui/dot-matrix/dotm-circular-14.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-14.js +37 -0
- package/dist/components/ui/dot-matrix/dotm-circular-15.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-15.js +49 -0
- package/dist/components/ui/dot-matrix/dotm-circular-17.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-17.js +31 -0
- package/dist/components/ui/dot-matrix/dotm-circular-2.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-2.js +37 -0
- package/dist/components/ui/dot-matrix/dotm-circular-3.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-3.js +54 -0
- package/dist/components/ui/dot-matrix/dotm-circular-4.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-4.js +35 -0
- package/dist/components/ui/dot-matrix/dotm-circular-5.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-5.js +30 -0
- package/dist/components/ui/dot-matrix/dotm-circular-6.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-6.js +37 -0
- package/dist/components/ui/dot-matrix/dotm-circular-7.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-7.js +25 -0
- package/dist/components/ui/dot-matrix/dotm-circular-8.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-8.js +26 -0
- package/dist/components/ui/dot-matrix/dotm-circular-9.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-circular-9.js +41 -0
- package/dist/components/ui/dot-matrix/dotm-square-1.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-1.js +27 -0
- package/dist/components/ui/dot-matrix/dotm-square-10.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-10.js +27 -0
- package/dist/components/ui/dot-matrix/dotm-square-11.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-11.js +25 -0
- package/dist/components/ui/dot-matrix/dotm-square-12.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-12.js +28 -0
- package/dist/components/ui/dot-matrix/dotm-square-13.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-13.js +45 -0
- package/dist/components/ui/dot-matrix/dotm-square-14.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-14.js +38 -0
- package/dist/components/ui/dot-matrix/dotm-square-15.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-15.js +31 -0
- package/dist/components/ui/dot-matrix/dotm-square-16.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-16.js +33 -0
- package/dist/components/ui/dot-matrix/dotm-square-17.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-17.js +27 -0
- package/dist/components/ui/dot-matrix/dotm-square-18.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-18.js +29 -0
- package/dist/components/ui/dot-matrix/dotm-square-19.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-19.js +74 -0
- package/dist/components/ui/dot-matrix/dotm-square-2.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-2.js +72 -0
- package/dist/components/ui/dot-matrix/dotm-square-20.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-20.js +79 -0
- package/dist/components/ui/dot-matrix/dotm-square-3.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-3.js +23 -0
- package/dist/components/ui/dot-matrix/dotm-square-4.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-4.js +41 -0
- package/dist/components/ui/dot-matrix/dotm-square-5.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-5.js +23 -0
- package/dist/components/ui/dot-matrix/dotm-square-6.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-6.js +20 -0
- package/dist/components/ui/dot-matrix/dotm-square-7.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-7.js +43 -0
- package/dist/components/ui/dot-matrix/dotm-square-8.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-8.js +57 -0
- package/dist/components/ui/dot-matrix/dotm-square-9.d.ts +4 -0
- package/dist/components/ui/dot-matrix/dotm-square-9.js +89 -0
- package/dist/components/ui/dot-matrix/session-dot-matrix.d.ts +46 -0
- package/dist/components/ui/dot-matrix/session-dot-matrix.js +153 -0
- package/dist/components/ui/drawer.d.ts +15 -0
- package/dist/components/ui/drawer.js +35 -0
- package/dist/components/ui/dropdown-menu.d.ts +49 -0
- package/dist/components/ui/dropdown-menu.js +113 -0
- package/dist/components/ui/emoji-picker.d.ts +15 -0
- package/dist/components/ui/emoji-picker.js +137 -0
- package/dist/components/ui/emoji-tint.d.ts +41 -0
- package/dist/components/ui/emoji-tint.js +131 -0
- package/dist/components/ui/empty.d.ts +11 -0
- package/dist/components/ui/empty.js +33 -0
- package/dist/components/ui/entity-avatar.d.ts +84 -0
- package/dist/components/ui/entity-avatar.js +106 -0
- package/dist/components/ui/faded-scroll-area.d.ts +8 -0
- package/dist/components/ui/faded-scroll-area.js +80 -0
- package/dist/components/ui/favicon-avatar.d.ts +32 -0
- package/dist/components/ui/favicon-avatar.js +18 -0
- package/dist/components/ui/field.d.ts +15 -0
- package/dist/components/ui/field.js +48 -0
- package/dist/components/ui/file-tree.d.ts +32 -0
- package/dist/components/ui/file-tree.js +30 -0
- package/dist/components/ui/glyph-face.d.ts +18 -0
- package/dist/components/ui/glyph-face.js +37 -0
- package/dist/components/ui/glyph-paths-source.d.ts +2 -0
- package/dist/components/ui/glyph-paths-source.js +40 -0
- package/dist/components/ui/glyph-paths.generated.d.ts +2 -0
- package/dist/components/ui/glyph-paths.generated.js +207 -0
- package/dist/components/ui/glyph-picker.d.ts +22 -0
- package/dist/components/ui/glyph-picker.js +118 -0
- package/dist/components/ui/glyph-registry.d.ts +36 -0
- package/dist/components/ui/glyph-registry.js +479 -0
- package/dist/components/ui/glyph-tint.d.ts +6 -0
- package/dist/components/ui/glyph-tint.js +93 -0
- package/dist/components/ui/hint.d.ts +14 -0
- package/dist/components/ui/hint.js +12 -0
- package/dist/components/ui/histogram-bars.d.ts +38 -0
- package/dist/components/ui/histogram-bars.js +93 -0
- package/dist/components/ui/hover-card.d.ts +28 -0
- package/dist/components/ui/hover-card.js +35 -0
- package/dist/components/ui/icon-provider.d.ts +23 -0
- package/dist/components/ui/icon-provider.js +30 -0
- package/dist/components/ui/info-banner.d.ts +14 -0
- package/dist/components/ui/info-banner.js +72 -0
- package/dist/components/ui/inline-meta.d.ts +6 -0
- package/dist/components/ui/inline-meta.js +8 -0
- package/dist/components/ui/input-group.d.ts +19 -0
- package/dist/components/ui/input-group.js +73 -0
- package/dist/components/ui/input.d.ts +26 -0
- package/dist/components/ui/input.js +23 -0
- package/dist/components/ui/item.d.ts +23 -0
- package/dist/components/ui/item.js +67 -0
- package/dist/components/ui/kbd.d.ts +3 -0
- package/dist/components/ui/kbd.js +20 -0
- package/dist/components/ui/kortix-asterisk.d.ts +6 -0
- package/dist/components/ui/kortix-asterisk.js +17 -0
- package/dist/components/ui/kortix-icons.d.ts +2 -0
- package/dist/components/ui/kortix-icons.js +17 -0
- package/dist/components/ui/kortix-loader.d.ts +76 -0
- package/dist/components/ui/kortix-loader.js +74 -0
- package/dist/components/ui/kortix-logo.d.ts +30 -0
- package/dist/components/ui/kortix-logo.js +47 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/label.js +9 -0
- package/dist/components/ui/list.d.ts +15 -0
- package/dist/components/ui/list.js +25 -0
- package/dist/components/ui/loading.d.ts +19 -0
- package/dist/components/ui/loading.js +31 -0
- package/dist/components/ui/local-time.d.ts +34 -0
- package/dist/components/ui/local-time.js +60 -0
- package/dist/components/ui/map.d.ts +101 -0
- package/dist/components/ui/map.js +257 -0
- package/dist/components/ui/marker.d.ts +14 -0
- package/dist/components/ui/marker.js +28 -0
- package/dist/components/ui/menu-recipe.d.ts +102 -0
- package/dist/components/ui/menu-recipe.js +129 -0
- package/dist/components/ui/mermaid-render.d.ts +51 -0
- package/dist/components/ui/mermaid-render.js +65 -0
- package/dist/components/ui/mermaid-renderer.d.ts +13 -0
- package/dist/components/ui/mermaid-renderer.js +340 -0
- package/dist/components/ui/message.d.ts +15 -0
- package/dist/components/ui/message.js +26 -0
- package/dist/components/ui/modal.d.ts +104 -0
- package/dist/components/ui/modal.js +180 -0
- package/dist/components/ui/navigation-menu.d.ts +16 -0
- package/dist/components/ui/navigation-menu.js +35 -0
- package/dist/components/ui/page-search-bar.d.ts +11 -0
- package/dist/components/ui/page-search-bar.js +13 -0
- package/dist/components/ui/phone-input.d.ts +7 -0
- package/dist/components/ui/phone-input.js +59 -0
- package/dist/components/ui/pixel-kortix-mark.d.ts +13 -0
- package/dist/components/ui/pixel-kortix-mark.js +40 -0
- package/dist/components/ui/popover.d.ts +10 -0
- package/dist/components/ui/popover.js +38 -0
- package/dist/components/ui/portal.d.ts +5 -0
- package/dist/components/ui/portal.js +15 -0
- package/dist/components/ui/preview-image.d.ts +14 -0
- package/dist/components/ui/preview-image.js +58 -0
- package/dist/components/ui/progress-ring.d.ts +6 -0
- package/dist/components/ui/progress-ring.js +9 -0
- package/dist/components/ui/progress.d.ts +6 -0
- package/dist/components/ui/progress.js +8 -0
- package/dist/components/ui/radio-group.d.ts +12 -0
- package/dist/components/ui/radio-group.js +20 -0
- package/dist/components/ui/resizable.d.ts +24 -0
- package/dist/components/ui/resizable.js +16 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/scroll-area.js +11 -0
- package/dist/components/ui/section-card.d.ts +37 -0
- package/dist/components/ui/section-card.js +14 -0
- package/dist/components/ui/section.d.ts +10 -0
- package/dist/components/ui/section.js +22 -0
- package/dist/components/ui/select.d.ts +25 -0
- package/dist/components/ui/select.js +59 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/separator.js +8 -0
- package/dist/components/ui/shader-safe.d.ts +48 -0
- package/dist/components/ui/shader-safe.js +74 -0
- package/dist/components/ui/sheet.d.ts +32 -0
- package/dist/components/ui/sheet.js +55 -0
- package/dist/components/ui/sidebar-context.d.ts +72 -0
- package/dist/components/ui/sidebar-context.js +36 -0
- package/dist/components/ui/sidebar-menu-primitives.d.ts +38 -0
- package/dist/components/ui/sidebar-menu-primitives.js +97 -0
- package/dist/components/ui/sidebar-panel.d.ts +36 -0
- package/dist/components/ui/sidebar-panel.js +265 -0
- package/dist/components/ui/sidebar-peek.d.ts +27 -0
- package/dist/components/ui/sidebar-peek.js +70 -0
- package/dist/components/ui/sidebar-width.d.ts +48 -0
- package/dist/components/ui/sidebar-width.js +62 -0
- package/dist/components/ui/sidebar.d.ts +18 -0
- package/dist/components/ui/sidebar.js +194 -0
- package/dist/components/ui/skeleton.d.ts +3 -0
- package/dist/components/ui/skeleton.js +6 -0
- package/dist/components/ui/slider-native.d.ts +7 -0
- package/dist/components/ui/slider-native.js +16 -0
- package/dist/components/ui/slider.d.ts +14 -0
- package/dist/components/ui/slider.js +48 -0
- package/dist/components/ui/sliding-tab-indicator.d.ts +61 -0
- package/dist/components/ui/sliding-tab-indicator.js +128 -0
- package/dist/components/ui/split-sheet.d.ts +61 -0
- package/dist/components/ui/split-sheet.js +239 -0
- package/dist/components/ui/spotlight-card.d.ts +8 -0
- package/dist/components/ui/spotlight-card.js +43 -0
- package/dist/components/ui/status-ring.d.ts +38 -0
- package/dist/components/ui/status-ring.js +38 -0
- package/dist/components/ui/status.d.ts +58 -0
- package/dist/components/ui/status.js +76 -0
- package/dist/components/ui/stepper.d.ts +28 -0
- package/dist/components/ui/stepper.js +73 -0
- package/dist/components/ui/switch.d.ts +8 -0
- package/dist/components/ui/switch.js +131 -0
- package/dist/components/ui/system-message.d.ts +23 -0
- package/dist/components/ui/system-message.js +51 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/table.js +28 -0
- package/dist/components/ui/tabs.d.ts +73 -0
- package/dist/components/ui/tabs.js +207 -0
- package/dist/components/ui/tag.d.ts +7 -0
- package/dist/components/ui/tag.js +22 -0
- package/dist/components/ui/text-shimmer.d.ts +13 -0
- package/dist/components/ui/text-shimmer.js +91 -0
- package/dist/components/ui/textarea.d.ts +33 -0
- package/dist/components/ui/textarea.js +87 -0
- package/dist/components/ui/toast.d.ts +105 -0
- package/dist/components/ui/toast.js +233 -0
- package/dist/components/ui/toggle.d.ts +12 -0
- package/dist/components/ui/toggle.js +26 -0
- package/dist/components/ui/tooltip.d.ts +9 -0
- package/dist/components/ui/tooltip.js +16 -0
- package/dist/components/ui/trigger-variants.d.ts +14 -0
- package/dist/components/ui/trigger-variants.js +67 -0
- package/dist/components/ui/type-to-confirm-dialog.d.ts +88 -0
- package/dist/components/ui/type-to-confirm-dialog.js +101 -0
- package/dist/components/ui/typed-title-logic.d.ts +22 -0
- package/dist/components/ui/typed-title-logic.js +33 -0
- package/dist/components/ui/typed-title.d.ts +38 -0
- package/dist/components/ui/typed-title.js +66 -0
- package/dist/components/ui/typing-animation.d.ts +36 -0
- package/dist/components/ui/typing-animation.js +141 -0
- package/dist/components/ui/user-avatar.d.ts +47 -0
- package/dist/components/ui/user-avatar.js +46 -0
- package/dist/hooks/use-debounce.d.ts +4 -0
- package/dist/hooks/use-debounce.js +17 -0
- package/dist/hooks/use-is-dark.d.ts +2 -0
- package/dist/hooks/use-is-dark.js +27 -0
- package/dist/hooks/use-mobile.d.ts +2 -0
- package/dist/hooks/use-mobile.js +15 -0
- package/dist/hooks/use-proximity-hover.d.ts +52 -0
- package/dist/hooks/use-proximity-hover.js +232 -0
- package/dist/icons/close.d.ts +2 -0
- package/dist/icons/close.js +7 -0
- package/dist/icons/copy.d.ts +3 -0
- package/dist/icons/copy.js +6 -0
- package/dist/icons/sidebar-toggle.d.ts +13 -0
- package/dist/icons/sidebar-toggle.js +13 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +33 -0
- package/dist/lib/dotmatrix-core.d.ts +113 -0
- package/dist/lib/dotmatrix-core.js +920 -0
- package/dist/lib/dotmatrix-hooks.d.ts +28 -0
- package/dist/lib/dotmatrix-hooks.js +151 -0
- package/dist/lib/favicon.d.ts +4 -0
- package/dist/lib/favicon.js +21 -0
- package/dist/lib/font-weight.d.ts +6 -0
- package/dist/lib/font-weight.js +6 -0
- package/dist/lib/icon-config.d.ts +33 -0
- package/dist/lib/icon-config.js +22 -0
- package/dist/lib/icon-context.d.ts +34 -0
- package/dist/lib/icon-context.js +81 -0
- package/dist/lib/portal-root.d.ts +8 -0
- package/dist/lib/portal-root.js +26 -0
- package/dist/lib/settle.d.ts +16 -0
- package/dist/lib/settle.js +29 -0
- package/dist/lib/springs.d.ts +31 -0
- package/dist/lib/springs.js +29 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/lib/z-stack.d.ts +55 -0
- package/dist/lib/z-stack.js +130 -0
- package/dist/providers/ui-provider.d.ts +141 -0
- package/dist/providers/ui-provider.js +93 -0
- package/dist/styles/dotmatrix-loader.css +1239 -0
- package/dist/styles/fonts.css +46 -0
- package/dist/styles/tailwind.css +10 -0
- package/dist/styles/theme.css +1019 -0
- package/dist/styles/tokens.css +146 -0
- package/dist/styles.css +2 -0
- package/package.json +874 -4
- package/skills/kortix-ui/SKILL.md +150 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { Slot } from 'radix-ui';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { useSidebar } from './sidebar-context.js';
|
|
7
|
+
import { Skeleton } from './skeleton.js';
|
|
8
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip.js';
|
|
9
|
+
import { cn } from '../../lib/utils.js';
|
|
10
|
+
function SidebarGroup({ className, ...props }) {
|
|
11
|
+
return (_jsx("div", { "data-slot": "sidebar-group", "data-sidebar": "group", className: cn('relative flex w-full min-w-0 flex-col p-2', className), ...props }));
|
|
12
|
+
}
|
|
13
|
+
function SidebarGroupLabel({ className, asChild = false, ...props }) {
|
|
14
|
+
const Comp = asChild ? Slot.Root : 'div';
|
|
15
|
+
return (_jsx(Comp, { "data-slot": "sidebar-group-label", "data-sidebar": "group-label", className: cn('text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0', 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0', className), ...props }));
|
|
16
|
+
}
|
|
17
|
+
function SidebarGroupAction({ className, asChild = false, ...props }) {
|
|
18
|
+
const Comp = asChild ? Slot.Root : 'button';
|
|
19
|
+
return (_jsx(Comp, { "data-slot": "sidebar-group-action", "data-sidebar": "group-action", className: cn('text-sidebar-foreground ring-sidebar-ring hover:bg-hover hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
|
20
|
+
// Increases the hit area of the button on mobile.
|
|
21
|
+
'after:absolute after:-inset-2 md:after:hidden', 'group-data-[collapsible=icon]:hidden', className), ...props }));
|
|
22
|
+
}
|
|
23
|
+
function SidebarGroupContent({ className, ...props }) {
|
|
24
|
+
return (_jsx("div", { "data-slot": "sidebar-group-content", "data-sidebar": "group-content", className: cn('w-full text-sm', className), ...props }));
|
|
25
|
+
}
|
|
26
|
+
function SidebarMenu({ className, ...props }) {
|
|
27
|
+
return (_jsx("ul", { "data-slot": "sidebar-menu", "data-sidebar": "menu", className: cn('flex w-full min-w-0 flex-col gap-px', className), ...props }));
|
|
28
|
+
}
|
|
29
|
+
function SidebarMenuItem({ className, ...props }) {
|
|
30
|
+
return (_jsx("li", { "data-slot": "sidebar-menu-item", "data-sidebar": "menu-item", className: cn('group/menu-item relative', className), ...props }));
|
|
31
|
+
}
|
|
32
|
+
const sidebarMenuButtonVariants = cva(
|
|
33
|
+
// No hover transition. Sidebar rows are hit tens–hundreds of times a day;
|
|
34
|
+
// animating bg/color makes the highlight lag the pointer (Raycast rule).
|
|
35
|
+
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none cursor-pointer shadow-none group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-hover hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-kortix-base focus-visible:ring-[0.6px] active:bg-active active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:bg-active data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-hover data-[state=open]:hover:text-sidebar-accent-foreground [&>span:last-child]:truncate [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 px-3 font-medium [&_svg]:size-4!", {
|
|
36
|
+
variants: {
|
|
37
|
+
variant: {
|
|
38
|
+
default: 'text-muted-foreground hover:bg-sidebar-row hover:text-sidebar-foreground',
|
|
39
|
+
outline: 'bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-hover hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]',
|
|
40
|
+
success: 'bg-kortix-green/10 text-kortix-green hover:bg-kortix-green/20 hover:text-kortix-green active:bg-kortix-green/25 active:text-kortix-green data-[active=true]:bg-kortix-green/15 data-[active=true]:text-kortix-green data-[state=open]:hover:bg-kortix-green/20 data-[state=open]:hover:text-kortix-green dark:bg-kortix-green/15 dark:text-kortix-green dark:hover:bg-kortix-green/25 dark:hover:text-kortix-green dark:active:bg-kortix-green/30 dark:active:text-kortix-green dark:data-[active=true]:bg-kortix-green/20 dark:data-[active=true]:text-kortix-green dark:data-[state=open]:hover:bg-kortix-green/25 dark:data-[state=open]:hover:text-kortix-green',
|
|
41
|
+
primary: 'bg-foreground text-background font-medium justify-center border-none hover:bg-foreground/90 hover:text-background',
|
|
42
|
+
},
|
|
43
|
+
size: {
|
|
44
|
+
default: 'h-8 text-sm',
|
|
45
|
+
sm: 'h-7 text-xs',
|
|
46
|
+
lg: 'h-12 text-sm group-data-[collapsible=icon]:p-0!',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
variant: 'default',
|
|
51
|
+
size: 'default',
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
function SidebarMenuButton({ asChild = false, isActive = false, variant = 'default', size = 'default', tooltip, className, ...props }) {
|
|
55
|
+
const Comp = asChild ? Slot.Root : 'button';
|
|
56
|
+
const { isMobile, state } = useSidebar();
|
|
57
|
+
const button = (_jsx(Comp, { "data-slot": "sidebar-menu-button", "data-sidebar": "menu-button", "data-size": size, "data-active": isActive, className: cn(sidebarMenuButtonVariants({ variant, size }), className), ...props }));
|
|
58
|
+
if (!tooltip) {
|
|
59
|
+
return button;
|
|
60
|
+
}
|
|
61
|
+
if (typeof tooltip === 'string') {
|
|
62
|
+
tooltip = {
|
|
63
|
+
children: tooltip,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: button }), _jsx(TooltipContent, { side: "right", align: "center", hidden: state !== 'collapsed' || isMobile, ...tooltip })] }));
|
|
67
|
+
}
|
|
68
|
+
function SidebarMenuAction({ className, asChild = false, showOnHover = false, ...props }) {
|
|
69
|
+
const Comp = asChild ? Slot.Root : 'button';
|
|
70
|
+
return (_jsx(Comp, { "data-slot": "sidebar-menu-action", "data-sidebar": "menu-action", className: cn('text-sidebar-foreground ring-sidebar-ring peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-hover hover:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
|
|
71
|
+
// Increases the hit area of the button on mobile.
|
|
72
|
+
'after:absolute after:-inset-2 md:after:hidden', 'peer-data-[size=sm]/menu-button:top-1', 'peer-data-[size=default]/menu-button:top-1.5', 'peer-data-[size=lg]/menu-button:top-2.5', 'group-data-[collapsible=icon]:hidden', showOnHover &&
|
|
73
|
+
'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0', className), ...props }));
|
|
74
|
+
}
|
|
75
|
+
function SidebarMenuBadge({ className, ...props }) {
|
|
76
|
+
return (_jsx("div", { "data-slot": "sidebar-menu-badge", "data-sidebar": "menu-badge", className: cn('text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none', 'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground', 'peer-data-[size=sm]/menu-button:top-1', 'peer-data-[size=default]/menu-button:top-1.5', 'peer-data-[size=lg]/menu-button:top-2.5', 'group-data-[collapsible=icon]:hidden', className), ...props }));
|
|
77
|
+
}
|
|
78
|
+
function SidebarMenuSkeleton({ className, showIcon = false, ...props }) {
|
|
79
|
+
// Random width between 50 to 90%.
|
|
80
|
+
const width = React.useMemo(() => {
|
|
81
|
+
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
82
|
+
}, []);
|
|
83
|
+
return (_jsxs("div", { "data-slot": "sidebar-menu-skeleton", "data-sidebar": "menu-skeleton", className: cn('flex h-8 items-center gap-2 rounded-md px-2', className), ...props, children: [showIcon && _jsx(Skeleton, { className: "size-4 rounded-md", "data-sidebar": "menu-skeleton-icon" }), _jsx(Skeleton, { className: "h-4 max-w-(--skeleton-width) flex-1", "data-sidebar": "menu-skeleton-text", style: {
|
|
84
|
+
'--skeleton-width': width,
|
|
85
|
+
} })] }));
|
|
86
|
+
}
|
|
87
|
+
function SidebarMenuSub({ className, ...props }) {
|
|
88
|
+
return (_jsx("ul", { "data-slot": "sidebar-menu-sub", "data-sidebar": "menu-sub", className: cn('border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5', 'group-data-[collapsible=icon]:hidden', className), ...props }));
|
|
89
|
+
}
|
|
90
|
+
function SidebarMenuSubItem({ className, ...props }) {
|
|
91
|
+
return (_jsx("li", { "data-slot": "sidebar-menu-sub-item", "data-sidebar": "menu-sub-item", className: cn('group/menu-sub-item relative', className), ...props }));
|
|
92
|
+
}
|
|
93
|
+
function SidebarMenuSubButton({ asChild = false, size = 'md', isActive = false, className, ...props }) {
|
|
94
|
+
const Comp = asChild ? Slot.Root : 'a';
|
|
95
|
+
return (_jsx(Comp, { "data-slot": "sidebar-menu-sub-button", "data-sidebar": "menu-sub-button", "data-size": size, "data-active": isActive, className: cn('text-sidebar-foreground ring-sidebar-ring hover:bg-hover hover:text-sidebar-accent-foreground active:bg-active active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0', 'data-[active=true]:bg-active data-[active=true]:text-sidebar-accent-foreground', size === 'sm' && 'text-xs', size === 'md' && 'text-sm', 'group-data-[collapsible=icon]:hidden', className), ...props }));
|
|
96
|
+
}
|
|
97
|
+
export { SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Button } from './button.js';
|
|
3
|
+
declare function Sidebar({ side, variant, collapsible, className, children, ...props }: React.ComponentProps<'div'> & {
|
|
4
|
+
side?: 'left' | 'right';
|
|
5
|
+
variant?: 'sidebar' | 'floating' | 'inset';
|
|
6
|
+
collapsible?: 'offcanvas' | 'icon' | 'none';
|
|
7
|
+
}): React.JSX.Element;
|
|
8
|
+
declare function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>): React.JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* Invisible strip along the viewport's left edge that summons the collapsed
|
|
11
|
+
* sidebar as a hover flyout. Renders nothing while the sidebar is docked
|
|
12
|
+
* open or on mobile — the mobile sidebar is a sheet.
|
|
13
|
+
*/
|
|
14
|
+
declare function SidebarEdgePeek({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element | null;
|
|
15
|
+
/**
|
|
16
|
+
* Drag handle on the panel's trailing edge — the sidebar's only resize
|
|
17
|
+
* affordance.
|
|
18
|
+
*
|
|
19
|
+
* Resize ONLY. It used to toggle the sidebar on click, which put a second
|
|
20
|
+
* collapse control on an edge that already reads as a resizer (it has shipped
|
|
21
|
+
* a `col-resize` cursor the whole time) while the real one sits in the panel
|
|
22
|
+
* header next to ⌘B. One edge, one job.
|
|
23
|
+
*
|
|
24
|
+
* Renders nothing while collapsed. There is nothing to resize, the strip is
|
|
25
|
+
* translated off-screen with the panel anyway, and that edge belongs to
|
|
26
|
+
* {@link SidebarEdgePeek} in the collapsed state.
|
|
27
|
+
*
|
|
28
|
+
* The drag writes `--sidebar-width` straight to the wrapper node and only
|
|
29
|
+
* commits to React state on pointer-up: one render per drag instead of one per
|
|
30
|
+
* pointermove. Width IS a layout property, so the content pane genuinely
|
|
31
|
+
* reflows per frame here — that is the point of a resize, and it is the one
|
|
32
|
+
* place in this file where per-frame layout is correct.
|
|
33
|
+
*/
|
|
34
|
+
declare function SidebarRail({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element | null;
|
|
35
|
+
declare function SidebarInset({ className, ...props }: React.ComponentProps<'main'>): React.JSX.Element;
|
|
36
|
+
export { Sidebar, SidebarTrigger, SidebarEdgePeek, SidebarRail, SidebarInset };
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Button } from './button.js';
|
|
5
|
+
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from './sheet.js';
|
|
6
|
+
import { SIDEBAR_RESIZE_STEP_COARSE_PX, SIDEBAR_RESIZE_STEP_PX, SIDEBAR_UNDOCK_MS, SIDEBAR_WIDTH_MOBILE, useSidebar, } from './sidebar-context.js';
|
|
7
|
+
import { SIDEBAR_MAX_WIDTH_PX, SIDEBAR_MIN_WIDTH_PX, SIDEBAR_WIDTH_PX, clampSidebarWidth, } from './sidebar-width.js';
|
|
8
|
+
import { cn } from '../../lib/utils.js';
|
|
9
|
+
import { SidebarToggle as PanelLeftIcon } from '../../icons/sidebar-toggle.js';
|
|
10
|
+
function Sidebar({ side = 'left', variant = 'sidebar', collapsible = 'offcanvas', className, children, ...props }) {
|
|
11
|
+
const { isMobile, state, openMobile, setOpenMobile, peek, peekEnter, peekLeave, instantToggle } = useSidebar();
|
|
12
|
+
const slides = collapsible === 'offcanvas' && side === 'left';
|
|
13
|
+
const peekable = slides && state === 'collapsed';
|
|
14
|
+
const peeking = peekable && peek;
|
|
15
|
+
// `undocking` is the transient frame-window right after a collapse, during
|
|
16
|
+
// which the panel is still on screen and sliding out. It is derived DURING
|
|
17
|
+
// RENDER, not in an effect: an effect would commit one frame in the flyout
|
|
18
|
+
// geometry first, and that single frame is exactly the pop the user reads as
|
|
19
|
+
// "it just disappeared". React re-renders from this before it paints.
|
|
20
|
+
const [renderedState, setRenderedState] = React.useState(state);
|
|
21
|
+
const [collapseStarted, setCollapseStarted] = React.useState(false);
|
|
22
|
+
if (renderedState !== state) {
|
|
23
|
+
setRenderedState(state);
|
|
24
|
+
// An instant toggle skips the undocking window entirely — there is no
|
|
25
|
+
// slide for the docked geometry to survive.
|
|
26
|
+
setCollapseStarted(slides && state === 'collapsed' && !instantToggle);
|
|
27
|
+
}
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
if (!collapseStarted)
|
|
30
|
+
return;
|
|
31
|
+
const id = setTimeout(() => setCollapseStarted(false), SIDEBAR_UNDOCK_MS);
|
|
32
|
+
return () => clearTimeout(id);
|
|
33
|
+
}, [collapseStarted]);
|
|
34
|
+
// A hover on the edge strip mid-collapse wins: the user asked for the panel
|
|
35
|
+
// back before it finished leaving, so hand it to the flyout.
|
|
36
|
+
const undocking = collapseStarted && !peek;
|
|
37
|
+
// The two boxes the panel can occupy. Docked and undocking share the flush
|
|
38
|
+
// full-height one; parked and peeking share the inset flyout card.
|
|
39
|
+
const flyout = peekable && !undocking;
|
|
40
|
+
// Everything that is not "on screen at rest" parks at the same transform, so
|
|
41
|
+
// the parked → undocking hand-off changes no value and starts no animation.
|
|
42
|
+
const offscreen = state === 'collapsed' && !peeking;
|
|
43
|
+
if (collapsible === 'none') {
|
|
44
|
+
return (_jsx("div", { "data-slot": "sidebar", className: cn('bg-background text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col', className), ...props, children: children }));
|
|
45
|
+
}
|
|
46
|
+
if (isMobile) {
|
|
47
|
+
return (_jsx(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: _jsxs(SheetContent, { "data-sidebar": "sidebar", "data-slot": "sidebar", "data-mobile": "true", className: "bg-background text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden", style: {
|
|
48
|
+
'--sidebar-width': SIDEBAR_WIDTH_MOBILE,
|
|
49
|
+
}, side: side, children: [_jsxs(SheetHeader, { className: "sr-only", children: [_jsx(SheetTitle, { children: "Sidebar" }), _jsx(SheetDescription, { children: "Displays the mobile sidebar." })] }), _jsx("div", { className: "flex h-full w-full flex-col", children: children })] }) }));
|
|
50
|
+
}
|
|
51
|
+
return (_jsxs("div", { className: "group peer text-sidebar-foreground hidden md:block", "data-state": state, "data-collapsible": state === 'collapsed' ? collapsible : '', "data-variant": variant, "data-side": side, "data-peek": peeking ? '' : undefined, "data-slot": "sidebar", children: [_jsx("div", { "data-slot": "sidebar-gap", className: cn('relative w-(--sidebar-width) bg-transparent', 'group-data-[collapsible=offcanvas]:w-0', 'group-data-[side=right]:rotate-180', variant === 'floating' || variant === 'inset'
|
|
52
|
+
? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]'
|
|
53
|
+
: 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)') }), _jsx("div", { "data-slot": "sidebar-container", "data-motion": slides
|
|
54
|
+
? state === 'expanded'
|
|
55
|
+
? 'docked'
|
|
56
|
+
: undocking
|
|
57
|
+
? 'undocking'
|
|
58
|
+
: peeking
|
|
59
|
+
? 'peeking'
|
|
60
|
+
: 'parked'
|
|
61
|
+
: undefined, onPointerEnter: peekable ? peekEnter : undefined, onPointerLeave: peekable ? peekLeave : undefined, className: cn('fixed z-10 hidden w-(--sidebar-width) md:flex',
|
|
62
|
+
// ─────────────────────────────────────────────────────────────────
|
|
63
|
+
// THE RULE, and it governs every branch below:
|
|
64
|
+
// layout resolves in one frame; only `transform` is ever animated.
|
|
65
|
+
//
|
|
66
|
+
// The content pane reclaims (or gives up) its 20rem in a single
|
|
67
|
+
// reflow at t=0. That reflow is free to be visible only because it
|
|
68
|
+
// happens UNDER this panel: at t=0 the panel still covers the exact
|
|
69
|
+
// strip the pane just grew into, so the collapse reads as the panel
|
|
70
|
+
// sliding off and uncovering content that was already there. On the
|
|
71
|
+
// way back the strip it uncovers is `bg-background` on a `bg-background`
|
|
72
|
+
// wrapper, so the band ahead of the incoming panel is seamless and
|
|
73
|
+
// only the panel's CONTENT appears to slide in.
|
|
74
|
+
//
|
|
75
|
+
// Corollary — geometry only ever changes while the panel is
|
|
76
|
+
// off-screen. Docked and undocking share the flush, full-height,
|
|
77
|
+
// square box; parked and peeking share the inset flyout card. The
|
|
78
|
+
// swap between the two therefore always lands on a frame where the
|
|
79
|
+
// panel is fully translated out of view. This is what the previous
|
|
80
|
+
// revision could not do: it swapped geometry at t=0, in full view,
|
|
81
|
+
// and the resulting pop is why collapsing read as instant even
|
|
82
|
+
// though a 220ms slide was running underneath it.
|
|
83
|
+
//
|
|
84
|
+
// OPENING IS NOT ANIMATED, from any trigger. A transition is read off
|
|
85
|
+
// the destination style, so the docked branch simply declares none
|
|
86
|
+
// and the panel, its contents, and the reflowed content pane all
|
|
87
|
+
// land on the same frame. Sliding the panel in looked considered and
|
|
88
|
+
// was not: the wrapper behind it is already `bg-background`, so the
|
|
89
|
+
// background arrived instantly while the panel's CONTENT trailed
|
|
90
|
+
// 300ms behind it, and the whole open read as laggy.
|
|
91
|
+
//
|
|
92
|
+
// Timing on the branches that DO animate is asymmetric: undocking
|
|
93
|
+
// 240ms, peek-in 260ms, peek-out 200ms, all on the iOS sheet curve.
|
|
94
|
+
// ─────────────────────────────────────────────────────────────────
|
|
95
|
+
slides
|
|
96
|
+
? cn(
|
|
97
|
+
// Above the content headers for the whole collapsed
|
|
98
|
+
// lifecycle, so the exit slide is never clipped by one.
|
|
99
|
+
state === 'collapsed' && 'z-40',
|
|
100
|
+
// The radius is declared on BOTH boxes on purpose. The card
|
|
101
|
+
// itself is `sidebar-inner`; this outer box only positions and
|
|
102
|
+
// transforms it — but `className` from the consumer lands
|
|
103
|
+
// HERE, and a consumer that paints a background on it (the
|
|
104
|
+
// project sidebar passed `bg-background`) fills a square behind a
|
|
105
|
+
// round card, which shows as four corner tabs sticking out
|
|
106
|
+
// past the arc. Matching the radius clips that paint to the
|
|
107
|
+
// same shape. No `overflow-hidden` — that would eat the card's
|
|
108
|
+
// `shadow-xl`.
|
|
109
|
+
flyout ? 'top-13 bottom-2 left-2 h-auto rounded-lg' : 'inset-y-0 left-0 h-svh', state === 'expanded'
|
|
110
|
+
? 'translate-x-0'
|
|
111
|
+
: cn('transition-transform ease-[cubic-bezier(0.32,0.72,0,1)] will-change-transform motion-reduce:transition-none', offscreen
|
|
112
|
+
? cn(
|
|
113
|
+
// The extra 2rem parks the card's shadow off-screen too.
|
|
114
|
+
'-translate-x-[calc(100%+2rem)]', undocking ? 'duration-[240ms]' : 'duration-[200ms]')
|
|
115
|
+
: 'translate-x-0 duration-[260ms]',
|
|
116
|
+
// ⌘B and Enter/Space collapse with no motion at all.
|
|
117
|
+
// Last in the `cn` on purpose: twMerge keeps the final
|
|
118
|
+
// `duration-*` in a class list, so this overrides
|
|
119
|
+
// whichever duration the branch above chose.
|
|
120
|
+
instantToggle && 'duration-0'))
|
|
121
|
+
: side === 'left'
|
|
122
|
+
? 'inset-y-0 left-0 h-svh group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
|
|
123
|
+
: 'inset-y-0 right-0 h-svh group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
|
|
124
|
+
// Adjust the padding for floating and inset variants.
|
|
125
|
+
variant === 'floating' || variant === 'inset'
|
|
126
|
+
? 'p-00 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
|
|
127
|
+
: 'group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l', className), ...props, children: _jsx("div", { "data-sidebar": "sidebar", "data-slot": "sidebar-inner", className: cn('bg-background group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm',
|
|
128
|
+
// Gated on `flyout`, not on `peekable`: parked ↔ peeking swaps no
|
|
129
|
+
// styles at all (the card slides in and out rigid), and the
|
|
130
|
+
// undocking panel keeps the flush docked chrome so its exit is a
|
|
131
|
+
// pure horizontal slide with no radius/shadow appearing mid-flight.
|
|
132
|
+
// border-border, not border-sidebar-border: the sidebar token is
|
|
133
|
+
// pure white in dark mode and reads as a glowing edge.
|
|
134
|
+
//
|
|
135
|
+
// No transition on the radius/shadow — same corollary as above,
|
|
136
|
+
// they only ever change while the panel is off-screen.
|
|
137
|
+
flyout && 'border-border overflow-hidden rounded-lg border shadow-xl'), children: children }) })] }));
|
|
138
|
+
}
|
|
139
|
+
function SidebarTrigger({ className, onClick, ...props }) {
|
|
140
|
+
const { toggleSidebar } = useSidebar();
|
|
141
|
+
return (_jsxs(Button, { "data-sidebar": "trigger", "data-slot": "sidebar-trigger", variant: "ghost", size: "icon", className: cn(className), onClick: (event) => {
|
|
142
|
+
onClick?.(event);
|
|
143
|
+
// Pass the event through: Enter/Space activation reports `detail === 0`
|
|
144
|
+
// and collapses with no motion, a real click animates.
|
|
145
|
+
toggleSidebar(event);
|
|
146
|
+
}, ...props, children: [_jsx(PanelLeftIcon, { className: "cn-rtl-flip" }), _jsx("span", { className: "sr-only", children: "Toggle Sidebar" })] }));
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Invisible strip along the viewport's left edge that summons the collapsed
|
|
150
|
+
* sidebar as a hover flyout. Renders nothing while the sidebar is docked
|
|
151
|
+
* open or on mobile — the mobile sidebar is a sheet.
|
|
152
|
+
*/
|
|
153
|
+
function SidebarEdgePeek({ className, ...props }) {
|
|
154
|
+
const { state, isMobile, peekEnter, peekLeave } = useSidebar();
|
|
155
|
+
if (state !== 'collapsed' || isMobile)
|
|
156
|
+
return null;
|
|
157
|
+
return (_jsx("div", { "aria-hidden": true, "data-slot": "sidebar-edge-peek", onPointerEnter: peekEnter, onPointerLeave: peekLeave, className: cn('fixed inset-y-0 left-0 z-60 hidden w-2 md:block', className), ...props }));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Drag handle on the panel's trailing edge — the sidebar's only resize
|
|
161
|
+
* affordance.
|
|
162
|
+
*
|
|
163
|
+
* Resize ONLY. It used to toggle the sidebar on click, which put a second
|
|
164
|
+
* collapse control on an edge that already reads as a resizer (it has shipped
|
|
165
|
+
* a `col-resize` cursor the whole time) while the real one sits in the panel
|
|
166
|
+
* header next to ⌘B. One edge, one job.
|
|
167
|
+
*
|
|
168
|
+
* Renders nothing while collapsed. There is nothing to resize, the strip is
|
|
169
|
+
* translated off-screen with the panel anyway, and that edge belongs to
|
|
170
|
+
* {@link SidebarEdgePeek} in the collapsed state.
|
|
171
|
+
*
|
|
172
|
+
* The drag writes `--sidebar-width` straight to the wrapper node and only
|
|
173
|
+
* commits to React state on pointer-up: one render per drag instead of one per
|
|
174
|
+
* pointermove. Width IS a layout property, so the content pane genuinely
|
|
175
|
+
* reflows per frame here — that is the point of a resize, and it is the one
|
|
176
|
+
* place in this file where per-frame layout is correct.
|
|
177
|
+
*/
|
|
178
|
+
function SidebarRail({ className, ...props }) {
|
|
179
|
+
const { state, width, setWidth, previewWidth } = useSidebar();
|
|
180
|
+
const [resizing, setResizing] = React.useState(false);
|
|
181
|
+
const drag = React.useRef(null);
|
|
182
|
+
const frame = React.useRef(null);
|
|
183
|
+
const stopDrag = React.useCallback((commit) => {
|
|
184
|
+
const active = drag.current;
|
|
185
|
+
drag.current = null;
|
|
186
|
+
if (frame.current !== null) {
|
|
187
|
+
cancelAnimationFrame(frame.current);
|
|
188
|
+
frame.current = null;
|
|
189
|
+
}
|
|
190
|
+
document.documentElement.removeAttribute('data-sidebar-resizing');
|
|
191
|
+
setResizing(false);
|
|
192
|
+
if (active)
|
|
193
|
+
setWidth(commit ? active.next : active.startWidth);
|
|
194
|
+
}, [setWidth]);
|
|
195
|
+
// Escape cancels a drag in flight and puts the width back. Bound to the
|
|
196
|
+
// window, not the handle: the pointer is captured, so the handle is not
|
|
197
|
+
// necessarily what has keyboard focus.
|
|
198
|
+
React.useEffect(() => {
|
|
199
|
+
if (!resizing)
|
|
200
|
+
return;
|
|
201
|
+
const onKeyDown = (event) => {
|
|
202
|
+
if (event.key === 'Escape')
|
|
203
|
+
stopDrag(false);
|
|
204
|
+
};
|
|
205
|
+
window.addEventListener('keydown', onKeyDown);
|
|
206
|
+
return () => window.removeEventListener('keydown', onKeyDown);
|
|
207
|
+
}, [resizing, stopDrag]);
|
|
208
|
+
// Unmounting mid-drag (collapse via ⌘B while dragging) must not leave the
|
|
209
|
+
// global resize cursor latched on <html>.
|
|
210
|
+
React.useEffect(() => () => {
|
|
211
|
+
if (frame.current !== null)
|
|
212
|
+
cancelAnimationFrame(frame.current);
|
|
213
|
+
document.documentElement.removeAttribute('data-sidebar-resizing');
|
|
214
|
+
}, []);
|
|
215
|
+
const nudge = (delta) => setWidth(width + delta);
|
|
216
|
+
if (state === 'collapsed')
|
|
217
|
+
return null;
|
|
218
|
+
return (_jsx("div", { "data-sidebar": "rail", "data-slot": "sidebar-rail", "data-resizing": resizing ? '' : undefined, role: "separator", "aria-orientation": "vertical", "aria-label": "Resize sidebar", "aria-valuenow": width, "aria-valuemin": SIDEBAR_MIN_WIDTH_PX, "aria-valuemax": SIDEBAR_MAX_WIDTH_PX, tabIndex: 0, title: "Drag to resize \u2014 double-click to reset", onPointerDown: (event) => {
|
|
219
|
+
if (event.button !== 0)
|
|
220
|
+
return;
|
|
221
|
+
event.preventDefault();
|
|
222
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
223
|
+
drag.current = { startX: event.clientX, startWidth: width, next: width };
|
|
224
|
+
document.documentElement.setAttribute('data-sidebar-resizing', '');
|
|
225
|
+
setResizing(true);
|
|
226
|
+
}, onPointerMove: (event) => {
|
|
227
|
+
const active = drag.current;
|
|
228
|
+
if (!active)
|
|
229
|
+
return;
|
|
230
|
+
active.next = clampSidebarWidth(active.startWidth + (event.clientX - active.startX), window.innerWidth);
|
|
231
|
+
// One paint per frame, whatever rate the pointer reports at.
|
|
232
|
+
if (frame.current === null) {
|
|
233
|
+
frame.current = requestAnimationFrame(() => {
|
|
234
|
+
frame.current = null;
|
|
235
|
+
if (drag.current)
|
|
236
|
+
previewWidth(drag.current.next);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}, onPointerUp: () => stopDrag(true), onPointerCancel: () => stopDrag(false), onDoubleClick: () => setWidth(SIDEBAR_WIDTH_PX), onKeyDown: (event) => {
|
|
240
|
+
const step = event.shiftKey ? SIDEBAR_RESIZE_STEP_COARSE_PX : SIDEBAR_RESIZE_STEP_PX;
|
|
241
|
+
if (event.key === 'ArrowLeft') {
|
|
242
|
+
event.preventDefault();
|
|
243
|
+
nudge(-step);
|
|
244
|
+
}
|
|
245
|
+
else if (event.key === 'ArrowRight') {
|
|
246
|
+
event.preventDefault();
|
|
247
|
+
nudge(step);
|
|
248
|
+
}
|
|
249
|
+
else if (event.key === 'Home') {
|
|
250
|
+
event.preventDefault();
|
|
251
|
+
setWidth(SIDEBAR_WIDTH_PX);
|
|
252
|
+
}
|
|
253
|
+
}, className: cn('absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 cursor-col-resize touch-none outline-none select-none group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex',
|
|
254
|
+
// The hairline is a pseudo-element so the 16px hit area stays 16px
|
|
255
|
+
// (well over the 8px a pointer needs) while the visible line stays 2px.
|
|
256
|
+
// Opacity only — a width/position transition here would animate layout
|
|
257
|
+
// on hover, on an element that sits over the content pane.
|
|
258
|
+
'after:pointer-events-none after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] after:-translate-x-1/2 after:opacity-0', 'after:bg-kortix-base after:transition-opacity after:duration-100 after:ease-out', 'hover:after:opacity-100 focus-visible:after:opacity-100 data-[resizing]:after:opacity-100',
|
|
259
|
+
// Tapered top and bottom so the line reads as a seam, not a border.
|
|
260
|
+
'after:[clip-path:polygon(calc(50%-0.0625rem)_0%,calc(50%+0.0625rem)_0%,calc(50%+0.125rem)_50%,calc(50%+0.0625rem)_100%,calc(50%-0.0625rem)_100%,calc(50%-0.125rem)_50%)]', 'after:[mask-image:linear-gradient(to_bottom,transparent,black_15%,black_85%,transparent)]', 'motion-reduce:after:transition-none', className), ...props }));
|
|
261
|
+
}
|
|
262
|
+
function SidebarInset({ className, ...props }) {
|
|
263
|
+
return (_jsx("main", { "data-slot": "sidebar-inset", className: cn('bg-background relative flex w-full flex-1 flex-col overflow-hidden', 'md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2', className), ...props }));
|
|
264
|
+
}
|
|
265
|
+
export { Sidebar, SidebarTrigger, SidebarEdgePeek, SidebarRail, SidebarInset };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const SIDEBAR_PEEK_OPEN_DELAY_MS = 100;
|
|
2
|
+
export declare const SIDEBAR_PEEK_CLOSE_DELAY_MS = 250;
|
|
3
|
+
type TimerId = ReturnType<typeof setTimeout>;
|
|
4
|
+
export interface PeekController {
|
|
5
|
+
enter: () => void;
|
|
6
|
+
leave: () => void;
|
|
7
|
+
cancel: () => void;
|
|
8
|
+
/**
|
|
9
|
+
* Hold the flyout open across pointer-leaves — used while a menu/popover
|
|
10
|
+
* anchored in the panel is open. Its content portals outside the panel, so
|
|
11
|
+
* moving the pointer onto it fires the panel's `leave` and would otherwise
|
|
12
|
+
* arm the close timer. Calls must be balanced: `hold(true)` on open,
|
|
13
|
+
* `hold(false)` on close. On the final release the close timer is armed
|
|
14
|
+
* unless `isPointerOver()` reports the pointer is back on the panel.
|
|
15
|
+
*/
|
|
16
|
+
hold: (held: boolean, isPointerOver?: () => boolean) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Hover intent for the collapsed sidebar's edge-peek flyout. `enter` arms the
|
|
20
|
+
* open delay (grazing the edge must not flash the panel), `leave` arms the
|
|
21
|
+
* close delay (the pointer needs time to travel from the edge zone onto the
|
|
22
|
+
* panel), and re-entering during a pending close keeps the panel up. `cancel`
|
|
23
|
+
* drops the peek immediately — used when the sidebar docks open, the viewport
|
|
24
|
+
* goes mobile, or the provider unmounts.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createPeekController(setPeek: (peek: boolean) => void, schedule?: (fn: () => void, ms: number) => TimerId, unschedule?: (id: TimerId) => void): PeekController;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export const SIDEBAR_PEEK_OPEN_DELAY_MS = 100;
|
|
2
|
+
export const SIDEBAR_PEEK_CLOSE_DELAY_MS = 250;
|
|
3
|
+
/**
|
|
4
|
+
* Hover intent for the collapsed sidebar's edge-peek flyout. `enter` arms the
|
|
5
|
+
* open delay (grazing the edge must not flash the panel), `leave` arms the
|
|
6
|
+
* close delay (the pointer needs time to travel from the edge zone onto the
|
|
7
|
+
* panel), and re-entering during a pending close keeps the panel up. `cancel`
|
|
8
|
+
* drops the peek immediately — used when the sidebar docks open, the viewport
|
|
9
|
+
* goes mobile, or the provider unmounts.
|
|
10
|
+
*/
|
|
11
|
+
export function createPeekController(setPeek, schedule = setTimeout, unschedule = clearTimeout) {
|
|
12
|
+
let timer = null;
|
|
13
|
+
let peeked = false;
|
|
14
|
+
// Number of menus/popovers currently pinning the flyout open. While > 0 a
|
|
15
|
+
// `leave` cannot close the panel; the last release re-arms the close timer.
|
|
16
|
+
let holds = 0;
|
|
17
|
+
const clear = () => {
|
|
18
|
+
if (timer !== null) {
|
|
19
|
+
unschedule(timer);
|
|
20
|
+
timer = null;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const armClose = () => {
|
|
24
|
+
clear();
|
|
25
|
+
if (!peeked)
|
|
26
|
+
return;
|
|
27
|
+
timer = schedule(() => {
|
|
28
|
+
timer = null;
|
|
29
|
+
peeked = false;
|
|
30
|
+
setPeek(false);
|
|
31
|
+
}, SIDEBAR_PEEK_CLOSE_DELAY_MS);
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
enter: () => {
|
|
35
|
+
clear();
|
|
36
|
+
if (peeked)
|
|
37
|
+
return;
|
|
38
|
+
timer = schedule(() => {
|
|
39
|
+
timer = null;
|
|
40
|
+
peeked = true;
|
|
41
|
+
setPeek(true);
|
|
42
|
+
}, SIDEBAR_PEEK_OPEN_DELAY_MS);
|
|
43
|
+
},
|
|
44
|
+
leave: () => {
|
|
45
|
+
if (holds > 0)
|
|
46
|
+
return;
|
|
47
|
+
armClose();
|
|
48
|
+
},
|
|
49
|
+
cancel: () => {
|
|
50
|
+
clear();
|
|
51
|
+
holds = 0;
|
|
52
|
+
if (!peeked)
|
|
53
|
+
return;
|
|
54
|
+
peeked = false;
|
|
55
|
+
setPeek(false);
|
|
56
|
+
},
|
|
57
|
+
hold: (held, isPointerOver) => {
|
|
58
|
+
if (held) {
|
|
59
|
+
holds += 1;
|
|
60
|
+
// Cancel any close armed by the leave that fired as the pointer
|
|
61
|
+
// travelled from the panel onto the portaled menu content.
|
|
62
|
+
clear();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
holds = Math.max(0, holds - 1);
|
|
66
|
+
if (holds === 0 && !isPointerOver?.())
|
|
67
|
+
armClose();
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar width: the numbers, the clamp, and the cookie.
|
|
3
|
+
*
|
|
4
|
+
* Kept framework-free (same shape as `sidebar-peek.ts`) so the ratio rules are
|
|
5
|
+
* testable without React, a DOM, or a viewport.
|
|
6
|
+
*
|
|
7
|
+
* The ratio, stated once so it stops being folklore:
|
|
8
|
+
*
|
|
9
|
+
* | Bound | Value | Why |
|
|
10
|
+
* |---------|----------------|--------------------------------------------------|
|
|
11
|
+
* | default | 20rem / 320px | 25% of a 1280px viewport — one session title fits on one line |
|
|
12
|
+
* | min | 13rem / 208px | below this the session rows truncate to nothing |
|
|
13
|
+
* | max | 26rem / 416px | above this the panel stops reading as a rail |
|
|
14
|
+
* | cap | 32% of the viewport | the panel may never own a third of the screen |
|
|
15
|
+
*
|
|
16
|
+
* `max` and `cap` are both ceilings and the SMALLER wins, so a 1024px laptop
|
|
17
|
+
* tops out at 328px while a 1600px display tops out at 416px. `min` always
|
|
18
|
+
* wins last: a narrow viewport clamps to 208px rather than producing an
|
|
19
|
+
* inverted range.
|
|
20
|
+
*/
|
|
21
|
+
/** Default docked width. Keep in sync with `SIDEBAR_WIDTH` (`20rem`). */
|
|
22
|
+
export declare const SIDEBAR_WIDTH_PX = 320;
|
|
23
|
+
export declare const SIDEBAR_MIN_WIDTH_PX = 208;
|
|
24
|
+
export declare const SIDEBAR_MAX_WIDTH_PX = 416;
|
|
25
|
+
/** The panel may never own more than this fraction of the viewport. */
|
|
26
|
+
export declare const SIDEBAR_MAX_WIDTH_RATIO = 0.32;
|
|
27
|
+
/** Drag lands on the default width when it comes within this many px of it. */
|
|
28
|
+
export declare const SIDEBAR_WIDTH_SNAP_PX = 12;
|
|
29
|
+
export declare const SIDEBAR_WIDTH_COOKIE_NAME = "sidebar_width";
|
|
30
|
+
/**
|
|
31
|
+
* Largest width allowed at this viewport. `Math.max(MIN, …)` keeps the range
|
|
32
|
+
* non-inverted on viewports narrow enough that the ratio cap falls under the
|
|
33
|
+
* minimum — the desktop sidebar is hidden below `md` anyway, but a clamp that
|
|
34
|
+
* can return a max below its own min is a bug waiting for a resize event.
|
|
35
|
+
*/
|
|
36
|
+
export declare function maxSidebarWidth(viewportWidth: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Clamp a proposed width into the allowed range, with a magnetic snap onto the
|
|
39
|
+
* default so "put it back how it was" costs no precision. The snap is applied
|
|
40
|
+
* before the clamp so it can never pull a value outside the range.
|
|
41
|
+
*/
|
|
42
|
+
export declare function clampSidebarWidth(width: number, viewportWidth: number): number;
|
|
43
|
+
/**
|
|
44
|
+
* Read the persisted width out of a cookie string. Returns `null` when absent
|
|
45
|
+
* or unparseable so callers fall back to the default rather than to `NaN` —
|
|
46
|
+
* a `NaN` here would render `--sidebar-width: NaNpx` and collapse the panel.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseSidebarWidthCookie(cookie: string | null | undefined): number | null;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar width: the numbers, the clamp, and the cookie.
|
|
3
|
+
*
|
|
4
|
+
* Kept framework-free (same shape as `sidebar-peek.ts`) so the ratio rules are
|
|
5
|
+
* testable without React, a DOM, or a viewport.
|
|
6
|
+
*
|
|
7
|
+
* The ratio, stated once so it stops being folklore:
|
|
8
|
+
*
|
|
9
|
+
* | Bound | Value | Why |
|
|
10
|
+
* |---------|----------------|--------------------------------------------------|
|
|
11
|
+
* | default | 20rem / 320px | 25% of a 1280px viewport — one session title fits on one line |
|
|
12
|
+
* | min | 13rem / 208px | below this the session rows truncate to nothing |
|
|
13
|
+
* | max | 26rem / 416px | above this the panel stops reading as a rail |
|
|
14
|
+
* | cap | 32% of the viewport | the panel may never own a third of the screen |
|
|
15
|
+
*
|
|
16
|
+
* `max` and `cap` are both ceilings and the SMALLER wins, so a 1024px laptop
|
|
17
|
+
* tops out at 328px while a 1600px display tops out at 416px. `min` always
|
|
18
|
+
* wins last: a narrow viewport clamps to 208px rather than producing an
|
|
19
|
+
* inverted range.
|
|
20
|
+
*/
|
|
21
|
+
/** Default docked width. Keep in sync with `SIDEBAR_WIDTH` (`20rem`). */
|
|
22
|
+
export const SIDEBAR_WIDTH_PX = 320;
|
|
23
|
+
export const SIDEBAR_MIN_WIDTH_PX = 208;
|
|
24
|
+
export const SIDEBAR_MAX_WIDTH_PX = 416;
|
|
25
|
+
/** The panel may never own more than this fraction of the viewport. */
|
|
26
|
+
export const SIDEBAR_MAX_WIDTH_RATIO = 0.32;
|
|
27
|
+
/** Drag lands on the default width when it comes within this many px of it. */
|
|
28
|
+
export const SIDEBAR_WIDTH_SNAP_PX = 12;
|
|
29
|
+
export const SIDEBAR_WIDTH_COOKIE_NAME = 'sidebar_width';
|
|
30
|
+
/**
|
|
31
|
+
* Largest width allowed at this viewport. `Math.max(MIN, …)` keeps the range
|
|
32
|
+
* non-inverted on viewports narrow enough that the ratio cap falls under the
|
|
33
|
+
* minimum — the desktop sidebar is hidden below `md` anyway, but a clamp that
|
|
34
|
+
* can return a max below its own min is a bug waiting for a resize event.
|
|
35
|
+
*/
|
|
36
|
+
export function maxSidebarWidth(viewportWidth) {
|
|
37
|
+
const ratioCap = Math.floor(viewportWidth * SIDEBAR_MAX_WIDTH_RATIO);
|
|
38
|
+
return Math.max(SIDEBAR_MIN_WIDTH_PX, Math.min(SIDEBAR_MAX_WIDTH_PX, ratioCap));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Clamp a proposed width into the allowed range, with a magnetic snap onto the
|
|
42
|
+
* default so "put it back how it was" costs no precision. The snap is applied
|
|
43
|
+
* before the clamp so it can never pull a value outside the range.
|
|
44
|
+
*/
|
|
45
|
+
export function clampSidebarWidth(width, viewportWidth) {
|
|
46
|
+
const snapped = Math.abs(width - SIDEBAR_WIDTH_PX) <= SIDEBAR_WIDTH_SNAP_PX ? SIDEBAR_WIDTH_PX : width;
|
|
47
|
+
return Math.round(Math.min(Math.max(snapped, SIDEBAR_MIN_WIDTH_PX), maxSidebarWidth(viewportWidth)));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Read the persisted width out of a cookie string. Returns `null` when absent
|
|
51
|
+
* or unparseable so callers fall back to the default rather than to `NaN` —
|
|
52
|
+
* a `NaN` here would render `--sidebar-width: NaNpx` and collapse the panel.
|
|
53
|
+
*/
|
|
54
|
+
export function parseSidebarWidthCookie(cookie) {
|
|
55
|
+
if (!cookie)
|
|
56
|
+
return null;
|
|
57
|
+
const match = cookie.match(/(?:^|;\s*)sidebar_width=(\d{2,4})\b/);
|
|
58
|
+
if (!match)
|
|
59
|
+
return null;
|
|
60
|
+
const value = Number(match[1]);
|
|
61
|
+
return Number.isFinite(value) && value > 0 ? value : null;
|
|
62
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Input } from './input.js';
|
|
3
|
+
import { Separator } from './separator.js';
|
|
4
|
+
import { SidebarContext, type SidebarToggleOptions, useOptionalSidebar, useSidebar } from './sidebar-context.js';
|
|
5
|
+
import { Sidebar, SidebarTrigger, SidebarEdgePeek, SidebarRail, SidebarInset } from './sidebar-panel.js';
|
|
6
|
+
import { SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem } from './sidebar-menu-primitives.js';
|
|
7
|
+
declare function SidebarProvider({ defaultOpen, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }: React.ComponentProps<'div'> & {
|
|
8
|
+
defaultOpen?: boolean;
|
|
9
|
+
open?: boolean;
|
|
10
|
+
onOpenChange?: (open: boolean) => void;
|
|
11
|
+
}): React.JSX.Element;
|
|
12
|
+
declare function SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>): React.JSX.Element;
|
|
13
|
+
declare function SidebarHeader({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
14
|
+
declare function SidebarFooter({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
15
|
+
declare function SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>): React.JSX.Element;
|
|
16
|
+
declare function SidebarContent({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
17
|
+
export { Sidebar, SidebarContent, SidebarContext, SidebarEdgePeek, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, useOptionalSidebar, useSidebar, };
|
|
18
|
+
export type { SidebarToggleOptions };
|