@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,48 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { useMediaQuery } from '../hooks/use-media-query.js';
|
|
5
|
+
import { cn } from '../lib/cn.js';
|
|
6
|
+
const SPINNER_FRAMES = [
|
|
7
|
+
'⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏',
|
|
8
|
+
];
|
|
9
|
+
const SPINNER_FALLBACK = SPINNER_FRAMES[0];
|
|
10
|
+
const TONE_CLASS = {
|
|
11
|
+
neutral: 'text-foreground',
|
|
12
|
+
accent: 'text-primary',
|
|
13
|
+
muted: 'text-muted-foreground',
|
|
14
|
+
};
|
|
15
|
+
function usePrefersReducedMotion() {
|
|
16
|
+
return useMediaQuery('(prefers-reduced-motion: reduce)');
|
|
17
|
+
}
|
|
18
|
+
function useSpinnerFrame(fps, reducedMotion) {
|
|
19
|
+
const [frame, setFrame] = useState(0);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (reducedMotion)
|
|
22
|
+
return;
|
|
23
|
+
const ms = Math.max(1, Math.round(1000 / Math.max(1, fps)));
|
|
24
|
+
const id = window.setInterval(() => {
|
|
25
|
+
setFrame((current) => (current + 1) % SPINNER_FRAMES.length);
|
|
26
|
+
}, ms);
|
|
27
|
+
return () => {
|
|
28
|
+
window.clearInterval(id);
|
|
29
|
+
};
|
|
30
|
+
}, [fps, reducedMotion]);
|
|
31
|
+
if (reducedMotion)
|
|
32
|
+
return SPINNER_FALLBACK;
|
|
33
|
+
return SPINNER_FRAMES[frame] ?? SPINNER_FALLBACK;
|
|
34
|
+
}
|
|
35
|
+
export function TerminalSpinner({ fps = 12, tone = 'neutral', ariaLabel, className, }) {
|
|
36
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
37
|
+
const glyph = useSpinnerFrame(fps, reducedMotion);
|
|
38
|
+
return (_jsxs("span", { role: "status", "aria-live": "polite", "aria-label": ariaLabel, className: cn('inline-flex items-baseline gap-1.5 font-mono text-[12px] leading-none', TONE_CLASS[tone], className), children: [_jsx(TerminalSpinnerStyle, {}), _jsx("span", { className: "terminal-spinner-glyph", "aria-hidden": true, children: glyph })] }));
|
|
39
|
+
}
|
|
40
|
+
function TerminalSpinnerStyle() {
|
|
41
|
+
return (_jsx("style", { children: `
|
|
42
|
+
.terminal-spinner-glyph {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
min-width: 1ch;
|
|
45
|
+
text-align: center;
|
|
46
|
+
}
|
|
47
|
+
` }));
|
|
48
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
function Textarea({ className, ...props }) {
|
|
5
|
+
return (_jsx("textarea", { "data-slot": "textarea", className: cn("flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
export { Textarea };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type FormatDateTime } from '../lib/date-time-format.js';
|
|
2
|
+
export declare function buildTimeSlots(step: number, minMinutes: number, maxMinutes: number): number[];
|
|
3
|
+
export declare function useTimeNavigation({ slots, selectedMinutes, }: {
|
|
4
|
+
slots: number[];
|
|
5
|
+
selectedMinutes: number | null;
|
|
6
|
+
}): {
|
|
7
|
+
active: number | null;
|
|
8
|
+
setActive: import("react").Dispatch<import("react").SetStateAction<number | null>>;
|
|
9
|
+
move: (dir: 1 | -1) => void;
|
|
10
|
+
};
|
|
11
|
+
export interface TimeColumnProps {
|
|
12
|
+
slots: number[];
|
|
13
|
+
selectedMinutes: number | null;
|
|
14
|
+
activeMinutes?: number | null;
|
|
15
|
+
onPick: (minutes: number) => void;
|
|
16
|
+
locale?: string;
|
|
17
|
+
format?: FormatDateTime;
|
|
18
|
+
hour12?: boolean;
|
|
19
|
+
'aria-label': string;
|
|
20
|
+
id?: string;
|
|
21
|
+
optionId?: (minutes: number) => string;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function TimeColumn({ slots, selectedMinutes, activeMinutes, onPick, locale, format, hour12, 'aria-label': ariaLabel, id, optionId, className, }: TimeColumnProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { cn } from '../lib/cn.js';
|
|
5
|
+
import { resolveDateTimeFormat } from '../lib/date-time-format.js';
|
|
6
|
+
export function buildTimeSlots(step, minMinutes, maxMinutes) {
|
|
7
|
+
const stride = Math.max(1, Math.round(step));
|
|
8
|
+
const out = [];
|
|
9
|
+
for (let m = minMinutes; m <= maxMinutes; m += stride)
|
|
10
|
+
out.push(m);
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
function nearestIndex(slots, minutes) {
|
|
14
|
+
let best = 0;
|
|
15
|
+
let bestDist = Infinity;
|
|
16
|
+
for (let i = 0; i < slots.length; i++) {
|
|
17
|
+
const dist = Math.abs((slots[i] ?? 0) - minutes);
|
|
18
|
+
if (dist < bestDist) {
|
|
19
|
+
bestDist = dist;
|
|
20
|
+
best = i;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return best;
|
|
24
|
+
}
|
|
25
|
+
export function useTimeNavigation({ slots, selectedMinutes, }) {
|
|
26
|
+
const [active, setActive] = useState(null);
|
|
27
|
+
const move = useCallback((dir) => {
|
|
28
|
+
if (!slots.length)
|
|
29
|
+
return;
|
|
30
|
+
setActive((cur) => {
|
|
31
|
+
if (cur == null) {
|
|
32
|
+
if (selectedMinutes != null)
|
|
33
|
+
return slots[nearestIndex(slots, selectedMinutes)] ?? null;
|
|
34
|
+
return (dir === 1 ? slots[0] : slots[slots.length - 1]) ?? null;
|
|
35
|
+
}
|
|
36
|
+
const i = nearestIndex(slots, cur);
|
|
37
|
+
const next = Math.min(Math.max(i + dir, 0), slots.length - 1);
|
|
38
|
+
return slots[next] ?? null;
|
|
39
|
+
});
|
|
40
|
+
}, [slots, selectedMinutes]);
|
|
41
|
+
return { active, setActive, move };
|
|
42
|
+
}
|
|
43
|
+
export function TimeColumn({ slots, selectedMinutes, activeMinutes = null, onPick, locale, format, hour12, 'aria-label': ariaLabel, id, optionId, className, }) {
|
|
44
|
+
const timeFmt = useMemo(() => {
|
|
45
|
+
const fmt = resolveDateTimeFormat(format, locale);
|
|
46
|
+
return (d) => fmt(d, { hour: 'numeric', minute: '2-digit', hour12 });
|
|
47
|
+
}, [format, locale, hour12]);
|
|
48
|
+
const scrollTarget = activeMinutes ?? selectedMinutes;
|
|
49
|
+
const currentRef = useRef(null);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
currentRef.current?.scrollIntoView({ block: 'center' });
|
|
52
|
+
}, [scrollTarget]);
|
|
53
|
+
return (_jsx("div", { id: id, role: "listbox", "aria-label": ariaLabel, className: cn('max-h-[316px] w-[92px] space-y-0.5 overflow-y-auto px-1.5 py-2', className), children: slots.map((minutes) => {
|
|
54
|
+
const selected = selectedMinutes === minutes;
|
|
55
|
+
const active = activeMinutes === minutes;
|
|
56
|
+
return (_jsx("button", { ref: minutes === scrollTarget ? currentRef : undefined, id: optionId?.(minutes), type: "button", role: "option", "aria-selected": selected, tabIndex: -1, onClick: () => onPick(minutes), className: cn('w-full cursor-pointer rounded-md px-2 py-1 text-left text-[12px] tabular-nums transition-colors', selected
|
|
57
|
+
? 'bg-primary text-primary-foreground font-medium'
|
|
58
|
+
: 'text-foreground/85 hover:bg-accent hover:text-accent-foreground', active && !selected && 'bg-accent text-accent-foreground', active && 'ring-ring/70 ring-2 ring-inset'), children: timeFmt(new Date(2000, 0, 1, Math.floor(minutes / 60), minutes % 60)) }, minutes));
|
|
59
|
+
}) }));
|
|
60
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface TimestampedTranscriptWord {
|
|
3
|
+
id?: string;
|
|
4
|
+
text: string;
|
|
5
|
+
startMs: number;
|
|
6
|
+
endMs: number;
|
|
7
|
+
confidence?: number;
|
|
8
|
+
speaker?: string;
|
|
9
|
+
final?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface TimestampedTranscriptUtterance {
|
|
12
|
+
id: string;
|
|
13
|
+
text: string;
|
|
14
|
+
startMs: number;
|
|
15
|
+
endMs: number;
|
|
16
|
+
speaker?: string;
|
|
17
|
+
words?: readonly TimestampedTranscriptWord[];
|
|
18
|
+
final?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface TimestampedTranscriptLabels {
|
|
21
|
+
transcript: string;
|
|
22
|
+
empty: string;
|
|
23
|
+
loadMore: string;
|
|
24
|
+
seekTo: (timestamp: string, text: string) => string;
|
|
25
|
+
confidence: (text: string) => string;
|
|
26
|
+
}
|
|
27
|
+
export interface TimestampedTranscriptProps extends Omit<React.ComponentProps<'div'>, 'children'> {
|
|
28
|
+
utterances: readonly TimestampedTranscriptUtterance[];
|
|
29
|
+
labels: TimestampedTranscriptLabels;
|
|
30
|
+
formatTimestamp: (milliseconds: number) => string;
|
|
31
|
+
activeTimeMs?: number;
|
|
32
|
+
showConfidenceBelow?: number;
|
|
33
|
+
hasMore?: boolean;
|
|
34
|
+
loadingMore?: boolean;
|
|
35
|
+
onLoadMore?: () => void;
|
|
36
|
+
onSeek?: (milliseconds: number, utteranceId: string, wordIndex?: number) => void;
|
|
37
|
+
}
|
|
38
|
+
export declare function TimestampedTranscript({ utterances, labels, formatTimestamp, activeTimeMs, showConfidenceBelow, hasMore, loadingMore, onLoadMore, onSeek, className, ...props }: TimestampedTranscriptProps): React.JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ChevronDown } from 'lucide-react';
|
|
5
|
+
import { cn } from '../lib/cn.js';
|
|
6
|
+
import { Button } from './button.js';
|
|
7
|
+
import { ConfidenceMeter } from './confidence-meter.js';
|
|
8
|
+
function isActive(startMs, endMs, activeTimeMs) {
|
|
9
|
+
return activeTimeMs !== undefined && activeTimeMs >= startMs && activeTimeMs < endMs;
|
|
10
|
+
}
|
|
11
|
+
export function TimestampedTranscript({ utterances, labels, formatTimestamp, activeTimeMs, showConfidenceBelow = 0.75, hasMore = false, loadingMore = false, onLoadMore, onSeek, className, ...props }) {
|
|
12
|
+
if (utterances.length === 0) {
|
|
13
|
+
return (_jsx("div", { "data-slot": "timestamped-transcript", "aria-label": labels.transcript, className: cn('border-border bg-muted/20 rounded-lg border border-dashed p-4', className), ...props, children: _jsx("p", { className: "text-muted-foreground text-sm", children: labels.empty }) }));
|
|
14
|
+
}
|
|
15
|
+
return (_jsxs("div", { "data-slot": "timestamped-transcript", "aria-label": labels.transcript, className: cn('border-border bg-card overflow-hidden rounded-xl border', className), ...props, children: [_jsx("ol", { className: "divide-border/70 divide-y", "aria-label": labels.transcript, children: utterances.map((utterance) => {
|
|
16
|
+
const utteranceActive = isActive(utterance.startMs, utterance.endMs, activeTimeMs);
|
|
17
|
+
const timestamp = formatTimestamp(utterance.startMs);
|
|
18
|
+
const words = utterance.words ?? [];
|
|
19
|
+
return (_jsxs("li", { "data-utterance-id": utterance.id, "data-final": utterance.final ?? true, className: cn('grid grid-cols-[auto_minmax(0,1fr)] gap-3 px-3 py-3 transition-colors motion-reduce:transition-none', utteranceActive && 'bg-primary/[0.06]', utterance.final === false && 'opacity-70'), children: [_jsx("button", { type: "button", onClick: onSeek ? () => onSeek(utterance.startMs, utterance.id) : undefined, disabled: !onSeek, "aria-label": labels.seekTo(timestamp, utterance.text), className: "text-muted-foreground focus-visible:ring-ring mt-0.5 rounded-sm font-mono text-[11px] tabular-nums outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-default", children: timestamp }), _jsxs("div", { className: "min-w-0", children: [utterance.speaker ? (_jsx("div", { className: "text-muted-foreground mb-1.5 text-xs font-medium", children: utterance.speaker })) : null, words.length > 0 ? (_jsx("p", { className: "flex flex-wrap items-baseline gap-x-1.5 gap-y-1 text-sm leading-relaxed", children: words.map((word, wordIndex) => {
|
|
20
|
+
const active = isActive(word.startMs, word.endMs, activeTimeMs);
|
|
21
|
+
const wordTimestamp = formatTimestamp(word.startMs);
|
|
22
|
+
const key = word.id ?? `${utterance.id}-${word.startMs}-${wordIndex}`;
|
|
23
|
+
const showConfidence = word.confidence !== undefined && word.confidence < showConfidenceBelow;
|
|
24
|
+
return (_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: onSeek
|
|
25
|
+
? () => onSeek(word.startMs, utterance.id, wordIndex)
|
|
26
|
+
: undefined, disabled: !onSeek, "aria-label": labels.seekTo(wordTimestamp, word.text), "aria-current": active ? 'true' : undefined, className: cn('focus-visible:ring-ring rounded-sm px-0.5 text-left transition-colors outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-text motion-reduce:transition-none', active && 'bg-primary/15 text-primary', word.final === false && 'text-muted-foreground'), children: word.text }), showConfidence ? (_jsx(ConfidenceMeter, { value: word.confidence ?? 0, label: labels.confidence(word.text) })) : null] }, key));
|
|
27
|
+
}) })) : (_jsx("button", { type: "button", onClick: onSeek ? () => onSeek(utterance.startMs, utterance.id) : undefined, disabled: !onSeek, "aria-current": utteranceActive ? 'true' : undefined, "aria-label": labels.seekTo(timestamp, utterance.text), className: cn('focus-visible:ring-ring rounded-sm text-left text-sm leading-relaxed outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-text', utteranceActive && 'text-primary'), children: utterance.text }))] })] }, utterance.id));
|
|
28
|
+
}) }), hasMore && onLoadMore ? (_jsx("div", { className: "border-border/70 flex justify-center border-t p-2", children: _jsxs(Button, { type: "button", variant: "ghost", size: "sm", disabled: loadingMore, "aria-busy": loadingMore, onClick: onLoadMore, children: [_jsx(ChevronDown, { className: "size-3.5", strokeWidth: 1.5, "aria-hidden": true }), labels.loadMore] }) })) : null] }));
|
|
29
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export interface TimezonePickerLabels {
|
|
3
|
+
search: string;
|
|
4
|
+
empty: string;
|
|
5
|
+
current: string;
|
|
6
|
+
all: string;
|
|
7
|
+
}
|
|
8
|
+
export interface TimezonePickerProps {
|
|
9
|
+
value: string;
|
|
10
|
+
onChange: (timeZone: string) => void;
|
|
11
|
+
labels: TimezonePickerLabels;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
defaultOpen?: boolean;
|
|
14
|
+
onOpenChange?: (open: boolean) => void;
|
|
15
|
+
align?: 'start' | 'center' | 'end';
|
|
16
|
+
timeZones?: readonly string[];
|
|
17
|
+
referenceDate?: Date;
|
|
18
|
+
}
|
|
19
|
+
export declare function TimezonePicker({ value, onChange, labels, children, defaultOpen, onOpenChange, align, timeZones, referenceDate, }: TimezonePickerProps): import("react").JSX.Element;
|
|
20
|
+
export declare function TimezoneList({ value, onChange, labels, timeZones, referenceDate }: Omit<TimezonePickerProps, 'children' | 'defaultOpen' | 'onOpenChange' | 'align'>): import("react").JSX.Element;
|
|
21
|
+
export declare function supportedTimeZones(): string[];
|
|
22
|
+
export declare function timezoneOffsetLabel(timeZone: string, at?: Date): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import { Check } from 'lucide-react';
|
|
5
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from './command.js';
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
|
|
7
|
+
export function TimezonePicker({ value, onChange, labels, children, defaultOpen = false, onOpenChange, align = 'end', timeZones, referenceDate, }) {
|
|
8
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
9
|
+
const setOpenState = (next) => {
|
|
10
|
+
setOpen(next);
|
|
11
|
+
onOpenChange?.(next);
|
|
12
|
+
};
|
|
13
|
+
return _jsxs(Popover, { open: open, onOpenChange: setOpenState, children: [_jsx(PopoverTrigger, { asChild: true, children: children }), _jsx(PopoverContent, { align: align, className: "w-72 p-0", children: _jsx(TimezoneList, { value: value, labels: labels, timeZones: timeZones, referenceDate: referenceDate, onChange: (timeZone) => {
|
|
14
|
+
onChange(timeZone);
|
|
15
|
+
setOpenState(false);
|
|
16
|
+
} }) })] });
|
|
17
|
+
}
|
|
18
|
+
export function TimezoneList({ value, onChange, labels, timeZones, referenceDate }) {
|
|
19
|
+
const zones = useMemo(() => {
|
|
20
|
+
const all = timeZones ? [...timeZones] : supportedTimeZones();
|
|
21
|
+
const local = browserTimeZone();
|
|
22
|
+
const pinned = [...new Set([value, local].filter(Boolean))];
|
|
23
|
+
return { pinned, rest: all.filter((zone) => !pinned.includes(zone)) };
|
|
24
|
+
}, [timeZones, value]);
|
|
25
|
+
const renderZone = (timeZone) => _jsxs(CommandItem, { value: timeZone, onSelect: () => onChange(timeZone), className: "flex items-center gap-2 text-xs", children: [_jsx("span", { className: "min-w-0 flex-1 truncate", children: timeZone.replaceAll('_', ' ') }), _jsx("span", { className: "text-muted-foreground text-[11px] tabular-nums", children: timezoneOffsetLabel(timeZone, referenceDate) }), timeZone === value ? _jsx(Check, { className: "text-muted-foreground size-3.5 shrink-0", "aria-hidden": true }) : null] }, timeZone);
|
|
26
|
+
return _jsxs(Command, { children: [_jsx(CommandInput, { placeholder: labels.search }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: labels.empty }), zones.pinned.length > 0 ? _jsx(CommandGroup, { heading: labels.current, children: zones.pinned.map(renderZone) }) : null, _jsx(CommandGroup, { heading: labels.all, children: zones.rest.map(renderZone) })] })] });
|
|
27
|
+
}
|
|
28
|
+
export function supportedTimeZones() {
|
|
29
|
+
try {
|
|
30
|
+
const supportedValuesOf = Reflect.get(Intl, 'supportedValuesOf');
|
|
31
|
+
if (typeof supportedValuesOf === 'function') {
|
|
32
|
+
const values = Reflect.apply(supportedValuesOf, Intl, ['timeZone']);
|
|
33
|
+
if (Array.isArray(values)) {
|
|
34
|
+
const zones = values.filter((value) => typeof value === 'string');
|
|
35
|
+
if (zones.length > 0)
|
|
36
|
+
return zones.includes('UTC') ? zones : ['UTC', ...zones];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch { /* Intl fallback */ }
|
|
41
|
+
return ['UTC'];
|
|
42
|
+
}
|
|
43
|
+
export function timezoneOffsetLabel(timeZone, at = new Date()) {
|
|
44
|
+
try {
|
|
45
|
+
return new Intl.DateTimeFormat('en-US', { timeZone, timeZoneName: 'shortOffset' })
|
|
46
|
+
.formatToParts(at)
|
|
47
|
+
.find((part) => part.type === 'timeZoneName')?.value ?? '';
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function browserTimeZone() {
|
|
54
|
+
try {
|
|
55
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return 'UTC';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
3
|
+
import { type VariantProps } from "class-variance-authority";
|
|
4
|
+
declare const tooltipVariants: (props?: ({
|
|
5
|
+
variant?: "default" | "compact" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function TooltipProvider({ delayDuration, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>): React.JSX.Element;
|
|
8
|
+
declare function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>): React.JSX.Element;
|
|
9
|
+
declare function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>): React.JSX.Element;
|
|
10
|
+
declare function TooltipContent({ className, variant, sideOffset, children, ...props }: React.ComponentProps<typeof TooltipPrimitive.Content> & VariantProps<typeof tooltipVariants>): React.JSX.Element;
|
|
11
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { cn } from "../lib/cn.js";
|
|
7
|
+
const tooltipVariants = cva("z-50 inline-flex w-fit origin-(--radix-tooltip-content-transform-origin) items-center data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", {
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
default: "max-w-xs gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm",
|
|
11
|
+
compact: "max-w-[16rem] gap-1 rounded-md bg-popover px-2 py-1 text-[11px] font-medium whitespace-nowrap text-popover-foreground shadow-md ring-1 ring-foreground/10",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: { variant: "default" },
|
|
15
|
+
});
|
|
16
|
+
function TooltipProvider({ delayDuration = 0, ...props }) {
|
|
17
|
+
return (_jsx(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration: delayDuration, ...props }));
|
|
18
|
+
}
|
|
19
|
+
function Tooltip({ ...props }) {
|
|
20
|
+
return _jsx(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
|
|
21
|
+
}
|
|
22
|
+
function TooltipTrigger({ ...props }) {
|
|
23
|
+
return _jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
24
|
+
}
|
|
25
|
+
function TooltipContent({ className, variant = "default", sideOffset, children, ...props }) {
|
|
26
|
+
const resolvedSideOffset = sideOffset ?? (variant === "compact" ? 6 : 0);
|
|
27
|
+
return (_jsx(TooltipPrimitive.Portal, { children: _jsxs(TooltipPrimitive.Content, { "data-slot": "tooltip-content", sideOffset: resolvedSideOffset, className: cn(tooltipVariants({ variant }), className), ...props, children: [children, variant === "default" ? (_jsx(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })) : null] }) }));
|
|
28
|
+
}
|
|
29
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type LucideIcon } from 'lucide-react';
|
|
3
|
+
import { type VoiceLineState } from './voice-line.js';
|
|
4
|
+
export type TranscriptionOverlayState = 'preflight' | 'recording' | 'processing' | 'completed' | 'cancelled' | 'error' | 'agent-inline' | 'agent-background' | 'speaking';
|
|
5
|
+
export interface TranscriptionOverlaySelector {
|
|
6
|
+
id: string;
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
icon?: LucideIcon;
|
|
9
|
+
avatar?: React.ReactNode;
|
|
10
|
+
ariaLabel?: string;
|
|
11
|
+
trailing?: 'menu' | 'switch' | 'none';
|
|
12
|
+
expanded?: boolean;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
onSelect?: () => void;
|
|
15
|
+
}
|
|
16
|
+
export interface TranscriptionOverlayLabels {
|
|
17
|
+
cancel: string;
|
|
18
|
+
dismiss: string;
|
|
19
|
+
moreActions: string;
|
|
20
|
+
retry: string;
|
|
21
|
+
stop: string;
|
|
22
|
+
undo: string;
|
|
23
|
+
}
|
|
24
|
+
export interface TranscriptionOverlayProps extends Omit<React.ComponentProps<'section'>, 'children'> {
|
|
25
|
+
state: TranscriptionOverlayState;
|
|
26
|
+
density?: 'default' | 'compact';
|
|
27
|
+
ariaLabel: string;
|
|
28
|
+
statusLabel: string;
|
|
29
|
+
labels: TranscriptionOverlayLabels;
|
|
30
|
+
transcript?: React.ReactNode;
|
|
31
|
+
actionLabel?: React.ReactNode;
|
|
32
|
+
duration?: React.ReactNode;
|
|
33
|
+
applicationIcon?: React.ReactNode;
|
|
34
|
+
applicationName?: string;
|
|
35
|
+
selectors?: readonly TranscriptionOverlaySelector[];
|
|
36
|
+
partial?: boolean;
|
|
37
|
+
micLevel?: number;
|
|
38
|
+
analyser?: AnalyserNode | null;
|
|
39
|
+
voiceState?: VoiceLineState;
|
|
40
|
+
onCancel?: () => void;
|
|
41
|
+
onDismiss?: () => void;
|
|
42
|
+
onMoreActions?: () => void;
|
|
43
|
+
onRetry?: () => void;
|
|
44
|
+
onStop?: () => void;
|
|
45
|
+
onUndo?: () => void;
|
|
46
|
+
}
|
|
47
|
+
export declare function TranscriptionOverlay({ state, density, ariaLabel, statusLabel, labels, transcript, actionLabel, duration, applicationIcon, applicationName, selectors, partial, micLevel, analyser, voiceState, onCancel, onDismiss, onMoreActions, onRetry, onStop, onUndo, className, ...props }: TranscriptionOverlayProps): React.JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ArrowLeftRight, ChevronDown, Ellipsis, RotateCcw, Square, X, } from 'lucide-react';
|
|
5
|
+
import { cn } from '../lib/cn.js';
|
|
6
|
+
import { Button } from './button.js';
|
|
7
|
+
import { IconButton } from './icon-button.js';
|
|
8
|
+
import { VoiceLine } from './voice-line.js';
|
|
9
|
+
const SPEAKING_BAR_COUNT = 11;
|
|
10
|
+
const VOICE_STATE = {
|
|
11
|
+
preflight: 'generating',
|
|
12
|
+
recording: 'listening',
|
|
13
|
+
processing: 'generating',
|
|
14
|
+
completed: 'idle',
|
|
15
|
+
cancelled: 'reprompt',
|
|
16
|
+
error: 'reprompt',
|
|
17
|
+
'agent-inline': 'speaking',
|
|
18
|
+
'agent-background': 'generating',
|
|
19
|
+
speaking: 'speaking',
|
|
20
|
+
};
|
|
21
|
+
export function TranscriptionOverlay({ state, density = 'default', ariaLabel, statusLabel, labels, transcript, actionLabel, duration, applicationIcon, applicationName, selectors = [], partial = state === 'recording', micLevel, analyser = null, voiceState, onCancel, onDismiss, onMoreActions, onRetry, onStop, onUndo, className, ...props }) {
|
|
22
|
+
const compact = density === 'compact';
|
|
23
|
+
const resolvedVoiceState = voiceState ?? VOICE_STATE[state];
|
|
24
|
+
const active = state === 'recording' || state === 'speaking' || state === 'agent-inline';
|
|
25
|
+
const showTopDismiss = Boolean(onDismiss) && state !== 'completed' && state !== 'agent-inline';
|
|
26
|
+
const showFooterDismiss = Boolean(onDismiss) && state === 'agent-inline';
|
|
27
|
+
return (_jsxs("section", { "data-slot": "transcription-overlay", "data-state": state, "aria-label": ariaLabel, className: cn('w-full min-w-0', compact ? 'max-w-md' : 'max-w-xl', state === 'completed' &&
|
|
28
|
+
'motion-safe:animate-out motion-safe:fade-out-0 motion-safe:slide-out-to-bottom-1 duration-300 motion-safe:[animation-fill-mode:forwards]', className), ...props, children: [selectors.length > 0 || onMoreActions ? (_jsxs("div", { className: cn('flex flex-wrap items-center px-2', compact ? 'mb-1 gap-1' : 'mb-1.5 gap-1.5'), children: [selectors.map(({ id, label, icon: Icon, avatar, ariaLabel, trailing = 'menu', expanded, disabled, onSelect, }) => (_jsxs(Button, { type: "button", variant: "outline", size: compact ? 'xs' : 'sm', disabled: disabled, "aria-expanded": expanded, "aria-label": ariaLabel, onClick: onSelect, className: cn('bg-card ring-foreground/10 rounded-full shadow-sm ring-1', 'dark:bg-card dark:hover:bg-muted', compact && 'text-[11px]'), children: [avatar ? (_jsx("span", { className: "size-4 overflow-hidden rounded-full", children: avatar })) : Icon ? (_jsx(Icon, { className: "size-3.5", strokeWidth: 1.5, "aria-hidden": true })) : null, _jsx("span", { children: label }), trailing === 'menu' ? (_jsx(ChevronDown, { className: "text-muted-foreground size-3.5", strokeWidth: 1.5, "aria-hidden": true })) : trailing === 'switch' ? (_jsx(ArrowLeftRight, { className: "text-muted-foreground size-3.5", strokeWidth: 1.5, "aria-hidden": true })) : null] }, id))), onMoreActions ? (_jsx(IconButton, { type: "button", size: compact ? 'xs' : 'sm', tooltip: labels.moreActions, "aria-label": labels.moreActions, onClick: onMoreActions, className: "bg-card border-border ring-foreground/10 dark:bg-card dark:hover:bg-muted rounded-full border shadow-sm ring-1", children: _jsx(Ellipsis, { className: "size-4", strokeWidth: 1.5, "aria-hidden": true }) })) : null] })) : null, _jsxs("div", { className: cn('border-border bg-card ring-foreground/10 overflow-hidden border shadow-2xl ring-1', compact ? 'rounded-xl' : 'rounded-2xl'), children: [showTopDismiss ? (_jsx("div", { className: cn('flex justify-end', compact ? 'px-1 pt-1' : 'px-2 pt-2'), children: _jsx(IconButton, { type: "button", size: compact ? 'xs' : 'sm', tooltip: labels.dismiss, "aria-label": labels.dismiss, onClick: onDismiss, children: _jsx(X, { className: "size-4", strokeWidth: 1.5, "aria-hidden": true }) }) })) : null, transcript != null ? (_jsxs("p", { "aria-live": "polite", className: cn('leading-relaxed tracking-[-0.005em]', compact ? 'min-h-8 px-3 py-2 text-xs' : 'min-h-12 px-4 pt-3 pb-3 text-sm', showTopDismiss && 'pt-0', partial ? 'text-muted-foreground' : 'text-foreground'), children: [transcript, partial ? (_jsx("span", { "aria-hidden": true, className: "bg-primary ml-0.5 inline-block h-[1em] w-0.5 -translate-y-px align-middle motion-safe:animate-pulse" })) : null] })) : null, _jsxs("div", { className: cn('border-border/70 relative flex min-w-0 items-center border-t', compact ? 'min-h-8 gap-1.5 px-2 py-1' : 'min-h-10 gap-2 px-3 py-2', transcript == null && !showTopDismiss && 'border-t-0'), children: [_jsx("span", { role: "img", "aria-label": applicationName, className: cn('border-border bg-muted inline-flex shrink-0 items-center justify-center overflow-hidden rounded-md border shadow-sm', compact ? 'size-6' : 'size-7'), children: applicationIcon }), onCancel && state === 'recording' ? (_jsxs(Button, { type: "button", variant: "ghost", size: compact ? 'xs' : 'sm', onClick: onCancel, children: [_jsx(X, { className: "size-3.5", strokeWidth: 1.5, "aria-hidden": true }), labels.cancel] })) : null, _jsx(VoiceLine, { state: resolvedVoiceState, layout: "waveform", analyser: analyser, active: active, micLevel: micLevel, bars: resolvedVoiceState === 'speaking' ? SPEAKING_BAR_COUNT : undefined, "aria-label": statusLabel, loadingVisualization: state === 'processing' ? 'shimmer-bars' : 'ripple', className: "absolute left-1/2 w-1/3 min-w-16 -translate-x-1/2 border-0 bg-transparent px-0 shadow-none ring-0" }), actionLabel && !['recording', 'processing', 'preflight', 'completed'].includes(state) ? (_jsx("div", { className: "text-foreground max-w-32 min-w-0 truncate text-xs font-medium", children: actionLabel })) : null, _jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-1", children: [duration ? (_jsx("span", { role: "timer", className: cn('text-muted-foreground mr-1 shrink-0 font-mono tabular-nums', compact ? 'text-[10px]' : 'text-[11px]'), children: duration })) : null, onStop &&
|
|
29
|
+
(state === 'recording' || state === 'speaking' || state === 'agent-inline') ? (_jsxs(Button, { type: "button", variant: "outline", size: compact ? 'xs' : 'sm', onClick: onStop, children: [_jsx(Square, { className: "size-3", strokeWidth: 1.5, "aria-hidden": true }), labels.stop] })) : null, onUndo && state === 'cancelled' ? (_jsxs(Button, { type: "button", variant: "outline", size: compact ? 'xs' : 'sm', onClick: onUndo, children: [_jsx(RotateCcw, { className: "size-3.5", strokeWidth: 1.5, "aria-hidden": true }), labels.undo] })) : null, onRetry && state === 'error' ? (_jsxs(Button, { type: "button", variant: "outline", size: compact ? 'xs' : 'sm', onClick: onRetry, children: [_jsx(RotateCcw, { className: "size-3.5", strokeWidth: 1.5, "aria-hidden": true }), labels.retry] })) : null, showFooterDismiss ? (_jsx(IconButton, { type: "button", size: compact ? 'xs' : 'sm', tooltip: labels.dismiss, "aria-label": labels.dismiss, onClick: onDismiss, children: _jsx(X, { className: "size-4", strokeWidth: 1.5, "aria-hidden": true }) })) : null] })] })] })] }));
|
|
30
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export type UsageBarTone = 'usage' | 'warning' | 'danger';
|
|
3
|
+
/**
|
|
4
|
+
* One place decides when a consumed quota stops being neutral and starts being a
|
|
5
|
+
* warning, so a five-hour window and a weekly one never disagree about what 92% means.
|
|
6
|
+
*/
|
|
7
|
+
export declare function usageTone(fraction: number): UsageBarTone;
|
|
8
|
+
export interface UsageBarProps extends Omit<React.ComponentProps<'div'>, 'children'> {
|
|
9
|
+
label: string;
|
|
10
|
+
/** Consumed share, 0–1. Values outside the range clamp rather than overflow the track. */
|
|
11
|
+
fraction: number;
|
|
12
|
+
/** Right-aligned readout — a percentage, "12k of 200k", whatever the caller measures in. */
|
|
13
|
+
value?: React.ReactNode;
|
|
14
|
+
caption?: React.ReactNode;
|
|
15
|
+
tone?: UsageBarTone;
|
|
16
|
+
}
|
|
17
|
+
export declare function UsageBar({ label, fraction, value, caption, tone, className, ...props }: UsageBarProps): React.JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { cn } from '../lib/cn.js';
|
|
5
|
+
const TONE_FILL = {
|
|
6
|
+
usage: 'bg-usage',
|
|
7
|
+
warning: 'bg-warning-9',
|
|
8
|
+
danger: 'bg-danger-9',
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* One place decides when a consumed quota stops being neutral and starts being a
|
|
12
|
+
* warning, so a five-hour window and a weekly one never disagree about what 92% means.
|
|
13
|
+
*/
|
|
14
|
+
export function usageTone(fraction) {
|
|
15
|
+
if (fraction >= 0.9)
|
|
16
|
+
return 'danger';
|
|
17
|
+
if (fraction >= 0.75)
|
|
18
|
+
return 'warning';
|
|
19
|
+
return 'usage';
|
|
20
|
+
}
|
|
21
|
+
export function UsageBar({ label, fraction, value, caption, tone, className, ...props }) {
|
|
22
|
+
const clamped = Math.max(0, Math.min(1, Number.isFinite(fraction) ? fraction : 0));
|
|
23
|
+
const percent = Math.round(clamped * 100);
|
|
24
|
+
const resolvedTone = tone ?? usageTone(clamped);
|
|
25
|
+
return (_jsxs("div", { "data-slot": "usage-bar", "data-tone": resolvedTone, role: "meter", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": percent, "aria-label": label, className: cn('flex flex-col gap-1', className), ...props, children: [_jsxs("div", { className: "flex items-baseline justify-between gap-2 text-[11.5px]", children: [_jsx("span", { className: "text-muted-foreground min-w-0 truncate", children: label }), value ? (_jsx("span", { className: "text-muted-foreground shrink-0 font-mono tabular-nums", children: value })) : null] }), _jsx("div", { className: "bg-muted h-1 overflow-hidden rounded-full", "aria-hidden": true, children: _jsx("span", { className: cn('block h-full rounded-full transition-[width] duration-150 ease-[var(--ease-out-expo)] motion-reduce:transition-none', TONE_FILL[resolvedTone]), style: { width: `${percent}%` } }) }), caption ? (_jsx("p", { className: "text-muted-foreground/75 font-mono text-[10.5px]", children: caption })) : null] }));
|
|
26
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
export interface ViewQueryBarProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
3
|
+
sort?: ReactNode;
|
|
4
|
+
/** Filter chips, one element per top-level clause. */
|
|
5
|
+
filters?: ReactNode[];
|
|
6
|
+
/** Trailing add-filter affordance. Shown only once the view already has a filter — with none, the view's own empty state offers the first one. */
|
|
7
|
+
addFilter?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The row of active query pills a collection view shows under its header.
|
|
11
|
+
* Collapses to nothing while the view is unqueried so the list starts flush.
|
|
12
|
+
*/
|
|
13
|
+
export declare function ViewQueryBar({ sort, filters, addFilter, className, ...props }: ViewQueryBarProps): React.ReactElement | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../lib/cn.js';
|
|
4
|
+
/**
|
|
5
|
+
* The row of active query pills a collection view shows under its header.
|
|
6
|
+
* Collapses to nothing while the view is unqueried so the list starts flush.
|
|
7
|
+
*/
|
|
8
|
+
export function ViewQueryBar({ sort, filters = [], addFilter, className, ...props }) {
|
|
9
|
+
const hasFilters = filters.length > 0;
|
|
10
|
+
if (!sort && !hasFilters)
|
|
11
|
+
return null;
|
|
12
|
+
return (_jsx("div", { "data-slot": "view-query-bar", className: cn('mx-auto w-full max-w-5xl shrink-0 px-6 pt-2 pb-1', className), ...props, children: _jsxs("div", { className: "flex min-h-7 flex-wrap items-center gap-1.5", children: [sort, filters, hasFilters ? addFilter : null] }) }));
|
|
13
|
+
}
|