@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,159 @@
|
|
|
1
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
|
+
import { Button } from './button.js';
|
|
3
|
+
import type { FieldRegistry, FilterOp } from '../lib/view-query/index.js';
|
|
4
|
+
import type { FormatDateTime } from '../lib/date-time-format.js';
|
|
5
|
+
import { type ViewSortEditorLabels, type ViewSortEditorSort } from './view-sort-editor.js';
|
|
6
|
+
export interface ViewQueryField {
|
|
7
|
+
id: string;
|
|
8
|
+
label: string;
|
|
9
|
+
icon?: ReactNode;
|
|
10
|
+
keywords?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface ViewFilterControlLabels {
|
|
13
|
+
addFilter: string;
|
|
14
|
+
searchFields: string;
|
|
15
|
+
noFields: string;
|
|
16
|
+
addGroup?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ViewFilterControlProps {
|
|
19
|
+
fields: ViewQueryField[];
|
|
20
|
+
labels: ViewFilterControlLabels;
|
|
21
|
+
onAddFilter: (field: string) => void;
|
|
22
|
+
onAddGroup?: () => void;
|
|
23
|
+
iconOnly?: boolean;
|
|
24
|
+
/** Replaces the default funnel glyph in `iconOnly` mode — a plus reads as "add another". */
|
|
25
|
+
icon?: ReactNode;
|
|
26
|
+
active?: boolean;
|
|
27
|
+
align?: 'start' | 'center' | 'end';
|
|
28
|
+
className?: string;
|
|
29
|
+
testId?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ViewSortControlLabels extends ViewSortEditorLabels {
|
|
32
|
+
sort: string;
|
|
33
|
+
sortedBy: (field: string) => string;
|
|
34
|
+
}
|
|
35
|
+
export interface ViewSortControlProps<TSort extends ViewSortEditorSort = ViewSortEditorSort> {
|
|
36
|
+
sorts: TSort[];
|
|
37
|
+
fields: ViewQueryField[];
|
|
38
|
+
labels: ViewSortControlLabels;
|
|
39
|
+
onChange: (sorts: TSort[]) => void;
|
|
40
|
+
createSort: (field: string) => TSort;
|
|
41
|
+
iconOnly?: boolean;
|
|
42
|
+
align?: 'start' | 'center' | 'end';
|
|
43
|
+
className?: string;
|
|
44
|
+
testId?: string;
|
|
45
|
+
addButtonTestId?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface ViewFilterChipProps {
|
|
48
|
+
label: string;
|
|
49
|
+
editor: ReactNode;
|
|
50
|
+
removeLabel: string;
|
|
51
|
+
onRemove: () => void;
|
|
52
|
+
icon?: ReactNode;
|
|
53
|
+
editorLabel?: string;
|
|
54
|
+
className?: string;
|
|
55
|
+
}
|
|
56
|
+
export declare function ViewFilterControl({ fields, labels, onAddFilter, onAddGroup, iconOnly, icon, active, align, className, testId, }: ViewFilterControlProps): React.ReactElement;
|
|
57
|
+
export declare function ViewSortControl<TSort extends ViewSortEditorSort>({ sorts, fields, labels, onChange, createSort, iconOnly, align, className, testId, addButtonTestId, }: ViewSortControlProps<TSort>): React.ReactElement;
|
|
58
|
+
export declare function ViewFilterChip({ label, editor, removeLabel, onRemove, icon, editorLabel, className, }: ViewFilterChipProps): React.ReactElement;
|
|
59
|
+
export type ViewQueryChipProps = ComponentProps<'div'>;
|
|
60
|
+
/**
|
|
61
|
+
* Reads a query clause as `property · verb · value`, each part its own trigger.
|
|
62
|
+
* Dividers are inserted between the parts so callers cannot render an
|
|
63
|
+
* inconsistent chip; conditional parts may be `null`.
|
|
64
|
+
*/
|
|
65
|
+
export declare function ViewQueryChip({ children, className, ...props }: ViewQueryChipProps): React.ReactElement;
|
|
66
|
+
export interface ViewQueryChipSegmentProps extends ComponentProps<typeof Button> {
|
|
67
|
+
icon?: ReactNode;
|
|
68
|
+
muted?: boolean;
|
|
69
|
+
chevron?: boolean;
|
|
70
|
+
iconOnly?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export declare function ViewQueryChipSegment({ icon, muted, chevron, iconOnly, children, className, ...props }: ViewQueryChipSegmentProps): React.ReactElement;
|
|
73
|
+
export interface ViewQueryChipInputProps extends ComponentProps<'input'> {
|
|
74
|
+
quoted?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** Value segment that stays a live text/number field instead of opening a popover. */
|
|
77
|
+
export declare function ViewQueryChipInput({ quoted, className, ...props }: ViewQueryChipInputProps): React.ReactElement;
|
|
78
|
+
export interface ViewQueryOperator {
|
|
79
|
+
id: string;
|
|
80
|
+
label: string;
|
|
81
|
+
}
|
|
82
|
+
export interface ViewQueryFilterChipLabels {
|
|
83
|
+
searchFields: string;
|
|
84
|
+
noFields: string;
|
|
85
|
+
searchOperators: string;
|
|
86
|
+
noOperators: string;
|
|
87
|
+
actions: string;
|
|
88
|
+
remove: string;
|
|
89
|
+
convertToGroup?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface ViewQueryFilterChipProps extends ViewQueryChipProps {
|
|
92
|
+
field: string;
|
|
93
|
+
fields: ViewQueryField[];
|
|
94
|
+
operator: string;
|
|
95
|
+
operators: ViewQueryOperator[];
|
|
96
|
+
labels: ViewQueryFilterChipLabels;
|
|
97
|
+
/** Value segment, owned by the caller because only it knows the field's shape. */
|
|
98
|
+
value?: ReactNode;
|
|
99
|
+
onChangeField: (field: string) => void;
|
|
100
|
+
onChangeOperator: (operator: string) => void;
|
|
101
|
+
onRemove: () => void;
|
|
102
|
+
onConvertToGroup?: () => void;
|
|
103
|
+
}
|
|
104
|
+
/** One filter clause, read left to right as property · verb · value, each part editable in place. */
|
|
105
|
+
export declare function ViewQueryFilterChip({ field, fields, operator, operators, labels, value, onChangeField, onChangeOperator, onRemove, onConvertToGroup, ...props }: ViewQueryFilterChipProps): React.ReactElement;
|
|
106
|
+
export interface ViewQueryChipActionsProps {
|
|
107
|
+
label: string;
|
|
108
|
+
removeLabel: string;
|
|
109
|
+
onRemove: () => void;
|
|
110
|
+
convertLabel?: string;
|
|
111
|
+
onConvertToGroup?: () => void;
|
|
112
|
+
}
|
|
113
|
+
/** Trailing overflow segment shared by every chip: remove, plus whatever the clause supports. */
|
|
114
|
+
export declare function ViewQueryChipActions({ label, removeLabel, onRemove, convertLabel, onConvertToGroup, }: ViewQueryChipActionsProps): React.ReactElement;
|
|
115
|
+
export interface FilterEditorOption {
|
|
116
|
+
id: string;
|
|
117
|
+
label: string;
|
|
118
|
+
icon?: ReactNode;
|
|
119
|
+
}
|
|
120
|
+
export interface FilterEditorCtx {
|
|
121
|
+
registry: FieldRegistry;
|
|
122
|
+
fieldLabel: (field: string) => string;
|
|
123
|
+
fieldIcon: (field: string) => ReactNode;
|
|
124
|
+
operatorLabel: (operator: FilterOp) => string;
|
|
125
|
+
/**
|
|
126
|
+
* Called per field while rendering, never eagerly for the whole registry, so a
|
|
127
|
+
* consumer can answer with options that only exist once its rows have loaded.
|
|
128
|
+
* Omit it when the field can name its own options through `selectOptions`.
|
|
129
|
+
*/
|
|
130
|
+
optionsFor?: (field: string) => readonly FilterEditorOption[];
|
|
131
|
+
/** Host-bound date formatter carrying the viewer's date-format preference. */
|
|
132
|
+
format?: FormatDateTime;
|
|
133
|
+
}
|
|
134
|
+
export interface FilterEditorLabels {
|
|
135
|
+
filterValue: string;
|
|
136
|
+
emptyFilterValue: string;
|
|
137
|
+
searchValues: string;
|
|
138
|
+
noValues: string;
|
|
139
|
+
valuePlaceholder: string;
|
|
140
|
+
relativeDays: string;
|
|
141
|
+
booleanTrue: string;
|
|
142
|
+
booleanFalse: string;
|
|
143
|
+
}
|
|
144
|
+
export declare function filterEditorOptions(ctx: FilterEditorCtx, field: string): readonly FilterEditorOption[];
|
|
145
|
+
export declare function ViewFilterSummaryRow({ label, onRemove, removeLabel, icon, }: {
|
|
146
|
+
label: string;
|
|
147
|
+
onRemove: () => void;
|
|
148
|
+
removeLabel: string;
|
|
149
|
+
icon?: ReactNode;
|
|
150
|
+
}): React.ReactElement;
|
|
151
|
+
export declare function ViewSortSummaryRow({ label, dir, ascendingLabel, descendingLabel, removeLabel, onToggleDir, onRemove, }: {
|
|
152
|
+
label: string;
|
|
153
|
+
dir: 'asc' | 'desc';
|
|
154
|
+
ascendingLabel: string;
|
|
155
|
+
descendingLabel: string;
|
|
156
|
+
removeLabel: string;
|
|
157
|
+
onToggleDir: () => void;
|
|
158
|
+
onRemove: () => void;
|
|
159
|
+
}): React.ReactElement;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// Two chips live here on purpose. `ViewQueryFilterChip` is the query-DSL chip: it
|
|
4
|
+
// requires `field`, `fields[]`, `operator` and `operators[]`, and renders two
|
|
5
|
+
// mandatory searchable selectors. `ViewFilterChip` is the ad-hoc chip, kept for
|
|
6
|
+
// surfaces with no DSL behind them: one such chip holds a plain React enum edited
|
|
7
|
+
// with radio buttons, another pairs an id list with an any/all toggle whose operator
|
|
8
|
+
// equivalent has no `FilterOp` member. Neither chip is a duplicate of the other;
|
|
9
|
+
// collapsing them would force one of the two shapes to lie.
|
|
10
|
+
//
|
|
11
|
+
// `ObjectsFilterEditorCtx` in the web app is a third editor context, still separate
|
|
12
|
+
// from `FilterEditorCtx` below, pending the objects-table migration.
|
|
13
|
+
import { Children, Fragment, useState } from 'react';
|
|
14
|
+
import { ArrowDown, ArrowDownUp, ArrowUp, ChevronDown, ListFilter, MoreHorizontal, Plus, SquareSplitVertical, X, } from 'lucide-react';
|
|
15
|
+
import { Button } from './button.js';
|
|
16
|
+
import { ButtonGroup, ButtonGroupSeparator } from './button-group.js';
|
|
17
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from './command.js';
|
|
18
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
|
|
19
|
+
import { PropertySelector } from './property-selector.js';
|
|
20
|
+
import { ViewSortEditor, } from './view-sort-editor.js';
|
|
21
|
+
import { viewControlClass, viewListRowClass, viewPopoverContentClass, viewSegmentControlClass, } from '../lib/view-chrome.js';
|
|
22
|
+
import { cn } from '../lib/cn.js';
|
|
23
|
+
const viewCommandClass = '[&_[data-slot=command-input-wrapper]]:px-2 [&_[data-slot=command-input-wrapper]]:py-1.5 [&_[data-slot=command-input]]:text-[12px] [&_[data-slot=command-item]]:min-h-7 [&_[data-slot=command-item]]:rounded-md [&_[data-slot=command-item]]:px-1.5 [&_[data-slot=command-item]]:py-1 [&_[data-slot=command-item]]:text-[12px]';
|
|
24
|
+
const viewSettingsRowClass = cn(viewListRowClass, 'flex w-full items-center gap-2 text-left leading-none');
|
|
25
|
+
export function ViewFilterControl({ fields, labels, onAddFilter, onAddGroup, iconOnly = false, icon, active = false, align = 'start', className, testId = 'view-query-add-filter', }) {
|
|
26
|
+
const [open, setOpen] = useState(false);
|
|
27
|
+
const hasGroupAction = Boolean(labels.addGroup && onAddGroup);
|
|
28
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: iconOnly ? 'icon-sm' : 'sm', variant: iconOnly ? 'ghost' : 'dashed', className: cn(iconOnly
|
|
29
|
+
? 'text-muted-foreground hover:text-foreground'
|
|
30
|
+
: cn(viewControlClass, 'border-border/70 text-muted-foreground bg-transparent'), active && (iconOnly ? 'bg-muted/45 text-foreground' : 'text-foreground'), className), title: labels.addFilter, "aria-label": iconOnly ? labels.addFilter : undefined, "data-testid": testId, "data-active": active ? 'true' : undefined, children: iconOnly ? ((icon ?? _jsx(ListFilter, { className: "size-3.5", strokeWidth: 1.5 }))) : (_jsxs(_Fragment, { children: [_jsx(Plus, { className: "size-3", strokeWidth: 1.5 }), labels.addFilter] })) }) }), _jsx(PopoverContent, { align: align, className: cn('w-[230px] p-0', viewPopoverContentClass), children: _jsxs(Command, { className: viewCommandClass, children: [_jsx(CommandInput, { variant: "inline", placeholder: labels.searchFields }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { className: "text-muted-foreground py-4 text-[12px]", children: labels.noFields }), _jsx(CommandGroup, { children: fields.map((field) => (_jsxs(CommandItem, { value: [field.label, field.id, ...(field.keywords ?? [])].join(' '), onSelect: () => {
|
|
31
|
+
onAddFilter(field.id);
|
|
32
|
+
setOpen(false);
|
|
33
|
+
}, children: [field.icon ? (_jsx("span", { className: "text-muted-foreground/70 inline-flex size-3.5 shrink-0 items-center justify-center", children: field.icon })) : null, _jsx("span", { className: "truncate", children: field.label })] }, field.id))) }), hasGroupAction ? (_jsxs(_Fragment, { children: [_jsx(CommandSeparator, { className: "mx-1 my-1" }), _jsx(CommandGroup, { children: _jsxs(CommandItem, { value: labels.addGroup, onSelect: () => {
|
|
34
|
+
onAddGroup?.();
|
|
35
|
+
setOpen(false);
|
|
36
|
+
}, className: "text-primary", children: [_jsx(Plus, { className: "text-primary/70 size-3.5", strokeWidth: 1.5 }), _jsx("span", { className: "truncate", children: labels.addGroup })] }) })] })) : null] })] }) })] }));
|
|
37
|
+
}
|
|
38
|
+
export function ViewSortControl({ sorts, fields, labels, onChange, createSort, iconOnly = false, align = 'end', className, testId = 'view-query-sort', addButtonTestId, }) {
|
|
39
|
+
const [open, setOpen] = useState(false);
|
|
40
|
+
const firstSort = sorts[0];
|
|
41
|
+
const firstFieldLabel = firstSort
|
|
42
|
+
? (fields.find((field) => field.id === firstSort.field)?.label ?? firstSort.field)
|
|
43
|
+
: '';
|
|
44
|
+
const summary = firstSort ? labels.sortedBy(firstFieldLabel) : labels.sort;
|
|
45
|
+
const extraSortCount = sorts.length > 1 ? `+${sorts.length - 1}` : null;
|
|
46
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", size: iconOnly ? 'icon-sm' : 'sm', variant: iconOnly ? 'ghost' : 'outline', className: cn(iconOnly
|
|
47
|
+
? 'text-muted-foreground hover:text-foreground'
|
|
48
|
+
: cn(viewControlClass, 'text-muted-foreground'), sorts.length > 0 && 'bg-muted/45 text-foreground', className), title: labels.sort, "aria-label": iconOnly ? labels.sort : undefined, "data-testid": testId, "data-active": sorts.length > 0 ? 'true' : undefined, children: [_jsx(ArrowDownUp, { className: "size-3.5", strokeWidth: 1.5 }), !iconOnly ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "max-w-[20ch] truncate", children: summary }), extraSortCount ? (_jsx("span", { className: "text-muted-foreground shrink-0 font-normal", children: extraSortCount })) : null] })) : null] }) }), _jsx(PopoverContent, { align: align, className: cn('w-[360px] max-w-[92vw] p-2', viewPopoverContentClass), children: _jsx(ViewSortEditor, { sorts: sorts, fields: fields, onChange: (next) => onChange(next), createSort: (field) => createSort(field), labels: labels, addButtonTestId: addButtonTestId }) })] }));
|
|
49
|
+
}
|
|
50
|
+
export function ViewFilterChip({ label, editor, removeLabel, onRemove, icon, editorLabel, className, }) {
|
|
51
|
+
return (_jsxs("div", { className: cn('border-border/70 bg-background inline-flex h-7 min-w-0 rounded-lg border', className), children: [_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": editorLabel, className: "text-foreground h-full min-w-0 justify-start gap-1.5 rounded-r-none px-2 text-[12px] font-normal", children: [icon ? (_jsx("span", { className: "text-muted-foreground/70 inline-flex size-3.5 shrink-0 items-center justify-center", children: icon })) : null, _jsx("span", { className: "truncate", children: label })] }) }), _jsx(PopoverContent, { align: "start", className: cn('w-[280px] p-2', viewPopoverContentClass), children: editor })] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", onClick: onRemove, "aria-label": removeLabel, className: "border-border/70 text-muted-foreground hover:bg-destructive/10 hover:text-destructive h-full w-7 shrink-0 rounded-l-none border-l", children: _jsx(X, { className: "size-3.5", strokeWidth: 1.5 }) })] }));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Reads a query clause as `property · verb · value`, each part its own trigger.
|
|
55
|
+
* Dividers are inserted between the parts so callers cannot render an
|
|
56
|
+
* inconsistent chip; conditional parts may be `null`.
|
|
57
|
+
*/
|
|
58
|
+
export function ViewQueryChip({ children, className, ...props }) {
|
|
59
|
+
const parts = Children.toArray(children);
|
|
60
|
+
return (_jsx(ButtonGroup, { className: cn('h-7 text-[12px]', className), ...props, children: parts.map((part, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx(ButtonGroupSeparator, {}) : null, part] }, index))) }));
|
|
61
|
+
}
|
|
62
|
+
export function ViewQueryChipSegment({ icon, muted = false, chevron = true, iconOnly = false, children, className, ...props }) {
|
|
63
|
+
return (_jsxs(Button, { type: "button", variant: "outline", size: "xs", ...props, className: cn(viewSegmentControlClass, muted ? 'text-muted-foreground' : 'text-foreground/90', iconOnly && 'w-7 px-0', className), children: [icon ? (_jsx("span", { className: "text-muted-foreground/70 inline-flex size-3.5 shrink-0 items-center justify-center", children: icon })) : null, iconOnly ? null : _jsx("span", { className: "max-w-[22ch] truncate", children: children }), chevron ? _jsx(ChevronDown, { className: "text-muted-foreground/55 size-3 shrink-0" }) : null] }));
|
|
64
|
+
}
|
|
65
|
+
/** Value segment that stays a live text/number field instead of opening a popover. */
|
|
66
|
+
export function ViewQueryChipInput({ quoted = false, className, ...props }) {
|
|
67
|
+
return (_jsxs("span", { className: "border-input focus-within:border-ring focus-within:ring-ring/50 inline-flex h-7 items-center gap-0.5 rounded-lg border px-2 text-[12px] transition-colors focus-within:ring-3", children: [quoted ? _jsx("span", { className: "text-muted-foreground/55", children: "\u201C" }) : null, _jsx("input", { ...props, className: cn('text-foreground/90 placeholder:text-muted-foreground/55 min-w-0 bg-transparent outline-none', className) }), quoted ? _jsx("span", { className: "text-muted-foreground/55", children: "\u201D" }) : null] }));
|
|
68
|
+
}
|
|
69
|
+
/** One filter clause, read left to right as property · verb · value, each part editable in place. */
|
|
70
|
+
export function ViewQueryFilterChip({ field, fields, operator, operators, labels, value, onChangeField, onChangeOperator, onRemove, onConvertToGroup, ...props }) {
|
|
71
|
+
const selectedField = fields.find((candidate) => candidate.id === field);
|
|
72
|
+
const selectedOperator = operators.find((candidate) => candidate.id === operator);
|
|
73
|
+
return (_jsxs(ViewQueryChip, { ...props, children: [_jsx(ViewQuerySegmentSelector, { items: fields.map((candidate) => ({
|
|
74
|
+
id: candidate.id,
|
|
75
|
+
label: candidate.label,
|
|
76
|
+
icon: candidate.icon,
|
|
77
|
+
keywords: candidate.keywords,
|
|
78
|
+
selected: candidate.id === field,
|
|
79
|
+
})), searchPlaceholder: labels.searchFields, emptyLabel: labels.noFields, onSelect: onChangeField, children: _jsx(ViewQueryChipSegment, { icon: selectedField?.icon, className: "font-medium", children: selectedField?.label ?? field }) }), _jsx(ViewQuerySegmentSelector, { items: operators.map((candidate) => ({
|
|
80
|
+
id: candidate.id,
|
|
81
|
+
label: candidate.label,
|
|
82
|
+
selected: candidate.id === operator,
|
|
83
|
+
})), searchPlaceholder: labels.searchOperators, emptyLabel: labels.noOperators, onSelect: onChangeOperator, children: _jsx(ViewQueryChipSegment, { muted: true, children: selectedOperator?.label ?? operator }) }), value, _jsx(ViewQueryChipActions, { label: labels.actions, removeLabel: labels.remove, onRemove: onRemove, convertLabel: labels.convertToGroup, onConvertToGroup: onConvertToGroup })] }));
|
|
84
|
+
}
|
|
85
|
+
function ViewQuerySegmentSelector({ items, searchPlaceholder, emptyLabel, onSelect, children, }) {
|
|
86
|
+
const [open, setOpen] = useState(false);
|
|
87
|
+
return (_jsx(PropertySelector, { open: open, onOpenChange: setOpen, triggerAsChild: true, items: items, onSelect: (item) => onSelect(item.id), searchPlaceholder: searchPlaceholder, labels: { noMatches: emptyLabel }, "aria-label": searchPlaceholder, children: children }));
|
|
88
|
+
}
|
|
89
|
+
/** Trailing overflow segment shared by every chip: remove, plus whatever the clause supports. */
|
|
90
|
+
export function ViewQueryChipActions({ label, removeLabel, onRemove, convertLabel, onConvertToGroup, }) {
|
|
91
|
+
const [open, setOpen] = useState(false);
|
|
92
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(ViewQueryChipSegment, { iconOnly: true, chevron: false, muted: true, "aria-label": label, title: label, icon: _jsx(MoreHorizontal, { className: "size-3", strokeWidth: 2.25 }) }) }), _jsxs(PopoverContent, { align: "start", className: cn('w-[220px] p-1', viewPopoverContentClass), children: [onConvertToGroup && convertLabel ? (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => {
|
|
93
|
+
onConvertToGroup();
|
|
94
|
+
setOpen(false);
|
|
95
|
+
}, className: cn(viewListRowClass, 'w-full justify-start gap-2 font-normal'), children: [_jsx(SquareSplitVertical, { className: "text-muted-foreground size-3.5", strokeWidth: 1.8 }), convertLabel] })) : null, _jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => {
|
|
96
|
+
onRemove();
|
|
97
|
+
setOpen(false);
|
|
98
|
+
}, className: cn(viewListRowClass, 'text-destructive hover:bg-destructive/10 hover:text-destructive w-full justify-start gap-2 font-normal'), children: [_jsx(X, { className: "size-3.5", strokeWidth: 1.8 }), removeLabel] })] })] }));
|
|
99
|
+
}
|
|
100
|
+
export function filterEditorOptions(ctx, field) {
|
|
101
|
+
return ctx.optionsFor?.(field) ?? ctx.registry.meta[field]?.selectOptions?.() ?? [];
|
|
102
|
+
}
|
|
103
|
+
export function ViewFilterSummaryRow({ label, onRemove, removeLabel, icon, }) {
|
|
104
|
+
return (_jsxs("div", { className: cn(viewSettingsRowClass, 'group text-foreground hover:bg-accent hover:text-accent-foreground'), children: [icon ?? _jsx(ListFilter, { className: "text-muted-foreground/70 size-4", strokeWidth: 1.5 }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: label }), _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", onClick: onRemove, "aria-label": removeLabel, className: "text-muted-foreground hover:bg-destructive/10 hover:text-destructive pointer-events-none size-6 rounded-md opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100", children: _jsx(X, { className: "size-3.5", strokeWidth: 1.5 }) })] }));
|
|
105
|
+
}
|
|
106
|
+
export function ViewSortSummaryRow({ label, dir, ascendingLabel, descendingLabel, removeLabel, onToggleDir, onRemove, }) {
|
|
107
|
+
const DirectionIcon = dir === 'asc' ? ArrowUp : ArrowDown;
|
|
108
|
+
return (_jsxs("div", { className: "border-border/60 bg-background flex h-9 items-center gap-2 rounded-lg border px-2 text-[13px]", children: [_jsx(ArrowDownUp, { className: "text-muted-foreground/70 size-4", strokeWidth: 1.5 }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: label }), _jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onToggleDir, className: "text-muted-foreground hover:text-foreground h-7 gap-1.5 rounded-lg px-2 text-[12px] font-normal", children: [_jsx(DirectionIcon, { className: "size-3.5", strokeWidth: 1.5 }), dir === 'asc' ? ascendingLabel : descendingLabel] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", onClick: onRemove, "aria-label": removeLabel, className: "text-muted-foreground hover:bg-destructive/10 hover:text-destructive size-7 rounded-lg", children: _jsx(X, { className: "size-3.5", strokeWidth: 1.5 }) })] }));
|
|
109
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ViewSaveMenuLabels {
|
|
2
|
+
saving: string;
|
|
3
|
+
savePersonal: string;
|
|
4
|
+
saveShared: string;
|
|
5
|
+
saveAsPersonal: string;
|
|
6
|
+
saveAsShared: string;
|
|
7
|
+
saveOptions: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ViewSaveMenuProps {
|
|
10
|
+
dirty: boolean;
|
|
11
|
+
saving: boolean;
|
|
12
|
+
shared: boolean;
|
|
13
|
+
labels: ViewSaveMenuLabels;
|
|
14
|
+
testId: string;
|
|
15
|
+
onSaveInPlace: () => void;
|
|
16
|
+
onSaveAsPersonal: () => void;
|
|
17
|
+
onSaveAsShared: () => void;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function ViewSaveMenu({ dirty, saving, shared, labels, testId, onSaveInPlace, onSaveAsPersonal, onSaveAsShared, className, }: ViewSaveMenuProps): React.ReactElement | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ChevronDown } from 'lucide-react';
|
|
4
|
+
import { Button } from './button.js';
|
|
5
|
+
import { ButtonGroup, ButtonGroupSeparator } from './button-group.js';
|
|
6
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from './dropdown-menu.js';
|
|
7
|
+
import { viewPrimaryControlClass } from '../lib/view-chrome.js';
|
|
8
|
+
import { cn } from '../lib/cn.js';
|
|
9
|
+
export function ViewSaveMenu({ dirty, saving, shared, labels, testId, onSaveInPlace, onSaveAsPersonal, onSaveAsShared, className, }) {
|
|
10
|
+
if (!dirty)
|
|
11
|
+
return null;
|
|
12
|
+
return (_jsxs(ButtonGroup, { className: className, "data-testid": testId, children: [_jsx(Button, { type: "button", size: "sm", variant: "outline", disabled: saving, onClick: onSaveInPlace, className: cn(viewPrimaryControlClass, 'shrink-0'), "data-testid": `${testId}-in-place`, children: saving ? labels.saving : shared ? labels.saveShared : labels.savePersonal }), _jsx(ButtonGroupSeparator, {}), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", disabled: saving, className: cn(viewPrimaryControlClass, 'h-7 w-8 shrink-0 px-0'), "aria-label": labels.saveOptions, "data-testid": `${testId}-options`, children: _jsx(ChevronDown, { className: "size-3.5", strokeWidth: 1.7 }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: cn('w-56', className), children: [_jsx(DropdownMenuItem, { onSelect: onSaveAsPersonal, "data-testid": `${testId}-as-personal`, children: labels.saveAsPersonal }), _jsx(DropdownMenuItem, { onSelect: onSaveAsShared, "data-testid": `${testId}-as-shared`, children: labels.saveAsShared })] })] })] }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export type ViewSortDirection = 'asc' | 'desc';
|
|
3
|
+
export interface ViewSortEditorSort {
|
|
4
|
+
id: string;
|
|
5
|
+
field: string;
|
|
6
|
+
dir: ViewSortDirection;
|
|
7
|
+
}
|
|
8
|
+
export interface ViewSortEditorField {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
icon?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export interface ViewSortEditorLabels {
|
|
14
|
+
addSort: string;
|
|
15
|
+
ascending: string;
|
|
16
|
+
descending: string;
|
|
17
|
+
chooseField: string;
|
|
18
|
+
noMatches: string;
|
|
19
|
+
remove: string;
|
|
20
|
+
reorder: string;
|
|
21
|
+
searchFields: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ViewSortEditorProps {
|
|
24
|
+
sorts: ViewSortEditorSort[];
|
|
25
|
+
fields: ViewSortEditorField[];
|
|
26
|
+
labels: ViewSortEditorLabels;
|
|
27
|
+
onChange: (sorts: ViewSortEditorSort[]) => void;
|
|
28
|
+
createSort: (field: string) => ViewSortEditorSort;
|
|
29
|
+
className?: string;
|
|
30
|
+
menuContentClassName?: string;
|
|
31
|
+
fieldWidthClassName?: string;
|
|
32
|
+
addButtonTestId?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare const viewEditorControlClassName = "h-7 min-w-0 rounded-lg px-2 text-[12px] font-normal leading-none";
|
|
35
|
+
export declare const viewEditorIconClassName = "size-3.5 shrink-0";
|
|
36
|
+
export declare const viewEditorFieldWidthClassName = "w-[136px]";
|
|
37
|
+
export declare const viewSortEditorControlClassName = "h-7 min-w-0 rounded-lg px-2 text-[12px] font-normal leading-none";
|
|
38
|
+
export declare const viewSortEditorIconClassName = "size-3.5 shrink-0";
|
|
39
|
+
export declare const viewSortEditorFieldWidthClassName = "w-[136px]";
|
|
40
|
+
export declare function ViewSortEditor({ sorts, fields, labels, onChange, createSort, className, menuContentClassName, fieldWidthClassName, addButtonTestId, }: ViewSortEditorProps): React.ReactElement;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { ArrowDown, ArrowUp, ChevronDown, Plus, X } from 'lucide-react';
|
|
5
|
+
import { Button } from './button.js';
|
|
6
|
+
import { PropertySelector } from './property-selector.js';
|
|
7
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './select.js';
|
|
8
|
+
import { DragHandle, SortableList, reorderById } from './sortable.js';
|
|
9
|
+
import { cn } from '../lib/cn.js';
|
|
10
|
+
export const viewEditorControlClassName = 'h-7 min-w-0 rounded-lg px-2 text-[12px] font-normal leading-none';
|
|
11
|
+
export const viewEditorIconClassName = 'size-3.5 shrink-0';
|
|
12
|
+
export const viewEditorFieldWidthClassName = 'w-[136px]';
|
|
13
|
+
export const viewSortEditorControlClassName = viewEditorControlClassName;
|
|
14
|
+
export const viewSortEditorIconClassName = viewEditorIconClassName;
|
|
15
|
+
export const viewSortEditorFieldWidthClassName = viewEditorFieldWidthClassName;
|
|
16
|
+
export function ViewSortEditor({ sorts, fields, labels, onChange, createSort, className, menuContentClassName, fieldWidthClassName = viewEditorFieldWidthClassName, addButtonTestId, }) {
|
|
17
|
+
const [addOpen, setAddOpen] = useState(false);
|
|
18
|
+
const used = new Set(sorts.map((sort) => sort.field));
|
|
19
|
+
const available = fields.filter((field) => !used.has(field.id));
|
|
20
|
+
const itemsForFields = (fieldIds, selected) => fieldIds.flatMap((fieldId) => {
|
|
21
|
+
const field = fields.find((option) => option.id === fieldId);
|
|
22
|
+
if (!field)
|
|
23
|
+
return [];
|
|
24
|
+
return [{ ...field, selected: selected === field.id }];
|
|
25
|
+
});
|
|
26
|
+
const addItems = itemsForFields(available.map((field) => field.id));
|
|
27
|
+
const onReorderSort = (movedId, { beforeId }) => {
|
|
28
|
+
onChange(reorderById(sorts, movedId, beforeId));
|
|
29
|
+
};
|
|
30
|
+
const addSort = (field) => {
|
|
31
|
+
onChange([...sorts, createSort(field)]);
|
|
32
|
+
setAddOpen(false);
|
|
33
|
+
};
|
|
34
|
+
const selectorLabels = { noMatches: labels.noMatches };
|
|
35
|
+
return (_jsxs("div", { className: cn('grid gap-2', className), children: [_jsx(SortableList, { items: sorts, keyOf: (sort) => sort.id, orientation: "vertical", handle: true, onReorder: onReorderSort, className: "flex flex-col gap-1.5", renderItem: (sort, { dragHandleProps, isDragging }) => {
|
|
36
|
+
const fieldIds = fields
|
|
37
|
+
.filter((field) => field.id === sort.field || !used.has(field.id))
|
|
38
|
+
.map((field) => field.id);
|
|
39
|
+
const field = fields.find((option) => option.id === sort.field);
|
|
40
|
+
return (_jsx(ViewSortEditorRow, { sort: sort, field: field, fieldItems: itemsForFields(fieldIds, sort.field), labels: labels, fieldWidthClassName: fieldWidthClassName, menuContentClassName: menuContentClassName, dragHandleProps: dragHandleProps, isDragging: isDragging, onFieldChange: (fieldId) => onChange(sorts.map((entry) => entry.id === sort.id ? { ...entry, field: fieldId } : entry)), onDirChange: (dir) => onChange(sorts.map((entry) => (entry.id === sort.id ? { ...entry, dir } : entry))), onRemove: () => onChange(sorts.filter((entry) => entry.id !== sort.id)) }));
|
|
41
|
+
} }), available.length > 0 ? (_jsx(PropertySelector, { open: addOpen, onOpenChange: setAddOpen, items: addItems, onSelect: (item) => addSort(item.id), searchPlaceholder: labels.searchFields, "aria-label": labels.addSort, labels: selectorLabels, contentClassName: fieldWidthClassName, children: _jsxs(Button, { type: "button", variant: "outline", size: "xs", className: cn(viewEditorControlClassName, 'gap-1.5'), "data-testid": addButtonTestId, children: [_jsx(Plus, { className: viewEditorIconClassName, strokeWidth: 1.8 }), " ", labels.addSort] }) })) : null] }));
|
|
42
|
+
}
|
|
43
|
+
function ViewSortEditorRow({ sort, field, fieldItems, labels, fieldWidthClassName, menuContentClassName, dragHandleProps, isDragging, onFieldChange, onDirChange, onRemove, }) {
|
|
44
|
+
const [fieldOpen, setFieldOpen] = useState(false);
|
|
45
|
+
const DirectionIcon = sort.dir === 'asc' ? ArrowUp : ArrowDown;
|
|
46
|
+
return (_jsxs("div", { className: cn('group grid grid-cols-[20px_minmax(0,max-content)_minmax(0,max-content)_28px] items-center gap-1.5 rounded-lg bg-background py-0.5', isDragging && 'opacity-70 shadow'), children: [_jsx(DragHandle, { dragHandleProps: dragHandleProps, "aria-label": labels.reorder, className: "size-4 justify-self-center text-muted-foreground/60 opacity-100" }), _jsx(PropertySelector, { open: fieldOpen, onOpenChange: setFieldOpen, items: fieldItems, onSelect: (item) => onFieldChange(item.id), searchPlaceholder: labels.searchFields, "aria-label": labels.chooseField, labels: { noMatches: labels.noMatches }, contentClassName: fieldWidthClassName, children: _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: cn(viewEditorControlClassName, 'justify-between gap-1.5', fieldWidthClassName), children: [_jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [field?.icon, _jsx("span", { className: "truncate", title: field?.label ?? sort.field, children: field?.label ?? sort.field })] }), _jsx(ChevronDown, { className: cn(viewEditorIconClassName, 'text-muted-foreground/70') })] }) }), _jsxs(Select, { value: sort.dir, onValueChange: (value) => onDirChange(value), children: [_jsx(SelectTrigger, { size: "sm", className: cn(viewEditorControlClassName, fieldWidthClassName), children: _jsx(SelectValue, { children: _jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [_jsx(DirectionIcon, { className: viewEditorIconClassName }), _jsx("span", { className: "truncate", children: sort.dir === 'asc' ? labels.ascending : labels.descending })] }) }) }), _jsxs(SelectContent, { className: menuContentClassName, children: [_jsxs(SelectItem, { value: "asc", children: [_jsx(ArrowUp, { className: viewEditorIconClassName }), labels.ascending] }), _jsxs(SelectItem, { value: "desc", children: [_jsx(ArrowDown, { className: viewEditorIconClassName }), labels.descending] })] })] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", onClick: onRemove, "aria-label": labels.remove, className: "size-7 shrink-0 rounded-lg text-muted-foreground hover:bg-destructive/10 hover:text-destructive", children: _jsx(X, { className: viewEditorIconClassName }) })] }));
|
|
47
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type LucideIcon } from 'lucide-react';
|
|
3
|
+
export type VoiceLineState = 'idle' | 'generating' | 'speaking' | 'listening' | 'verifying' | 'reprompt';
|
|
4
|
+
export interface VoiceLineProps extends Omit<React.ComponentProps<'div'>, 'children'> {
|
|
5
|
+
/** Which turn state the single morphing surface currently shows. */
|
|
6
|
+
state: VoiceLineState;
|
|
7
|
+
/** The one cross-fading line — the system's spoken line, or the caller's transcript. */
|
|
8
|
+
caption?: React.ReactNode;
|
|
9
|
+
/** Short role label shown in the tinted chip (e.g. "System" / "Listening…"). */
|
|
10
|
+
who?: string;
|
|
11
|
+
/** Overrides the state's default glyph. */
|
|
12
|
+
icon?: LucideIcon;
|
|
13
|
+
/** Dims the caption and shows a blinking caret — a live/partial transcript. */
|
|
14
|
+
partial?: boolean;
|
|
15
|
+
/** Audio analyser: TTS frequency data while `speaking`+`active`, mic time-domain while `listening`. */
|
|
16
|
+
analyser?: AnalyserNode | null;
|
|
17
|
+
/** Whether TTS audio is actively playing (speaking waveform reads live levels vs. resting). */
|
|
18
|
+
active?: boolean;
|
|
19
|
+
/** Optional 0..1 listening level fallback when there is no mic analyser. */
|
|
20
|
+
micLevel?: number;
|
|
21
|
+
/** Silence/endpoint countdown in ms; renders a shrinking ring while listening. */
|
|
22
|
+
countdownMs?: number;
|
|
23
|
+
/** Stacked conversation surface or a compact waveform row for an enclosing overlay. */
|
|
24
|
+
layout?: 'stacked' | 'waveform';
|
|
25
|
+
/** Loading treatment for compact waveform layouts. */
|
|
26
|
+
loadingVisualization?: 'ripple' | 'shimmer-bars';
|
|
27
|
+
/** Fixed bar count instead of filling the width — compact surfaces want fewer bars. */
|
|
28
|
+
bars?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The unified voice line — one dynamic-island pill whose tint, glyph, caption and
|
|
32
|
+
* waveform cross-fade between speaking → listening → verifying → reprompt. It is a
|
|
33
|
+
* single morphing surface (never two stacked boxes): the system's spoken line and the
|
|
34
|
+
* caller's transcribed line share it. Presentational; the caption is announced via
|
|
35
|
+
* aria-live so the spoken/heard line reaches a screen reader.
|
|
36
|
+
*/
|
|
37
|
+
export declare function VoiceLine({ state, caption, who, icon, partial, analyser, active, micLevel, countdownMs, layout, loadingVisualization, bars, className, ...props }: VoiceLineProps): React.JSX.Element;
|