@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,228 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { Prec } from '@codemirror/state';
|
|
5
|
+
import { EditorView, keymap } from '@codemirror/view';
|
|
6
|
+
import CodeMirror from '@uiw/react-codemirror';
|
|
7
|
+
import { PostgreSQL, keywordCompletionSource, schemaCompletionSource, sql, } from '@codemirror/lang-sql';
|
|
8
|
+
import { autocompletion, moveCompletionSelection, } from '@codemirror/autocomplete';
|
|
9
|
+
import { syntaxHighlighting } from '@codemirror/language';
|
|
10
|
+
import { atmosEditorHighlight, atmosEditorTheme } from './code-editor-theme.js';
|
|
11
|
+
const READ_ONLY_KEYWORDS = new Set([
|
|
12
|
+
'select', 'distinct', 'from', 'where', 'group', 'by', 'having', 'order',
|
|
13
|
+
'limit', 'offset', 'fetch', 'first', 'next', 'only', 'rows', 'row', 'with',
|
|
14
|
+
'as', 'on', 'using',
|
|
15
|
+
'join', 'inner', 'left', 'right', 'full', 'outer', 'cross', 'natural', 'lateral',
|
|
16
|
+
'union', 'intersect', 'except', 'all',
|
|
17
|
+
'and', 'or', 'not', 'in', 'is', 'null', 'like', 'ilike', 'similar', 'between',
|
|
18
|
+
'exists', 'any', 'some', 'case', 'when', 'then', 'else', 'end', 'asc', 'desc', 'nulls',
|
|
19
|
+
'over', 'partition', 'window', 'filter', 'range', 'groups', 'unbounded',
|
|
20
|
+
'preceding', 'following', 'current',
|
|
21
|
+
'true', 'false', 'cast', 'coalesce', 'nullif', 'interval', 'array',
|
|
22
|
+
'int', 'integer', 'bigint', 'smallint', 'numeric', 'decimal', 'real', 'double',
|
|
23
|
+
'precision', 'text', 'varchar', 'char', 'boolean', 'bool', 'date', 'timestamp',
|
|
24
|
+
'timestamptz', 'time', 'uuid', 'json', 'jsonb',
|
|
25
|
+
]);
|
|
26
|
+
function readOnlyKeywords(base) {
|
|
27
|
+
return (ctx) => {
|
|
28
|
+
const res = base(ctx);
|
|
29
|
+
if (res && !(res instanceof Promise)) {
|
|
30
|
+
return {
|
|
31
|
+
...res,
|
|
32
|
+
options: res.options.filter((o) => READ_ONLY_KEYWORDS.has(o.label.toLowerCase())),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return res;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function remapTypes(base, map) {
|
|
39
|
+
return (ctx) => {
|
|
40
|
+
const res = base(ctx);
|
|
41
|
+
if (res && !(res instanceof Promise)) {
|
|
42
|
+
return { ...res, options: res.options.map((o) => ({ ...o, type: map(o.type) })) };
|
|
43
|
+
}
|
|
44
|
+
return res;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function paramCompletionSource(params) {
|
|
48
|
+
const options = params.map((name) => ({
|
|
49
|
+
label: '@' + name,
|
|
50
|
+
type: 'constant',
|
|
51
|
+
detail: 'param',
|
|
52
|
+
}));
|
|
53
|
+
return (ctx) => {
|
|
54
|
+
if (options.length === 0)
|
|
55
|
+
return null;
|
|
56
|
+
const token = ctx.matchBefore(/@[\w]*/);
|
|
57
|
+
if (!token)
|
|
58
|
+
return null;
|
|
59
|
+
if (token.from === token.to && !ctx.explicit)
|
|
60
|
+
return null;
|
|
61
|
+
return { from: token.from, options, validFor: /^@[\w]*$/ };
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const ICON_GEOMETRY = {
|
|
65
|
+
table: [['path', { d: 'M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18' }]],
|
|
66
|
+
column: [
|
|
67
|
+
['rect', { width: '18', height: '18', x: '3', y: '3', rx: '2' }],
|
|
68
|
+
['path', { d: 'M9 3v18' }],
|
|
69
|
+
['path', { d: 'M15 3v18' }],
|
|
70
|
+
],
|
|
71
|
+
keyword: [
|
|
72
|
+
['circle', { cx: '7', cy: '12', r: '3' }],
|
|
73
|
+
['path', { d: 'M10 9v6' }],
|
|
74
|
+
['circle', { cx: '17', cy: '12', r: '3' }],
|
|
75
|
+
['path', { d: 'M14 7v8' }],
|
|
76
|
+
['path', { d: 'M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1' }],
|
|
77
|
+
],
|
|
78
|
+
datatype: [
|
|
79
|
+
['polyline', { points: '4 7 4 4 20 4 20 7' }],
|
|
80
|
+
['line', { x1: '9', x2: '15', y1: '20', y2: '20' }],
|
|
81
|
+
['line', { x1: '12', x2: '12', y1: '4', y2: '20' }],
|
|
82
|
+
],
|
|
83
|
+
func: [
|
|
84
|
+
['rect', { width: '18', height: '18', x: '3', y: '3', rx: '2', ry: '2' }],
|
|
85
|
+
['path', { d: 'M9 17c2 0 2.8-1 2.8-2.8V10c0-2 1-3.3 3.2-3' }],
|
|
86
|
+
['path', { d: 'M9 11.2h5.7' }],
|
|
87
|
+
],
|
|
88
|
+
param: [
|
|
89
|
+
['circle', { cx: '12', cy: '12', r: '4' }],
|
|
90
|
+
['path', { d: 'M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94' }],
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
const TYPE_ICON = {
|
|
94
|
+
table: { geometry: ICON_GEOMETRY.table, cls: 'cm-ac-table' },
|
|
95
|
+
property: { geometry: ICON_GEOMETRY.column, cls: 'cm-ac-column' },
|
|
96
|
+
keyword: { geometry: ICON_GEOMETRY.keyword, cls: 'cm-ac-keyword' },
|
|
97
|
+
datatype: { geometry: ICON_GEOMETRY.datatype, cls: 'cm-ac-datatype' },
|
|
98
|
+
variable: { geometry: ICON_GEOMETRY.func, cls: 'cm-ac-func' },
|
|
99
|
+
constant: { geometry: ICON_GEOMETRY.param, cls: 'cm-ac-param' },
|
|
100
|
+
};
|
|
101
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
102
|
+
function buildIcon(geometry) {
|
|
103
|
+
const svg = document.createElementNS(SVG_NS, 'svg');
|
|
104
|
+
svg.setAttribute('viewBox', '0 0 24 24');
|
|
105
|
+
svg.setAttribute('width', '14');
|
|
106
|
+
svg.setAttribute('height', '14');
|
|
107
|
+
svg.setAttribute('fill', 'none');
|
|
108
|
+
svg.setAttribute('stroke', 'currentColor');
|
|
109
|
+
svg.setAttribute('stroke-width', '1.9');
|
|
110
|
+
svg.setAttribute('stroke-linecap', 'round');
|
|
111
|
+
svg.setAttribute('stroke-linejoin', 'round');
|
|
112
|
+
for (const [tag, attrs] of geometry) {
|
|
113
|
+
const el = document.createElementNS(SVG_NS, tag);
|
|
114
|
+
for (const [k, v] of Object.entries(attrs))
|
|
115
|
+
el.setAttribute(k, v);
|
|
116
|
+
svg.appendChild(el);
|
|
117
|
+
}
|
|
118
|
+
return svg;
|
|
119
|
+
}
|
|
120
|
+
function renderCompletionIcon(completion) {
|
|
121
|
+
const wrap = document.createElement('span');
|
|
122
|
+
const spec = TYPE_ICON[completion.type ?? ''];
|
|
123
|
+
wrap.className = `cm-ac-icon ${spec?.cls ?? 'cm-ac-generic'}`;
|
|
124
|
+
if (spec)
|
|
125
|
+
wrap.appendChild(buildIcon(spec.geometry));
|
|
126
|
+
return wrap;
|
|
127
|
+
}
|
|
128
|
+
const completionTheme = EditorView.theme({
|
|
129
|
+
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
130
|
+
border: '1px solid var(--border)',
|
|
131
|
+
borderRadius: 'var(--radius-lg, 0.625rem)',
|
|
132
|
+
backgroundColor: 'var(--popover)',
|
|
133
|
+
color: 'var(--popover-foreground)',
|
|
134
|
+
boxShadow: '0 12px 32px -12px rgb(0 0 0 / 0.28)',
|
|
135
|
+
padding: '4px',
|
|
136
|
+
overflow: 'hidden',
|
|
137
|
+
},
|
|
138
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul': {
|
|
139
|
+
fontFamily: 'inherit',
|
|
140
|
+
fontSize: '12.5px',
|
|
141
|
+
maxHeight: '17rem',
|
|
142
|
+
},
|
|
143
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li': {
|
|
144
|
+
display: 'flex',
|
|
145
|
+
alignItems: 'center',
|
|
146
|
+
gap: '7px',
|
|
147
|
+
padding: '4px 8px',
|
|
148
|
+
borderRadius: 'var(--radius-sm, 0.375rem)',
|
|
149
|
+
color: 'var(--popover-foreground)',
|
|
150
|
+
},
|
|
151
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
|
|
152
|
+
backgroundColor: 'var(--accent)',
|
|
153
|
+
color: 'var(--accent-foreground)',
|
|
154
|
+
},
|
|
155
|
+
'.cm-ac-icon': {
|
|
156
|
+
display: 'inline-flex',
|
|
157
|
+
alignItems: 'center',
|
|
158
|
+
justifyContent: 'center',
|
|
159
|
+
width: '15px',
|
|
160
|
+
height: '15px',
|
|
161
|
+
flex: '0 0 auto',
|
|
162
|
+
opacity: '0.95',
|
|
163
|
+
},
|
|
164
|
+
'.cm-ac-table': { color: 'var(--cm-ident)' },
|
|
165
|
+
'.cm-ac-column': { color: 'var(--cm-name)' },
|
|
166
|
+
'.cm-ac-keyword': { color: 'var(--cm-keyword)' },
|
|
167
|
+
'.cm-ac-datatype': { color: 'var(--cm-number)' },
|
|
168
|
+
'.cm-ac-func': { color: 'var(--cm-function)' },
|
|
169
|
+
'.cm-ac-param': { color: 'var(--cm-string)' },
|
|
170
|
+
'.cm-ac-generic': { color: 'var(--muted-foreground)' },
|
|
171
|
+
'.cm-completionLabel': { flex: '1 1 auto', minWidth: '0' },
|
|
172
|
+
'.cm-completionMatchedText': {
|
|
173
|
+
textDecoration: 'none',
|
|
174
|
+
fontWeight: '600',
|
|
175
|
+
color: 'inherit',
|
|
176
|
+
},
|
|
177
|
+
'.cm-completionDetail': {
|
|
178
|
+
marginLeft: 'auto',
|
|
179
|
+
fontStyle: 'normal',
|
|
180
|
+
fontFamily: 'var(--font-geist-mono, ui-monospace, monospace)',
|
|
181
|
+
fontSize: '10.5px',
|
|
182
|
+
color: 'var(--muted-foreground)',
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
const completionNavKeymap = Prec.high(keymap.of([
|
|
186
|
+
{ key: 'Ctrl-n', run: moveCompletionSelection(true) },
|
|
187
|
+
{ key: 'Ctrl-p', run: moveCompletionSelection(false) },
|
|
188
|
+
]));
|
|
189
|
+
export function SqlEditor({ value, onChange, schema, placeholder, params }) {
|
|
190
|
+
const paramNames = useMemo(() => Array.from(new Set((params ?? []).map((p) => p.replace(/^@/, '').trim()).filter((p) => p !== ''))), [params]);
|
|
191
|
+
const extensions = useMemo(() => {
|
|
192
|
+
const objects = {};
|
|
193
|
+
for (const obj of schema) {
|
|
194
|
+
if (typeof obj.slug !== 'string')
|
|
195
|
+
continue;
|
|
196
|
+
const attributes = Array.isArray(obj.attributes)
|
|
197
|
+
? obj.attributes.flatMap((attribute) => attribute && typeof attribute === 'object' && 'slug' in attribute
|
|
198
|
+
&& typeof attribute.slug === 'string'
|
|
199
|
+
? [attribute.slug]
|
|
200
|
+
: [])
|
|
201
|
+
: [];
|
|
202
|
+
objects[obj.slug] = attributes;
|
|
203
|
+
}
|
|
204
|
+
return [
|
|
205
|
+
sql({ dialect: PostgreSQL }),
|
|
206
|
+
syntaxHighlighting(atmosEditorHighlight),
|
|
207
|
+
completionNavKeymap,
|
|
208
|
+
autocompletion({
|
|
209
|
+
icons: false,
|
|
210
|
+
addToOptions: [{ render: renderCompletionIcon, position: 20 }],
|
|
211
|
+
override: [
|
|
212
|
+
paramCompletionSource(paramNames),
|
|
213
|
+
remapTypes(schemaCompletionSource({ dialect: PostgreSQL, schema: objects }), (type) => type === 'type' ? 'table' : type),
|
|
214
|
+
remapTypes(readOnlyKeywords(keywordCompletionSource(PostgreSQL, false)), (type) => type === 'type' ? 'datatype' : type),
|
|
215
|
+
],
|
|
216
|
+
}),
|
|
217
|
+
atmosEditorTheme,
|
|
218
|
+
completionTheme,
|
|
219
|
+
];
|
|
220
|
+
}, [schema, paramNames]);
|
|
221
|
+
return (_jsx(CodeMirror, { value: value, onChange: onChange, extensions: extensions, theme: "none", placeholder: placeholder, basicSetup: {
|
|
222
|
+
lineNumbers: true,
|
|
223
|
+
highlightActiveLine: true,
|
|
224
|
+
highlightActiveLineGutter: true,
|
|
225
|
+
foldGutter: false,
|
|
226
|
+
autocompletion: false,
|
|
227
|
+
}, height: "100%", style: { height: '100%', fontSize: '13px' }, className: "h-full font-mono" }));
|
|
228
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../lib/cn.js';
|
|
4
|
+
export function StatTile({ label, value, tone = 'neutral', className }) {
|
|
5
|
+
return (_jsxs("div", { "data-testid": "stat-tile", className: cn('rounded-md border px-2 py-2 text-center', tone === 'positive' && 'border-emerald-500/30 bg-emerald-500/5', tone === 'negative' && 'border-destructive/30 bg-destructive/5', tone === 'neutral' && 'border-border/60 bg-background', className), children: [_jsx("div", { className: "text-foreground font-mono text-[18px] tabular-nums", children: value }), _jsx("div", { className: "text-muted-foreground text-[10.5px]", children: label })] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
import { Badge } from './badge.js';
|
|
4
|
+
import type { Tone } from './status-tone.js';
|
|
5
|
+
export interface StatusBadgeProps extends React.ComponentProps<typeof Badge> {
|
|
6
|
+
tone: Tone;
|
|
7
|
+
label: string;
|
|
8
|
+
icon?: LucideIcon;
|
|
9
|
+
size?: 'sm' | 'md';
|
|
10
|
+
/**
|
|
11
|
+
* Spins the icon, for a status that is still resolving. A spinner glyph handed
|
|
12
|
+
* in as `icon` sits frozen without this and reads as a stuck process rather
|
|
13
|
+
* than a moving one. Clamped under prefers-reduced-motion.
|
|
14
|
+
*/
|
|
15
|
+
busy?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function StatusBadge({ tone, label, icon: Icon, size, busy, className, ...props }: StatusBadgeProps): React.JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Badge } from './badge.js';
|
|
5
|
+
import { cn } from '../lib/cn.js';
|
|
6
|
+
export function StatusBadge({ tone, label, icon: Icon, size = 'sm', busy = false, className, ...props }) {
|
|
7
|
+
return (_jsxs(Badge, { variant: "outline", "data-tone": tone, "data-busy": busy ? '' : undefined, className: cn('gap-1.5 font-medium', size === 'md' && 'h-6 px-2.5 text-sm', className), ...props, children: [Icon ? (_jsx(Icon, { "aria-hidden": true, className: cn('shrink-0 text-muted-foreground', busy && 'motion-safe:animate-spin') })) : (_jsx("span", { "aria-hidden": true, className: "size-1.5 shrink-0 rounded-full bg-muted-foreground" })), _jsx("span", { children: label })] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const TONES = {
|
|
2
|
+
success: { dot: 'bg-success', text: 'text-success', bg: 'bg-success/15', border: 'border-success/30', rail: 'bg-success/70' },
|
|
3
|
+
warning: { dot: 'bg-warning', text: 'text-warning', bg: 'bg-warning/15', border: 'border-warning/30', rail: 'bg-warning/70' },
|
|
4
|
+
danger: { dot: 'bg-danger', text: 'text-danger', bg: 'bg-danger/15', border: 'border-danger/30', rail: 'bg-danger/70' },
|
|
5
|
+
info: { dot: 'bg-info', text: 'text-info', bg: 'bg-info/15', border: 'border-info/30', rail: 'bg-info/70' },
|
|
6
|
+
neutral: { dot: 'bg-muted-foreground/40', text: 'text-muted-foreground', bg: 'bg-muted', border: 'border-border', rail: 'bg-muted-foreground/35' },
|
|
7
|
+
};
|
|
8
|
+
export function statusTone(tone) {
|
|
9
|
+
return TONES[tone];
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
export type StickyHeaderFadeProps = ComponentPropsWithoutRef<'div'>;
|
|
3
|
+
/**
|
|
4
|
+
* The strip a pinned header trails, so content passing beneath it dissolves into the header's
|
|
5
|
+
* surface instead of being sheared off at a hard line. Sits inside the header, which owns the
|
|
6
|
+
* positioning context; the surface it fades from comes from the header's own `from-*` colour.
|
|
7
|
+
*/
|
|
8
|
+
export declare function StickyHeaderFade({ className, ...props }: StickyHeaderFadeProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../lib/cn.js';
|
|
4
|
+
/**
|
|
5
|
+
* The strip a pinned header trails, so content passing beneath it dissolves into the header's
|
|
6
|
+
* surface instead of being sheared off at a hard line. Sits inside the header, which owns the
|
|
7
|
+
* positioning context; the surface it fades from comes from the header's own `from-*` colour.
|
|
8
|
+
*/
|
|
9
|
+
export function StickyHeaderFade({ className, ...props }) {
|
|
10
|
+
return (_jsx("div", { "aria-hidden": true, "data-slot": "sticky-header-fade", className: cn('from-background/95 pointer-events-none absolute inset-x-0 top-full h-4 bg-gradient-to-b to-transparent', className), ...props }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
declare const swatchVariants: (props?: ({
|
|
4
|
+
size?: "sm" | "md" | "lg" | null | undefined;
|
|
5
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
|
+
export interface SwatchButtonProps extends Omit<React.ComponentProps<'button'>, 'color' | 'onSelect'>, VariantProps<typeof swatchVariants> {
|
|
7
|
+
color: string;
|
|
8
|
+
selected?: boolean;
|
|
9
|
+
onSelect?: () => void;
|
|
10
|
+
label?: string;
|
|
11
|
+
showCheck?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const SwatchButton: React.ForwardRefExoticComponent<Omit<SwatchButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
14
|
+
export { swatchVariants };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
5
|
+
import { Check } from 'lucide-react';
|
|
6
|
+
import { cn } from '../lib/cn.js';
|
|
7
|
+
const swatchVariants = cva('inline-flex shrink-0 cursor-pointer items-center justify-center rounded-md bg-clip-padding ring-1 ring-border transition-transform outline-none hover:scale-110 focus-visible:ring-2 focus-visible:ring-ring data-[selected=true]:ring-2 data-[selected=true]:ring-foreground data-[selected=true]:ring-offset-1 data-[selected=true]:ring-offset-popover disabled:pointer-events-none disabled:opacity-40', {
|
|
8
|
+
variants: {
|
|
9
|
+
size: {
|
|
10
|
+
sm: 'size-5 [&_svg]:size-3',
|
|
11
|
+
md: 'size-6 [&_svg]:size-3.5',
|
|
12
|
+
lg: 'size-7 [&_svg]:size-4',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
size: 'md',
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
export const SwatchButton = React.forwardRef(function SwatchButton({ className, color, selected = false, onSelect, label, size, showCheck = true, style, type, onClick, ...props }, ref) {
|
|
20
|
+
return (_jsx("button", { ref: ref, type: type ?? 'button', "data-slot": "swatch-button", "data-selected": selected, "aria-pressed": selected, "aria-label": label ?? color, title: label ?? color, onClick: (event) => {
|
|
21
|
+
onClick?.(event);
|
|
22
|
+
onSelect?.();
|
|
23
|
+
}, className: cn(swatchVariants({ size, className })), style: { backgroundColor: color, ...style }, ...props, children: selected && showCheck ? (_jsx(Check, { className: "text-white drop-shadow", strokeWidth: 2.5, "aria-hidden": true })) : null }));
|
|
24
|
+
});
|
|
25
|
+
export { swatchVariants };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Switch as SwitchPrimitive } from "radix-ui";
|
|
3
|
+
declare function Switch({ className, size, ...props }: React.ComponentProps<typeof SwitchPrimitive.Root> & {
|
|
4
|
+
size?: "sm" | "default";
|
|
5
|
+
}): React.JSX.Element;
|
|
6
|
+
export { Switch };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Switch as SwitchPrimitive } from "radix-ui";
|
|
5
|
+
import { cn } from '../lib/cn.js';
|
|
6
|
+
function Switch({ className, size = "default", ...props }) {
|
|
7
|
+
return (_jsx(SwitchPrimitive.Root, { "data-slot": "switch", "data-size": size, className: cn("peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50", className), ...props, children: _jsx(SwitchPrimitive.Thumb, { "data-slot": "switch-thumb", className: "pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] dark:data-checked:bg-primary-foreground group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground" }) }));
|
|
8
|
+
}
|
|
9
|
+
export { Switch };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { LoadGrid, type LoadGridProps } from './load-grid.js';
|
|
2
|
+
export { ResourceMeter, type ResourceMeterProps } from './resource-meter.js';
|
|
3
|
+
export { LoadMeter, type LoadMeterProps } from './load-meter.js';
|
|
4
|
+
export { MeterRow, MeterRowGroup, type MeterRowProps } from './meter-row.js';
|
|
5
|
+
export { type LoadBlockSize } from './load-block.js';
|
|
6
|
+
export { ALERT_AT, type LoadTone } from './load-tone.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { LoadGrid } from './load-grid.js';
|
|
2
|
+
export { ResourceMeter } from './resource-meter.js';
|
|
3
|
+
export { LoadMeter } from './load-meter.js';
|
|
4
|
+
export { MeterRow, MeterRowGroup } from './meter-row.js';
|
|
5
|
+
export {} from './load-block.js';
|
|
6
|
+
export { ALERT_AT } from './load-tone.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type LoadTone } from './load-tone.js';
|
|
2
|
+
/**
|
|
3
|
+
* Two sizes, because the same reading is read two ways: a panel that exists to be watched
|
|
4
|
+
* gives a block enough room to count, and a line inside a spec list has to sit on the type
|
|
5
|
+
* around it without becoming the loudest thing on the page.
|
|
6
|
+
*/
|
|
7
|
+
export type LoadBlockSize = 'sm' | 'md';
|
|
8
|
+
/** The space between blocks belongs with the size that sets it. */
|
|
9
|
+
export declare const LOAD_BLOCK_GAP: Record<LoadBlockSize, string>;
|
|
10
|
+
/**
|
|
11
|
+
* The unit every load reading on this surface is built from: an empty well with a weighted
|
|
12
|
+
* fill. Weight rather than a second colour, because a block that picks its own hue turns a
|
|
13
|
+
* dense reading into a rash — how dark the block sits between muted and the usage hue is
|
|
14
|
+
* the whole reading.
|
|
15
|
+
*/
|
|
16
|
+
export declare function LoadBlock({ tone, fill, size, }: {
|
|
17
|
+
tone: LoadTone;
|
|
18
|
+
fill: number;
|
|
19
|
+
size?: LoadBlockSize;
|
|
20
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/cn.js';
|
|
4
|
+
import { LOAD_FILL } from './load-tone.js';
|
|
5
|
+
const SQUARE = 'shrink-0 [corner-shape:squircle]';
|
|
6
|
+
const SIZE = {
|
|
7
|
+
md: 'size-3.5 rounded-[5px] supports-[corner-shape:squircle]:rounded-[45%]',
|
|
8
|
+
sm: 'size-2 rounded-[3px] supports-[corner-shape:squircle]:rounded-[45%]',
|
|
9
|
+
};
|
|
10
|
+
/** The space between blocks belongs with the size that sets it. */
|
|
11
|
+
export const LOAD_BLOCK_GAP = {
|
|
12
|
+
md: 'gap-1.5',
|
|
13
|
+
sm: 'gap-1',
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The unit every load reading on this surface is built from: an empty well with a weighted
|
|
17
|
+
* fill. Weight rather than a second colour, because a block that picks its own hue turns a
|
|
18
|
+
* dense reading into a rash — how dark the block sits between muted and the usage hue is
|
|
19
|
+
* the whole reading.
|
|
20
|
+
*/
|
|
21
|
+
export function LoadBlock({ tone, fill, size = 'md', }) {
|
|
22
|
+
return (_jsx("span", { "aria-hidden": true, className: cn(SQUARE, SIZE[size], 'bg-muted relative block'), children: fill > 0 ? (_jsx("span", { className: cn(SQUARE, SIZE[size], 'absolute inset-0 size-full transition-opacity duration-500 ease-[var(--ease-out-expo)]', LOAD_FILL[tone]), style: { opacity: fill } })) : null }));
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface LoadGridProps extends Omit<React.ComponentProps<'div'>, 'children'> {
|
|
3
|
+
/** One reading per unit — a CPU core, a shard, a worker. */
|
|
4
|
+
readings: readonly number[];
|
|
5
|
+
/** Describes the whole grid, since the individual blocks carry no labels. */
|
|
6
|
+
ariaLabel: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* One block per unit, unlabelled. Twenty cores with a number beside each is a table nobody
|
|
10
|
+
* reads; twenty blocks is a texture you take in at a glance, and how dark it is is the only
|
|
11
|
+
* question a reading this dense can usefully answer.
|
|
12
|
+
*
|
|
13
|
+
* Laid out roughly square rather than in one long row, so the grid reads as the machine
|
|
14
|
+
* itself rather than as another bar in a column of bars.
|
|
15
|
+
*/
|
|
16
|
+
export declare function LoadGrid({ readings, ariaLabel, className, ...props }: LoadGridProps): React.JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { cn } from '../../lib/cn.js';
|
|
5
|
+
import { LoadBlock } from './load-block.js';
|
|
6
|
+
import { clampPercent } from './load-tone.js';
|
|
7
|
+
const MIN_VISIBLE_FILL = 0.25;
|
|
8
|
+
const WIDEST_GRID = 12;
|
|
9
|
+
/**
|
|
10
|
+
* One block per unit, unlabelled. Twenty cores with a number beside each is a table nobody
|
|
11
|
+
* reads; twenty blocks is a texture you take in at a glance, and how dark it is is the only
|
|
12
|
+
* question a reading this dense can usefully answer.
|
|
13
|
+
*
|
|
14
|
+
* Laid out roughly square rather than in one long row, so the grid reads as the machine
|
|
15
|
+
* itself rather than as another bar in a column of bars.
|
|
16
|
+
*/
|
|
17
|
+
export function LoadGrid({ readings, ariaLabel, className, ...props }) {
|
|
18
|
+
const columns = Math.min(WIDEST_GRID, Math.ceil(Math.sqrt(readings.length)));
|
|
19
|
+
return (_jsx("div", { "data-slot": "load-grid", "data-tone": "usage", role: "img", "aria-label": ariaLabel, className: cn('grid w-fit gap-1.5', className), style: { gridTemplateColumns: `repeat(${columns}, auto)` }, ...props, children: readings.map((reading, index) => {
|
|
20
|
+
const value = clampPercent(reading);
|
|
21
|
+
return (_jsx(LoadBlock, { tone: "usage", fill: value === 0 ? 0 : MIN_VISIBLE_FILL + (1 - MIN_VISIBLE_FILL) * (value / 100) }, index));
|
|
22
|
+
}) }));
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type LoadBlockSize } from './load-block.js';
|
|
3
|
+
export interface LoadMeterProps extends Omit<React.ComponentProps<'span'>, 'children'> {
|
|
4
|
+
/** What is being measured. Named here because the blocks carry no text of their own. */
|
|
5
|
+
label: string;
|
|
6
|
+
/** Utilisation, 0–100. */
|
|
7
|
+
percent: number;
|
|
8
|
+
/** The reading in the reader's units, already formatted: "27.9 GB of 64 GB". */
|
|
9
|
+
detail?: string;
|
|
10
|
+
/** How many blocks the line is long; each one is a slice of the whole. */
|
|
11
|
+
blocks?: number;
|
|
12
|
+
/** Past this reading the meter turns red. Left out, it never does. */
|
|
13
|
+
alertAt?: number;
|
|
14
|
+
size?: LoadBlockSize;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The reading itself, with nothing around it: counting dark blocks answers "how full is it"
|
|
18
|
+
* faster than reading where a bar happens to stop. ResourceMeter puts a label and a figure
|
|
19
|
+
* beside it; a surface that already has both in its own layout uses this on its own.
|
|
20
|
+
*
|
|
21
|
+
* The block the reading lands inside is filled by how far into it the reading got, so ten
|
|
22
|
+
* blocks still resolve a percent: 65% is six blocks and a half-lit seventh, not a choice
|
|
23
|
+
* between six and seven.
|
|
24
|
+
*/
|
|
25
|
+
export declare function LoadMeter({ label, percent, detail, blocks, alertAt, size, className, ...props }: LoadMeterProps): React.JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { cn } from '../../lib/cn.js';
|
|
5
|
+
import { LOAD_BLOCK_GAP, LoadBlock } from './load-block.js';
|
|
6
|
+
import { resolveLoadReading } from './load-tone.js';
|
|
7
|
+
const DEFAULT_BLOCKS = 24;
|
|
8
|
+
/** Enough weight that a reading too small to fill a block still shows one. */
|
|
9
|
+
const MIN_VISIBLE_FILL = 0.2;
|
|
10
|
+
/**
|
|
11
|
+
* The reading itself, with nothing around it: counting dark blocks answers "how full is it"
|
|
12
|
+
* faster than reading where a bar happens to stop. ResourceMeter puts a label and a figure
|
|
13
|
+
* beside it; a surface that already has both in its own layout uses this on its own.
|
|
14
|
+
*
|
|
15
|
+
* The block the reading lands inside is filled by how far into it the reading got, so ten
|
|
16
|
+
* blocks still resolve a percent: 65% is six blocks and a half-lit seventh, not a choice
|
|
17
|
+
* between six and seven.
|
|
18
|
+
*/
|
|
19
|
+
export function LoadMeter({ label, percent, detail, blocks = DEFAULT_BLOCKS, alertAt, size = 'md', className, ...props }) {
|
|
20
|
+
const { value, rounded, reading, tone } = resolveLoadReading(percent, detail, alertAt);
|
|
21
|
+
const reach = (value / 100) * blocks;
|
|
22
|
+
return (_jsx("span", { role: "meter", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": rounded, "aria-valuetext": reading, "aria-label": label, className: cn('flex', LOAD_BLOCK_GAP[size], className), ...props, children: Array.from({ length: blocks }, (_, index) => (_jsx(LoadBlock, { tone: tone, fill: blockFill(reach, index), size: size }, index))) }));
|
|
23
|
+
}
|
|
24
|
+
function blockFill(reach, index) {
|
|
25
|
+
const fill = Math.min(1, Math.max(0, reach - index));
|
|
26
|
+
if (index === 0 && reach > 0)
|
|
27
|
+
return Math.max(fill, MIN_VISIBLE_FILL);
|
|
28
|
+
return fill;
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One ramp for every utilisation reading on a surface: the usage hue laid over muted,
|
|
3
|
+
* weighted by how much of the resource is gone. Colour changes only where a reading stops
|
|
4
|
+
* being information and becomes a problem — a disk with no room left — so red still means
|
|
5
|
+
* something on the rare occasion it appears. Tone is carried on a `data-tone` attribute as
|
|
6
|
+
* well as the fill, because colour alone is not a status.
|
|
7
|
+
*/
|
|
8
|
+
export type LoadTone = 'usage' | 'alert';
|
|
9
|
+
/** Above this, a resource is close enough to full that the reader has to act. */
|
|
10
|
+
export declare const ALERT_AT = 90;
|
|
11
|
+
export declare const LOAD_FILL: Record<LoadTone, string>;
|
|
12
|
+
export declare const LOAD_TEXT: Record<LoadTone, string>;
|
|
13
|
+
/** One rule for when a reading stops being information and becomes a problem. */
|
|
14
|
+
export declare function loadTone(percent: number, alertAt?: number): LoadTone;
|
|
15
|
+
export declare function clampPercent(value: number): number;
|
|
16
|
+
export declare function resolveLoadReading(percent: number, detail?: string, alertAt?: number): {
|
|
17
|
+
value: number;
|
|
18
|
+
rounded: number;
|
|
19
|
+
reading: string;
|
|
20
|
+
tone: LoadTone;
|
|
21
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Above this, a resource is close enough to full that the reader has to act. */
|
|
2
|
+
export const ALERT_AT = 90;
|
|
3
|
+
export const LOAD_FILL = {
|
|
4
|
+
usage: 'bg-usage',
|
|
5
|
+
alert: 'bg-danger-9',
|
|
6
|
+
};
|
|
7
|
+
export const LOAD_TEXT = {
|
|
8
|
+
usage: 'text-muted-foreground',
|
|
9
|
+
alert: 'text-danger-11',
|
|
10
|
+
};
|
|
11
|
+
/** One rule for when a reading stops being information and becomes a problem. */
|
|
12
|
+
export function loadTone(percent, alertAt) {
|
|
13
|
+
return alertAt !== undefined && clampPercent(percent) > alertAt ? 'alert' : 'usage';
|
|
14
|
+
}
|
|
15
|
+
export function clampPercent(value) {
|
|
16
|
+
if (!Number.isFinite(value))
|
|
17
|
+
return 0;
|
|
18
|
+
return Math.max(0, Math.min(100, value));
|
|
19
|
+
}
|
|
20
|
+
export function resolveLoadReading(percent, detail, alertAt) {
|
|
21
|
+
const value = clampPercent(percent);
|
|
22
|
+
const rounded = Math.round(value);
|
|
23
|
+
return {
|
|
24
|
+
value,
|
|
25
|
+
rounded,
|
|
26
|
+
reading: detail ?? `${rounded}%`,
|
|
27
|
+
tone: loadTone(value, alertAt),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The grid the rows inside it borrow. Each row is its own subgrid, so a stack of readings
|
|
4
|
+
* puts its blocks and its figures on the same two edges however wide the labels run — which
|
|
5
|
+
* a row that sized itself could not do, and which is the whole reason a column of readings
|
|
6
|
+
* scans as one instrument.
|
|
7
|
+
*/
|
|
8
|
+
export declare function MeterRowGroup({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
9
|
+
export interface MeterRowProps extends Omit<React.ComponentProps<'div'>, 'children'> {
|
|
10
|
+
/** What is being measured — "Context usage", "Weekly limit". */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Utilisation, 0–100. */
|
|
13
|
+
percent: number;
|
|
14
|
+
/** The reading in the reader's units, already formatted: "144.7K of 258.4K". */
|
|
15
|
+
detail?: string;
|
|
16
|
+
/** A second line under the reading — when the window resets, how stale the sample is. */
|
|
17
|
+
caption?: React.ReactNode;
|
|
18
|
+
/** Past this reading the meter turns red. Left out, it never does. */
|
|
19
|
+
alertAt?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Keep the label as the row's accessible name without spending a line of the surface on
|
|
22
|
+
* it — for a reading whose blocks and figure already say what is being measured.
|
|
23
|
+
*/
|
|
24
|
+
labelHidden?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A reading on one line: what it measures, a short run of blocks filled to it, the figure.
|
|
28
|
+
* ResourceMeter is the same reading given a panel to live in; this is the form that belongs
|
|
29
|
+
* beside rows of text, where a full-width track would claim the surface for a single number.
|
|
30
|
+
*/
|
|
31
|
+
export declare function MeterRow({ label, percent, detail, caption, alertAt, labelHidden, className, ...props }: MeterRowProps): React.JSX.Element;
|