@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,101 @@
|
|
|
1
|
+
import * as MapLibreGL from 'maplibre-gl';
|
|
2
|
+
import type { MarkerOptions, PopupOptions } from 'maplibre-gl';
|
|
3
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
4
|
+
import { type ReactNode } from 'react';
|
|
5
|
+
/**
|
|
6
|
+
* `compact: false` keeps the attribution expanded at every width. Collapsed, it is
|
|
7
|
+
* an "i" button whose glyph is a black background image, invisible on a dark
|
|
8
|
+
* basemap, and the tile license (OpenStreetMap and the style provider) requires
|
|
9
|
+
* the text to be visible.
|
|
10
|
+
*/
|
|
11
|
+
declare const MAP_DEFAULTS: {
|
|
12
|
+
renderWorldCopies: false;
|
|
13
|
+
attributionControl: {
|
|
14
|
+
compact: false;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
type Theme = 'light' | 'dark';
|
|
18
|
+
type MapStyleOption = string | MapLibreGL.StyleSpecification;
|
|
19
|
+
type MapContextValue = {
|
|
20
|
+
map: MapLibreGL.Map | null;
|
|
21
|
+
isLoaded: boolean;
|
|
22
|
+
};
|
|
23
|
+
declare function useMap(): MapContextValue;
|
|
24
|
+
type MapProps = {
|
|
25
|
+
children?: ReactNode;
|
|
26
|
+
/** Additional CSS classes for the map container */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** The app's resolved theme; picks `styles.light` or `styles.dark`. */
|
|
29
|
+
theme: Theme;
|
|
30
|
+
/** Basemap style per theme. There is no default basemap. */
|
|
31
|
+
styles: {
|
|
32
|
+
light: MapStyleOption;
|
|
33
|
+
dark: MapStyleOption;
|
|
34
|
+
};
|
|
35
|
+
/** Shown in place of the map when its style fails to load. Without it the failed map is blank, never a spinner. */
|
|
36
|
+
fallback?: ReactNode;
|
|
37
|
+
} & Omit<MapLibreGL.MapOptions, 'container' | 'style'>;
|
|
38
|
+
type MapEvents = {
|
|
39
|
+
on(type: string, listener: () => void): unknown;
|
|
40
|
+
off(type: string, listener: () => void): unknown;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Wires the load gates. An `error` before the first `style.load` means the style (or the worker)
|
|
44
|
+
* failed, so `load` never comes: report `fail` so the spinner does not stay forever. A tile error
|
|
45
|
+
* after the style loaded still ends in `load` (an errored tile counts as loaded), so it is ignored.
|
|
46
|
+
*/
|
|
47
|
+
declare function watchMapLoad(map: MapEvents, gates: {
|
|
48
|
+
load: () => void;
|
|
49
|
+
styleLoad: () => void;
|
|
50
|
+
fail: () => void;
|
|
51
|
+
}): () => void;
|
|
52
|
+
declare function Map({ children, className, theme, styles, fallback, ...props }: MapProps): import("react").JSX.Element;
|
|
53
|
+
type MapMarkerProps = {
|
|
54
|
+
/** Longitude coordinate for marker position */
|
|
55
|
+
longitude: number;
|
|
56
|
+
/** Latitude coordinate for marker position */
|
|
57
|
+
latitude: number;
|
|
58
|
+
/** Accessible name of the marker element (MapLibre makes a marker with a popup focusable). */
|
|
59
|
+
label?: string;
|
|
60
|
+
/** Marker subcomponents (MarkerContent, MarkerPopup) */
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
} & Omit<MarkerOptions, 'element'>;
|
|
63
|
+
declare function MapMarker({ longitude, latitude, label, children, ...markerOptions }: MapMarkerProps): import("react").JSX.Element;
|
|
64
|
+
type MarkerContentProps = {
|
|
65
|
+
/** Custom marker content. Defaults to an ink dot if not provided */
|
|
66
|
+
children?: ReactNode;
|
|
67
|
+
/** Additional CSS classes for the marker container */
|
|
68
|
+
className?: string;
|
|
69
|
+
};
|
|
70
|
+
declare function MarkerContent({ children, className }: MarkerContentProps): import("react").ReactPortal;
|
|
71
|
+
type MarkerPopupProps = {
|
|
72
|
+
/** Popup content */
|
|
73
|
+
children: ReactNode;
|
|
74
|
+
/** Additional CSS classes for the popup container */
|
|
75
|
+
className?: string;
|
|
76
|
+
} & Omit<PopupOptions, 'className' | 'closeButton'>;
|
|
77
|
+
declare function MarkerPopup({ children, className, ...popupOptions }: MarkerPopupProps): import("react").ReactPortal;
|
|
78
|
+
type MapControlsProps = {
|
|
79
|
+
/** Accessible names of the zoom buttons, translated by the caller. */
|
|
80
|
+
labels: {
|
|
81
|
+
zoomIn: string;
|
|
82
|
+
zoomOut: string;
|
|
83
|
+
};
|
|
84
|
+
/** Additional CSS classes for the controls container */
|
|
85
|
+
className?: string;
|
|
86
|
+
};
|
|
87
|
+
/** Zoom in and out, bottom right, above the attribution. */
|
|
88
|
+
declare function MapControls({ labels, className }: MapControlsProps): import("react").JSX.Element;
|
|
89
|
+
type MapRouteProps = {
|
|
90
|
+
/** The route as [longitude, latitude] pairs, at least two. */
|
|
91
|
+
coordinates: [number, number][];
|
|
92
|
+
/** Line color. MapLibre paints it, so it must be a color MapLibre parses (hex or rgb), not a CSS variable. */
|
|
93
|
+
color: string;
|
|
94
|
+
/** Line width in pixels (default: 3) */
|
|
95
|
+
width?: number;
|
|
96
|
+
/** Line opacity from 0 to 1 (default: 0.8) */
|
|
97
|
+
opacity?: number;
|
|
98
|
+
};
|
|
99
|
+
declare function MapRoute({ coordinates, color, width, opacity }: MapRouteProps): null;
|
|
100
|
+
export { Map, MAP_DEFAULTS, MapControls, watchMapLoad, MapMarker, MapRoute, MarkerContent, MarkerPopup, useMap };
|
|
101
|
+
export type { MapControlsProps, MapMarkerProps, MapProps, MapRouteProps, MapStyleOption, MarkerContentProps, MarkerPopupProps };
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* mapcn (https://mapcn.dev, `@mapcn/map`) on MapLibre GL, trimmed to the parts
|
|
5
|
+
* Kortix uses: Map, MapMarker, MarkerContent, MarkerPopup, MapRoute, MapControls.
|
|
6
|
+
* Changes from upstream:
|
|
7
|
+
* - No default basemap. Upstream falls back to CARTO, whose commercial use needs
|
|
8
|
+
* an enterprise license; every caller passes `styles`.
|
|
9
|
+
* - The MapLibre worker loads from this origin (`/maplibre/`, copied out of
|
|
10
|
+
* node_modules by `scripts/viewer-wasm.mjs`), not from unpkg.
|
|
11
|
+
* - Phosphor icons and the Kortix `Loading` spinner; token colors only; labels
|
|
12
|
+
* come from the caller so they can be translated.
|
|
13
|
+
* - Removed: the theme auto-detection (callers pass `theme`), the controlled
|
|
14
|
+
* viewport, projection, tooltips, labels, standalone popups, route progress,
|
|
15
|
+
* arcs, GeoJSON, clusters, and the compass, locate and fullscreen controls.
|
|
16
|
+
*/
|
|
17
|
+
import { MinusIcon, PlusIcon } from '@phosphor-icons/react';
|
|
18
|
+
import * as MapLibreGL from 'maplibre-gl';
|
|
19
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
20
|
+
import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
21
|
+
import { createPortal } from 'react-dom';
|
|
22
|
+
import Loading from './loading.js';
|
|
23
|
+
import { cn } from '../../lib/utils.js';
|
|
24
|
+
/** Same-origin copy of `maplibre-gl/dist/maplibre-gl-worker.mjs` (it imports `./maplibre-gl-shared.mjs` beside it). */
|
|
25
|
+
const WORKER_URL = '/maplibre/maplibre-gl-worker.mjs';
|
|
26
|
+
if (typeof window !== 'undefined' && !MapLibreGL.getWorkerUrl()) {
|
|
27
|
+
MapLibreGL.setWorkerUrl(WORKER_URL);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* `compact: false` keeps the attribution expanded at every width. Collapsed, it is
|
|
31
|
+
* an "i" button whose glyph is a black background image, invisible on a dark
|
|
32
|
+
* basemap, and the tile license (OpenStreetMap and the style provider) requires
|
|
33
|
+
* the text to be visible.
|
|
34
|
+
*/
|
|
35
|
+
const MAP_DEFAULTS = {
|
|
36
|
+
renderWorldCopies: false,
|
|
37
|
+
attributionControl: { compact: false },
|
|
38
|
+
};
|
|
39
|
+
// Prevent equivalent inline style objects from triggering a full map style reload.
|
|
40
|
+
function useStableValue(value) {
|
|
41
|
+
const key = useMemo(() => JSON.stringify(value) ?? '', [value]);
|
|
42
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
|
+
return useMemo(() => value, [key]);
|
|
44
|
+
}
|
|
45
|
+
const MapContext = createContext(null);
|
|
46
|
+
function useMap() {
|
|
47
|
+
const context = useContext(MapContext);
|
|
48
|
+
if (!context) {
|
|
49
|
+
throw new Error('useMap must be used within a Map component');
|
|
50
|
+
}
|
|
51
|
+
return context;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* MapLibre's stylesheet is unlayered, so it beats Tailwind's layered utilities:
|
|
55
|
+
* these overrides need `!`. Popups draw their own surface (MarkerPopup); the
|
|
56
|
+
* attribution takes the app's surface tokens.
|
|
57
|
+
*/
|
|
58
|
+
const MAPLIBRE_OVERRIDES = cn('[&_.maplibregl-popup-content]:rounded-none! [&_.maplibregl-popup-content]:bg-transparent! [&_.maplibregl-popup-content]:p-0! [&_.maplibregl-popup-content]:shadow-none!', '[&_.maplibregl-popup-tip]:hidden!', '[&_.maplibregl-ctrl-attrib]:bg-background! [&_.maplibregl-ctrl-attrib]:text-muted-foreground! [&_.maplibregl-ctrl-attrib]:border-border! [&_.maplibregl-ctrl-attrib]:rounded-md! [&_.maplibregl-ctrl-attrib]:border!', '[&_.maplibregl-ctrl-attrib_a]:text-muted-foreground! [&_.maplibregl-ctrl-attrib_a:hover]:text-foreground!');
|
|
59
|
+
/**
|
|
60
|
+
* Wires the load gates. An `error` before the first `style.load` means the style (or the worker)
|
|
61
|
+
* failed, so `load` never comes: report `fail` so the spinner does not stay forever. A tile error
|
|
62
|
+
* after the style loaded still ends in `load` (an errored tile counts as loaded), so it is ignored.
|
|
63
|
+
*/
|
|
64
|
+
function watchMapLoad(map, gates) {
|
|
65
|
+
let styled = false;
|
|
66
|
+
const styleLoad = () => {
|
|
67
|
+
styled = true;
|
|
68
|
+
gates.styleLoad();
|
|
69
|
+
};
|
|
70
|
+
const error = () => {
|
|
71
|
+
if (!styled)
|
|
72
|
+
gates.fail();
|
|
73
|
+
};
|
|
74
|
+
map.on('load', gates.load);
|
|
75
|
+
map.on('style.load', styleLoad);
|
|
76
|
+
map.on('error', error);
|
|
77
|
+
return () => {
|
|
78
|
+
map.off('load', gates.load);
|
|
79
|
+
map.off('style.load', styleLoad);
|
|
80
|
+
map.off('error', error);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function Map({ children, className, theme, styles, fallback, ...props }) {
|
|
84
|
+
const containerRef = useRef(null);
|
|
85
|
+
const [mapInstance, setMapInstance] = useState(null);
|
|
86
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
87
|
+
const [isStyleLoaded, setIsStyleLoaded] = useState(false);
|
|
88
|
+
const [failed, setFailed] = useState(false);
|
|
89
|
+
const currentStyleRef = useRef(null);
|
|
90
|
+
const stableStyles = useStableValue(styles);
|
|
91
|
+
// Initialize the map
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!containerRef.current)
|
|
94
|
+
return;
|
|
95
|
+
const initialStyle = theme === 'dark' ? stableStyles.dark : stableStyles.light;
|
|
96
|
+
currentStyleRef.current = initialStyle;
|
|
97
|
+
const map = new MapLibreGL.Map({
|
|
98
|
+
container: containerRef.current,
|
|
99
|
+
style: initialStyle,
|
|
100
|
+
...MAP_DEFAULTS,
|
|
101
|
+
...props,
|
|
102
|
+
});
|
|
103
|
+
const unwatch = watchMapLoad(map, {
|
|
104
|
+
load: () => setIsLoaded(true),
|
|
105
|
+
styleLoad: () => setIsStyleLoaded(true),
|
|
106
|
+
fail: () => setFailed(true),
|
|
107
|
+
});
|
|
108
|
+
setMapInstance(map);
|
|
109
|
+
return () => {
|
|
110
|
+
unwatch();
|
|
111
|
+
map.remove();
|
|
112
|
+
setIsLoaded(false);
|
|
113
|
+
setIsStyleLoaded(false);
|
|
114
|
+
setMapInstance(null);
|
|
115
|
+
};
|
|
116
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
117
|
+
}, []);
|
|
118
|
+
// Theme change: close the gate so layer children (MapRoute) re-add on the
|
|
119
|
+
// incoming style once `style.load` fires. Full reload (no diff) so
|
|
120
|
+
// `style.load` fires deterministically; a diff would leave the gate closed.
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (!mapInstance)
|
|
123
|
+
return;
|
|
124
|
+
const newStyle = theme === 'dark' ? stableStyles.dark : stableStyles.light;
|
|
125
|
+
if (currentStyleRef.current === newStyle)
|
|
126
|
+
return;
|
|
127
|
+
currentStyleRef.current = newStyle;
|
|
128
|
+
setIsStyleLoaded(false);
|
|
129
|
+
mapInstance.setStyle(newStyle, { diff: false });
|
|
130
|
+
}, [mapInstance, theme, stableStyles]);
|
|
131
|
+
const contextValue = useMemo(() => ({ map: mapInstance, isLoaded: isLoaded && isStyleLoaded }), [mapInstance, isLoaded, isStyleLoaded]);
|
|
132
|
+
return (_jsx(MapContext.Provider, { value: contextValue, children: _jsxs("div", { ref: containerRef, className: cn('relative h-full w-full', MAPLIBRE_OVERRIDES, className), children: [failed ? (_jsx("div", { className: "bg-background absolute inset-0 z-10 overflow-auto", children: fallback })) : (!isLoaded && (_jsx("div", { className: "bg-background absolute inset-0 z-10 flex items-center justify-center", children: _jsx(Loading, {}) }))), mapInstance && !failed && children] }) }));
|
|
133
|
+
}
|
|
134
|
+
const MarkerContext = createContext(null);
|
|
135
|
+
function useMarkerContext() {
|
|
136
|
+
const context = useContext(MarkerContext);
|
|
137
|
+
if (!context) {
|
|
138
|
+
throw new Error('Marker components must be used within MapMarker');
|
|
139
|
+
}
|
|
140
|
+
return context;
|
|
141
|
+
}
|
|
142
|
+
function MapMarker({ longitude, latitude, label, children, ...markerOptions }) {
|
|
143
|
+
const { map } = useMap();
|
|
144
|
+
const marker = useMemo(() => new MapLibreGL.Marker({ ...markerOptions, element: document.createElement('div') }).setLngLat([longitude, latitude]),
|
|
145
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
146
|
+
[]);
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
if (label)
|
|
149
|
+
marker.getElement().setAttribute('aria-label', label);
|
|
150
|
+
}, [marker, label]);
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (!map)
|
|
153
|
+
return;
|
|
154
|
+
marker.addTo(map);
|
|
155
|
+
return () => {
|
|
156
|
+
marker.remove();
|
|
157
|
+
};
|
|
158
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
159
|
+
}, [map]);
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
const current = marker.getLngLat();
|
|
162
|
+
if (current.lng !== longitude || current.lat !== latitude) {
|
|
163
|
+
marker.setLngLat([longitude, latitude]);
|
|
164
|
+
}
|
|
165
|
+
}, [marker, longitude, latitude]);
|
|
166
|
+
return _jsx(MarkerContext.Provider, { value: { marker, map }, children: children });
|
|
167
|
+
}
|
|
168
|
+
function MarkerContent({ children, className }) {
|
|
169
|
+
const { marker } = useMarkerContext();
|
|
170
|
+
return createPortal(_jsx("div", { className: cn('relative cursor-pointer', className), children: children || _jsx(DefaultMarkerIcon, {}) }), marker.getElement());
|
|
171
|
+
}
|
|
172
|
+
function DefaultMarkerIcon() {
|
|
173
|
+
return _jsx("div", { className: "bg-foreground border-background relative size-4 rounded-full border-2 shadow-md" });
|
|
174
|
+
}
|
|
175
|
+
function MarkerPopup({ children, className, ...popupOptions }) {
|
|
176
|
+
const { marker, map } = useMarkerContext();
|
|
177
|
+
const container = useMemo(() => document.createElement('div'), []);
|
|
178
|
+
const popup = useMemo(() => new MapLibreGL.Popup({ offset: 16, ...popupOptions, closeButton: false }).setMaxWidth('none').setDOMContent(container),
|
|
179
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
180
|
+
[]);
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (!map)
|
|
183
|
+
return;
|
|
184
|
+
popup.setDOMContent(container);
|
|
185
|
+
marker.setPopup(popup);
|
|
186
|
+
return () => {
|
|
187
|
+
marker.setPopup(null);
|
|
188
|
+
};
|
|
189
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
190
|
+
}, [map]);
|
|
191
|
+
// A popup opens on a click, a few times per answer: it appears at once, like the app's menus.
|
|
192
|
+
return createPortal(_jsx("div", { className: cn('bg-popover text-popover-foreground relative max-w-62 rounded-md border p-3 shadow-md', className), children: children }), container);
|
|
193
|
+
}
|
|
194
|
+
function ControlButton({ onClick, label, children }) {
|
|
195
|
+
return (_jsx("button", { onClick: onClick, "aria-label": label, title: label, type: "button", className: cn('text-foreground hover:bg-muted duration-fast flex size-8 items-center justify-center transition-colors', 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-inset'), children: children }));
|
|
196
|
+
}
|
|
197
|
+
/** Zoom in and out, bottom right, above the attribution. */
|
|
198
|
+
function MapControls({ labels, className }) {
|
|
199
|
+
const { map } = useMap();
|
|
200
|
+
// MapLibre camera durations are milliseconds, and MapLibre drops them to 0 under prefers-reduced-motion.
|
|
201
|
+
const zoomIn = useCallback(() => map?.zoomTo(map.getZoom() + 1, { duration: 200 }), [map]); // audit:allow MapLibre ms, not motion/react seconds
|
|
202
|
+
const zoomOut = useCallback(() => map?.zoomTo(map.getZoom() - 1, { duration: 200 }), [map]); // audit:allow MapLibre ms, not motion/react seconds
|
|
203
|
+
return (_jsx("div", { className: cn('absolute right-2 bottom-10 z-10', className), children: _jsxs("div", { className: "border-border bg-background divide-border flex flex-col divide-y overflow-hidden rounded-md border shadow-sm", children: [_jsx(ControlButton, { onClick: zoomIn, label: labels.zoomIn, children: _jsx(PlusIcon, { className: "size-4" }) }), _jsx(ControlButton, { onClick: zoomOut, label: labels.zoomOut, children: _jsx(MinusIcon, { className: "size-4" }) })] }) }));
|
|
204
|
+
}
|
|
205
|
+
function MapRoute({ coordinates, color, width = 3, opacity = 0.8 }) {
|
|
206
|
+
const { map, isLoaded } = useMap();
|
|
207
|
+
const id = useId();
|
|
208
|
+
const sourceId = `route-source-${id}`;
|
|
209
|
+
const layerId = `route-layer-${id}`;
|
|
210
|
+
// Add source and layer once the style is loaded, and again after each style swap.
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
if (!isLoaded || !map)
|
|
213
|
+
return;
|
|
214
|
+
map.addSource(sourceId, {
|
|
215
|
+
type: 'geojson',
|
|
216
|
+
data: { type: 'Feature', properties: {}, geometry: { type: 'LineString', coordinates: [] } },
|
|
217
|
+
});
|
|
218
|
+
map.addLayer({
|
|
219
|
+
id: layerId,
|
|
220
|
+
type: 'line',
|
|
221
|
+
source: sourceId,
|
|
222
|
+
layout: { 'line-join': 'round', 'line-cap': 'round' },
|
|
223
|
+
paint: { 'line-color': color, 'line-width': width, 'line-opacity': opacity },
|
|
224
|
+
});
|
|
225
|
+
return () => {
|
|
226
|
+
try {
|
|
227
|
+
if (map.getLayer(layerId))
|
|
228
|
+
map.removeLayer(layerId);
|
|
229
|
+
if (map.getSource(sourceId))
|
|
230
|
+
map.removeSource(sourceId);
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// The map was removed with its style.
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
237
|
+
}, [isLoaded, map]);
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
if (!isLoaded || !map)
|
|
240
|
+
return;
|
|
241
|
+
const source = map.getSource(sourceId);
|
|
242
|
+
source?.setData({
|
|
243
|
+
type: 'Feature',
|
|
244
|
+
properties: {},
|
|
245
|
+
geometry: { type: 'LineString', coordinates },
|
|
246
|
+
});
|
|
247
|
+
}, [isLoaded, map, coordinates, sourceId]);
|
|
248
|
+
useEffect(() => {
|
|
249
|
+
if (!isLoaded || !map || !map.getLayer(layerId))
|
|
250
|
+
return;
|
|
251
|
+
map.setPaintProperty(layerId, 'line-color', color);
|
|
252
|
+
map.setPaintProperty(layerId, 'line-width', width);
|
|
253
|
+
map.setPaintProperty(layerId, 'line-opacity', opacity);
|
|
254
|
+
}, [isLoaded, map, layerId, color, width, opacity]);
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
export { Map, MAP_DEFAULTS, MapControls, watchMapLoad, MapMarker, MapRoute, MarkerContent, MarkerPopup, useMap };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Marker: an inline conversation note (a status update, a system note, a
|
|
5
|
+
* "working" row, a labeled separator). `default` is inline, `border` is a row
|
|
6
|
+
* with a bottom hairline, `separator` centers the label between two rules.
|
|
7
|
+
*/
|
|
8
|
+
declare const markerVariants: (props?: ({
|
|
9
|
+
variant?: "separator" | "default" | "border" | null | undefined;
|
|
10
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
11
|
+
declare function Marker({ className, variant, ...props }: React.ComponentProps<'div'> & VariantProps<typeof markerVariants>): React.JSX.Element;
|
|
12
|
+
declare function MarkerIcon({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
13
|
+
declare function MarkerContent({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
14
|
+
export { Marker, MarkerContent, MarkerIcon, markerVariants };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Marker: an inline conversation note (a status update, a system note, a
|
|
6
|
+
* "working" row, a labeled separator). `default` is inline, `border` is a row
|
|
7
|
+
* with a bottom hairline, `separator` centers the label between two rules.
|
|
8
|
+
*/
|
|
9
|
+
const markerVariants = cva('text-muted-foreground flex items-center gap-1.5 text-xs', {
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: '',
|
|
13
|
+
border: 'border-border border-b pb-2',
|
|
14
|
+
separator: "justify-center before:bg-border after:bg-border before:h-px before:flex-1 before:content-[''] after:h-px after:flex-1 after:content-['']",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: { variant: 'default' },
|
|
18
|
+
});
|
|
19
|
+
function Marker({ className, variant, ...props }) {
|
|
20
|
+
return _jsx("div", { "data-slot": "marker", className: cn(markerVariants({ variant }), className), ...props });
|
|
21
|
+
}
|
|
22
|
+
function MarkerIcon({ className, ...props }) {
|
|
23
|
+
return (_jsx("span", { "data-slot": "marker-icon", "aria-hidden": "true", className: cn('inline-flex shrink-0 items-center [&_svg]:size-3.5', className), ...props }));
|
|
24
|
+
}
|
|
25
|
+
function MarkerContent({ className, ...props }) {
|
|
26
|
+
return _jsx("span", { "data-slot": "marker-content", className: cn('min-w-0 truncate', className), ...props });
|
|
27
|
+
}
|
|
28
|
+
export { Marker, MarkerContent, MarkerIcon, markerVariants };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ONE recipe for every row in every menu.
|
|
3
|
+
*
|
|
4
|
+
* `dropdown-menu.tsx` used to own this. Its four row components — Item,
|
|
5
|
+
* SubTrigger, CheckboxItem and RadioItem — had each hardcoded their own
|
|
6
|
+
* spacing, radius, focus colour and type, drifted apart, and been reconciled
|
|
7
|
+
* into a single recipe. `context-menu.tsx` was still running the stock shadcn
|
|
8
|
+
* styling, so the same menu rendered two different ways depending on whether
|
|
9
|
+
* you reached it by click or by right-click:
|
|
10
|
+
*
|
|
11
|
+
* dropdown Item rounded-md px-2.5 py-1.5 focus:bg-primary/10 text-foreground/80
|
|
12
|
+
* context Item rounded-sm px-2 py-1.5 focus:bg-accent (inherited colour)
|
|
13
|
+
*
|
|
14
|
+
* Duplicating the recipe into the second file would recreate exactly the drift
|
|
15
|
+
* the first file's comment describes. It lives here instead, imported by both.
|
|
16
|
+
*
|
|
17
|
+
* A menu row is a row regardless of what opened it, so there is deliberately
|
|
18
|
+
* no per-menu escape hatch in this module. Anything that genuinely differs
|
|
19
|
+
* between the two menus — panel width, transform origin, scroll behaviour —
|
|
20
|
+
* stays in the component file that owns it.
|
|
21
|
+
*/
|
|
22
|
+
export type MenuRowSize = 'sm' | 'md' | 'lg';
|
|
23
|
+
export type MenuRowTone = 'default' | 'destructive';
|
|
24
|
+
/** Leading/trailing slot for an icon or a check. Same width as a row icon. */
|
|
25
|
+
export declare const MENU_INDICATOR = "flex size-4 shrink-0 items-center justify-center";
|
|
26
|
+
/** The check glyph inside `MENU_INDICATOR` — a notch lighter than an icon. */
|
|
27
|
+
export declare const MENU_INDICATOR_ICON = "text-muted-foreground size-3.5";
|
|
28
|
+
/** `px-2` + slot + `gap-2`: where a label starts when a slot precedes it. */
|
|
29
|
+
export declare const MENU_INSET = "pl-8";
|
|
30
|
+
/** The same offset on the trailing side, for a row with a trailing check. */
|
|
31
|
+
export declare const MENU_INSET_END = "pr-8";
|
|
32
|
+
/** `className` last so a caller can still override any of it. */
|
|
33
|
+
export declare function menuRow(size: MenuRowSize, tone: MenuRowTone, className?: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* The floating surface. Every panel that opens over the page wears it:
|
|
36
|
+
* `DropdownMenuContent` / `SubContent`, `ContextMenuContent` / `SubContent`,
|
|
37
|
+
* `SelectContent`, `PopoverContent`.
|
|
38
|
+
*
|
|
39
|
+
* They are the same object — a hairline-bordered card lifted off the canvas —
|
|
40
|
+
* and they had four different descriptions of it:
|
|
41
|
+
*
|
|
42
|
+
* dropdown bg-background radius calc(--radius+0.2rem) shadow-lg p-1
|
|
43
|
+
* context bg-popover radius --radius-md shadow-md p-1
|
|
44
|
+
* select bg-background radius calc(--radius+0.2rem) shadow-lg p-1 + hover:text-foreground
|
|
45
|
+
* popover bg-popover radius --radius-lg (none) p-4
|
|
46
|
+
*
|
|
47
|
+
* `bg-popover` is the resolved answer. In light mode `--popover` and
|
|
48
|
+
* `--background` are both `oklch(1 0 0)`, so nothing moves; in dark mode
|
|
49
|
+
* `--popover` is `oklch(0.1913)` against a `oklch(0.1398)` canvas, and
|
|
50
|
+
* `globals.css` describes it as "top surface, separated by hairline + shadow" —
|
|
51
|
+
* which is this element's entire job. On `bg-background` a dark-mode dropdown
|
|
52
|
+
* was the same colour as the page behind it.
|
|
53
|
+
*
|
|
54
|
+
* Popover also had no shadow at all, so it sat flat on the canvas while the
|
|
55
|
+
* menus lifted. `shadow-lg` for all of them.
|
|
56
|
+
*
|
|
57
|
+
* Four things are deliberately absent, because each is dictated by what the
|
|
58
|
+
* panel holds rather than by what it is:
|
|
59
|
+
*
|
|
60
|
+
* - **Padding.** A list of rows uses `p-1` (see `MENU_PANEL`); a popover holds
|
|
61
|
+
* prose and controls and uses `p-4`.
|
|
62
|
+
* - **Width.** Every menu call site passes its own (`w-40`, `w-48`, `w-64`),
|
|
63
|
+
* and `width` and `min-width` are separate tailwind-merge groups, so a shared
|
|
64
|
+
* `min-w-[14rem]` would survive and silently override a caller's `w-40`.
|
|
65
|
+
* - **Overflow.** A context menu's root panel scrolls; the rest clip. `overflow`,
|
|
66
|
+
* `overflow-x` and `overflow-y` are three separate tailwind-merge groups, so a
|
|
67
|
+
* shared `overflow-hidden` would survive alongside a later `overflow-y-auto`
|
|
68
|
+
* and the winner would come down to Tailwind's generated property order.
|
|
69
|
+
* - **Transform origin.** Anchored panels scale out of their trigger, and the
|
|
70
|
+
* Radix variable that carries it is named per primitive.
|
|
71
|
+
*
|
|
72
|
+
* No `hover:text-foreground` here either — select had it. On the panel it
|
|
73
|
+
* recoloured every row at once whenever the pointer entered, fighting the
|
|
74
|
+
* per-row hover the rows define themselves. Colour is a row concern.
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* The surface itself — colour, hairline, radius, elevation. No motion.
|
|
78
|
+
*
|
|
79
|
+
* Split out from the motion classes so a panel that must appear INSTANTLY can
|
|
80
|
+
* take the surface without inheriting the enter/exit animation. A submenu is
|
|
81
|
+
* the case that needs it: it opens under a pointer that is already travelling
|
|
82
|
+
* toward its first row, so the 150ms `animate-in` is 150ms of the row sliding
|
|
83
|
+
* away from the cursor.
|
|
84
|
+
*/
|
|
85
|
+
export declare const FLOATING_PANEL_SURFACE = "bg-popover text-popover-foreground border-border rounded-lg border shadow-md";
|
|
86
|
+
/** Enter/exit for panels that appear away from the pointer's path. */
|
|
87
|
+
export declare const FLOATING_PANEL_MOTION = "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ease-out";
|
|
88
|
+
export declare const FLOATING_PANEL: string;
|
|
89
|
+
/** The floating surface holding a list of rows: dropdown, context menu, select. */
|
|
90
|
+
export declare const MENU_PANEL: string;
|
|
91
|
+
/**
|
|
92
|
+
* `MENU_PANEL` with no enter/exit animation — paints on the same frame it
|
|
93
|
+
* mounts. Every dropdown panel (root and submenu) and every select list uses
|
|
94
|
+
* it, and `PopoverContent` takes `FLOATING_PANEL_SURFACE` for the same reason.
|
|
95
|
+
* The animated `MENU_PANEL` / `FLOATING_PANEL` remain for the context menu and
|
|
96
|
+
* the animated hover card.
|
|
97
|
+
*/
|
|
98
|
+
export declare const MENU_PANEL_STATIC: string;
|
|
99
|
+
/** Group label: `px-2` matches every row, so labels and rows share a left edge. */
|
|
100
|
+
export declare const MENU_LABEL = "text-muted-foreground px-2 py-1 text-xs font-medium tracking-normal";
|
|
101
|
+
export declare const MENU_SEPARATOR = "bg-border -mx-1.5 my-1 h-px";
|
|
102
|
+
export declare const MENU_SHORTCUT = "ml-auto text-xs tracking-widest opacity-60";
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { cn } from '../../lib/utils.js';
|
|
2
|
+
/**
|
|
3
|
+
* Row geometry — the one grid every row in every menu sits on.
|
|
4
|
+
*
|
|
5
|
+
* | px-2 | slot (size-4) | gap-2 | label … | slot | px-2 |
|
|
6
|
+
*
|
|
7
|
+
* Only HEIGHT changes between sizes. Padding, gap, type and the icon slot are
|
|
8
|
+
* fixed, so a label starts on the same x in every row type and every size: a
|
|
9
|
+
* plain row with a leading icon, an `inset` row, a checkbox row, a left-radio
|
|
10
|
+
* row. `min-h` (not a fixed `h`) sets the height so a row with a description
|
|
11
|
+
* still grows; `py` only matters once content outgrows it.
|
|
12
|
+
*
|
|
13
|
+
* sm min-h-8 ≈ 29px menus (default)
|
|
14
|
+
* md min-h-9 ≈ 33px one step roomier — matches the `sm` Input height
|
|
15
|
+
* lg min-h-10 ≈ 37px touch-first lists
|
|
16
|
+
*/
|
|
17
|
+
const MENU_ROW_SIZE = {
|
|
18
|
+
sm: 'min-h-8 py-[0.275rem]',
|
|
19
|
+
md: 'min-h-9 py-1.5',
|
|
20
|
+
lg: 'min-h-10 py-2',
|
|
21
|
+
};
|
|
22
|
+
/** Leading/trailing slot for an icon or a check. Same width as a row icon. */
|
|
23
|
+
export const MENU_INDICATOR = 'flex size-4 shrink-0 items-center justify-center';
|
|
24
|
+
/** The check glyph inside `MENU_INDICATOR` — a notch lighter than an icon. */
|
|
25
|
+
export const MENU_INDICATOR_ICON = 'text-muted-foreground size-3.5';
|
|
26
|
+
/** `px-2` + slot + `gap-2`: where a label starts when a slot precedes it. */
|
|
27
|
+
export const MENU_INSET = 'pl-8';
|
|
28
|
+
/** The same offset on the trailing side, for a row with a trailing check. */
|
|
29
|
+
export const MENU_INSET_END = 'pr-8';
|
|
30
|
+
/**
|
|
31
|
+
* `transition-colors`, not `transition-all`: a hover highlight only needs its
|
|
32
|
+
* background and text to move, and 150ms keeps the highlight under the cursor
|
|
33
|
+
* rather than trailing it.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* `rounded-sm` (6px) is concentric with the panel: `rounded-lg` (10px) minus
|
|
37
|
+
* its `p-1` inset. `[&_svg:not([class*='size-'])]` defaults a bare icon to the
|
|
38
|
+
* slot size without overriding an explicit one — the old `[&_svg]:size-4`
|
|
39
|
+
* out-ranked every `size-3.5` check and caret, so they all rendered at 16px
|
|
40
|
+
* inside 14px boxes.
|
|
41
|
+
*/
|
|
42
|
+
const MENU_ROW_BASE = "relative flex w-full items-center gap-2 rounded-sm px-2 text-sm font-medium outline-none select-none transition-colors duration-150 ease-out data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
|
|
43
|
+
/**
|
|
44
|
+
* Keyboard focus and pointer hover resolve to the same treatment on purpose —
|
|
45
|
+
* Radix marks the keyboard-focused row `data-highlighted`, and a row you
|
|
46
|
+
* arrowed onto should look exactly like a row you hovered.
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* Keyboard focus and pointer hover resolve to the same treatment on purpose —
|
|
50
|
+
* Radix marks the keyboard-focused row `data-highlighted`, and a row you
|
|
51
|
+
* arrowed onto should look exactly like a row you hovered.
|
|
52
|
+
*/
|
|
53
|
+
const MENU_ROW_TONE = {
|
|
54
|
+
default: 'text-foreground/80 hover:bg-primary/10 hover:text-foreground focus:bg-primary/10 focus:text-foreground data-highlighted:bg-primary/10 data-highlighted:text-foreground data-[state=open]:bg-primary/10 data-[state=open]:text-foreground',
|
|
55
|
+
destructive: 'text-destructive hover:bg-destructive/10 hover:text-destructive focus:bg-destructive/10 focus:text-destructive data-highlighted:bg-destructive/10 data-highlighted:text-destructive',
|
|
56
|
+
};
|
|
57
|
+
/** `className` last so a caller can still override any of it. */
|
|
58
|
+
export function menuRow(size, tone, className) {
|
|
59
|
+
return cn(MENU_ROW_BASE, MENU_ROW_SIZE[size], MENU_ROW_TONE[tone], className);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The floating surface. Every panel that opens over the page wears it:
|
|
63
|
+
* `DropdownMenuContent` / `SubContent`, `ContextMenuContent` / `SubContent`,
|
|
64
|
+
* `SelectContent`, `PopoverContent`.
|
|
65
|
+
*
|
|
66
|
+
* They are the same object — a hairline-bordered card lifted off the canvas —
|
|
67
|
+
* and they had four different descriptions of it:
|
|
68
|
+
*
|
|
69
|
+
* dropdown bg-background radius calc(--radius+0.2rem) shadow-lg p-1
|
|
70
|
+
* context bg-popover radius --radius-md shadow-md p-1
|
|
71
|
+
* select bg-background radius calc(--radius+0.2rem) shadow-lg p-1 + hover:text-foreground
|
|
72
|
+
* popover bg-popover radius --radius-lg (none) p-4
|
|
73
|
+
*
|
|
74
|
+
* `bg-popover` is the resolved answer. In light mode `--popover` and
|
|
75
|
+
* `--background` are both `oklch(1 0 0)`, so nothing moves; in dark mode
|
|
76
|
+
* `--popover` is `oklch(0.1913)` against a `oklch(0.1398)` canvas, and
|
|
77
|
+
* `globals.css` describes it as "top surface, separated by hairline + shadow" —
|
|
78
|
+
* which is this element's entire job. On `bg-background` a dark-mode dropdown
|
|
79
|
+
* was the same colour as the page behind it.
|
|
80
|
+
*
|
|
81
|
+
* Popover also had no shadow at all, so it sat flat on the canvas while the
|
|
82
|
+
* menus lifted. `shadow-lg` for all of them.
|
|
83
|
+
*
|
|
84
|
+
* Four things are deliberately absent, because each is dictated by what the
|
|
85
|
+
* panel holds rather than by what it is:
|
|
86
|
+
*
|
|
87
|
+
* - **Padding.** A list of rows uses `p-1` (see `MENU_PANEL`); a popover holds
|
|
88
|
+
* prose and controls and uses `p-4`.
|
|
89
|
+
* - **Width.** Every menu call site passes its own (`w-40`, `w-48`, `w-64`),
|
|
90
|
+
* and `width` and `min-width` are separate tailwind-merge groups, so a shared
|
|
91
|
+
* `min-w-[14rem]` would survive and silently override a caller's `w-40`.
|
|
92
|
+
* - **Overflow.** A context menu's root panel scrolls; the rest clip. `overflow`,
|
|
93
|
+
* `overflow-x` and `overflow-y` are three separate tailwind-merge groups, so a
|
|
94
|
+
* shared `overflow-hidden` would survive alongside a later `overflow-y-auto`
|
|
95
|
+
* and the winner would come down to Tailwind's generated property order.
|
|
96
|
+
* - **Transform origin.** Anchored panels scale out of their trigger, and the
|
|
97
|
+
* Radix variable that carries it is named per primitive.
|
|
98
|
+
*
|
|
99
|
+
* No `hover:text-foreground` here either — select had it. On the panel it
|
|
100
|
+
* recoloured every row at once whenever the pointer entered, fighting the
|
|
101
|
+
* per-row hover the rows define themselves. Colour is a row concern.
|
|
102
|
+
*/
|
|
103
|
+
/**
|
|
104
|
+
* The surface itself — colour, hairline, radius, elevation. No motion.
|
|
105
|
+
*
|
|
106
|
+
* Split out from the motion classes so a panel that must appear INSTANTLY can
|
|
107
|
+
* take the surface without inheriting the enter/exit animation. A submenu is
|
|
108
|
+
* the case that needs it: it opens under a pointer that is already travelling
|
|
109
|
+
* toward its first row, so the 150ms `animate-in` is 150ms of the row sliding
|
|
110
|
+
* away from the cursor.
|
|
111
|
+
*/
|
|
112
|
+
export const FLOATING_PANEL_SURFACE = 'bg-popover text-popover-foreground border-border rounded-lg border shadow-md';
|
|
113
|
+
/** Enter/exit for panels that appear away from the pointer's path. */
|
|
114
|
+
export const FLOATING_PANEL_MOTION = 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ease-out';
|
|
115
|
+
export const FLOATING_PANEL = cn(FLOATING_PANEL_SURFACE, FLOATING_PANEL_MOTION);
|
|
116
|
+
/** The floating surface holding a list of rows: dropdown, context menu, select. */
|
|
117
|
+
export const MENU_PANEL = cn(FLOATING_PANEL, 'p-1');
|
|
118
|
+
/**
|
|
119
|
+
* `MENU_PANEL` with no enter/exit animation — paints on the same frame it
|
|
120
|
+
* mounts. Every dropdown panel (root and submenu) and every select list uses
|
|
121
|
+
* it, and `PopoverContent` takes `FLOATING_PANEL_SURFACE` for the same reason.
|
|
122
|
+
* The animated `MENU_PANEL` / `FLOATING_PANEL` remain for the context menu and
|
|
123
|
+
* the animated hover card.
|
|
124
|
+
*/
|
|
125
|
+
export const MENU_PANEL_STATIC = cn(FLOATING_PANEL_SURFACE, 'p-1 py-[0.25rem]');
|
|
126
|
+
/** Group label: `px-2` matches every row, so labels and rows share a left edge. */
|
|
127
|
+
export const MENU_LABEL = 'text-muted-foreground px-2 py-1 text-xs font-medium tracking-normal';
|
|
128
|
+
export const MENU_SEPARATOR = 'bg-border -mx-1.5 my-1 h-px';
|
|
129
|
+
export const MENU_SHORTCUT = 'ml-auto text-xs tracking-widest opacity-60';
|