@kortix/ui 0.0.0-stage → 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 +155 -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 +881 -4
- package/skills/kortix-ui/SKILL.md +150 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Command as CommandPrimitive } from 'cmdk';
|
|
4
|
+
import { useUiStrings } from '../../providers/ui-provider.js';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from './dialog.js';
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
|
|
8
|
+
import { cn } from '../../lib/utils.js';
|
|
9
|
+
const CMDK_SHARED_CLASSES = [
|
|
10
|
+
'[&_[cmdk-group]]:px-1.5',
|
|
11
|
+
'[&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0',
|
|
12
|
+
].join(' ');
|
|
13
|
+
/**
|
|
14
|
+
* `data-nav` records which input moved the highlight last: `pointer` or
|
|
15
|
+
* `keyboard`. `CommandItem` reads it to pick ONE highlight source.
|
|
16
|
+
*
|
|
17
|
+
* cmdk 0.2.1 selects a row on every `pointermove` through its store, so
|
|
18
|
+
* `data-selected` moves only after React re-renders the whole list. In the ⌘K
|
|
19
|
+
* palette that re-render trails the cursor: the row you left stays lit until
|
|
20
|
+
* it lands, which reads as a hover transition. In pointer mode the row paints
|
|
21
|
+
* from CSS `:hover` alone — the same instant highlight the sidebar session
|
|
22
|
+
* rows use. Keyboard mode keeps `data-selected`, because arrow keys have no
|
|
23
|
+
* `:hover` to follow.
|
|
24
|
+
*
|
|
25
|
+
* Written straight to the DOM node, not React state: a state update here would
|
|
26
|
+
* re-render the list on every pointer move, which is the lag this removes.
|
|
27
|
+
* cmdk calls a caller's `onKeyDown` before its own handler and spreads
|
|
28
|
+
* `onPointerMove` onto the root, so both reach the same element.
|
|
29
|
+
*/
|
|
30
|
+
function Command({ className, onKeyDown, onPointerMove, ...props }) {
|
|
31
|
+
return (_jsx(CommandPrimitive, { "data-slot": "command", className: cn('bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md', className), onKeyDown: (event) => {
|
|
32
|
+
event.currentTarget.dataset.nav = 'keyboard';
|
|
33
|
+
onKeyDown?.(event);
|
|
34
|
+
}, onPointerMove: (event) => {
|
|
35
|
+
if (event.pointerType === 'mouse' || event.pointerType === 'pen') {
|
|
36
|
+
event.currentTarget.dataset.nav = 'pointer';
|
|
37
|
+
}
|
|
38
|
+
onPointerMove?.(event);
|
|
39
|
+
}, ...props }));
|
|
40
|
+
}
|
|
41
|
+
function CommandDialog({ title, description, children, className, showCloseButton = true, ...props }) {
|
|
42
|
+
const strings = useUiStrings();
|
|
43
|
+
return (_jsxs(Dialog, { ...props, children: [_jsxs(DialogHeader, { className: "sr-only", children: [_jsx(DialogTitle, { children: title ?? strings.commandPaletteTitle }), _jsx(DialogDescription, { children: description ?? strings.commandPaletteDescription })] }), _jsx(DialogContent
|
|
44
|
+
// `data-[state=closed]:animate-none!` on the panel AND the overlay: the
|
|
45
|
+
// palette closes on the frame you dismiss it, with no exit animation.
|
|
46
|
+
// `DialogContent` and `DialogOverlay` both play a 200ms `animate-out`
|
|
47
|
+
// (fade, plus a zoom to 95% on the panel), and Radix Presence keeps the
|
|
48
|
+
// node mounted until `animationend` — so Escape, a selected command,
|
|
49
|
+
// or an outside click left the palette on screen for 200ms after it
|
|
50
|
+
// was done. With `animation-name: none`, Presence unmounts at once.
|
|
51
|
+
// `!` because tailwind-merge does not know `animate-out` (it comes from
|
|
52
|
+
// tw-animate-css) and keeps both classes; without it, the winner would
|
|
53
|
+
// be whichever utility Tailwind happens to emit last.
|
|
54
|
+
//
|
|
55
|
+
// `data-[state=open]:animate-none!` does the same for the way in. The
|
|
56
|
+
// stock 200ms fade + zoom from 95% made ⌘K — opened dozens of times a
|
|
57
|
+
// day, almost always from the keyboard — read as late and as growing
|
|
58
|
+
// out of the page. The palette now paints complete on the first frame.
|
|
59
|
+
, {
|
|
60
|
+
// `data-[state=closed]:animate-none!` on the panel AND the overlay: the
|
|
61
|
+
// palette closes on the frame you dismiss it, with no exit animation.
|
|
62
|
+
// `DialogContent` and `DialogOverlay` both play a 200ms `animate-out`
|
|
63
|
+
// (fade, plus a zoom to 95% on the panel), and Radix Presence keeps the
|
|
64
|
+
// node mounted until `animationend` — so Escape, a selected command,
|
|
65
|
+
// or an outside click left the palette on screen for 200ms after it
|
|
66
|
+
// was done. With `animation-name: none`, Presence unmounts at once.
|
|
67
|
+
// `!` because tailwind-merge does not know `animate-out` (it comes from
|
|
68
|
+
// tw-animate-css) and keeps both classes; without it, the winner would
|
|
69
|
+
// be whichever utility Tailwind happens to emit last.
|
|
70
|
+
//
|
|
71
|
+
// `data-[state=open]:animate-none!` does the same for the way in. The
|
|
72
|
+
// stock 200ms fade + zoom from 95% made ⌘K — opened dozens of times a
|
|
73
|
+
// day, almost always from the keyboard — read as late and as growing
|
|
74
|
+
// out of the page. The palette now paints complete on the first frame.
|
|
75
|
+
className: cn('p-0 shadow-[0_0_50px_0] shadow-black/10 data-[state=open]:animate-none! data-[state=closed]:animate-none! border', className), hideCloseButton: !showCloseButton, overlayClassName: "bg-black/20 backdrop-blur-[1px] data-[state=open]:animate-none! data-[state=closed]:animate-none!", children: _jsx(Command, { loop: true, className: "[&_[cmdk-group-heading]]:text-muted-foreground bg-popover **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12", children: children }) })] }));
|
|
76
|
+
}
|
|
77
|
+
function CommandInput({ className, compact, leftElement, rightElement, ...props }) {
|
|
78
|
+
return (_jsxs("div", { "data-slot": "command-input-wrapper", className: cn('border-border flex items-center border-b', compact ? 'h-11 gap-2.5 px-4' : 'h-10 gap-3 px-4'), children: [leftElement, _jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50', compact ? 'h-11' : 'h-10', className), ...props }), rightElement] }));
|
|
79
|
+
}
|
|
80
|
+
function CommandList({ className, ...props }) {
|
|
81
|
+
return (_jsx(CommandPrimitive.List, { "data-slot": "command-list", className: cn('max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto', className), ...props }));
|
|
82
|
+
}
|
|
83
|
+
function CommandEmpty({ ...props }) {
|
|
84
|
+
return (_jsx(CommandPrimitive.Empty, { "data-slot": "command-empty", className: "py-6 text-center text-sm", ...props }));
|
|
85
|
+
}
|
|
86
|
+
function CommandGroup({ className, ...props }) {
|
|
87
|
+
return (_jsx(CommandPrimitive.Group, { "data-slot": "command-group", className: cn('text-foreground [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:text-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-[13px] [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:tracking-normal', className), ...props }));
|
|
88
|
+
}
|
|
89
|
+
function CommandSeparator({ className, ...props }) {
|
|
90
|
+
return (_jsx(CommandPrimitive.Separator, { "data-slot": "command-separator", className: cn('bg-border -mx-1 h-px', className), ...props }));
|
|
91
|
+
}
|
|
92
|
+
function CommandItem({ className, ...props }) {
|
|
93
|
+
return (_jsx(CommandPrimitive.Item, { "data-slot": "command-item",
|
|
94
|
+
// `hover:` mirrors the cmdk `data-[selected=true]` styling on purpose:
|
|
95
|
+
// cmdk paints its highlight from a JS pointermove -> select loop, and a
|
|
96
|
+
// page where anything swallows pointermove (observed on dev.kortix.com)
|
|
97
|
+
// renders NO hover feedback at all while clicks keep working. CSS :hover
|
|
98
|
+
// is driven by browser hit-testing, so the row under the cursor is
|
|
99
|
+
// always highlighted; when cmdk's pointer selection works the two states
|
|
100
|
+
// coincide on the same row.
|
|
101
|
+
//
|
|
102
|
+
// `data-[selected=true]` is scoped to NOT pointer mode (`data-nav` on the
|
|
103
|
+
// `Command` root — see there). With a mouse, `:hover` is the only
|
|
104
|
+
// highlight, so it follows the cursor on the frame it moves instead of
|
|
105
|
+
// waiting for cmdk's re-render. With the keyboard, `data-selected` is.
|
|
106
|
+
// A caller that restyles the selected row must write the same
|
|
107
|
+
// `[&:not([data-nav=pointer]_*)]:data-[selected=true]:` prefix, so
|
|
108
|
+
// tailwind-merge replaces this class instead of stacking a second one.
|
|
109
|
+
className: cn(
|
|
110
|
+
// `bg-hover`: the fill of a project sidebar session row on hover.
|
|
111
|
+
// That row paints `--card` on the canvas; in light mode `--hover`
|
|
112
|
+
// (ink @ 4.5%) over the white popover blends to the same #f3f3f3–
|
|
113
|
+
// #f4f4f4. `bg-card` itself cannot be used here: dark-theme `--card`
|
|
114
|
+
// and `--accent` ARE `--popover` (all surface-1), so it would paint
|
|
115
|
+
// invisibly on this panel. `--hover` is translucent ink, so it reads
|
|
116
|
+
// on any surface in both themes. It replaced `bg-primary/10`, which
|
|
117
|
+
// read too dark next to the sidebar rows.
|
|
118
|
+
'hover:bg-hover hover:text-foreground transition-none', '[&:not([data-nav=pointer]_*)]:data-[selected=true]:bg-hover [&:not([data-nav=pointer]_*)]:data-[selected=true]:text-foreground', "[&_svg:not([class*='text-'])]:text-muted-foreground relative flex items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props }));
|
|
119
|
+
}
|
|
120
|
+
function CommandShortcut({ className, ...props }) {
|
|
121
|
+
return (_jsx("span", { "data-slot": "command-shortcut", className: cn('text-muted-foreground ml-auto text-xs tracking-widest', className), ...props }));
|
|
122
|
+
}
|
|
123
|
+
function CommandFooter({ className, children, ...props }) {
|
|
124
|
+
return (_jsx("div", { "data-slot": "command-footer", className: cn('text-muted-foreground flex items-center gap-4 border-t px-4 py-2 text-xs', className), ...props, children: children }));
|
|
125
|
+
}
|
|
126
|
+
function CommandPopover({ open, onOpenChange, children, modal = true, }) {
|
|
127
|
+
return (_jsx(Popover, { open: open, onOpenChange: onOpenChange, modal: modal, children: children }));
|
|
128
|
+
}
|
|
129
|
+
const CommandPopoverTrigger = React.forwardRef(function CommandPopoverTrigger({ children, ...props }, ref) {
|
|
130
|
+
return (_jsx(PopoverTrigger, { ref: ref, asChild: true, ...props, children: children }));
|
|
131
|
+
});
|
|
132
|
+
function CommandPopoverContent({ children, side = 'top', align = 'start', sideOffset = 8, className, shouldFilter = false, defaultValue, }) {
|
|
133
|
+
return (_jsx(PopoverContent, { side: side, align: align, sideOffset: sideOffset, className: cn('bg-sidebar text-sidebar-foreground hover:text-foreground relative w-[300px] overflow-hidden rounded-lg border p-0 shadow-xs ease-out', 'border-border', 'data-[state=closed]:duration-[140ms] data-[state=open]:duration-[180ms]', 'data-[state=open]:zoom-in-[0.97] data-[state=closed]:zoom-out-[0.97]', '[&_[data-slot=command-input-wrapper]]:h-9 [&_[data-slot=command-input-wrapper]]:gap-2 [&_[data-slot=command-input-wrapper]]:px-3', '[&_[data-slot=command-input]]:h-9 [&_[data-slot=command-input]]:text-sm', '[&_[data-slot=command-list]]:py-0', '[&_[data-slot=command-group]]:py-1', '[&_[cmdk-group-heading]]:!px-2 [&_[cmdk-group-heading]]:!pt-2 [&_[cmdk-group-heading]]:!pb-1 [&_[cmdk-group-heading]]:!text-xs [&_[cmdk-group-heading]]:!tracking-[0.12em]', className), children: _jsx(Command, { shouldFilter: shouldFilter, defaultValue: defaultValue, className: CMDK_SHARED_CLASSES, children: children }) }));
|
|
134
|
+
}
|
|
135
|
+
export { Command, CommandDialog, CommandEmpty, CommandFooter, CommandGroup, CommandInput, CommandItem, CommandList, CommandPopover, CommandPopoverContent, CommandPopoverTrigger, CommandSeparator, CommandShortcut, };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface ConfirmDialogProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
onOpenChange: (open: boolean) => void;
|
|
4
|
+
title: string;
|
|
5
|
+
description: React.ReactNode;
|
|
6
|
+
confirmLabel?: string;
|
|
7
|
+
cancelLabel?: string;
|
|
8
|
+
onConfirm: () => void;
|
|
9
|
+
isPending?: boolean;
|
|
10
|
+
/** Render the confirm button in destructive red. Use for delete /
|
|
11
|
+
* revoke / disable-security-feature flows. */
|
|
12
|
+
confirmVariant?: 'default' | 'destructive';
|
|
13
|
+
/** Optional leading icon on the confirm button. */
|
|
14
|
+
confirmIcon?: React.ReactNode;
|
|
15
|
+
/** Keep the confirm button disabled, e.g. until a typed confirmation matches. */
|
|
16
|
+
confirmDisabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function ConfirmDialog({ open, onOpenChange, title, description, confirmLabel, cancelLabel, onConfirm, isPending, confirmVariant, confirmIcon, confirmDisabled, }: ConfirmDialogProps): import("react").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Reusable confirmation dialog — used for delete, destructive actions, etc.
|
|
5
|
+
*
|
|
6
|
+
* <ConfirmDialog
|
|
7
|
+
* open={open}
|
|
8
|
+
* onOpenChange={setOpen}
|
|
9
|
+
* title="Delete task"
|
|
10
|
+
* description="This will permanently delete the task and all comments."
|
|
11
|
+
* confirmLabel="Delete"
|
|
12
|
+
* onConfirm={() => deleteMutation.mutate(id)}
|
|
13
|
+
* isPending={deleteMutation.isPending}
|
|
14
|
+
* destructive
|
|
15
|
+
* />
|
|
16
|
+
*/
|
|
17
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from './alert-dialog.js';
|
|
18
|
+
import { buttonVariants } from './button.js';
|
|
19
|
+
import { useUiStrings } from '../../providers/ui-provider.js';
|
|
20
|
+
import { cn } from '../../lib/utils.js';
|
|
21
|
+
export function ConfirmDialog({ open, onOpenChange, title, description, confirmLabel, cancelLabel, onConfirm, isPending, confirmVariant = 'default', confirmIcon, confirmDisabled, }) {
|
|
22
|
+
// The defaults are the viewer's language: an English literal here put
|
|
23
|
+
// "Cancel" under every translated dialog that passed no label (KRTX-2326).
|
|
24
|
+
const strings = useUiStrings();
|
|
25
|
+
const confirmText = confirmLabel ?? strings.confirm;
|
|
26
|
+
return (_jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(AlertDialogContent, { className: "sm:max-w-md", overlayClassName: "bg-black/25 backdrop-blur-sm", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: title }), _jsx(AlertDialogDescription, { asChild: true, children: _jsx("div", { children: description }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isPending, children: cancelLabel ?? strings.cancel }), _jsxs(AlertDialogAction, { onClick: (e) => {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
onConfirm();
|
|
29
|
+
}, disabled: isPending || confirmDisabled, className: cn(buttonVariants({ variant: confirmVariant, size: 'sm' }), 'gap-1.5'), children: [confirmIcon, isPending ? `${confirmText}…` : confirmText] })] })] }) }));
|
|
30
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { type MenuRowSize } from './menu-recipe.js';
|
|
4
|
+
declare const ContextMenu: React.FC<ContextMenuPrimitive.ContextMenuProps>;
|
|
5
|
+
declare const ContextMenuTrigger: React.ForwardRefExoticComponent<ContextMenuPrimitive.ContextMenuTriggerProps & React.RefAttributes<HTMLSpanElement>>;
|
|
6
|
+
declare const ContextMenuPortal: React.FC<ContextMenuPrimitive.ContextMenuPortalProps>;
|
|
7
|
+
declare const ContextMenuSub: React.FC<ContextMenuPrimitive.ContextMenuSubProps>;
|
|
8
|
+
declare const ContextMenuRadioGroup: React.ForwardRefExoticComponent<ContextMenuPrimitive.ContextMenuRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
9
|
+
declare const ContextMenuGroup: React.ForwardRefExoticComponent<ContextMenuPrimitive.ContextMenuGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
10
|
+
/**
|
|
11
|
+
* Takes the same `size` and `inset` props as `ContextMenuItem`, because a
|
|
12
|
+
* submenu trigger is a row like any other and has to line up with its siblings.
|
|
13
|
+
*
|
|
14
|
+
* The caret is `size-3.5` against the leading icon's `size-4`: it is an
|
|
15
|
+
* affordance, not content, and matching the icon's weight makes it compete with
|
|
16
|
+
* the label. `text-muted-foreground` for the same reason.
|
|
17
|
+
*/
|
|
18
|
+
declare const ContextMenuSubTrigger: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSubTriggerProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
19
|
+
inset?: boolean;
|
|
20
|
+
size?: MenuRowSize;
|
|
21
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
22
|
+
declare const ContextMenuSubContent: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSubContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
23
|
+
declare const ContextMenuContent: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
24
|
+
declare const ContextMenuItem: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
25
|
+
inset?: boolean;
|
|
26
|
+
variant?: "default" | "destructive";
|
|
27
|
+
size?: MenuRowSize;
|
|
28
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
29
|
+
declare const ContextMenuCheckboxItem: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuCheckboxItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
30
|
+
reverse?: boolean;
|
|
31
|
+
size?: MenuRowSize;
|
|
32
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
33
|
+
declare const ContextMenuRadioItem: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuRadioItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
34
|
+
size?: MenuRowSize;
|
|
35
|
+
side?: "left" | "right";
|
|
36
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
37
|
+
declare const ContextMenuLabel: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuLabelProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
38
|
+
inset?: boolean;
|
|
39
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
40
|
+
declare const ContextMenuSeparator: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
41
|
+
declare const ContextMenuShortcut: {
|
|
42
|
+
({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): React.JSX.Element;
|
|
43
|
+
displayName: string;
|
|
44
|
+
};
|
|
45
|
+
export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { CheckIcon as Check, CaretRightIcon as ChevronRight } from '@phosphor-icons/react';
|
|
4
|
+
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { cn } from '../../lib/utils.js';
|
|
7
|
+
import { floatingZ, useDialogDepth } from '../../lib/z-stack.js';
|
|
8
|
+
import { MENU_INDICATOR, MENU_INDICATOR_ICON, MENU_INSET, MENU_INSET_END, MENU_LABEL, MENU_PANEL, MENU_SEPARATOR, MENU_SHORTCUT, menuRow, } from './menu-recipe.js';
|
|
9
|
+
/**
|
|
10
|
+
* A right-click menu is the same menu as a click menu. It shares the row
|
|
11
|
+
* recipe, panel, label, separator and shortcut in `./menu-recipe` with
|
|
12
|
+
* `dropdown-menu.tsx`, so a `Rename` row looks identical whichever way the
|
|
13
|
+
* user reached it. Before this, the two menus disagreed on radius (sm vs md),
|
|
14
|
+
* horizontal padding (2 vs 2.5), highlight colour (`accent` vs `primary/10`)
|
|
15
|
+
* and resting text colour — and the file browser shows both.
|
|
16
|
+
*
|
|
17
|
+
* Three things stay local, because they are genuinely different:
|
|
18
|
+
*
|
|
19
|
+
* 1. **Width floor** — a dropdown matches its trigger, so it floors at 14rem.
|
|
20
|
+
* A context menu opens at the pointer with nothing to match, and every call
|
|
21
|
+
* site here passes its own width (`w-40`, `w-48`, `w-64`). A 14rem floor
|
|
22
|
+
* would override `w-40`, so this menu floors at 8rem.
|
|
23
|
+
*
|
|
24
|
+
* 2. **Transform origin** — the panel scales out of the point that was
|
|
25
|
+
* right-clicked (`--radix-context-menu-content-transform-origin`) rather
|
|
26
|
+
* than its own centre. The menu appearing to grow from the cursor is the
|
|
27
|
+
* whole spatial story of a context menu.
|
|
28
|
+
*
|
|
29
|
+
* 3. **Scroll** — `Content` caps at the available viewport height and scrolls,
|
|
30
|
+
* while `SubContent` clips like a dropdown. A context menu opened near the
|
|
31
|
+
* bottom edge of the window has no room to grow downward; clipping it would
|
|
32
|
+
* hide the last rows with no way to reach them.
|
|
33
|
+
*
|
|
34
|
+
* No trigger styling. `DropdownMenuTrigger` applies `triggerVariants` because
|
|
35
|
+
* a dropdown trigger is a button; a context-menu trigger is the region you
|
|
36
|
+
* right-click and must stay visually untouched.
|
|
37
|
+
*/
|
|
38
|
+
const CONTEXT_PANEL = cn(MENU_PANEL, 'min-w-[8rem] origin-(--radix-context-menu-content-transform-origin)');
|
|
39
|
+
const ContextMenu = ContextMenuPrimitive.Root;
|
|
40
|
+
const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
|
41
|
+
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
|
42
|
+
const ContextMenuSub = ContextMenuPrimitive.Sub;
|
|
43
|
+
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
|
44
|
+
const ContextMenuGroup = ContextMenuPrimitive.Group;
|
|
45
|
+
/**
|
|
46
|
+
* Takes the same `size` and `inset` props as `ContextMenuItem`, because a
|
|
47
|
+
* submenu trigger is a row like any other and has to line up with its siblings.
|
|
48
|
+
*
|
|
49
|
+
* The caret is `size-3.5` against the leading icon's `size-4`: it is an
|
|
50
|
+
* affordance, not content, and matching the icon's weight makes it compete with
|
|
51
|
+
* the label. `text-muted-foreground` for the same reason.
|
|
52
|
+
*/
|
|
53
|
+
const ContextMenuSubTrigger = React.forwardRef(({ className, inset, size = 'sm', children, ...props }, ref) => (_jsxs(ContextMenuPrimitive.SubTrigger, { ref: ref, "data-slot": "context-menu-sub-trigger", className: cn(menuRow(size, 'default'), inset && MENU_INSET, className), ...props, children: [children, _jsx(ChevronRight, { className: "text-muted-foreground ml-auto size-3.5" })] })));
|
|
54
|
+
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
|
55
|
+
const ContextMenuSubContent = React.forwardRef(({ className, sideOffset = 4, style, ...props }, ref) => {
|
|
56
|
+
const depth = useDialogDepth();
|
|
57
|
+
return (_jsx(ContextMenuPrimitive.SubContent, { ref: ref, sideOffset: sideOffset, "data-slot": "context-menu-sub-content", className: cn(CONTEXT_PANEL, 'overflow-hidden', className), style: { zIndex: floatingZ(depth), ...style }, ...props }));
|
|
58
|
+
});
|
|
59
|
+
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
60
|
+
const ContextMenuContent = React.forwardRef(({ className, style, ...props }, ref) => {
|
|
61
|
+
const depth = useDialogDepth();
|
|
62
|
+
return (_jsx(ContextMenuPrimitive.Portal, { children: _jsx(ContextMenuPrimitive.Content, { ref: ref, "data-slot": "context-menu-content", className: cn(CONTEXT_PANEL, 'max-h-(--radix-context-menu-content-available-height) overflow-x-hidden overflow-y-auto', className), style: { zIndex: floatingZ(depth), ...style }, ...props }) }));
|
|
63
|
+
});
|
|
64
|
+
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
65
|
+
const ContextMenuItem = React.forwardRef(({ className, inset, variant = 'default', size = 'sm', ...props }, ref) => (_jsx(ContextMenuPrimitive.Item, { ref: ref, "data-slot": "context-menu-item", className: cn(menuRow(size, variant), inset && MENU_INSET, className), ...props })));
|
|
66
|
+
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
|
67
|
+
const ContextMenuCheckboxItem = React.forwardRef(({ className, children, checked, reverse, size = 'sm', ...props }, ref) => (_jsxs(ContextMenuPrimitive.CheckboxItem, { ref: ref, "data-slot": "context-menu-checkbox-item",
|
|
68
|
+
// Same geometry as `DropdownMenuCheckboxItem` — see there.
|
|
69
|
+
className: cn(menuRow(size, 'default'), reverse ? MENU_INSET_END : MENU_INSET, className), checked: checked, ...props, children: [_jsx("span", { className: cn(MENU_INDICATOR, 'absolute', reverse ? 'right-2' : 'left-2'), children: _jsx(ContextMenuPrimitive.ItemIndicator, { children: _jsx(Check, { className: MENU_INDICATOR_ICON }) }) }), children] })));
|
|
70
|
+
ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
|
|
71
|
+
const ContextMenuRadioItem = React.forwardRef(({ className, children, size = 'sm', side = 'right', ...props }, ref) => {
|
|
72
|
+
/**
|
|
73
|
+
* A check, not a dot, and the same check `ContextMenuCheckboxItem` uses.
|
|
74
|
+
*
|
|
75
|
+
* This was `<CircleIcon className="size-2 fill-current" />`, which could not
|
|
76
|
+
* work: Phosphor's CircleIcon is a stroked outline, so `fill-current` painted
|
|
77
|
+
* nothing, and the row recipe's `[&_svg]:size-4` — a descendant selector —
|
|
78
|
+
* outranked the `size-2` sitting on the icon itself. The mark rendered as a
|
|
79
|
+
* hollow ring. No consumer renders a RadioItem, so nobody saw it.
|
|
80
|
+
*/
|
|
81
|
+
const indicator = (_jsx("span", { className: MENU_INDICATOR, children: _jsx(ContextMenuPrimitive.ItemIndicator, { children: _jsx(Check, { className: MENU_INDICATOR_ICON }) }) }));
|
|
82
|
+
return (_jsx(ContextMenuPrimitive.RadioItem, { ref: ref, "data-slot": "context-menu-radio-item", className: cn(menuRow(size, 'default'), className), ...props, children: side === 'left' ? (_jsxs(_Fragment, { children: [indicator, _jsx("span", { className: "flex min-w-0 flex-1 items-center gap-2", children: children })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex min-w-0 flex-1 items-center gap-2", children: children }), indicator] })) }));
|
|
83
|
+
});
|
|
84
|
+
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
|
85
|
+
const ContextMenuLabel = React.forwardRef(({ className, inset, ...props }, ref) => (_jsx(ContextMenuPrimitive.Label, { ref: ref, "data-slot": "context-menu-label", className: cn(MENU_LABEL, inset && MENU_INSET, className), ...props })));
|
|
86
|
+
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
|
87
|
+
const ContextMenuSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx(ContextMenuPrimitive.Separator, { ref: ref, "data-slot": "context-menu-separator", className: cn(MENU_SEPARATOR, className), ...props })));
|
|
88
|
+
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
|
89
|
+
const ContextMenuShortcut = ({ className, ...props }) => {
|
|
90
|
+
return (_jsx("span", { "data-slot": "context-menu-shortcut", className: cn(MENU_SHORTCUT, className), ...props }));
|
|
91
|
+
};
|
|
92
|
+
ContextMenuShortcut.displayName = 'ContextMenuShortcut';
|
|
93
|
+
export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE count beside a label: a sidebar row, a tab, a menu item, a button. The
|
|
3
|
+
* project sidebar's Review count is the reference: a tabular pill in the
|
|
4
|
+
* row's own text colour on a 15% tint, clamped at 99+ so it never pushes the
|
|
5
|
+
* label into an ellipsis. The tint carries the meaning, never decoration:
|
|
6
|
+
*
|
|
7
|
+
* - `waiting`: something waits on the person (Review, changes to review).
|
|
8
|
+
* - `reminder`: active reminders.
|
|
9
|
+
* - `conflict`: conflicts to resolve.
|
|
10
|
+
* - `neutral`: a plain tally (members, child sessions, a group's size).
|
|
11
|
+
*
|
|
12
|
+
* An overlay badge on an icon button's corner is a different pattern and does
|
|
13
|
+
* not use this.
|
|
14
|
+
*/
|
|
15
|
+
declare const TONE: {
|
|
16
|
+
readonly neutral: "bg-foreground/6";
|
|
17
|
+
readonly waiting: "bg-kortix-yellow/15";
|
|
18
|
+
readonly reminder: "bg-kortix-purple/15";
|
|
19
|
+
readonly conflict: "bg-kortix-orange/15";
|
|
20
|
+
};
|
|
21
|
+
export type CountBadgeTone = keyof typeof TONE;
|
|
22
|
+
export declare function CountBadge({ count, tone, className, ...props }: {
|
|
23
|
+
count: number;
|
|
24
|
+
tone?: CountBadgeTone;
|
|
25
|
+
} & Omit<React.ComponentProps<'span'>, 'children'>): import("react").JSX.Element;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from './badge.js';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* THE count beside a label: a sidebar row, a tab, a menu item, a button. The
|
|
6
|
+
* project sidebar's Review count is the reference: a tabular pill in the
|
|
7
|
+
* row's own text colour on a 15% tint, clamped at 99+ so it never pushes the
|
|
8
|
+
* label into an ellipsis. The tint carries the meaning, never decoration:
|
|
9
|
+
*
|
|
10
|
+
* - `waiting`: something waits on the person (Review, changes to review).
|
|
11
|
+
* - `reminder`: active reminders.
|
|
12
|
+
* - `conflict`: conflicts to resolve.
|
|
13
|
+
* - `neutral`: a plain tally (members, child sessions, a group's size).
|
|
14
|
+
*
|
|
15
|
+
* An overlay badge on an icon button's corner is a different pattern and does
|
|
16
|
+
* not use this.
|
|
17
|
+
*/
|
|
18
|
+
const TONE = {
|
|
19
|
+
neutral: 'bg-foreground/6',
|
|
20
|
+
waiting: 'bg-kortix-yellow/15',
|
|
21
|
+
reminder: 'bg-kortix-purple/15',
|
|
22
|
+
conflict: 'bg-kortix-orange/15',
|
|
23
|
+
};
|
|
24
|
+
export function CountBadge({ count, tone = 'neutral', className, ...props }) {
|
|
25
|
+
return (_jsx(Badge, { variant: "transparent", size: "tabular", className: cn(TONE[tone], 'shrink-0 text-current', className), ...props, children: count > 99 ? '99+' : count }));
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ColDef, type GridReadyEvent } from 'ag-grid-community';
|
|
2
|
+
export interface DataGridProps {
|
|
3
|
+
/** Column definitions. If omitted, auto-generated from data keys. */
|
|
4
|
+
columnDefs?: ColDef[];
|
|
5
|
+
/** Row data array (objects keyed by header names). */
|
|
6
|
+
rowData: Record<string, unknown>[];
|
|
7
|
+
/** Quick-filter text (global search). */
|
|
8
|
+
quickFilterText?: string;
|
|
9
|
+
/** Column keys to hide. */
|
|
10
|
+
hiddenColumns?: Set<string>;
|
|
11
|
+
/** Whether the grid is read-only (default: true). */
|
|
12
|
+
readOnly?: boolean;
|
|
13
|
+
/** Container className. */
|
|
14
|
+
className?: string;
|
|
15
|
+
/** Called when grid is ready. */
|
|
16
|
+
onGridReady?: (event: GridReadyEvent) => void;
|
|
17
|
+
/** Whether to auto-size columns to fit content on first render. */
|
|
18
|
+
autoSizeColumns?: boolean;
|
|
19
|
+
/** Whether to suppress right-click context menu (default: false). */
|
|
20
|
+
suppressContextMenu?: boolean;
|
|
21
|
+
/** Status bar info text (e.g. "1,234 rows"). */
|
|
22
|
+
statusText?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function DataGrid({ columnDefs: columnDefsProp, rowData, quickFilterText, hiddenColumns, readOnly, className, onGridReady, autoSizeColumns, suppressContextMenu, }: DataGridProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
import { AllCommunityModule, colorSchemeDarkBlue, colorSchemeLight, ModuleRegistry, themeQuartz, } from 'ag-grid-community';
|
|
5
|
+
import { AgGridReact } from 'ag-grid-react';
|
|
6
|
+
import { useIsDark } from '../../hooks/use-is-dark.js';
|
|
7
|
+
import { useCallback, useMemo, useRef } from 'react';
|
|
8
|
+
// Register all community modules once
|
|
9
|
+
ModuleRegistry.registerModules([AllCommunityModule]);
|
|
10
|
+
// ── Theme ────────────────────────────────────────────────────────────────
|
|
11
|
+
const gridTheme = themeQuartz.withParams({
|
|
12
|
+
spacing: 6,
|
|
13
|
+
headerFontSize: 12,
|
|
14
|
+
fontSize: 12,
|
|
15
|
+
rowHeight: 36,
|
|
16
|
+
headerHeight: 38,
|
|
17
|
+
wrapperBorderRadius: 0,
|
|
18
|
+
borderRadius: 0,
|
|
19
|
+
cellHorizontalPaddingScale: 1,
|
|
20
|
+
});
|
|
21
|
+
// ── Component ────────────────────────────────────────────────────────────
|
|
22
|
+
export function DataGrid({ columnDefs: columnDefsProp, rowData, quickFilterText, hiddenColumns, readOnly = true, className, onGridReady, autoSizeColumns = true, suppressContextMenu = false, }) {
|
|
23
|
+
const gridRef = useRef(null);
|
|
24
|
+
const isDark = useIsDark();
|
|
25
|
+
// ── Column defs ──────────────────────────────────────────────────────
|
|
26
|
+
const columnDefs = useMemo(() => {
|
|
27
|
+
if (columnDefsProp)
|
|
28
|
+
return columnDefsProp;
|
|
29
|
+
// Auto-generate from first row keys
|
|
30
|
+
if (!rowData || rowData.length === 0)
|
|
31
|
+
return [];
|
|
32
|
+
const keys = Object.keys(rowData[0]);
|
|
33
|
+
return keys.map((key) => ({
|
|
34
|
+
field: key,
|
|
35
|
+
headerName: key,
|
|
36
|
+
hide: hiddenColumns?.has(key) ?? false,
|
|
37
|
+
}));
|
|
38
|
+
}, [columnDefsProp, rowData, hiddenColumns]);
|
|
39
|
+
// ── Default col def — Excel-like defaults ────────────────────────────
|
|
40
|
+
const defaultColDef = useMemo(() => ({
|
|
41
|
+
sortable: true,
|
|
42
|
+
filter: true,
|
|
43
|
+
resizable: true,
|
|
44
|
+
editable: !readOnly,
|
|
45
|
+
minWidth: 80,
|
|
46
|
+
flex: columnDefs.length <= 8 ? 1 : undefined,
|
|
47
|
+
width: columnDefs.length > 8 ? 150 : undefined,
|
|
48
|
+
suppressHeaderMenuButton: false,
|
|
49
|
+
// Cell value formatting
|
|
50
|
+
valueFormatter: (params) => {
|
|
51
|
+
const v = params.value;
|
|
52
|
+
if (v == null || v === '')
|
|
53
|
+
return '';
|
|
54
|
+
if (typeof v === 'number')
|
|
55
|
+
return v.toLocaleString();
|
|
56
|
+
if (typeof v === 'boolean')
|
|
57
|
+
return v ? 'Yes' : 'No';
|
|
58
|
+
return String(v);
|
|
59
|
+
},
|
|
60
|
+
cellClass: (params) => {
|
|
61
|
+
if (typeof params.value === 'number')
|
|
62
|
+
return 'ag-right-aligned-cell';
|
|
63
|
+
return '';
|
|
64
|
+
},
|
|
65
|
+
}), [readOnly, columnDefs.length]);
|
|
66
|
+
// ── Auto-size columns on first data render ───────────────────────────
|
|
67
|
+
const handleFirstDataRendered = useCallback((event) => {
|
|
68
|
+
if (!autoSizeColumns)
|
|
69
|
+
return;
|
|
70
|
+
try {
|
|
71
|
+
// If few columns, let flex handle it. Otherwise auto-size.
|
|
72
|
+
if (columnDefs.length > 8) {
|
|
73
|
+
event.api.autoSizeAllColumns();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Silently fail — auto-size can throw if columns aren't ready
|
|
78
|
+
}
|
|
79
|
+
}, [autoSizeColumns, columnDefs.length]);
|
|
80
|
+
const handleGridReady = useCallback((event) => {
|
|
81
|
+
onGridReady?.(event);
|
|
82
|
+
}, [onGridReady]);
|
|
83
|
+
// ── Theme resolved ───────────────────────────────────────────────────
|
|
84
|
+
const theme = useMemo(() => {
|
|
85
|
+
const colorScheme = isDark ? colorSchemeDarkBlue : colorSchemeLight;
|
|
86
|
+
return gridTheme.withPart(colorScheme);
|
|
87
|
+
}, [isDark]);
|
|
88
|
+
// ── No data ──────────────────────────────────────────────────────────
|
|
89
|
+
if (!rowData || rowData.length === 0) {
|
|
90
|
+
return (_jsx("div", { className: cn('text-muted-foreground flex h-full w-full items-center justify-center text-sm', className), children: "No data" }));
|
|
91
|
+
}
|
|
92
|
+
return (_jsx("div", { className: cn('h-full w-full', className), children: _jsx(AgGridReact, { ref: gridRef, theme: theme, rowData: rowData, columnDefs: columnDefs, defaultColDef: defaultColDef,
|
|
93
|
+
// Virtual scrolling — no DOM bloat
|
|
94
|
+
rowBuffer: 20,
|
|
95
|
+
// Quick filter
|
|
96
|
+
quickFilterText: quickFilterText, cacheQuickFilter: true,
|
|
97
|
+
// Selection & clipboard
|
|
98
|
+
enableCellTextSelection: true, ensureDomOrder: true,
|
|
99
|
+
// Misc
|
|
100
|
+
animateRows: false, suppressContextMenu: suppressContextMenu, suppressMovableColumns: false, suppressColumnVirtualisation: columnDefs.length <= 20,
|
|
101
|
+
// Tooltips
|
|
102
|
+
tooltipShowDelay: 500,
|
|
103
|
+
// Events
|
|
104
|
+
onGridReady: handleGridReady, onFirstDataRendered: handleFirstDataRendered,
|
|
105
|
+
// No rows overlay
|
|
106
|
+
overlayNoRowsTemplate: '<span class="text-muted-foreground text-sm">No matching rows</span>' }) }));
|
|
107
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { DateRange } from 'react-day-picker';
|
|
2
|
+
export type CostRangePreset = '24h' | '7d' | '30d' | '90d' | 'custom';
|
|
3
|
+
export interface CostRange {
|
|
4
|
+
preset: CostRangePreset;
|
|
5
|
+
/** ISO 8601, UTC. Window start — inclusive. */
|
|
6
|
+
from: string;
|
|
7
|
+
/** ISO 8601, UTC. Window end — exclusive: bounds are always [from, to). */
|
|
8
|
+
to: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a preset to concrete UTC ISO bounds, anchored to `now`. Presets are
|
|
12
|
+
* a UI affordance only — every cost endpoint takes just `from`/`to`, so this
|
|
13
|
+
* is where a preset turns into the wire values.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolvePreset(preset: Exclude<CostRangePreset, 'custom'>, now: Date): CostRange;
|
|
16
|
+
/**
|
|
17
|
+
* Turn a calendar day selection into a half-open UTC window: `from` is the
|
|
18
|
+
* start of `startDay`, `to` is the start of the day *after* `endDay`, so the
|
|
19
|
+
* end day the user clicked is fully covered under `[from, to)`.
|
|
20
|
+
*
|
|
21
|
+
* `startDay`/`endDay` are the `Date` objects `react-day-picker` hands back —
|
|
22
|
+
* local midnight on the clicked calendar day. Reading their *local* calendar
|
|
23
|
+
* parts (`getFullYear`/`getMonth`/`getDate`) and rebuilding the instant with
|
|
24
|
+
* `Date.UTC` is what makes the result independent of the host's timezone;
|
|
25
|
+
* calling `.toISOString()` on the picked `Date` directly would instead bake
|
|
26
|
+
* in the host's UTC offset (see the test file for a worked example).
|
|
27
|
+
*/
|
|
28
|
+
export declare function toUtcDayRange(startDay: Date, endDay: Date): CostRange;
|
|
29
|
+
/**
|
|
30
|
+
* The inverse of `toUtcDayRange`, for feeding a stored `CostRange` back into
|
|
31
|
+
* `<Calendar mode="range">` on reopen. The stored bounds are UTC-midnight
|
|
32
|
+
* instants; `react-day-picker` highlights by *local* calendar day. Shifting
|
|
33
|
+
* the instant by milliseconds (an earlier version of this function did
|
|
34
|
+
* `getTime() - 86_400_000`) only relocates the instant — it does nothing to
|
|
35
|
+
* account for how a *different* host timezone reads that instant's local
|
|
36
|
+
* calendar day, so it "corrects" the display for positive-UTC-offset viewers
|
|
37
|
+
* by coincidence and is wrong in the opposite direction for negative-offset
|
|
38
|
+
* viewers (e.g. the Americas): both bounds land a day early there.
|
|
39
|
+
*
|
|
40
|
+
* The fix mirrors `toUtcDayRange` with its two steps reversed: read the
|
|
41
|
+
* *UTC* calendar parts off the stored instant (`getUTCFullYear`/
|
|
42
|
+
* `getUTCMonth`/`getUTCDate` — always host-independent), then rebuild via
|
|
43
|
+
* the *local* `Date` constructor, so the viewer's own host offset decides
|
|
44
|
+
* how the resulting `Date` reads back — the same offset `react-day-picker`
|
|
45
|
+
* itself will later use to highlight it. `new Date(y, m, d)` normalizes an
|
|
46
|
+
* out-of-range day (`d - 1` below zero, `d + 1` past the month's end), so
|
|
47
|
+
* month/year rollover needs no special-casing.
|
|
48
|
+
*/
|
|
49
|
+
export declare function toCalendarSelection(value: CostRange): {
|
|
50
|
+
from: Date;
|
|
51
|
+
to: Date;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The widest label `formatRangeLabel` can ever emit, used to reserve the
|
|
55
|
+
* trigger's width so the control does not resize when the range changes.
|
|
56
|
+
*
|
|
57
|
+
* The shape is fixed: `MMM D – MMM D, YYYY`. Every `en-US` short month name is
|
|
58
|
+
* three characters, the year is always four digits, and the widest day number
|
|
59
|
+
* is two digits — so a two-digit/two-digit pair is the maximum at 21
|
|
60
|
+
* characters. Digits are rendered `tabular-nums` on the trigger, so any
|
|
61
|
+
* two-digit day is exactly as wide as `28` and this string is not merely the
|
|
62
|
+
* longest, it is the widest for its digit positions.
|
|
63
|
+
*
|
|
64
|
+
* NOT `Dec 28, 2026 – Jan 3, 2027`: `formatRangeLabel` prints the year once,
|
|
65
|
+
* after the second day, so a range spanning a year boundary is *shorter* than
|
|
66
|
+
* this (`Dec 28 – Jan 3, 2027`), not longer. Sizing to the two-year shape
|
|
67
|
+
* would reserve ~5 characters of permanent dead space.
|
|
68
|
+
*
|
|
69
|
+
* The four preset labels are all shorter (`Last 24 hours`, 13 characters), so
|
|
70
|
+
* this one string governs the trigger width in every state.
|
|
71
|
+
*/
|
|
72
|
+
export declare const WIDEST_RANGE_LABEL = "Dec 28 \u2013 Dec 30, 2026";
|
|
73
|
+
/** Human label for the trigger button: the preset name, or both dates for a custom range. */
|
|
74
|
+
export declare function formatRangeLabel(range: CostRange): string;
|
|
75
|
+
/** One click's effect on a range that is being picked. */
|
|
76
|
+
export type RangeDraftStep = {
|
|
77
|
+
kind: 'pending';
|
|
78
|
+
draft: DateRange;
|
|
79
|
+
} | {
|
|
80
|
+
kind: 'complete';
|
|
81
|
+
from: Date;
|
|
82
|
+
to: Date;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* What a click on `day` does, given the half-made range currently on screen.
|
|
86
|
+
*
|
|
87
|
+
* This deliberately ignores the range `react-day-picker` hands to `onSelect`,
|
|
88
|
+
* because that value is the bug. Its `addToRange` folds the clicked day into
|
|
89
|
+
* whatever is currently `selected`, and `selected` is always a *complete*
|
|
90
|
+
* range here — a preset resolves to real bounds, so `from` and `to` are both
|
|
91
|
+
* set before the user ever opens the calendar. Feeding a complete range in
|
|
92
|
+
* takes the `from && to` branch, which returns another complete range from a
|
|
93
|
+
* single click:
|
|
94
|
+
*
|
|
95
|
+
* addToRange(Jul 10, { from: Jul 1, to: Jul 31 }) -> { from: Jul 1, to: Jul 10 }
|
|
96
|
+
*
|
|
97
|
+
* So the first click looked finished, the picker committed and closed, and a
|
|
98
|
+
* second date could never be chosen. Worse, the committed range was one the
|
|
99
|
+
* user never asked for: their click became the *end* of the previous range
|
|
100
|
+
* instead of the start of a new one.
|
|
101
|
+
*
|
|
102
|
+
* Deriving from the clicked day instead makes the two clicks explicit — the
|
|
103
|
+
* first opens a range, the second closes it, in whichever order they are
|
|
104
|
+
* clicked. Clicking the same day twice is a legitimate single-day range and
|
|
105
|
+
* completes normally.
|
|
106
|
+
*/
|
|
107
|
+
export declare function nextRangeDraft(draft: DateRange | undefined, day: Date): RangeDraftStep;
|
|
108
|
+
interface DateRangePickerProps {
|
|
109
|
+
value: CostRange;
|
|
110
|
+
onChange: (next: CostRange) => void;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The main control for all three levels of the cost explorer (project,
|
|
114
|
+
* sessions, session). A Popover holding a vertical preset rail beside a range
|
|
115
|
+
* Calendar; both paths resolve to concrete UTC ISO bounds before calling
|
|
116
|
+
* `onChange`.
|
|
117
|
+
*/
|
|
118
|
+
export declare function DateRangePicker({ value, onChange }: DateRangePickerProps): import("react").JSX.Element;
|
|
119
|
+
export {};
|