@atmos.build/ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/components/alert-dialog.d.ts +14 -0
- package/dist/components/alert-dialog.js +40 -0
- package/dist/components/at-search.d.ts +35 -0
- package/dist/components/at-search.js +57 -0
- package/dist/components/attachment-thumbnail-stack.d.ts +13 -0
- package/dist/components/attachment-thumbnail-stack.js +23 -0
- package/dist/components/audio-preview.d.ts +33 -0
- package/dist/components/audio-preview.js +176 -0
- package/dist/components/avatar-uploader.d.ts +29 -0
- package/dist/components/avatar-uploader.js +67 -0
- package/dist/components/avatar.d.ts +12 -0
- package/dist/components/avatar.js +38 -0
- package/dist/components/badge.d.ts +9 -0
- package/dist/components/badge.js +25 -0
- package/dist/components/button-group.d.ts +12 -0
- package/dist/components/button-group.js +29 -0
- package/dist/components/button.d.ts +10 -0
- package/dist/components/button.js +42 -0
- package/dist/components/calendar.d.ts +26 -0
- package/dist/components/calendar.js +154 -0
- package/dist/components/channel-list.d.ts +33 -0
- package/dist/components/channel-list.js +40 -0
- package/dist/components/charts/area-chart.d.ts +2 -0
- package/dist/components/charts/area-chart.js +5 -0
- package/dist/components/charts/bar-chart.d.ts +2 -0
- package/dist/components/charts/bar-chart.js +58 -0
- package/dist/components/charts/colors.d.ts +2 -0
- package/dist/components/charts/colors.js +42 -0
- package/dist/components/charts/hover.d.ts +20 -0
- package/dist/components/charts/hover.js +31 -0
- package/dist/components/charts/index.d.ts +10 -0
- package/dist/components/charts/index.js +9 -0
- package/dist/components/charts/layout.d.ts +35 -0
- package/dist/components/charts/layout.js +101 -0
- package/dist/components/charts/legend.d.ts +6 -0
- package/dist/components/charts/legend.js +7 -0
- package/dist/components/charts/line-area-chart.d.ts +4 -0
- package/dist/components/charts/line-area-chart.js +86 -0
- package/dist/components/charts/line-chart.d.ts +2 -0
- package/dist/components/charts/line-chart.js +5 -0
- package/dist/components/charts/pie-chart.d.ts +2 -0
- package/dist/components/charts/pie-chart.js +22 -0
- package/dist/components/charts/radar-chart.d.ts +2 -0
- package/dist/components/charts/radar-chart.js +29 -0
- package/dist/components/charts/radial-chart.d.ts +2 -0
- package/dist/components/charts/radial-chart.js +19 -0
- package/dist/components/charts/scatter-chart.d.ts +2 -0
- package/dist/components/charts/scatter-chart.js +16 -0
- package/dist/components/charts/story-data.d.ts +24 -0
- package/dist/components/charts/story-data.js +48 -0
- package/dist/components/charts/types.d.ts +43 -0
- package/dist/components/charts/types.js +1 -0
- package/dist/components/checkbox.d.ts +4 -0
- package/dist/components/checkbox.js +10 -0
- package/dist/components/chip.d.ts +25 -0
- package/dist/components/chip.js +36 -0
- package/dist/components/code-editor-theme.d.ts +19 -0
- package/dist/components/code-editor-theme.js +100 -0
- package/dist/components/collapsible-section-header.d.ts +82 -0
- package/dist/components/collapsible-section-header.js +82 -0
- package/dist/components/collection-view/collection-view-group-settings.d.ts +73 -0
- package/dist/components/collection-view/collection-view-group-settings.js +55 -0
- package/dist/components/collection-view/collection-view-settings.d.ts +115 -0
- package/dist/components/collection-view/collection-view-settings.js +146 -0
- package/dist/components/collection-view/collection-view.d.ts +87 -0
- package/dist/components/collection-view/collection-view.js +95 -0
- package/dist/components/collection-view/index.d.ts +6 -0
- package/dist/components/collection-view/index.js +6 -0
- package/dist/components/collection-view/use-collection-detail-navigation.d.ts +11 -0
- package/dist/components/collection-view/use-collection-detail-navigation.js +12 -0
- package/dist/components/collection-view/use-collection-escape.d.ts +9 -0
- package/dist/components/collection-view/use-collection-escape.js +20 -0
- package/dist/components/collection-view/use-collection-selection.d.ts +42 -0
- package/dist/components/collection-view/use-collection-selection.js +203 -0
- package/dist/components/color-picker.d.ts +18 -0
- package/dist/components/color-picker.js +77 -0
- package/dist/components/color-swatch-list.d.ts +16 -0
- package/dist/components/color-swatch-list.js +60 -0
- package/dist/components/combobox/combobox.d.ts +4 -0
- package/dist/components/combobox/combobox.js +70 -0
- package/dist/components/combobox/compound.d.ts +68 -0
- package/dist/components/combobox/compound.js +151 -0
- package/dist/components/combobox/context.d.ts +34 -0
- package/dist/components/combobox/context.js +123 -0
- package/dist/components/combobox/create-step.d.ts +12 -0
- package/dist/components/combobox/create-step.js +8 -0
- package/dist/components/combobox/index.d.ts +10 -0
- package/dist/components/combobox/index.js +5 -0
- package/dist/components/combobox/inline-create-form.d.ts +24 -0
- package/dist/components/combobox/inline-create-form.js +43 -0
- package/dist/components/combobox/types.d.ts +57 -0
- package/dist/components/combobox/types.js +10 -0
- package/dist/components/command.d.ts +35 -0
- package/dist/components/command.js +76 -0
- package/dist/components/comment-pin.d.ts +13 -0
- package/dist/components/comment-pin.js +33 -0
- package/dist/components/confidence-meter.d.ts +11 -0
- package/dist/components/confidence-meter.js +24 -0
- package/dist/components/context-menu.d.ts +31 -0
- package/dist/components/context-menu.js +54 -0
- package/dist/components/copy-button.d.ts +12 -0
- package/dist/components/copy-button.js +32 -0
- package/dist/components/date-picker.d.ts +29 -0
- package/dist/components/date-picker.js +86 -0
- package/dist/components/date-tile.d.ts +11 -0
- package/dist/components/date-tile.js +16 -0
- package/dist/components/date-time-picker.d.ts +25 -0
- package/dist/components/date-time-picker.js +153 -0
- package/dist/components/detail-breadcrumb-utils.d.ts +2 -0
- package/dist/components/detail-breadcrumb-utils.js +18 -0
- package/dist/components/detail-nav-bar.d.ts +28 -0
- package/dist/components/detail-nav-bar.js +28 -0
- package/dist/components/detail-top-bar.d.ts +49 -0
- package/dist/components/detail-top-bar.js +41 -0
- package/dist/components/dialog.d.ts +22 -0
- package/dist/components/dialog.js +51 -0
- package/dist/components/dropdown-menu.d.ts +29 -0
- package/dist/components/dropdown-menu.js +52 -0
- package/dist/components/editable-doc-title.d.ts +17 -0
- package/dist/components/editable-doc-title.js +147 -0
- package/dist/components/empty-state.d.ts +12 -0
- package/dist/components/empty-state.js +6 -0
- package/dist/components/filter-condition-editor.d.ts +18 -0
- package/dist/components/filter-condition-editor.js +102 -0
- package/dist/components/form-dialog.d.ts +30 -0
- package/dist/components/form-dialog.js +52 -0
- package/dist/components/formula-editor.d.ts +18 -0
- package/dist/components/formula-editor.js +154 -0
- package/dist/components/hover-card.d.ts +52 -0
- package/dist/components/hover-card.js +51 -0
- package/dist/components/icon-button.d.ts +15 -0
- package/dist/components/icon-button.js +18 -0
- package/dist/components/inline-alert.d.ts +11 -0
- package/dist/components/inline-alert.js +17 -0
- package/dist/components/input.d.ts +3 -0
- package/dist/components/input.js +7 -0
- package/dist/components/kanban-board.d.ts +27 -0
- package/dist/components/kanban-board.js +145 -0
- package/dist/components/kbd.d.ts +3 -0
- package/dist/components/kbd.js +8 -0
- package/dist/components/label.d.ts +4 -0
- package/dist/components/label.js +9 -0
- package/dist/components/markdown-editor/index.d.ts +4 -0
- package/dist/components/markdown-editor/index.js +2 -0
- package/dist/components/markdown-editor/markdown-editor.d.ts +16 -0
- package/dist/components/markdown-editor/markdown-editor.js +53 -0
- package/dist/components/markdown-editor/serialize.d.ts +12 -0
- package/dist/components/markdown-editor/serialize.js +122 -0
- package/dist/components/markdown-editor/vim.d.ts +8 -0
- package/dist/components/markdown-editor/vim.js +394 -0
- package/dist/components/metric-grid.d.ts +41 -0
- package/dist/components/metric-grid.js +39 -0
- package/dist/components/microphone-priority.d.ts +29 -0
- package/dist/components/microphone-priority.js +15 -0
- package/dist/components/middle-truncate.d.ts +6 -0
- package/dist/components/middle-truncate.js +15 -0
- package/dist/components/multi-combobox.d.ts +48 -0
- package/dist/components/multi-combobox.js +221 -0
- package/dist/components/naut-avatar-engine.d.ts +83 -0
- package/dist/components/naut-avatar-engine.js +803 -0
- package/dist/components/naut-avatar.d.ts +31 -0
- package/dist/components/naut-avatar.js +108 -0
- package/dist/components/navigable-list.d.ts +4 -0
- package/dist/components/navigable-list.js +20 -0
- package/dist/components/note-icon-picker.d.ts +20 -0
- package/dist/components/note-icon-picker.js +84 -0
- package/dist/components/note-icon.d.ts +690 -0
- package/dist/components/note-icon.js +353 -0
- package/dist/components/note-row.d.ts +33 -0
- package/dist/components/note-row.js +29 -0
- package/dist/components/overlapping-dots.d.ts +10 -0
- package/dist/components/overlapping-dots.js +13 -0
- package/dist/components/overview-card.d.ts +12 -0
- package/dist/components/overview-card.js +9 -0
- package/dist/components/panel-header.d.ts +8 -0
- package/dist/components/panel-header.js +6 -0
- package/dist/components/panel-section-states.d.ts +9 -0
- package/dist/components/panel-section-states.js +10 -0
- package/dist/components/person-avatar.d.ts +10 -0
- package/dist/components/person-avatar.js +23 -0
- package/dist/components/photo-avatar.d.ts +11 -0
- package/dist/components/photo-avatar.js +24 -0
- package/dist/components/picker-field.d.ts +23 -0
- package/dist/components/picker-field.js +24 -0
- package/dist/components/popover-stack.d.ts +26 -0
- package/dist/components/popover-stack.js +89 -0
- package/dist/components/popover.d.ts +12 -0
- package/dist/components/popover.js +31 -0
- package/dist/components/portal-login-barrier.d.ts +12 -0
- package/dist/components/portal-login-barrier.js +41 -0
- package/dist/components/presence-dot.d.ts +8 -0
- package/dist/components/presence-dot.js +15 -0
- package/dist/components/presence-overlay.d.ts +27 -0
- package/dist/components/presence-overlay.js +34 -0
- package/dist/components/property-list.d.ts +64 -0
- package/dist/components/property-list.js +313 -0
- package/dist/components/property-panel.d.ts +54 -0
- package/dist/components/property-panel.js +87 -0
- package/dist/components/property-selector.d.ts +36 -0
- package/dist/components/property-selector.js +141 -0
- package/dist/components/provenance-chip.d.ts +12 -0
- package/dist/components/provenance-chip.js +17 -0
- package/dist/components/qr-code.d.ts +13 -0
- package/dist/components/qr-code.js +42 -0
- package/dist/components/qr-encode.d.ts +2 -0
- package/dist/components/qr-encode.js +469 -0
- package/dist/components/quantity-stepper.d.ts +25 -0
- package/dist/components/quantity-stepper.js +43 -0
- package/dist/components/radio-group.d.ts +5 -0
- package/dist/components/radio-group.js +13 -0
- package/dist/components/rename-dialog.d.ts +19 -0
- package/dist/components/rename-dialog.js +35 -0
- package/dist/components/row-surface.d.ts +1 -0
- package/dist/components/row-surface.js +5 -0
- package/dist/components/row-trailing.d.ts +30 -0
- package/dist/components/row-trailing.js +59 -0
- package/dist/components/run-status-badge.d.ts +16 -0
- package/dist/components/run-status-badge.js +43 -0
- package/dist/components/scroll-area.d.ts +5 -0
- package/dist/components/scroll-area.js +12 -0
- package/dist/components/select.d.ts +15 -0
- package/dist/components/select.js +39 -0
- package/dist/components/selectable-card.d.ts +33 -0
- package/dist/components/selectable-card.js +66 -0
- package/dist/components/separator.d.ts +3 -0
- package/dist/components/separator.js +8 -0
- package/dist/components/settings-dialog-shell.d.ts +46 -0
- package/dist/components/settings-dialog-shell.js +48 -0
- package/dist/components/shimmer-text.d.ts +8 -0
- package/dist/components/shimmer-text.js +26 -0
- package/dist/components/side-panel-tokens.d.ts +27 -0
- package/dist/components/side-panel-tokens.js +26 -0
- package/dist/components/side-panel.d.ts +94 -0
- package/dist/components/side-panel.js +106 -0
- package/dist/components/skeleton.d.ts +2 -0
- package/dist/components/skeleton.js +6 -0
- package/dist/components/sortable.d.ts +65 -0
- package/dist/components/sortable.js +110 -0
- package/dist/components/spec-strip.d.ts +18 -0
- package/dist/components/spec-strip.js +15 -0
- package/dist/components/speech-playback.d.ts +25 -0
- package/dist/components/speech-playback.js +35 -0
- package/dist/components/sql-editor.d.ts +13 -0
- package/dist/components/sql-editor.js +228 -0
- package/dist/components/stat-tile.d.ts +7 -0
- package/dist/components/stat-tile.js +6 -0
- package/dist/components/status-badge.d.ts +17 -0
- package/dist/components/status-badge.js +8 -0
- package/dist/components/status-tone.d.ts +9 -0
- package/dist/components/status-tone.js +10 -0
- package/dist/components/sticky-header-fade.d.ts +8 -0
- package/dist/components/sticky-header-fade.js +11 -0
- package/dist/components/swatch-button.d.ts +14 -0
- package/dist/components/swatch-button.js +25 -0
- package/dist/components/switch.d.ts +6 -0
- package/dist/components/switch.js +9 -0
- package/dist/components/system-load/index.d.ts +6 -0
- package/dist/components/system-load/index.js +6 -0
- package/dist/components/system-load/load-block.d.ts +20 -0
- package/dist/components/system-load/load-block.js +23 -0
- package/dist/components/system-load/load-grid.d.ts +16 -0
- package/dist/components/system-load/load-grid.js +23 -0
- package/dist/components/system-load/load-meter.d.ts +25 -0
- package/dist/components/system-load/load-meter.js +29 -0
- package/dist/components/system-load/load-tone.d.ts +21 -0
- package/dist/components/system-load/load-tone.js +29 -0
- package/dist/components/system-load/meter-row.d.ts +31 -0
- package/dist/components/system-load/meter-row.js +29 -0
- package/dist/components/system-load/resource-meter.d.ts +19 -0
- package/dist/components/system-load/resource-meter.js +15 -0
- package/dist/components/tab-title-bar.d.ts +12 -0
- package/dist/components/tab-title-bar.js +9 -0
- package/dist/components/table.d.ts +10 -0
- package/dist/components/table.js +29 -0
- package/dist/components/tabs.d.ts +11 -0
- package/dist/components/tabs.js +97 -0
- package/dist/components/template-chip-input.d.ts +36 -0
- package/dist/components/template-chip-input.js +271 -0
- package/dist/components/template-input.d.ts +24 -0
- package/dist/components/template-input.js +57 -0
- package/dist/components/terminal-spinner.d.ts +11 -0
- package/dist/components/terminal-spinner.js +48 -0
- package/dist/components/textarea.d.ts +3 -0
- package/dist/components/textarea.js +7 -0
- package/dist/components/time-column.d.ts +24 -0
- package/dist/components/time-column.js +60 -0
- package/dist/components/timestamped-transcript.d.ts +38 -0
- package/dist/components/timestamped-transcript.js +29 -0
- package/dist/components/timezone-picker.d.ts +22 -0
- package/dist/components/timezone-picker.js +60 -0
- package/dist/components/tooltip.d.ts +11 -0
- package/dist/components/tooltip.js +29 -0
- package/dist/components/transcription-overlay.d.ts +47 -0
- package/dist/components/transcription-overlay.js +30 -0
- package/dist/components/usage-bar.d.ts +17 -0
- package/dist/components/usage-bar.js +26 -0
- package/dist/components/view-query-bar.d.ts +13 -0
- package/dist/components/view-query-bar.js +13 -0
- package/dist/components/view-query-controls.d.ts +159 -0
- package/dist/components/view-query-controls.js +109 -0
- package/dist/components/view-save-menu.d.ts +20 -0
- package/dist/components/view-save-menu.js +13 -0
- package/dist/components/view-sort-editor.d.ts +40 -0
- package/dist/components/view-sort-editor.js +47 -0
- package/dist/components/voice-line.d.ts +37 -0
- package/dist/components/voice-line.js +293 -0
- package/dist/components/weekly-schedule-editor.d.ts +15 -0
- package/dist/components/weekly-schedule-editor.js +28 -0
- package/dist/flow/canvas/canvas-frame.d.ts +160 -0
- package/dist/flow/canvas/canvas-frame.js +521 -0
- package/dist/flow/canvas/collaborator-layer.d.ts +12 -0
- package/dist/flow/canvas/collaborator-layer.js +43 -0
- package/dist/flow/canvas/connector-edge.d.ts +22 -0
- package/dist/flow/canvas/connector-edge.js +61 -0
- package/dist/flow/canvas/editor-context.d.ts +23 -0
- package/dist/flow/canvas/editor-context.js +6 -0
- package/dist/flow/canvas/graph-core.d.ts +60 -0
- package/dist/flow/canvas/graph-core.js +296 -0
- package/dist/flow/canvas/minimap-sticky-overlay.d.ts +4 -0
- package/dist/flow/canvas/minimap-sticky-overlay.js +45 -0
- package/dist/flow/canvas/node-card.d.ts +46 -0
- package/dist/flow/canvas/node-card.js +56 -0
- package/dist/flow/canvas/node-library.d.ts +40 -0
- package/dist/flow/canvas/node-library.js +54 -0
- package/dist/flow/canvas/sticky-notes.d.ts +25 -0
- package/dist/flow/canvas/sticky-notes.js +101 -0
- package/dist/flow/collaborative-graph-presence.d.ts +28 -0
- package/dist/flow/collaborative-graph-presence.js +55 -0
- package/dist/flow/collaborative-graph-sync.d.ts +40 -0
- package/dist/flow/collaborative-graph-sync.js +127 -0
- package/dist/flow/editor/adapter.d.ts +64 -0
- package/dist/flow/editor/adapter.js +1 -0
- package/dist/flow/editor/command-registry.d.ts +10 -0
- package/dist/flow/editor/command-registry.js +35 -0
- package/dist/flow/editor/dag-canvas.d.ts +18 -0
- package/dist/flow/editor/dag-canvas.js +33 -0
- package/dist/flow/editor/flow-editor.d.ts +54 -0
- package/dist/flow/editor/flow-editor.js +199 -0
- package/dist/flow/editor/issues-popover.d.ts +11 -0
- package/dist/flow/editor/issues-popover.js +70 -0
- package/dist/flow/editor/library-rail.d.ts +19 -0
- package/dist/flow/editor/library-rail.js +25 -0
- package/dist/flow/editor/make-controller.d.ts +18 -0
- package/dist/flow/editor/make-controller.js +44 -0
- package/dist/flow/editor/node-chip.d.ts +2 -0
- package/dist/flow/editor/node-chip.js +16 -0
- package/dist/flow/editor/save-publish-bar.d.ts +27 -0
- package/dist/flow/editor/save-publish-bar.js +14 -0
- package/dist/flow/editor/settings-dialog.d.ts +11 -0
- package/dist/flow/editor/settings-dialog.js +11 -0
- package/dist/flow/editor/settings-shell.d.ts +21 -0
- package/dist/flow/editor/settings-shell.js +20 -0
- package/dist/flow/editor/side-rail.d.ts +22 -0
- package/dist/flow/editor/side-rail.js +15 -0
- package/dist/flow/editor/use-dag-editor.d.ts +94 -0
- package/dist/flow/editor/use-dag-editor.js +502 -0
- package/dist/flow/index.d.ts +25 -0
- package/dist/flow/index.js +25 -0
- package/dist/flow/presence-motion.d.ts +10 -0
- package/dist/flow/presence-motion.js +88 -0
- package/dist/flow/styles.css +1 -0
- package/dist/flow/use-collaborative-graph.d.ts +61 -0
- package/dist/flow/use-collaborative-graph.js +396 -0
- package/dist/flow/use-debounced-value.d.ts +1 -0
- package/dist/flow/use-debounced-value.js +10 -0
- package/dist/hooks/use-detail-nav.d.ts +11 -0
- package/dist/hooks/use-detail-nav.js +49 -0
- package/dist/hooks/use-flush-on-hide.d.ts +1 -0
- package/dist/hooks/use-flush-on-hide.js +21 -0
- package/dist/hooks/use-media-query.d.ts +1 -0
- package/dist/hooks/use-media-query.js +20 -0
- package/dist/hooks/use-virtualizer.d.ts +1 -0
- package/dist/hooks/use-virtualizer.js +1 -0
- package/dist/index.d.ts +139 -0
- package/dist/index.js +139 -0
- package/dist/lib/brand-style.d.ts +6 -0
- package/dist/lib/brand-style.js +16 -0
- package/dist/lib/cn.d.ts +2 -0
- package/dist/lib/cn.js +5 -0
- package/dist/lib/composited-glint.d.ts +7 -0
- package/dist/lib/composited-glint.js +98 -0
- package/dist/lib/date-time-format.d.ts +2 -0
- package/dist/lib/date-time-format.js +21 -0
- package/dist/lib/disclosure-state.d.ts +11 -0
- package/dist/lib/disclosure-state.js +22 -0
- package/dist/lib/label-swatches.d.ts +10 -0
- package/dist/lib/label-swatches.js +24 -0
- package/dist/lib/local-ui-state.d.ts +10 -0
- package/dist/lib/local-ui-state.js +95 -0
- package/dist/lib/parse-loose-datetime.d.ts +1 -0
- package/dist/lib/parse-loose-datetime.js +180 -0
- package/dist/lib/parse-loose-time.d.ts +6 -0
- package/dist/lib/parse-loose-time.js +53 -0
- package/dist/lib/parse-loose.d.ts +1 -0
- package/dist/lib/parse-loose.js +170 -0
- package/dist/lib/react-19-jsx.d.ts +8 -0
- package/dist/lib/react-19-jsx.js +1 -0
- package/dist/lib/view-chrome.d.ts +5 -0
- package/dist/lib/view-chrome.js +5 -0
- package/dist/lib/view-query/config.d.ts +26 -0
- package/dist/lib/view-query/config.js +162 -0
- package/dist/lib/view-query/evaluate.d.ts +11 -0
- package/dist/lib/view-query/evaluate.js +196 -0
- package/dist/lib/view-query/group-order.d.ts +25 -0
- package/dist/lib/view-query/group-order.js +49 -0
- package/dist/lib/view-query/index.d.ts +6 -0
- package/dist/lib/view-query/index.js +6 -0
- package/dist/lib/view-query/model.d.ts +34 -0
- package/dist/lib/view-query/model.js +88 -0
- package/dist/lib/view-query/sort.d.ts +7 -0
- package/dist/lib/view-query/sort.js +30 -0
- package/dist/lib/view-query/types.d.ts +70 -0
- package/dist/lib/view-query/types.js +12 -0
- package/dist/lib/weekly-schedule.d.ts +8 -0
- package/dist/lib/weekly-schedule.js +10 -0
- package/dist/mcp-app/index.d.ts +4 -0
- package/dist/mcp-app/index.js +3 -0
- package/dist/mcp-app/shadcn.css +629 -0
- package/dist/mcp-app/styles.css +72 -0
- package/dist/mcp-app/theme.d.ts +2 -0
- package/dist/mcp-app/theme.js +62 -0
- package/dist/mcp-app/use-atmos-mcp-app.d.ts +109 -0
- package/dist/mcp-app/use-atmos-mcp-app.js +30 -0
- package/dist/mcp-app/vite.d.ts +7 -0
- package/dist/mcp-app/vite.js +30 -0
- package/dist/tokens/index.d.ts +7 -0
- package/dist/tokens/index.js +7 -0
- package/dist/tokens/semantic.css +110 -0
- package/dist/tokens/tokens.css +195 -0
- package/package.json +98 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, } from 'react';
|
|
4
|
+
import { Plus } from 'lucide-react';
|
|
5
|
+
import { TerminalSpinner } from '../terminal-spinner.js';
|
|
6
|
+
import { StackedPopover, StackedPopoverContent, StackedPopoverTrigger, } from '../popover-stack.js';
|
|
7
|
+
import { Kbd } from '../kbd.js';
|
|
8
|
+
import { cn } from '../../lib/cn.js';
|
|
9
|
+
import { CREATE_ROW, ComboboxProvider, useCombobox, } from './context.js';
|
|
10
|
+
const PORTAL_MARKER = 'data-combobox-portal';
|
|
11
|
+
function isInsidePickerPortal(node) {
|
|
12
|
+
let el = node instanceof Element ? node : node?.parentElement ?? null;
|
|
13
|
+
while (el) {
|
|
14
|
+
if (el.hasAttribute(PORTAL_MARKER))
|
|
15
|
+
return true;
|
|
16
|
+
el = el.parentElement;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
export function ComboboxRoot(props) {
|
|
21
|
+
return (_jsx(ComboboxProvider, { ...props, children: _jsx(PopoverBridge, { children: props.children }) }));
|
|
22
|
+
}
|
|
23
|
+
function PopoverBridge({ children }) {
|
|
24
|
+
const { open, setOpen } = useCombobox();
|
|
25
|
+
return (_jsx(StackedPopover, { open: open, onOpenChange: setOpen, children: children }));
|
|
26
|
+
}
|
|
27
|
+
export function ComboboxTrigger({ asChild, children, className, ...rest }) {
|
|
28
|
+
const { open, mode } = useCombobox();
|
|
29
|
+
const inCreateMode = mode === 'create';
|
|
30
|
+
if (asChild) {
|
|
31
|
+
return (_jsx(StackedPopoverTrigger, { asChild: true, ...rest, children: children }));
|
|
32
|
+
}
|
|
33
|
+
return (_jsx(StackedPopoverTrigger, { asChild: true, ...rest, children: _jsx("div", { className: cn('inline-flex', className), "aria-haspopup": inCreateMode ? 'dialog' : 'listbox', "aria-expanded": open, children: children }) }));
|
|
34
|
+
}
|
|
35
|
+
export function ComboboxContent({ className, ...rest }) {
|
|
36
|
+
const { inputRef } = useCombobox();
|
|
37
|
+
return (_jsx(StackedPopoverContent, { className: cn('w-72 p-0 gap-0 overflow-hidden relative isolate', className), align: "start", onCloseAutoFocus: (e) => {
|
|
38
|
+
rest.onCloseAutoFocus?.(e);
|
|
39
|
+
}, onInteractOutside: (e) => {
|
|
40
|
+
if (isInsidePickerPortal(e.target)) {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
rest.onInteractOutside?.(e);
|
|
45
|
+
}, onOpenAutoFocus: (e) => {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
inputRef.current?.focus();
|
|
48
|
+
rest.onOpenAutoFocus?.(e);
|
|
49
|
+
}, ...rest }));
|
|
50
|
+
}
|
|
51
|
+
export function ComboboxInput({ placeholder, triggerKey, loading, className }) {
|
|
52
|
+
const { listId, query, setQuery, activeId, inputRef, rowDomId, moveActive, selectActive, setOpen } = useCombobox();
|
|
53
|
+
const onKeyDown = useCallback((e) => {
|
|
54
|
+
if (e.key === 'ArrowDown') {
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
moveActive(1);
|
|
57
|
+
}
|
|
58
|
+
else if (e.key === 'ArrowUp') {
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
moveActive(-1);
|
|
61
|
+
}
|
|
62
|
+
else if (e.key === 'Enter') {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
selectActive();
|
|
65
|
+
}
|
|
66
|
+
else if (e.key === 'Escape') {
|
|
67
|
+
e.preventDefault();
|
|
68
|
+
setOpen(false);
|
|
69
|
+
}
|
|
70
|
+
}, [moveActive, selectActive, setOpen]);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
inputRef.current?.focus();
|
|
73
|
+
}, [inputRef]);
|
|
74
|
+
return (_jsxs("div", { className: "flex items-center gap-2 px-2.5 pt-2.5 pb-1.5 border-b border-border/60", children: [_jsx("input", { ref: inputRef, type: "text", role: "combobox", "aria-autocomplete": "list", "aria-controls": listId, "aria-expanded": true, "aria-activedescendant": activeId ? rowDomId(activeId) : undefined, value: query, placeholder: placeholder, onChange: (e) => setQuery(e.target.value), onKeyDown: onKeyDown, className: cn('flex-1 min-w-0 bg-transparent outline-none text-[13px] placeholder:text-muted-foreground/70', className) }), loading ? _jsx(TerminalSpinner, { tone: "muted", className: "shrink-0 text-[13px]" }) : null, triggerKey ? _jsx(Kbd, { className: "text-[10.5px] shrink-0", children: triggerKey }) : null] }));
|
|
75
|
+
}
|
|
76
|
+
export function ComboboxList({ children, className, label }) {
|
|
77
|
+
const { listId } = useCombobox();
|
|
78
|
+
return (_jsx("ul", { id: listId, role: "listbox", "aria-label": label ?? 'Search results', className: cn('max-h-[280px] overflow-y-auto py-1', className), children: children }));
|
|
79
|
+
}
|
|
80
|
+
export function ComboboxItem({ value, onSelect, selected = false, children, className, }) {
|
|
81
|
+
const { activeId, setActiveId, registerItem, rowDomId } = useCombobox();
|
|
82
|
+
const ref = useRef(null);
|
|
83
|
+
const active = activeId === value;
|
|
84
|
+
const onSelectRef = useRef(onSelect);
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
onSelectRef.current = onSelect;
|
|
87
|
+
});
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
const el = ref.current;
|
|
90
|
+
if (!el)
|
|
91
|
+
return;
|
|
92
|
+
return registerItem({ value, element: el, onSelect: () => onSelectRef.current() });
|
|
93
|
+
}, [registerItem, value]);
|
|
94
|
+
const content = typeof children === 'function' ? children({ active, selected }) : children;
|
|
95
|
+
return (
|
|
96
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events -- keyboard handled by the parent input via aria-activedescendant
|
|
97
|
+
_jsx("li", { ref: ref, id: rowDomId(value), role: "option", "aria-selected": selected, "data-active": active || undefined, onMouseEnter: () => setActiveId(value), onClick: () => onSelect(), className: cn('mx-1 px-2 py-1.5 rounded-md cursor-pointer text-[13px] text-foreground flex items-center gap-2', active && 'bg-accent text-accent-foreground', className), children: content }));
|
|
98
|
+
}
|
|
99
|
+
export function ComboboxItemActions({ children, className }) {
|
|
100
|
+
const stop = useCallback((e) => {
|
|
101
|
+
e.stopPropagation();
|
|
102
|
+
}, []);
|
|
103
|
+
return (_jsx("span", { role: "button", tabIndex: -1, className: cn('ml-auto flex items-center', className), onClick: stop, onKeyDown: stop, onMouseDown: stop, onPointerDown: stop, children: children }));
|
|
104
|
+
}
|
|
105
|
+
export const comboboxPortalProps = { [PORTAL_MARKER]: '' };
|
|
106
|
+
export function ComboboxEmpty({ children, pending, pendingText, className }) {
|
|
107
|
+
if (pending) {
|
|
108
|
+
return (_jsxs("li", { className: cn('flex items-center justify-center gap-2 px-3 py-6 text-[12px] text-muted-foreground', className), children: [_jsx(TerminalSpinner, { tone: "muted" }), pendingText] }));
|
|
109
|
+
}
|
|
110
|
+
return _jsx("li", { className: cn('px-3 py-6 text-center text-[12px] text-muted-foreground', className), children: children });
|
|
111
|
+
}
|
|
112
|
+
export function ComboboxCreate({ query, onCreate, label, className }) {
|
|
113
|
+
const { activeId, setActiveId, registerItem, rowDomId } = useCombobox();
|
|
114
|
+
const ref = useRef(null);
|
|
115
|
+
const active = activeId === CREATE_ROW;
|
|
116
|
+
const trimmedQuery = query.trim();
|
|
117
|
+
const onCreateRef = useRef(onCreate);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
onCreateRef.current = onCreate;
|
|
120
|
+
});
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
const el = ref.current;
|
|
123
|
+
if (!el)
|
|
124
|
+
return;
|
|
125
|
+
return registerItem({ value: CREATE_ROW, element: el, onSelect: () => onCreateRef.current() });
|
|
126
|
+
}, [registerItem]);
|
|
127
|
+
return (
|
|
128
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events -- keyboard handled by the parent input via aria-activedescendant
|
|
129
|
+
_jsxs("li", { ref: ref, id: rowDomId(CREATE_ROW), role: "option", "aria-selected": active, "data-active": active || undefined, onMouseEnter: () => setActiveId(CREATE_ROW), onClick: () => onCreate(), className: cn('mx-1 mt-1 px-2 py-1.5 rounded-md cursor-pointer border-t border-border/60 pt-2 flex items-center gap-2 text-[13px]', active && 'bg-accent text-accent-foreground', className), children: [_jsx(Plus, { className: "size-3.5 text-muted-foreground", strokeWidth: 1.8, "aria-hidden": true }), _jsx("span", { className: "text-foreground", children: trimmedQuery.length > 0 ? (_jsxs(_Fragment, { children: [label, ": ", _jsxs("span", { className: "text-foreground/90", children: ["\"", query, "\""] })] })) : (label) })] }));
|
|
130
|
+
}
|
|
131
|
+
export function ComboboxAction({ value, onSelect, children, className, }) {
|
|
132
|
+
const { activeId, setActiveId, registerItem, rowDomId } = useCombobox();
|
|
133
|
+
const ref = useRef(null);
|
|
134
|
+
const active = activeId === value;
|
|
135
|
+
const onSelectRef = useRef(onSelect);
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
onSelectRef.current = onSelect;
|
|
138
|
+
});
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
const el = ref.current;
|
|
141
|
+
if (!el)
|
|
142
|
+
return;
|
|
143
|
+
return registerItem({ value, element: el, onSelect: () => onSelectRef.current() });
|
|
144
|
+
}, [registerItem, value]);
|
|
145
|
+
return (
|
|
146
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events -- keyboard handled by the parent input via aria-activedescendant
|
|
147
|
+
_jsx("li", { ref: ref, id: rowDomId(value), role: "option", "aria-selected": active, "data-active": active || undefined, onMouseEnter: () => setActiveId(value), onClick: () => onSelect(), className: cn('mx-1 px-2 py-1.5 rounded-md cursor-pointer text-[13px] text-foreground flex items-center gap-2', active && 'bg-accent text-accent-foreground', className), children: children }));
|
|
148
|
+
}
|
|
149
|
+
export function ComboboxGroup({ label, children, className }) {
|
|
150
|
+
return (_jsxs("li", { role: "presentation", className: className, children: [label ? (_jsx("div", { className: "px-3 pt-2 pb-1 text-[11px] font-medium text-muted-foreground", children: label })) : null, _jsx("ul", { role: "group", "aria-label": label, children: children })] }));
|
|
151
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ReactNode, type RefObject } from 'react';
|
|
2
|
+
export declare const CREATE_ROW = "__create__";
|
|
3
|
+
type RegisteredItem = {
|
|
4
|
+
value: string;
|
|
5
|
+
order: number;
|
|
6
|
+
onSelect: () => void;
|
|
7
|
+
element: HTMLElement;
|
|
8
|
+
};
|
|
9
|
+
export type ComboboxContextValue = {
|
|
10
|
+
listId: string;
|
|
11
|
+
open: boolean;
|
|
12
|
+
setOpen: (next: boolean) => void;
|
|
13
|
+
mode: 'list' | 'create';
|
|
14
|
+
setMode: (next: 'list' | 'create') => void;
|
|
15
|
+
query: string;
|
|
16
|
+
setQuery: (next: string) => void;
|
|
17
|
+
debouncedQuery: string;
|
|
18
|
+
activeId: string | null;
|
|
19
|
+
setActiveId: (id: string | null) => void;
|
|
20
|
+
inputRef: RefObject<HTMLInputElement | null>;
|
|
21
|
+
rowDomId: (value: string) => string;
|
|
22
|
+
registerItem: (item: Omit<RegisteredItem, 'order'>) => () => void;
|
|
23
|
+
selectActive: () => void;
|
|
24
|
+
moveActive: (delta: 1 | -1) => void;
|
|
25
|
+
};
|
|
26
|
+
export declare function useCombobox(): ComboboxContextValue;
|
|
27
|
+
export type ComboboxProviderProps = {
|
|
28
|
+
open?: boolean;
|
|
29
|
+
onOpenChange?: (open: boolean) => void;
|
|
30
|
+
resetOnClose?: boolean;
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
};
|
|
33
|
+
export declare function ComboboxProvider({ open: openProp, onOpenChange, resetOnClose, children, }: ComboboxProviderProps): import("react").JSX.Element;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, } from 'react';
|
|
4
|
+
export const CREATE_ROW = '__create__';
|
|
5
|
+
const ComboboxContext = createContext(null);
|
|
6
|
+
export function useCombobox() {
|
|
7
|
+
const ctx = useContext(ComboboxContext);
|
|
8
|
+
if (!ctx) {
|
|
9
|
+
throw new Error('Combobox compound components must be used within <Combobox>');
|
|
10
|
+
}
|
|
11
|
+
return ctx;
|
|
12
|
+
}
|
|
13
|
+
export function ComboboxProvider({ open: openProp, onOpenChange, resetOnClose = true, children, }) {
|
|
14
|
+
const listId = useId();
|
|
15
|
+
const isControlled = openProp !== undefined;
|
|
16
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
|
|
17
|
+
const open = isControlled ? openProp : uncontrolledOpen;
|
|
18
|
+
const [mode, setMode] = useState('list');
|
|
19
|
+
const [query, setQueryState] = useState('');
|
|
20
|
+
const [debouncedQuery, setDebouncedQuery] = useState('');
|
|
21
|
+
const [activeOverride, setActiveOverride] = useState(null);
|
|
22
|
+
const inputRef = useRef(null);
|
|
23
|
+
const itemsRef = useRef(new Map());
|
|
24
|
+
const orderCounter = useRef(0);
|
|
25
|
+
const [orderedValues, setOrderedValues] = useState([]);
|
|
26
|
+
const syncOrder = useCallback(() => {
|
|
27
|
+
setOrderedValues(Array.from(itemsRef.current.values())
|
|
28
|
+
.sort((a, b) => a.order - b.order)
|
|
29
|
+
.map((i) => i.value));
|
|
30
|
+
}, []);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const handle = setTimeout(() => setDebouncedQuery(query), 100);
|
|
33
|
+
return () => clearTimeout(handle);
|
|
34
|
+
}, [query]);
|
|
35
|
+
const reset = useCallback(() => {
|
|
36
|
+
setQueryState('');
|
|
37
|
+
setDebouncedQuery('');
|
|
38
|
+
setMode('list');
|
|
39
|
+
setActiveOverride(null);
|
|
40
|
+
}, []);
|
|
41
|
+
const setOpen = useCallback((next) => {
|
|
42
|
+
if (!isControlled)
|
|
43
|
+
setUncontrolledOpen(next);
|
|
44
|
+
onOpenChange?.(next);
|
|
45
|
+
if (!next && resetOnClose)
|
|
46
|
+
reset();
|
|
47
|
+
}, [isControlled, onOpenChange, resetOnClose, reset]);
|
|
48
|
+
const setQuery = useCallback((next) => {
|
|
49
|
+
setQueryState(next);
|
|
50
|
+
setActiveOverride(null);
|
|
51
|
+
}, []);
|
|
52
|
+
const rowDomId = useCallback((value) => (value === CREATE_ROW ? `${listId}-create` : `${listId}-row-${value}`), [listId]);
|
|
53
|
+
const registerItem = useCallback((item) => {
|
|
54
|
+
itemsRef.current.set(item.value, { ...item, order: orderCounter.current++ });
|
|
55
|
+
syncOrder();
|
|
56
|
+
return () => {
|
|
57
|
+
itemsRef.current.delete(item.value);
|
|
58
|
+
syncOrder();
|
|
59
|
+
};
|
|
60
|
+
}, [syncOrder]);
|
|
61
|
+
const activeId = activeOverride && orderedValues.includes(activeOverride)
|
|
62
|
+
? activeOverride
|
|
63
|
+
: (orderedValues[0] ?? null);
|
|
64
|
+
const scrollActiveIntoView = useCallback((id) => {
|
|
65
|
+
if (!id)
|
|
66
|
+
return;
|
|
67
|
+
itemsRef.current.get(id)?.element.scrollIntoView({ block: 'nearest' });
|
|
68
|
+
}, []);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
scrollActiveIntoView(activeId);
|
|
71
|
+
}, [activeId, scrollActiveIntoView]);
|
|
72
|
+
const setActiveId = useCallback((id) => setActiveOverride(id), []);
|
|
73
|
+
const moveActive = useCallback((delta) => {
|
|
74
|
+
const values = Array.from(itemsRef.current.values())
|
|
75
|
+
.sort((a, b) => a.order - b.order)
|
|
76
|
+
.map((i) => i.value);
|
|
77
|
+
if (values.length === 0)
|
|
78
|
+
return;
|
|
79
|
+
setActiveOverride((prev) => {
|
|
80
|
+
const current = prev && values.includes(prev) ? prev : (values[0] ?? null);
|
|
81
|
+
const idx = current ? values.indexOf(current) : -1;
|
|
82
|
+
const next = (idx + delta + values.length) % values.length;
|
|
83
|
+
return values[next] ?? null;
|
|
84
|
+
});
|
|
85
|
+
}, []);
|
|
86
|
+
const selectActive = useCallback(() => {
|
|
87
|
+
if (!activeId)
|
|
88
|
+
return;
|
|
89
|
+
itemsRef.current.get(activeId)?.onSelect();
|
|
90
|
+
}, [activeId]);
|
|
91
|
+
const value = useMemo(() => ({
|
|
92
|
+
listId,
|
|
93
|
+
open,
|
|
94
|
+
setOpen,
|
|
95
|
+
mode,
|
|
96
|
+
setMode,
|
|
97
|
+
query,
|
|
98
|
+
setQuery,
|
|
99
|
+
debouncedQuery,
|
|
100
|
+
activeId,
|
|
101
|
+
setActiveId,
|
|
102
|
+
inputRef,
|
|
103
|
+
rowDomId,
|
|
104
|
+
registerItem,
|
|
105
|
+
selectActive,
|
|
106
|
+
moveActive,
|
|
107
|
+
}), [
|
|
108
|
+
listId,
|
|
109
|
+
open,
|
|
110
|
+
setOpen,
|
|
111
|
+
mode,
|
|
112
|
+
query,
|
|
113
|
+
setQuery,
|
|
114
|
+
debouncedQuery,
|
|
115
|
+
activeId,
|
|
116
|
+
setActiveId,
|
|
117
|
+
rowDomId,
|
|
118
|
+
registerItem,
|
|
119
|
+
selectActive,
|
|
120
|
+
moveActive,
|
|
121
|
+
]);
|
|
122
|
+
return (_jsx(ComboboxContext.Provider, { value: value, children: children }));
|
|
123
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type ComboboxLabels } from './types.js';
|
|
3
|
+
export interface ComboboxCreateStepContext<TItem> {
|
|
4
|
+
query: string;
|
|
5
|
+
onCreated: (item: TItem) => void;
|
|
6
|
+
onCancel: () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function ComboboxCreateStep({ label, children, labels: labelsProp, }: {
|
|
9
|
+
label: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
labels?: Partial<ComboboxLabels>;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { DEFAULT_COMBOBOX_LABELS } from './types.js';
|
|
4
|
+
export function ComboboxCreateStep({ label, children, labels: labelsProp, }) {
|
|
5
|
+
const labels = { ...DEFAULT_COMBOBOX_LABELS, ...labelsProp };
|
|
6
|
+
const noun = label.replace(/^create\s+/i, '');
|
|
7
|
+
return (_jsxs("div", { role: "form", "aria-label": labels.createForm(noun), children: [_jsx("div", { className: "px-3 pt-3 pb-1.5 text-[12px] font-medium text-muted-foreground", children: labels.creatingHeader(noun.toLowerCase()) }), _jsx("div", { className: "px-3 pb-3", children: children })] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Combobox } from './combobox.js';
|
|
2
|
+
export type { ComboboxProps, UseItemsResult } from './combobox.js';
|
|
3
|
+
export { InlineCreateForm } from './inline-create-form.js';
|
|
4
|
+
export type { InlineCreateFormProps } from './inline-create-form.js';
|
|
5
|
+
export { ComboboxCreateStep } from './create-step.js';
|
|
6
|
+
export type { ComboboxCreateStepContext } from './create-step.js';
|
|
7
|
+
export { ComboboxRoot, ComboboxTrigger, ComboboxContent, ComboboxInput, ComboboxList, ComboboxItem, ComboboxItemActions, ComboboxEmpty, ComboboxCreate, ComboboxAction, ComboboxGroup, comboboxPortalProps, } from './compound.js';
|
|
8
|
+
export type { ComboboxRootProps, ComboboxTriggerProps, ComboboxContentProps, ComboboxInputProps, ComboboxListProps, ComboboxItemProps, ComboboxItemActionsProps, ComboboxEmptyProps, ComboboxCreateProps, ComboboxActionProps, ComboboxGroupProps, } from './compound.js';
|
|
9
|
+
export { useCombobox, CREATE_ROW } from './context.js';
|
|
10
|
+
export type { ComboboxContextValue } from './context.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Combobox } from './combobox.js';
|
|
2
|
+
export { InlineCreateForm } from './inline-create-form.js';
|
|
3
|
+
export { ComboboxCreateStep } from './create-step.js';
|
|
4
|
+
export { ComboboxRoot, ComboboxTrigger, ComboboxContent, ComboboxInput, ComboboxList, ComboboxItem, ComboboxItemActions, ComboboxEmpty, ComboboxCreate, ComboboxAction, ComboboxGroup, comboboxPortalProps, } from './compound.js';
|
|
5
|
+
export { useCombobox, CREATE_ROW } from './context.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export type InlineCreateFormProps<TValues, TItem> = {
|
|
3
|
+
initialValues: TValues;
|
|
4
|
+
submit: (values: TValues) => Promise<TItem>;
|
|
5
|
+
onCreated: (item: TItem) => void;
|
|
6
|
+
onCancel: () => void;
|
|
7
|
+
children: (api: {
|
|
8
|
+
values: TValues;
|
|
9
|
+
setValues: (next: TValues | ((prev: TValues) => TValues)) => void;
|
|
10
|
+
submitting: boolean;
|
|
11
|
+
error: string | null;
|
|
12
|
+
}) => ReactNode;
|
|
13
|
+
submitLabel?: string;
|
|
14
|
+
cancelLabel?: string;
|
|
15
|
+
canSubmit?: (values: TValues) => boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
labels?: {
|
|
18
|
+
create: string;
|
|
19
|
+
cancel: string;
|
|
20
|
+
createFailed: string;
|
|
21
|
+
saving: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare function InlineCreateForm<TValues, TItem>(props: InlineCreateFormProps<TValues, TItem>): ReactNode;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState, } from 'react';
|
|
4
|
+
import { Button } from '../button.js';
|
|
5
|
+
import { cn } from '../../lib/cn.js';
|
|
6
|
+
export function InlineCreateForm(props) {
|
|
7
|
+
const labels = props.labels ?? { create: 'Create', cancel: 'Cancel', createFailed: 'Could not create item', saving: 'Saving…' };
|
|
8
|
+
const { initialValues, submit, onCreated, onCancel, children, submitLabel = labels.create, cancelLabel = labels.cancel, canSubmit, className, } = props;
|
|
9
|
+
const [values, setValues] = useState(initialValues);
|
|
10
|
+
const [submitting, setSubmitting] = useState(false);
|
|
11
|
+
const [error, setError] = useState(null);
|
|
12
|
+
const allowSubmit = !submitting && (canSubmit ? canSubmit(values) : true);
|
|
13
|
+
const doSubmit = useCallback(async () => {
|
|
14
|
+
if (!allowSubmit)
|
|
15
|
+
return;
|
|
16
|
+
setSubmitting(true);
|
|
17
|
+
setError(null);
|
|
18
|
+
try {
|
|
19
|
+
const item = await submit(values);
|
|
20
|
+
onCreated(item);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
setError(err instanceof Error ? err.message : labels.createFailed);
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
setSubmitting(false);
|
|
27
|
+
}
|
|
28
|
+
}, [allowSubmit, submit, values, onCreated, labels.createFailed]);
|
|
29
|
+
const onFormSubmit = (e) => {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
void doSubmit();
|
|
32
|
+
};
|
|
33
|
+
const onKeyDown = (e) => {
|
|
34
|
+
if (e.key === 'Escape') {
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
e.stopPropagation();
|
|
37
|
+
onCancel();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
return (
|
|
41
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- Esc cancel is a usability affordance for the popover host
|
|
42
|
+
_jsxs("form", { onSubmit: onFormSubmit, onKeyDown: onKeyDown, className: cn('flex flex-col gap-2.5', className), noValidate: true, children: [children({ values, setValues, submitting, error }), error && (_jsx("div", { role: "alert", className: "rounded-md border border-destructive/30 bg-destructive/5 px-2 py-1 text-[11.5px] text-destructive", children: error })), _jsxs("div", { className: "flex items-center justify-end gap-1.5 pt-1", children: [_jsx(Button, { type: "button", variant: "ghost", size: "xs", onClick: onCancel, disabled: submitting, children: cancelLabel }), _jsx(Button, { type: "submit", size: "xs", disabled: !allowSubmit, children: submitting ? labels.saving : submitLabel })] })] }));
|
|
43
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ComboboxCreateStepContext } from './create-step.js';
|
|
3
|
+
export type UseItemsResult<TItem> = {
|
|
4
|
+
data: TItem[] | undefined;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
isError: boolean;
|
|
7
|
+
refetch?: () => void;
|
|
8
|
+
};
|
|
9
|
+
export interface ComboboxLabels {
|
|
10
|
+
searchPlaceholder: string;
|
|
11
|
+
typeToSearch: string;
|
|
12
|
+
noMatches: string;
|
|
13
|
+
loadFailed: string;
|
|
14
|
+
retry: string;
|
|
15
|
+
searchResults: string;
|
|
16
|
+
createForm: (label: string) => string;
|
|
17
|
+
creatingHeader: (label: string) => string;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEFAULT_COMBOBOX_LABELS: ComboboxLabels;
|
|
20
|
+
export type ComboboxProps<TItem> = {
|
|
21
|
+
value: string | null;
|
|
22
|
+
onSelect: (item: TItem) => void;
|
|
23
|
+
useItems: (query: string) => UseItemsResult<TItem>;
|
|
24
|
+
getId: (item: TItem) => string;
|
|
25
|
+
getLabel?: (item: TItem) => string;
|
|
26
|
+
renderItem: (item: TItem, opts: {
|
|
27
|
+
active: boolean;
|
|
28
|
+
selected: boolean;
|
|
29
|
+
}) => ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* Optional section heading per item. When consecutive items resolve to
|
|
32
|
+
* different sections, a divider plus the new section's heading is rendered
|
|
33
|
+
* before the item; `undefined` items form the headingless leading section.
|
|
34
|
+
*/
|
|
35
|
+
getSection?: (item: TItem) => string | undefined;
|
|
36
|
+
createLabel: string;
|
|
37
|
+
renderCreateStep?: (ctx: ComboboxCreateStepContext<TItem>) => ReactNode;
|
|
38
|
+
CreateForm?: (props: {
|
|
39
|
+
initialValue: string;
|
|
40
|
+
onCreated: (item: TItem) => void;
|
|
41
|
+
onCancel: () => void;
|
|
42
|
+
}) => ReactNode;
|
|
43
|
+
onQuickCreate?: (query: string) => void;
|
|
44
|
+
children: ReactNode;
|
|
45
|
+
emptyText?: string;
|
|
46
|
+
loadingText?: string;
|
|
47
|
+
placeholder?: string;
|
|
48
|
+
triggerKey?: string;
|
|
49
|
+
allowCreate?: boolean;
|
|
50
|
+
showCreateWhenEmpty?: boolean;
|
|
51
|
+
createLabelWhenEmpty?: string;
|
|
52
|
+
contentClassName?: string;
|
|
53
|
+
triggerClassName?: string;
|
|
54
|
+
open?: boolean;
|
|
55
|
+
onOpenChange?: (open: boolean) => void;
|
|
56
|
+
labels?: Partial<ComboboxLabels>;
|
|
57
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const DEFAULT_COMBOBOX_LABELS = {
|
|
2
|
+
searchPlaceholder: 'Search…',
|
|
3
|
+
typeToSearch: 'Type to search',
|
|
4
|
+
noMatches: 'No matches',
|
|
5
|
+
loadFailed: 'Could not load results',
|
|
6
|
+
retry: 'Retry',
|
|
7
|
+
searchResults: 'Search results',
|
|
8
|
+
createForm: (label) => `Create ${label}`,
|
|
9
|
+
creatingHeader: (label) => `Creating ${label}`,
|
|
10
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Command as CommandPrimitive } from 'cmdk';
|
|
3
|
+
import { Dialog, DialogContent } from './dialog.js';
|
|
4
|
+
export type CommandDialogLayout = 'standard' | 'browser' | 'wide-preview';
|
|
5
|
+
declare function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>): React.JSX.Element;
|
|
6
|
+
declare function CommandDialog({ title, description, children, className, showCloseButton, contentProps, layout, ...props }: React.ComponentProps<typeof Dialog> & {
|
|
7
|
+
title: string;
|
|
8
|
+
description: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
showCloseButton?: boolean;
|
|
11
|
+
contentProps?: React.ComponentProps<typeof DialogContent>;
|
|
12
|
+
layout?: CommandDialogLayout;
|
|
13
|
+
}): React.JSX.Element;
|
|
14
|
+
declare function CommandInput({ className, variant, loading, leading, trailing, ...props }: React.ComponentProps<typeof CommandPrimitive.Input> & {
|
|
15
|
+
variant?: 'boxed' | 'inline' | 'footer';
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
leading?: React.ReactNode;
|
|
18
|
+
trailing?: React.ReactNode;
|
|
19
|
+
}): React.JSX.Element;
|
|
20
|
+
declare function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>): React.JSX.Element;
|
|
21
|
+
declare function CommandEmpty({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>): React.JSX.Element;
|
|
22
|
+
declare function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>): React.JSX.Element;
|
|
23
|
+
declare function CommandSeparator({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Separator>): React.JSX.Element;
|
|
24
|
+
declare function CommandItem({ className, children, showCheck, ...props }: React.ComponentProps<typeof CommandPrimitive.Item> & {
|
|
25
|
+
showCheck?: boolean;
|
|
26
|
+
}): React.JSX.Element;
|
|
27
|
+
declare function CommandShortcut({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
28
|
+
export interface CommandHint {
|
|
29
|
+
keys: string[];
|
|
30
|
+
label: string;
|
|
31
|
+
}
|
|
32
|
+
declare function CommandHints({ hints, className, children, ...props }: React.ComponentProps<'div'> & {
|
|
33
|
+
hints: readonly CommandHint[];
|
|
34
|
+
}): React.JSX.Element;
|
|
35
|
+
export { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandHints, CommandItem, CommandShortcut, CommandSeparator, };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Command as CommandPrimitive } from 'cmdk';
|
|
5
|
+
import { cva } from 'class-variance-authority';
|
|
6
|
+
import { cn } from '../lib/cn.js';
|
|
7
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './dialog.js';
|
|
8
|
+
import { SearchIcon, CheckIcon } from 'lucide-react';
|
|
9
|
+
import { Kbd, KbdGroup } from './kbd.js';
|
|
10
|
+
import { TerminalSpinner } from './terminal-spinner.js';
|
|
11
|
+
const commandDialogLayoutClassName = {
|
|
12
|
+
standard: 'sm:max-w-[40rem]',
|
|
13
|
+
browser: 'sm:max-w-[35rem]',
|
|
14
|
+
'wide-preview': 'sm:max-w-[55rem]',
|
|
15
|
+
};
|
|
16
|
+
function InputGroup({ className, ...props }) {
|
|
17
|
+
return (_jsx("div", { "data-slot": "input-group", role: "group", className: cn('group/input-group border-input has-disabled:bg-input/50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 relative flex h-8 w-full min-w-0 items-center rounded-lg border transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5', className), ...props }));
|
|
18
|
+
}
|
|
19
|
+
const inputGroupAddonVariants = cva("flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4", {
|
|
20
|
+
variants: {
|
|
21
|
+
align: {
|
|
22
|
+
'inline-start': 'order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]',
|
|
23
|
+
'inline-end': 'order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]',
|
|
24
|
+
'block-start': 'order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2',
|
|
25
|
+
'block-end': 'order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
defaultVariants: { align: 'inline-start' },
|
|
29
|
+
});
|
|
30
|
+
function InputGroupAddon({ className, align = 'inline-start', ...props }) {
|
|
31
|
+
return (_jsx("div", { role: "button", tabIndex: 0, "data-slot": "input-group-addon", "data-align": align, className: cn(inputGroupAddonVariants({ align }), className), onClick: (event) => {
|
|
32
|
+
if (event.target.closest('button'))
|
|
33
|
+
return;
|
|
34
|
+
event.currentTarget.parentElement?.querySelector('input')?.focus();
|
|
35
|
+
}, onKeyDown: (event) => {
|
|
36
|
+
if (event.key !== 'Enter' && event.key !== ' ')
|
|
37
|
+
return;
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
event.currentTarget.parentElement?.querySelector('input')?.focus();
|
|
40
|
+
}, ...props }));
|
|
41
|
+
}
|
|
42
|
+
function Command({ className, ...props }) {
|
|
43
|
+
return (_jsx(CommandPrimitive, { "data-slot": "command", className: cn('bg-popover text-popover-foreground flex size-full flex-col overflow-hidden rounded-xl! p-1', className), ...props }));
|
|
44
|
+
}
|
|
45
|
+
function CommandDialog({ title, description, children, className, showCloseButton = false, contentProps, layout = 'standard', ...props }) {
|
|
46
|
+
const { className: contentClassName, ...resolvedContentProps } = contentProps ?? {};
|
|
47
|
+
return (_jsxs(Dialog, { ...props, children: [_jsxs(DialogHeader, { className: "sr-only", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: description })] }), _jsx(DialogContent, { ...resolvedContentProps, "data-layout": layout, className: cn('atmos-blur-surface border-border/70 gap-0 overflow-hidden rounded-xl! border p-0 shadow-2xl', commandDialogLayoutClassName[layout], contentClassName, className), showCloseButton: showCloseButton, children: children })] }));
|
|
48
|
+
}
|
|
49
|
+
function CommandInput({ className, variant = 'boxed', loading = false, leading, trailing, ...props }) {
|
|
50
|
+
if (variant === 'inline' || variant === 'footer') {
|
|
51
|
+
return (_jsxs("div", { "data-slot": "command-input-wrapper", className: cn('border-border/60 flex min-h-11 items-center gap-2 px-3 py-2.5', variant === 'footer' ? 'border-t' : 'border-b'), children: [leading ? _jsx("div", { className: "flex shrink-0 items-center", children: leading }) : null, _jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('placeholder:text-muted-foreground/70 min-w-0 flex-1 bg-transparent text-sm leading-none outline-none disabled:cursor-not-allowed disabled:opacity-50', className), ...props }), trailing ? _jsx("div", { className: "flex shrink-0 items-center", children: trailing }) : null, loading ? _jsx(TerminalSpinner, { tone: "muted", className: "shrink-0 text-[14px]" }) : null] }));
|
|
52
|
+
}
|
|
53
|
+
return (_jsx("div", { "data-slot": "command-input-wrapper", className: "px-2 pt-1 pb-1", children: _jsxs(InputGroup, { className: "border-input/30 bg-input/30 h-8! rounded-lg! shadow-none! *:data-[slot=input-group-addon]:pl-2!", children: [_jsx(InputGroupAddon, { children: leading ?? _jsx(SearchIcon, { className: "size-4 shrink-0 opacity-50" }) }), _jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('min-w-0 flex-1 bg-transparent px-1.5 text-[13px] outline-hidden disabled:cursor-not-allowed disabled:opacity-50', className), ...props }), loading ? (_jsx(InputGroupAddon, { align: "inline-end", children: _jsx(TerminalSpinner, { tone: "muted", className: "text-[14px]" }) })) : null, trailing ? _jsx(InputGroupAddon, { align: "inline-end", children: trailing }) : null] }) }));
|
|
54
|
+
}
|
|
55
|
+
function CommandList({ className, ...props }) {
|
|
56
|
+
return (_jsx(CommandPrimitive.List, { "data-slot": "command-list", onWheel: (event) => event.stopPropagation(), onTouchMove: (event) => event.stopPropagation(), className: cn('no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto overscroll-contain outline-none', className), ...props }));
|
|
57
|
+
}
|
|
58
|
+
function CommandEmpty({ className, ...props }) {
|
|
59
|
+
return (_jsx(CommandPrimitive.Empty, { "data-slot": "command-empty", className: cn('py-6 text-center text-sm', className), ...props }));
|
|
60
|
+
}
|
|
61
|
+
function CommandGroup({ className, ...props }) {
|
|
62
|
+
return (_jsx(CommandPrimitive.Group, { "data-slot": "command-group", className: cn('text-foreground **:[[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium', className), ...props }));
|
|
63
|
+
}
|
|
64
|
+
function CommandSeparator({ className, ...props }) {
|
|
65
|
+
return (_jsx(CommandPrimitive.Separator, { "data-slot": "command-separator", className: cn('bg-border -mx-1 h-px', className), ...props }));
|
|
66
|
+
}
|
|
67
|
+
function CommandItem({ className, children, showCheck = true, ...props }) {
|
|
68
|
+
return (_jsxs(CommandPrimitive.Item, { "data-slot": "command-item", className: cn("group/command-item data-[selected=true]:bg-muted data-[selected=true]:text-foreground data-[selected=true]:*:[svg]:text-foreground relative flex cursor-pointer items-center gap-2 rounded-lg 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, children: [children, showCheck ? (_jsx(CheckIcon, { className: "ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" })) : null] }));
|
|
69
|
+
}
|
|
70
|
+
function CommandShortcut({ className, ...props }) {
|
|
71
|
+
return (_jsx("span", { "data-slot": "command-shortcut", className: cn('text-muted-foreground group-data-[selected=true]/command-item:text-foreground ml-auto text-xs tracking-widest', className), ...props }));
|
|
72
|
+
}
|
|
73
|
+
function CommandHints({ hints, className, children, ...props }) {
|
|
74
|
+
return (_jsxs("div", { "data-slot": "command-hints", className: cn('border-border/60 flex items-center justify-between border-t px-3 py-2', className), ...props, children: [_jsx("div", { className: "text-muted-foreground/85 flex items-center gap-3 font-mono text-[10.5px]", children: hints.map((hint) => (_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(KbdGroup, { children: hint.keys.map((key) => (_jsx(Kbd, { className: "h-4 min-w-4 px-1 font-mono text-[9px]", children: key }, key))) }), _jsx("span", { children: hint.label })] }, hint.label))) }), children] }));
|
|
75
|
+
}
|
|
76
|
+
export { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandHints, CommandItem, CommandShortcut, CommandSeparator, };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
declare const commentPinVariants: (props?: ({
|
|
4
|
+
tone?: "open" | "resolved" | null | undefined;
|
|
5
|
+
active?: boolean | null | undefined;
|
|
6
|
+
size?: "sm" | "default" | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
export interface CommentPinProps extends Omit<React.ComponentProps<'button'>, 'children'>, VariantProps<typeof commentPinVariants> {
|
|
9
|
+
count?: number;
|
|
10
|
+
resolved?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function CommentPin({ className, count, resolved, active, size, tone, ...props }: CommentPinProps): React.JSX.Element;
|
|
13
|
+
export { commentPinVariants };
|