basalt-ui 1.26.0 → 1.28.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/AGENTS.md +23 -23
- package/CHANGELOG.md +67 -0
- package/MIGRATING.md +896 -37
- package/README.md +33 -3
- package/agent/rules/basalt-batteries.md +25 -10
- package/agent/rules/basalt-controls.md +73 -43
- package/agent/rules/basalt-mantine.md +17 -6
- package/agent/rules/basalt-state.md +5 -0
- package/agent/rules/basalt-tokens.md +1 -1
- package/configs/oxlint-plugin.js +1286 -73
- package/configs/oxlint-plugin.test.ts +1338 -29
- package/configs/oxlint.json +12 -5
- package/dist/agent/coalesce.d.ts.map +1 -1
- package/dist/agent/coalesce.js +2 -1
- package/dist/agent/merge.d.ts.map +1 -1
- package/dist/agent/merge.js +2 -1
- package/dist/agent/part-list.d.ts.map +1 -1
- package/dist/agent/part-list.js +2 -0
- package/dist/agent/stick-to-bottom.d.ts +3 -6
- package/dist/agent/stick-to-bottom.d.ts.map +1 -1
- package/dist/agent/stick-to-bottom.js +6 -3
- package/dist/agent-chat/composer.d.ts +6 -2
- package/dist/agent-chat/composer.d.ts.map +1 -1
- package/dist/agent-chat/composer.js +49 -33
- package/dist/agent-chat/relative-time.d.ts +0 -9
- package/dist/agent-chat/relative-time.d.ts.map +1 -1
- package/dist/agent-chat/relative-time.js +2 -1
- package/dist/agent-chat/thread-detail-panel.d.ts +3 -2
- package/dist/agent-chat/thread-detail-panel.d.ts.map +1 -1
- package/dist/agent-chat/thread-detail-panel.js +8 -5
- package/dist/agent-chat/thread-feed-row.d.ts +2 -1
- package/dist/agent-chat/thread-feed-row.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed-row.js +92 -92
- package/dist/agent-chat/thread-feed.d.ts +3 -2
- package/dist/agent-chat/thread-feed.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed.js +8 -3
- package/dist/agent-chat/thread-message.d.ts +4 -3
- package/dist/agent-chat/thread-message.d.ts.map +1 -1
- package/dist/agent-chat/thread-message.js +70 -31
- package/dist/agent-chat/thread-outcome-card.d.ts +3 -2
- package/dist/agent-chat/thread-outcome-card.d.ts.map +1 -1
- package/dist/agent-chat/thread-outcome-card.js +9 -2
- package/dist/agent-chat/thread-workspace.d.ts +7 -2
- package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
- package/dist/agent-chat/thread-workspace.js +62 -29
- package/dist/agent-chat/tool-chip.d.ts +3 -2
- package/dist/agent-chat/tool-chip.d.ts.map +1 -1
- package/dist/agent-chat/tool-chip.js +7 -2
- package/dist/charts/hooks/useBandPlot.d.ts.map +1 -1
- package/dist/charts/hooks/useBandPlot.js +15 -8
- package/dist/charts/index.d.ts +8 -7
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +45 -5
- package/dist/charts/kinds/BandStrip.d.ts +10 -7
- package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
- package/dist/charts/kinds/BandStrip.js +12 -7
- package/dist/charts/kinds/Bars.d.ts +12 -6
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.js +37 -11
- package/dist/charts/kinds/Donut.d.ts +6 -5
- package/dist/charts/kinds/Donut.d.ts.map +1 -1
- package/dist/charts/kinds/Donut.js +19 -2
- package/dist/charts/kinds/DualPanel.d.ts +6 -5
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.js +36 -8
- package/dist/charts/kinds/Heatmap.d.ts +10 -6
- package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
- package/dist/charts/kinds/Heatmap.js +58 -31
- package/dist/charts/kinds/MirroredBars.d.ts +6 -5
- package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
- package/dist/charts/kinds/MirroredBars.js +9 -2
- package/dist/charts/kinds/MultiLine.d.ts +11 -6
- package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
- package/dist/charts/kinds/MultiLine.js +24 -15
- package/dist/charts/kinds/StackedArea.d.ts +18 -8
- package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
- package/dist/charts/kinds/StackedArea.js +29 -4
- package/dist/charts/kinds/ZonedLine.d.ts +12 -8
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/charts/kinds/ZonedLine.js +33 -23
- package/dist/charts/layout/auto-margin.d.ts +65 -8
- package/dist/charts/layout/auto-margin.d.ts.map +1 -1
- package/dist/charts/layout/auto-margin.js +45 -10
- package/dist/charts/layout/log-ticks.d.ts +27 -0
- package/dist/charts/layout/log-ticks.d.ts.map +1 -0
- package/dist/charts/layout/log-ticks.js +42 -0
- package/dist/charts/primitives/Axes.d.ts +11 -2
- package/dist/charts/primitives/Axes.d.ts.map +1 -1
- package/dist/charts/primitives/Axes.js +15 -5
- package/dist/charts/primitives/CartesianChart.d.ts +45 -7
- package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
- package/dist/charts/primitives/CartesianChart.js +86 -28
- package/dist/charts/primitives/ChartCard.d.ts +27 -2
- package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.js +37 -17
- package/dist/charts/primitives/ChartFrame.d.ts +30 -4
- package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
- package/dist/charts/primitives/ChartFrame.js +45 -15
- package/dist/charts/primitives/ChartLegend.d.ts +13 -2
- package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
- package/dist/charts/primitives/ChartLegend.js +33 -13
- package/dist/charts/primitives/ChartPending.d.ts +77 -4
- package/dist/charts/primitives/ChartPending.d.ts.map +1 -1
- package/dist/charts/primitives/ChartPending.js +100 -6
- package/dist/charts/primitives/ChartTooltip.d.ts +7 -0
- package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
- package/dist/charts/primitives/ChartTooltip.js +18 -5
- package/dist/charts/primitives/Crosshair.d.ts +3 -0
- package/dist/charts/primitives/Crosshair.d.ts.map +1 -1
- package/dist/charts/primitives/Crosshair.js +3 -1
- package/dist/charts/primitives/chart-frame-layout.d.ts +95 -0
- package/dist/charts/primitives/chart-frame-layout.d.ts.map +1 -0
- package/dist/charts/primitives/chart-frame-layout.js +89 -0
- package/dist/charts/primitives/chart-tier.d.ts +16 -0
- package/dist/charts/primitives/chart-tier.d.ts.map +1 -0
- package/dist/charts/primitives/chart-tier.js +20 -0
- package/dist/charts/series.d.ts +55 -1
- package/dist/charts/series.d.ts.map +1 -1
- package/dist/charts/series.js +27 -1
- package/dist/charts/sparklines/BarSparkline.d.ts +3 -3
- package/dist/charts/sparklines/BarSparkline.d.ts.map +1 -1
- package/dist/charts/sparklines/BarSparkline.js +9 -3
- package/dist/charts/sparklines/LineSparkline.d.ts +3 -3
- package/dist/charts/sparklines/LineSparkline.d.ts.map +1 -1
- package/dist/charts/sparklines/LineSparkline.js +15 -3
- package/dist/charts/sparklines/index.d.ts +2 -2
- package/dist/charts/sparklines/index.d.ts.map +1 -1
- package/dist/charts/utils/format.d.ts +92 -2
- package/dist/charts/utils/format.d.ts.map +1 -1
- package/dist/charts/utils/format.js +64 -1
- package/dist/charts/utils/ticks.d.ts +81 -2
- package/dist/charts/utils/ticks.d.ts.map +1 -1
- package/dist/charts/utils/ticks.js +54 -4
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/commands/ShortcutsHelp.d.ts +3 -2
- package/dist/commands/ShortcutsHelp.d.ts.map +1 -1
- package/dist/commands/ShortcutsHelp.js +8 -2
- package/dist/commands/define-commands.d.ts.map +1 -1
- package/dist/commands/define-commands.js +2 -2
- package/dist/commands/define-overlays.d.ts +102 -0
- package/dist/commands/define-overlays.d.ts.map +1 -1
- package/dist/commands/define-overlays.js +102 -2
- package/dist/commands/index.d.ts +10 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +3 -1
- package/dist/commands/overlays-mount.d.ts +13 -6
- package/dist/commands/overlays-mount.d.ts.map +1 -1
- package/dist/commands/overlays-mount.js +23 -14
- package/dist/common/errors.d.ts +34 -0
- package/dist/common/errors.d.ts.map +1 -0
- package/dist/common/errors.js +36 -0
- package/dist/common/index.d.ts +15 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +29 -0
- package/dist/common/props.d.ts +63 -0
- package/dist/common/props.d.ts.map +1 -0
- package/dist/common/props.js +6 -0
- package/dist/common/query-state-like.d.ts +43 -0
- package/dist/common/query-state-like.d.ts.map +1 -0
- package/dist/common/query-state-like.js +20 -0
- package/dist/common/refs.d.ts +29 -0
- package/dist/common/refs.d.ts.map +1 -0
- package/dist/common/refs.js +29 -0
- package/dist/common/scroll-parent.d.ts +23 -0
- package/dist/common/scroll-parent.d.ts.map +1 -0
- package/dist/common/scroll-parent.js +21 -0
- package/dist/common/validate.d.ts +38 -0
- package/dist/common/validate.d.ts.map +1 -0
- package/dist/common/validate.js +36 -0
- package/dist/connectivity/connectivity-indicator.d.ts +3 -1
- package/dist/connectivity/connectivity-indicator.d.ts.map +1 -1
- package/dist/connectivity/connectivity-indicator.js +3 -1
- package/dist/connectivity/connectivity-provider.d.ts.map +1 -1
- package/dist/connectivity/connectivity-provider.js +4 -1
- package/dist/connectivity/index.d.ts +1 -0
- package/dist/connectivity/index.d.ts.map +1 -1
- package/dist/connectivity/types.d.ts +2 -2
- package/dist/connectivity/types.d.ts.map +1 -1
- package/dist/connectivity/use-connectivity.d.ts.map +1 -1
- package/dist/content/article-layout.module.css +11 -4
- package/dist/content/callout.d.ts +8 -4
- package/dist/content/callout.d.ts.map +1 -1
- package/dist/content/callout.js +15 -8
- package/dist/content/guide.d.ts +5 -4
- package/dist/content/guide.d.ts.map +1 -1
- package/dist/content/guide.js +13 -4
- package/dist/content/heading-anchor.d.ts +24 -2
- package/dist/content/heading-anchor.d.ts.map +1 -1
- package/dist/content/heading-anchor.js +23 -9
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +2 -0
- package/dist/content/prose.module.css +9 -7
- package/dist/content/reading-progress.d.ts +10 -4
- package/dist/content/reading-progress.d.ts.map +1 -1
- package/dist/content/reading-progress.js +26 -10
- package/dist/content/slug.d.ts +4 -0
- package/dist/content/slug.d.ts.map +1 -1
- package/dist/content/toc.d.ts +11 -0
- package/dist/content/toc.d.ts.map +1 -1
- package/dist/content/toc.js +23 -10
- package/dist/controls/actions.d.ts +49 -6
- package/dist/controls/actions.d.ts.map +1 -1
- package/dist/controls/actions.js +39 -8
- package/dist/controls/compare-filter.d.ts +3 -2
- package/dist/controls/compare-filter.d.ts.map +1 -1
- package/dist/controls/compare-filter.js +17 -2
- package/dist/controls/control-group.d.ts +3 -3
- package/dist/controls/control-group.d.ts.map +1 -1
- package/dist/controls/control-group.js +9 -2
- package/dist/controls/controls.module.css +169 -186
- package/dist/controls/controls.module.css.d.ts +9 -11
- package/dist/controls/enum-filter.d.ts +13 -3
- package/dist/controls/enum-filter.d.ts.map +1 -1
- package/dist/controls/enum-filter.js +32 -15
- package/dist/controls/filter-context.d.ts +15 -6
- package/dist/controls/filter-context.d.ts.map +1 -1
- package/dist/controls/filter-pill.d.ts +3 -3
- package/dist/controls/filter-pill.d.ts.map +1 -1
- package/dist/controls/filter-pill.js +4 -1
- package/dist/controls/filter-set.d.ts +3 -2
- package/dist/controls/filter-set.d.ts.map +1 -1
- package/dist/controls/filter-set.js +66 -41
- package/dist/controls/filter-sheet.d.ts +20 -80
- package/dist/controls/filter-sheet.d.ts.map +1 -1
- package/dist/controls/filter-sheet.js +9 -95
- package/dist/controls/index.d.ts +3 -0
- package/dist/controls/index.d.ts.map +1 -1
- package/dist/controls/index.js +6 -0
- package/dist/controls/multi-select-filter.d.ts +18 -2
- package/dist/controls/multi-select-filter.d.ts.map +1 -1
- package/dist/controls/multi-select-filter.js +124 -22
- package/dist/controls/number-filter.d.ts +28 -0
- package/dist/controls/number-filter.d.ts.map +1 -0
- package/dist/controls/number-filter.js +172 -0
- package/dist/controls/panel-row.d.ts +132 -0
- package/dist/controls/panel-row.d.ts.map +1 -0
- package/dist/controls/panel-row.js +173 -0
- package/dist/controls/panel-row.module.css +86 -0
- package/dist/controls/panel-row.module.css.d.ts +13 -0
- package/dist/controls/range-filter.d.ts +20 -5
- package/dist/controls/range-filter.d.ts.map +1 -1
- package/dist/controls/range-filter.js +75 -38
- package/dist/controls/search-filter.d.ts +3 -2
- package/dist/controls/search-filter.d.ts.map +1 -1
- package/dist/controls/search-filter.js +26 -11
- package/dist/controls/select-filter.d.ts +2 -1
- package/dist/controls/select-filter.d.ts.map +1 -1
- package/dist/controls/select-filter.js +4 -0
- package/dist/controls/slider-control.d.ts +36 -0
- package/dist/controls/slider-control.d.ts.map +1 -0
- package/dist/controls/slider-control.js +64 -0
- package/dist/controls/sync-button.d.ts +3 -2
- package/dist/controls/sync-button.d.ts.map +1 -1
- package/dist/controls/sync-button.js +16 -3
- package/dist/controls/toggle-filter.d.ts +3 -2
- package/dist/controls/toggle-filter.d.ts.map +1 -1
- package/dist/controls/toggle-filter.js +29 -12
- package/dist/controls/view-tabs.d.ts +3 -2
- package/dist/controls/view-tabs.d.ts.map +1 -1
- package/dist/controls/view-tabs.js +43 -11
- package/dist/controls-dates/date-range-picker.d.ts +1 -1
- package/dist/controls-dates/date-range-picker.d.ts.map +1 -1
- package/dist/controls-dates/date-range-picker.js +6 -1
- package/dist/dashboard/delta-badge.d.ts +5 -1
- package/dist/dashboard/delta-badge.d.ts.map +1 -1
- package/dist/dashboard/empty-state.d.ts +10 -3
- package/dist/dashboard/empty-state.d.ts.map +1 -1
- package/dist/dashboard/empty-state.js +37 -6
- package/dist/dashboard/index.d.ts +6 -4
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +10 -2
- package/dist/dashboard/query-state.d.ts +48 -27
- package/dist/dashboard/query-state.d.ts.map +1 -1
- package/dist/dashboard/query-state.js +111 -57
- package/dist/dashboard/settings-section.d.ts +19 -9
- package/dist/dashboard/settings-section.d.ts.map +1 -1
- package/dist/dashboard/settings-section.js +74 -25
- package/dist/dashboard/stat-card.d.ts +76 -19
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +78 -38
- package/dist/dashboard/stat-card.module.css +112 -26
- package/dist/dashboard/stat-card.module.css.d.ts +5 -0
- package/dist/dashboard/stat-group.d.ts +41 -0
- package/dist/dashboard/stat-group.d.ts.map +1 -0
- package/dist/dashboard/stat-group.js +30 -0
- package/dist/dashboard/stat-group.module.css +66 -0
- package/dist/dashboard/stat-group.module.css.d.ts +8 -0
- package/dist/dashboard/widget-grid.d.ts +27 -0
- package/dist/dashboard/widget-grid.d.ts.map +1 -0
- package/dist/dashboard/widget-grid.js +41 -0
- package/dist/dashboard/widget-grid.module.css +53 -0
- package/dist/dashboard/widget-grid.module.css.d.ts +9 -0
- package/dist/data/data-table.d.ts +151 -12
- package/dist/data/data-table.d.ts.map +1 -1
- package/dist/data/data-table.js +392 -138
- package/dist/data/data-table.module.css +64 -0
- package/dist/data/data-table.module.css.d.ts +11 -0
- package/dist/data/index.d.ts +2 -2
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +24 -2
- package/dist/data/query-branch.d.ts +28 -0
- package/dist/data/query-branch.d.ts.map +1 -0
- package/dist/data/query-branch.js +10 -0
- package/dist/data/table.d.ts +2 -2
- package/dist/data/table.d.ts.map +1 -1
- package/dist/data/virtual-list.d.ts +65 -6
- package/dist/data/virtual-list.d.ts.map +1 -1
- package/dist/data/virtual-list.js +89 -38
- package/dist/data/virtual.d.ts +1 -1
- package/dist/data/virtual.d.ts.map +1 -1
- package/dist/forms/FormErrorSummary.d.ts +4 -3
- package/dist/forms/FormErrorSummary.d.ts.map +1 -1
- package/dist/forms/FormErrorSummary.js +6 -4
- package/dist/forms/create-form.d.ts +2 -2
- package/dist/forms/field.d.ts +46 -6
- package/dist/forms/field.d.ts.map +1 -1
- package/dist/forms/field.js +10 -5
- package/dist/forms/form-layout.d.ts +142 -0
- package/dist/forms/form-layout.d.ts.map +1 -0
- package/dist/forms/form-layout.js +110 -0
- package/dist/forms/form-layout.module.css +145 -0
- package/dist/forms/form-layout.module.css.d.ts +20 -0
- package/dist/forms/form-state.d.ts +42 -0
- package/dist/forms/form-state.d.ts.map +1 -0
- package/dist/forms/form-state.js +26 -0
- package/dist/forms/index.d.ts +22 -6
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +19 -3
- package/dist/forms/use-field-array.d.ts +60 -0
- package/dist/forms/use-field-array.d.ts.map +1 -0
- package/dist/forms/use-field-array.js +20 -0
- package/dist/forms/use-form-draft.d.ts +25 -10
- package/dist/forms/use-form-draft.d.ts.map +1 -1
- package/dist/forms/use-form-draft.js +55 -18
- package/dist/forms/use-form-submit.d.ts +88 -0
- package/dist/forms/use-form-submit.d.ts.map +1 -0
- package/dist/forms/use-form-submit.js +63 -0
- package/dist/guard/index.d.ts +1 -1
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +27 -11
- package/dist/index.d.ts +10 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -4
- package/dist/nav/types.d.ts +15 -6
- package/dist/nav/types.d.ts.map +1 -1
- package/dist/notifications/bell.d.ts +3 -2
- package/dist/notifications/bell.d.ts.map +1 -1
- package/dist/notifications/bell.js +73 -56
- package/dist/notifications/center.d.ts +15 -4
- package/dist/notifications/center.d.ts.map +1 -1
- package/dist/notifications/center.js +5 -2
- package/dist/notifications/define-notifications.d.ts +56 -14
- package/dist/notifications/define-notifications.d.ts.map +1 -1
- package/dist/notifications/define-notifications.js +2 -1
- package/dist/notifications/index.d.ts +6 -2
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +5 -1
- package/dist/notifications/mount-guard.d.ts +8 -0
- package/dist/notifications/mount-guard.d.ts.map +1 -0
- package/dist/notifications/mount-guard.js +19 -0
- package/dist/notifications/notify.d.ts +58 -1
- package/dist/notifications/notify.d.ts.map +1 -1
- package/dist/notifications/notify.js +46 -2
- package/dist/notifications/overlay.d.ts.map +1 -1
- package/dist/notifications/overlay.js +2 -0
- package/dist/notifications/store.d.ts +7 -0
- package/dist/notifications/store.d.ts.map +1 -1
- package/dist/provider/index.d.ts +37 -5
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +66 -28
- package/dist/provider/lab-theme.d.ts.map +1 -1
- package/dist/provider/lab-theme.js +2 -1
- package/dist/query/devtools.d.ts.map +1 -1
- package/dist/query/devtools.js +1 -0
- package/dist/router-tanstack/field.d.ts +1 -1
- package/dist/router-tanstack/field.d.ts.map +1 -1
- package/dist/router-tanstack/index.d.ts +1 -1
- package/dist/router-tanstack/index.d.ts.map +1 -1
- package/dist/router-tanstack/search-store.d.ts +4 -1
- package/dist/router-tanstack/search-store.d.ts.map +1 -1
- package/dist/router-tanstack/search-store.js +92 -8
- package/dist/router-tanstack/use-nav.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.js +1 -1
- package/dist/section/index.d.ts +1 -1
- package/dist/section/index.d.ts.map +1 -1
- package/dist/section/section.d.ts +36 -2
- package/dist/section/section.d.ts.map +1 -1
- package/dist/section/section.js +49 -57
- package/dist/section/section.module.css +11 -0
- package/dist/shell/account-types.d.ts +5 -2
- package/dist/shell/account-types.d.ts.map +1 -1
- package/dist/shell/app-brand.d.ts +13 -0
- package/dist/shell/app-brand.d.ts.map +1 -0
- package/dist/shell/app-brand.js +94 -0
- package/dist/shell/app-brand.module.css +109 -0
- package/dist/shell/app-brand.module.css.d.ts +14 -0
- package/dist/shell/app-breadcrumbs.d.ts +4 -2
- package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
- package/dist/shell/app-breadcrumbs.js +33 -22
- package/dist/shell/app-header.module.css +10 -5
- package/dist/shell/app-main.module.css +107 -0
- package/dist/shell/app-main.module.css.d.ts +11 -0
- package/dist/shell/app-mobile-nav.d.ts +3 -2
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +29 -15
- package/dist/shell/app-mobile-nav.module.css +48 -27
- package/dist/shell/app-mobile-nav.module.css.d.ts +0 -1
- package/dist/shell/app-sidebar-account.d.ts +2 -1
- package/dist/shell/app-sidebar-account.d.ts.map +1 -1
- package/dist/shell/app-sidebar-account.js +57 -22
- package/dist/shell/app-sidebar.d.ts +9 -3
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +55 -109
- package/dist/shell/app-sidebar.module.css +53 -96
- package/dist/shell/app-sidebar.module.css.d.ts +0 -5
- package/dist/shell/index.d.ts +14 -6
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +47 -12
- package/dist/shell/isomorphic-layout-effect.d.ts +14 -0
- package/dist/shell/isomorphic-layout-effect.d.ts.map +1 -0
- package/dist/shell/isomorphic-layout-effect.js +5 -0
- package/dist/shell/mobile-nav-model.d.ts.map +1 -1
- package/dist/shell/mobile-nav-model.js +27 -6
- package/dist/shell/nav-count-badge.d.ts +5 -3
- package/dist/shell/nav-count-badge.d.ts.map +1 -1
- package/dist/shell/nav-count-badge.js +3 -1
- package/dist/shell/page-aside.d.ts +43 -0
- package/dist/shell/page-aside.d.ts.map +1 -0
- package/dist/shell/page-aside.js +202 -0
- package/dist/shell/page-aside.module.css +174 -0
- package/dist/shell/page-aside.module.css.d.ts +14 -0
- package/dist/shell/page-bar.d.ts +55 -15
- package/dist/shell/page-bar.d.ts.map +1 -1
- package/dist/shell/page-bar.js +130 -41
- package/dist/shell/page-bar.module.css +107 -13
- package/dist/shell/page-bar.module.css.d.ts +4 -1
- package/dist/shell/sidebar-search.d.ts +4 -2
- package/dist/shell/sidebar-search.d.ts.map +1 -1
- package/dist/shell/sidebar-search.js +9 -4
- package/dist/shell/sidebar-search.module.css +1 -1
- package/dist/state/fields.d.ts +227 -34
- package/dist/state/fields.d.ts.map +1 -1
- package/dist/state/fields.js +77 -30
- package/dist/state/persisted-or-local.d.ts +9 -0
- package/dist/state/persisted-or-local.d.ts.map +1 -0
- package/dist/state/persisted-or-local.js +24 -0
- package/dist/state/persisted.d.ts +12 -0
- package/dist/state/persisted.d.ts.map +1 -1
- package/dist/state/persisted.js +36 -18
- package/dist/state.d.ts +1 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +2 -6
- package/dist/surfaces.d.ts +12 -11
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +43 -12
- package/dist/theme/ctl-theme.d.ts.map +1 -1
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +102 -17
- package/dist/theme/nav-link.module.css +37 -26
- package/dist/theme/segmented-control.module.css +22 -0
- package/dist/theme/segmented-control.module.css.d.ts +1 -0
- package/dist/theme-lab/boot.d.ts +66 -0
- package/dist/theme-lab/boot.d.ts.map +1 -0
- package/dist/theme-lab/boot.js +82 -0
- package/dist/theme-lab/index.d.ts +4 -43
- package/dist/theme-lab/index.d.ts.map +1 -1
- package/dist/theme-lab/index.js +9 -69
- package/dist/theme-toggle/index.d.ts +3 -2
- package/dist/theme-toggle/index.d.ts.map +1 -1
- package/dist/theme-toggle/index.js +8 -2
- package/dist/tokens/index.d.ts +42 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +35 -6
- package/dist/tokens/palette.d.ts +45 -25
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +31 -14
- package/dist/tokens.css +4 -5
- package/dist/utils/is-dev.d.ts +3 -0
- package/dist/utils/is-dev.d.ts.map +1 -0
- package/dist/utils/is-dev.js +6 -0
- package/dist/widget-header/delta-badge.d.ts +7 -1
- package/dist/widget-header/delta-badge.d.ts.map +1 -1
- package/dist/widget-header/delta-badge.js +8 -1
- package/dist/widget-header/index.d.ts +2 -2
- package/dist/widget-header/index.d.ts.map +1 -1
- package/dist/widget-header/index.js +3 -1
- package/dist/widget-header/widget-header.d.ts +99 -4
- package/dist/widget-header/widget-header.d.ts.map +1 -1
- package/dist/widget-header/widget-header.js +45 -18
- package/dist/widget-header/widget-header.module.css +87 -7
- package/dist/widget-header/widget-header.module.css.d.ts +1 -0
- package/llms.txt +6 -6
- package/package.json +49 -25
- package/src/agent/coalesce.ts +2 -1
- package/src/agent/merge.ts +2 -1
- package/src/agent/part-list.tsx +2 -0
- package/src/agent/stick-to-bottom.tsx +9 -11
- package/src/agent-chat/composer.tsx +124 -103
- package/src/agent-chat/relative-time.ts +2 -1
- package/src/agent-chat/thread-detail-panel.tsx +9 -5
- package/src/agent-chat/thread-feed-row.tsx +17 -9
- package/src/agent-chat/thread-feed.tsx +9 -3
- package/src/agent-chat/thread-message.tsx +48 -13
- package/src/agent-chat/thread-outcome-card.tsx +9 -1
- package/src/agent-chat/thread-workspace.tsx +72 -33
- package/src/agent-chat/tool-chip.tsx +8 -2
- package/src/charts/hooks/useBandPlot.ts +26 -8
- package/src/charts/index.ts +39 -4
- package/src/charts/kinds/BandStrip.tsx +36 -14
- package/src/charts/kinds/Bars.tsx +67 -16
- package/src/charts/kinds/Donut.tsx +30 -3
- package/src/charts/kinds/DualPanel.tsx +56 -10
- package/src/charts/kinds/Heatmap.tsx +90 -33
- package/src/charts/kinds/MirroredBars.tsx +21 -3
- package/src/charts/kinds/MultiLine.tsx +61 -18
- package/src/charts/kinds/StackedArea.tsx +77 -6
- package/src/charts/kinds/ZonedLine.tsx +71 -31
- package/src/charts/layout/auto-margin.ts +134 -21
- package/src/charts/layout/log-ticks.ts +90 -0
- package/src/charts/primitives/Axes.tsx +33 -5
- package/src/charts/primitives/CartesianChart.tsx +194 -41
- package/src/charts/primitives/ChartCard.tsx +66 -25
- package/src/charts/primitives/ChartFrame.tsx +107 -26
- package/src/charts/primitives/ChartLegend.tsx +43 -13
- package/src/charts/primitives/ChartPending.tsx +185 -7
- package/src/charts/primitives/ChartTooltip.tsx +37 -5
- package/src/charts/primitives/Crosshair.tsx +6 -3
- package/src/charts/primitives/chart-frame-layout.ts +212 -0
- package/src/charts/primitives/chart-tier.tsx +37 -0
- package/src/charts/series.ts +77 -1
- package/src/charts/sparklines/BarSparkline.tsx +11 -3
- package/src/charts/sparklines/LineSparkline.tsx +18 -4
- package/src/charts/sparklines/index.ts +2 -2
- package/src/charts/utils/format.ts +163 -2
- package/src/charts/utils/ticks.ts +149 -4
- package/src/cli/index.ts +8 -3
- package/src/commands/ShortcutsHelp.tsx +10 -3
- package/src/commands/define-commands.ts +2 -2
- package/src/commands/define-overlays.ts +216 -1
- package/src/commands/index.ts +12 -0
- package/src/commands/overlays-mount.tsx +60 -26
- package/src/common/errors.ts +73 -0
- package/src/common/index.ts +21 -0
- package/src/common/props.ts +71 -0
- package/src/common/query-state-like.ts +64 -0
- package/src/common/refs.ts +58 -0
- package/src/common/scroll-parent.ts +42 -0
- package/src/common/validate.ts +94 -0
- package/src/connectivity/connectivity-indicator.tsx +6 -1
- package/src/connectivity/connectivity-provider.tsx +4 -1
- package/src/connectivity/index.ts +1 -0
- package/src/connectivity/types.ts +5 -2
- package/src/connectivity/use-connectivity.ts +3 -2
- package/src/content/article-layout.module.css +11 -4
- package/src/content/callout.tsx +13 -7
- package/src/content/guide.tsx +14 -4
- package/src/content/heading-anchor.tsx +14 -3
- package/src/content/index.ts +2 -0
- package/src/content/markdown.tsx +2 -0
- package/src/content/prose.module.css +9 -7
- package/src/content/reading-progress.tsx +40 -15
- package/src/content/slug.ts +4 -0
- package/src/content/toc.tsx +47 -10
- package/src/controls/actions.tsx +89 -9
- package/src/controls/compare-filter.tsx +20 -3
- package/src/controls/control-group.tsx +11 -4
- package/src/controls/controls.module.css +169 -186
- package/src/controls/controls.module.css.d.ts +9 -11
- package/src/controls/enum-filter.tsx +46 -19
- package/src/controls/filter-context.tsx +21 -8
- package/src/controls/filter-pill.tsx +6 -3
- package/src/controls/filter-set.tsx +32 -13
- package/src/controls/filter-sheet.tsx +44 -194
- package/src/controls/index.ts +8 -0
- package/src/controls/multi-select-filter.tsx +179 -29
- package/src/controls/number-filter.tsx +329 -0
- package/src/controls/panel-row.module.css +86 -0
- package/src/controls/panel-row.module.css.d.ts +13 -0
- package/src/controls/panel-row.tsx +392 -0
- package/src/controls/range-filter.tsx +133 -43
- package/src/controls/search-filter.tsx +31 -13
- package/src/controls/select-filter.tsx +11 -1
- package/src/controls/slider-control.tsx +159 -0
- package/src/controls/sync-button.tsx +13 -3
- package/src/controls/toggle-filter.tsx +37 -17
- package/src/controls/view-tabs.tsx +63 -11
- package/src/controls-dates/date-range-picker.tsx +8 -1
- package/src/dashboard/delta-badge.tsx +5 -1
- package/src/dashboard/empty-state.tsx +72 -25
- package/src/dashboard/index.ts +19 -2
- package/src/dashboard/query-state.tsx +154 -84
- package/src/dashboard/settings-section.tsx +87 -31
- package/src/dashboard/stat-card.module.css +112 -26
- package/src/dashboard/stat-card.module.css.d.ts +5 -0
- package/src/dashboard/stat-card.tsx +207 -68
- package/src/dashboard/stat-group.module.css +66 -0
- package/src/dashboard/stat-group.module.css.d.ts +8 -0
- package/src/dashboard/stat-group.tsx +74 -0
- package/src/dashboard/widget-grid.module.css +53 -0
- package/src/dashboard/widget-grid.module.css.d.ts +9 -0
- package/src/dashboard/widget-grid.tsx +127 -0
- package/src/data/data-table.module.css +64 -0
- package/src/data/data-table.module.css.d.ts +11 -0
- package/src/data/data-table.tsx +927 -346
- package/src/data/index.ts +30 -2
- package/src/data/query-branch.ts +53 -0
- package/src/data/table.ts +5 -0
- package/src/data/virtual-list.tsx +189 -55
- package/src/data/virtual.ts +5 -1
- package/src/forms/FormErrorSummary.tsx +13 -6
- package/src/forms/create-form.ts +2 -2
- package/src/forms/field.ts +60 -11
- package/src/forms/form-layout.module.css +145 -0
- package/src/forms/form-layout.module.css.d.ts +20 -0
- package/src/forms/form-layout.tsx +305 -0
- package/src/forms/form-state.tsx +94 -0
- package/src/forms/index.ts +38 -7
- package/src/forms/use-field-array.ts +94 -0
- package/src/forms/use-form-draft.ts +145 -53
- package/src/forms/use-form-submit.ts +199 -0
- package/src/guard/index.ts +91 -23
- package/src/index.ts +79 -10
- package/src/nav/types.ts +15 -6
- package/src/notifications/bell.tsx +18 -4
- package/src/notifications/center.tsx +18 -5
- package/src/notifications/define-notifications.ts +64 -18
- package/src/notifications/index.ts +12 -1
- package/src/notifications/mount-guard.ts +41 -0
- package/src/notifications/notify.tsx +122 -3
- package/src/notifications/overlay.tsx +2 -0
- package/src/notifications/store.ts +7 -0
- package/src/provider/index.tsx +101 -13
- package/src/provider/lab-theme.ts +2 -1
- package/src/query/devtools.tsx +1 -0
- package/src/router-tanstack/field.ts +5 -0
- package/src/router-tanstack/index.ts +4 -0
- package/src/router-tanstack/search-store.ts +171 -12
- package/src/router-tanstack/use-nav.ts +18 -13
- package/src/section/index.ts +1 -1
- package/src/section/section.module.css +11 -0
- package/src/section/section.tsx +163 -96
- package/src/shell/account-types.ts +5 -2
- package/src/shell/app-brand.module.css +109 -0
- package/src/shell/app-brand.module.css.d.ts +14 -0
- package/src/shell/app-brand.tsx +140 -0
- package/src/shell/app-breadcrumbs.tsx +19 -9
- package/src/shell/app-header.module.css +10 -5
- package/src/shell/app-main.module.css +107 -0
- package/src/shell/app-main.module.css.d.ts +11 -0
- package/src/shell/app-mobile-nav.module.css +48 -27
- package/src/shell/app-mobile-nav.module.css.d.ts +0 -1
- package/src/shell/app-mobile-nav.tsx +43 -11
- package/src/shell/app-sidebar-account.tsx +29 -6
- package/src/shell/app-sidebar.module.css +53 -96
- package/src/shell/app-sidebar.module.css.d.ts +0 -5
- package/src/shell/app-sidebar.tsx +40 -113
- package/src/shell/index.tsx +156 -65
- package/src/shell/isomorphic-layout-effect.ts +14 -0
- package/src/shell/mobile-nav-model.ts +66 -10
- package/src/shell/nav-count-badge.tsx +6 -1
- package/src/shell/page-aside.module.css +174 -0
- package/src/shell/page-aside.module.css.d.ts +14 -0
- package/src/shell/page-aside.tsx +377 -0
- package/src/shell/page-bar.module.css +107 -13
- package/src/shell/page-bar.module.css.d.ts +4 -1
- package/src/shell/page-bar.tsx +294 -94
- package/src/shell/sidebar-search.module.css +1 -1
- package/src/shell/sidebar-search.tsx +13 -4
- package/src/state/fields.ts +360 -69
- package/src/state/persisted-or-local.ts +50 -0
- package/src/state/persisted.ts +76 -26
- package/src/state.ts +4 -7
- package/src/surfaces.ts +43 -12
- package/src/theme/ctl-theme.tsx +10 -0
- package/src/theme/index.ts +129 -16
- package/src/theme/nav-link.module.css +37 -26
- package/src/theme/segmented-control.module.css +22 -0
- package/src/theme/segmented-control.module.css.d.ts +1 -0
- package/src/theme-lab/boot.ts +140 -0
- package/src/theme-lab/index.tsx +21 -112
- package/src/theme-toggle/index.tsx +10 -3
- package/src/tokens/index.ts +50 -6
- package/src/tokens/palette.ts +58 -30
- package/src/utils/is-dev.ts +4 -0
- package/src/widget-header/delta-badge.tsx +25 -5
- package/src/widget-header/index.ts +10 -2
- package/src/widget-header/widget-header.module.css +87 -7
- package/src/widget-header/widget-header.module.css.d.ts +1 -0
- package/src/widget-header/widget-header.tsx +166 -42
- package/dist/agent/adapter.test.d.ts +0 -2
- package/dist/agent/adapter.test.d.ts.map +0 -1
- package/dist/agent/ai-sdk-transport.test.d.ts +0 -2
- package/dist/agent/ai-sdk-transport.test.d.ts.map +0 -1
- package/dist/agent/coalesce.test.d.ts +0 -2
- package/dist/agent/coalesce.test.d.ts.map +0 -1
- package/dist/agent/foreign.test.d.ts +0 -2
- package/dist/agent/foreign.test.d.ts.map +0 -1
- package/dist/agent/id.test.d.ts +0 -2
- package/dist/agent/id.test.d.ts.map +0 -1
- package/dist/agent/merge.test.d.ts +0 -2
- package/dist/agent/merge.test.d.ts.map +0 -1
- package/dist/agent/part-list.test.d.ts +0 -2
- package/dist/agent/part-list.test.d.ts.map +0 -1
- package/dist/agent/parts.test.d.ts +0 -2
- package/dist/agent/parts.test.d.ts.map +0 -1
- package/dist/agent/thread.test.d.ts +0 -2
- package/dist/agent/thread.test.d.ts.map +0 -1
- package/dist/agent/transport.test.d.ts +0 -2
- package/dist/agent/transport.test.d.ts.map +0 -1
- package/dist/agent/use-agent-stream.test.d.ts +0 -2
- package/dist/agent/use-agent-stream.test.d.ts.map +0 -1
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts +0 -2
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts.map +0 -1
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts +0 -2
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts.map +0 -1
- package/dist/agent/use-agent-thread-runs.test.d.ts +0 -2
- package/dist/agent/use-agent-thread-runs.test.d.ts.map +0 -1
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts +0 -2
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts.map +0 -1
- package/dist/agent-chat/composer.test.d.ts +0 -2
- package/dist/agent-chat/composer.test.d.ts.map +0 -1
- package/dist/agent-chat/relative-time.test.d.ts +0 -2
- package/dist/agent-chat/relative-time.test.d.ts.map +0 -1
- package/dist/agent-chat/thread-feed-row.test.d.ts +0 -2
- package/dist/agent-chat/thread-feed-row.test.d.ts.map +0 -1
- package/dist/agent-chat/thread-feed.test.d.ts +0 -2
- package/dist/agent-chat/thread-feed.test.d.ts.map +0 -1
- package/dist/agent-chat/thread-message.test.d.ts +0 -2
- package/dist/agent-chat/thread-message.test.d.ts.map +0 -1
- package/dist/agent-chat/thread-workspace.test.d.ts +0 -2
- package/dist/agent-chat/thread-workspace.test.d.ts.map +0 -1
- package/dist/agent-chat/tool-chip.test.d.ts +0 -2
- package/dist/agent-chat/tool-chip.test.d.ts.map +0 -1
- package/dist/agent-chat/virtualize.type-guard.test.d.ts +0 -2
- package/dist/agent-chat/virtualize.type-guard.test.d.ts.map +0 -1
- package/dist/charts/cursor/resolve.test.d.ts +0 -2
- package/dist/charts/cursor/resolve.test.d.ts.map +0 -1
- package/dist/charts/cursor/store.test.d.ts +0 -2
- package/dist/charts/cursor/store.test.d.ts.map +0 -1
- package/dist/charts/kinds/BandStrip.test.d.ts +0 -2
- package/dist/charts/kinds/BandStrip.test.d.ts.map +0 -1
- package/dist/charts/kinds/Bars.test.d.ts +0 -2
- package/dist/charts/kinds/Bars.test.d.ts.map +0 -1
- package/dist/charts/kinds/DualPanel.test.d.ts +0 -2
- package/dist/charts/kinds/DualPanel.test.d.ts.map +0 -1
- package/dist/charts/kinds/MirroredBars.test.d.ts +0 -2
- package/dist/charts/kinds/MirroredBars.test.d.ts.map +0 -1
- package/dist/charts/kinds/MultiLine.test.d.ts +0 -2
- package/dist/charts/kinds/MultiLine.test.d.ts.map +0 -1
- package/dist/charts/kinds/StackedArea.test.d.ts +0 -2
- package/dist/charts/kinds/StackedArea.test.d.ts.map +0 -1
- package/dist/charts/kinds/ZonedLine.test.d.ts +0 -2
- package/dist/charts/kinds/ZonedLine.test.d.ts.map +0 -1
- package/dist/charts/layout/auto-margin.test.d.ts +0 -2
- package/dist/charts/layout/auto-margin.test.d.ts.map +0 -1
- package/dist/charts/primitives/CartesianChart.test.d.ts +0 -2
- package/dist/charts/primitives/CartesianChart.test.d.ts.map +0 -1
- package/dist/charts/primitives/ChartCard.test.d.ts +0 -2
- package/dist/charts/primitives/ChartCard.test.d.ts.map +0 -1
- package/dist/charts/primitives/ChartFrame.test.d.ts +0 -2
- package/dist/charts/primitives/ChartFrame.test.d.ts.map +0 -1
- package/dist/charts/primitives/ChartLegend.test.d.ts +0 -2
- package/dist/charts/primitives/ChartLegend.test.d.ts.map +0 -1
- package/dist/charts/primitives/ChartTooltip.test.d.ts +0 -2
- package/dist/charts/primitives/ChartTooltip.test.d.ts.map +0 -1
- package/dist/charts/primitives/XZoneRects.test.d.ts +0 -2
- package/dist/charts/primitives/XZoneRects.test.d.ts.map +0 -1
- package/dist/charts/series.test.d.ts +0 -2
- package/dist/charts/series.test.d.ts.map +0 -1
- package/dist/charts/utils/domain.test.d.ts +0 -2
- package/dist/charts/utils/domain.test.d.ts.map +0 -1
- package/dist/charts/utils/measure-text.test.d.ts +0 -2
- package/dist/charts/utils/measure-text.test.d.ts.map +0 -1
- package/dist/cli/check-coverage.test.d.ts +0 -2
- package/dist/cli/check-coverage.test.d.ts.map +0 -1
- package/dist/cli/check-theme.test.d.ts +0 -2
- package/dist/cli/check-theme.test.d.ts.map +0 -1
- package/dist/cli/help.test.d.ts +0 -2
- package/dist/cli/help.test.d.ts.map +0 -1
- package/dist/cli/init-sync.test.d.ts +0 -2
- package/dist/cli/init-sync.test.d.ts.map +0 -1
- package/dist/cli/placement-engine.test.d.ts +0 -2
- package/dist/cli/placement-engine.test.d.ts.map +0 -1
- package/dist/cli/shipped-versions.test.d.ts +0 -2
- package/dist/cli/shipped-versions.test.d.ts.map +0 -1
- package/dist/cli/tarball-parity.test.d.ts +0 -2
- package/dist/cli/tarball-parity.test.d.ts.map +0 -1
- package/dist/cli/template-format.test.d.ts +0 -2
- package/dist/cli/template-format.test.d.ts.map +0 -1
- package/dist/cli/template-ledger.test.d.ts +0 -2
- package/dist/cli/template-ledger.test.d.ts.map +0 -1
- package/dist/cli/tokens-css.test.d.ts +0 -2
- package/dist/cli/tokens-css.test.d.ts.map +0 -1
- package/dist/cli/toolchain-wiring.test.d.ts +0 -2
- package/dist/cli/toolchain-wiring.test.d.ts.map +0 -1
- package/dist/cli/waiver-audit.test.d.ts +0 -2
- package/dist/cli/waiver-audit.test.d.ts.map +0 -1
- package/dist/content/article-actions.test.d.ts +0 -2
- package/dist/content/article-actions.test.d.ts.map +0 -1
- package/dist/content/article-model.test.d.ts +0 -2
- package/dist/content/article-model.test.d.ts.map +0 -1
- package/dist/content/block-split.test.d.ts +0 -2
- package/dist/content/block-split.test.d.ts.map +0 -1
- package/dist/content/heading-components.test.d.ts +0 -2
- package/dist/content/heading-components.test.d.ts.map +0 -1
- package/dist/content/markdown.test.d.ts +0 -2
- package/dist/content/markdown.test.d.ts.map +0 -1
- package/dist/content/prose.module.css.test.d.ts +0 -2
- package/dist/content/prose.module.css.test.d.ts.map +0 -1
- package/dist/content/sanitize.test.d.ts +0 -2
- package/dist/content/sanitize.test.d.ts.map +0 -1
- package/dist/content/slug.test.d.ts +0 -2
- package/dist/content/slug.test.d.ts.map +0 -1
- package/dist/controls/actions.test.d.ts +0 -2
- package/dist/controls/actions.test.d.ts.map +0 -1
- package/dist/controls/actions.type-guard.test.d.ts +0 -2
- package/dist/controls/actions.type-guard.test.d.ts.map +0 -1
- package/dist/controls/control-group.test.d.ts +0 -2
- package/dist/controls/control-group.test.d.ts.map +0 -1
- package/dist/controls/controls.router.test.d.ts +0 -2
- package/dist/controls/controls.router.test.d.ts.map +0 -1
- package/dist/controls/filter-set.test.d.ts +0 -2
- package/dist/controls/filter-set.test.d.ts.map +0 -1
- package/dist/controls/peer-boundary.test.d.ts +0 -2
- package/dist/controls/peer-boundary.test.d.ts.map +0 -1
- package/dist/controls/props-contract.test.d.ts +0 -2
- package/dist/controls/props-contract.test.d.ts.map +0 -1
- package/dist/controls/sync-button.test.d.ts +0 -2
- package/dist/controls/sync-button.test.d.ts.map +0 -1
- package/dist/dashboard/query-state.test.d.ts +0 -2
- package/dist/dashboard/query-state.test.d.ts.map +0 -1
- package/dist/dashboard/settings-section.test.d.ts +0 -2
- package/dist/dashboard/settings-section.test.d.ts.map +0 -1
- package/dist/dashboard/stat-card.test.d.ts +0 -2
- package/dist/dashboard/stat-card.test.d.ts.map +0 -1
- package/dist/data/data-table.test.d.ts +0 -2
- package/dist/data/data-table.test.d.ts.map +0 -1
- package/dist/guard/check-source.test.d.ts +0 -2
- package/dist/guard/check-source.test.d.ts.map +0 -1
- package/dist/guard/grace.test.d.ts +0 -20
- package/dist/guard/grace.test.d.ts.map +0 -1
- package/dist/guard/guard-hook.test.d.ts +0 -2
- package/dist/guard/guard-hook.test.d.ts.map +0 -1
- package/dist/provider/index.test.d.ts +0 -2
- package/dist/provider/index.test.d.ts.map +0 -1
- package/dist/provider/lab-theme.test.d.ts +0 -2
- package/dist/provider/lab-theme.test.d.ts.map +0 -1
- package/dist/query/error-message.test.d.ts +0 -2
- package/dist/query/error-message.test.d.ts.map +0 -1
- package/dist/router-tanstack/multi-search-param-store.test.d.ts +0 -2
- package/dist/router-tanstack/multi-search-param-store.test.d.ts.map +0 -1
- package/dist/router-tanstack/nav.test.d.ts +0 -2
- package/dist/router-tanstack/nav.test.d.ts.map +0 -1
- package/dist/router-tanstack/search-param-store.test.d.ts +0 -2
- package/dist/router-tanstack/search-param-store.test.d.ts.map +0 -1
- package/dist/router-tanstack/search-store.router.test.d.ts +0 -2
- package/dist/router-tanstack/search-store.router.test.d.ts.map +0 -1
- package/dist/router-tanstack/search-store.test.d.ts +0 -2
- package/dist/router-tanstack/search-store.test.d.ts.map +0 -1
- package/dist/router-tanstack/use-nav.test.d.ts +0 -2
- package/dist/router-tanstack/use-nav.test.d.ts.map +0 -1
- package/dist/section/section.test.d.ts +0 -2
- package/dist/section/section.test.d.ts.map +0 -1
- package/dist/shell/app-mobile-nav.test.d.ts +0 -2
- package/dist/shell/app-mobile-nav.test.d.ts.map +0 -1
- package/dist/shell/app-sidebar.test.d.ts +0 -2
- package/dist/shell/app-sidebar.test.d.ts.map +0 -1
- package/dist/shell/index.test.d.ts +0 -2
- package/dist/shell/index.test.d.ts.map +0 -1
- package/dist/shell/mobile-nav-model.test.d.ts +0 -2
- package/dist/shell/mobile-nav-model.test.d.ts.map +0 -1
- package/dist/shell/page-bar.test.d.ts +0 -2
- package/dist/shell/page-bar.test.d.ts.map +0 -1
- package/dist/state/fields.test.d.ts +0 -2
- package/dist/state/fields.test.d.ts.map +0 -1
- package/dist/styles.floor.test.d.ts +0 -2
- package/dist/styles.floor.test.d.ts.map +0 -1
- package/dist/theme/border-coverage.test.d.ts +0 -18
- package/dist/theme/border-coverage.test.d.ts.map +0 -1
- package/dist/theme/contrast.test.d.ts +0 -2
- package/dist/theme/contrast.test.d.ts.map +0 -1
- package/dist/theme/ctl-theme.test.d.ts +0 -2
- package/dist/theme/ctl-theme.test.d.ts.map +0 -1
- package/dist/theme/ctl-tier-coverage.test.d.ts +0 -2
- package/dist/theme/ctl-tier-coverage.test.d.ts.map +0 -1
- package/dist/theme/density-option.test.d.ts +0 -2
- package/dist/theme/density-option.test.d.ts.map +0 -1
- package/dist/theme/density-relations.test.d.ts +0 -2
- package/dist/theme/density-relations.test.d.ts.map +0 -1
- package/dist/theme/derive-theme.test.d.ts +0 -2
- package/dist/theme/derive-theme.test.d.ts.map +0 -1
- package/dist/theme/divider-law.test.d.ts +0 -2
- package/dist/theme/divider-law.test.d.ts.map +0 -1
- package/dist/theme/fonts-option.test.d.ts +0 -2
- package/dist/theme/fonts-option.test.d.ts.map +0 -1
- package/dist/theme/icon-slot.test.d.ts +0 -2
- package/dist/theme/icon-slot.test.d.ts.map +0 -1
- package/dist/theme/layout-rhythm-css.test.d.ts +0 -2
- package/dist/theme/layout-rhythm-css.test.d.ts.map +0 -1
- package/dist/theme/radius-option.test.d.ts +0 -2
- package/dist/theme/radius-option.test.d.ts.map +0 -1
- package/dist/theme/radius.test.d.ts +0 -2
- package/dist/theme/radius.test.d.ts.map +0 -1
- package/dist/theme/shadow-surfaces.test.d.ts +0 -26
- package/dist/theme/shadow-surfaces.test.d.ts.map +0 -1
- package/dist/theme/spacing.test.d.ts +0 -2
- package/dist/theme/spacing.test.d.ts.map +0 -1
- package/dist/theme/use-basalt-spacing.test.d.ts +0 -2
- package/dist/theme/use-basalt-spacing.test.d.ts.map +0 -1
- package/dist/theme-lab/derive-controls.test.d.ts +0 -2
- package/dist/theme-lab/derive-controls.test.d.ts.map +0 -1
- package/dist/theme-lab/derive-state.test.d.ts +0 -2
- package/dist/theme-lab/derive-state.test.d.ts.map +0 -1
- package/dist/theme-lab/theme-lab.test.d.ts +0 -2
- package/dist/theme-lab/theme-lab.test.d.ts.map +0 -1
- package/dist/tokens/build-fonts-css.test.d.ts +0 -2
- package/dist/tokens/build-fonts-css.test.d.ts.map +0 -1
- package/dist/tokens/build-radius-css.test.d.ts +0 -2
- package/dist/tokens/build-radius-css.test.d.ts.map +0 -1
- package/dist/tokens/chart-margin.test.d.ts +0 -2
- package/dist/tokens/chart-margin.test.d.ts.map +0 -1
- package/dist/tokens/density.test.d.ts +0 -2
- package/dist/tokens/density.test.d.ts.map +0 -1
- package/dist/tokens/derive-radius.test.d.ts +0 -2
- package/dist/tokens/derive-radius.test.d.ts.map +0 -1
- package/dist/tokens/derive.test.d.ts +0 -2
- package/dist/tokens/derive.test.d.ts.map +0 -1
- package/dist/tokens/palette.test.d.ts +0 -2
- package/dist/tokens/palette.test.d.ts.map +0 -1
- package/dist/tokens/text-scale.test.d.ts +0 -2
- package/dist/tokens/text-scale.test.d.ts.map +0 -1
- package/dist/vite-color-mix.test.d.ts +0 -2
- package/dist/vite-color-mix.test.d.ts.map +0 -1
- package/dist/vite.test.d.ts +0 -2
- package/dist/vite.test.d.ts.map +0 -1
- package/dist/widget-header/delta-badge.test.d.ts +0 -2
- package/dist/widget-header/delta-badge.test.d.ts.map +0 -1
- package/dist/widget-header/no-mantine.test.d.ts +0 -2
- package/dist/widget-header/no-mantine.test.d.ts.map +0 -1
- package/dist/widget-header/widget-header.test.d.ts +0 -2
- package/dist/widget-header/widget-header.test.d.ts.map +0 -1
- package/src/agent/adapter.test.ts +0 -1640
- package/src/agent/ai-sdk-transport.test.ts +0 -658
- package/src/agent/coalesce.test.ts +0 -387
- package/src/agent/foreign.test.ts +0 -51
- package/src/agent/id.test.ts +0 -169
- package/src/agent/merge.test.ts +0 -206
- package/src/agent/part-list.test.tsx +0 -112
- package/src/agent/parts.test.ts +0 -720
- package/src/agent/thread.test.ts +0 -220
- package/src/agent/transport.test.ts +0 -70
- package/src/agent/use-agent-stream.test.tsx +0 -287
- package/src/agent/use-agent-thread-runs.foreign.test.tsx +0 -138
- package/src/agent/use-agent-thread-runs.resume.test.tsx +0 -294
- package/src/agent/use-agent-thread-runs.test.tsx +0 -1120
- package/src/agent/use-agent-thread-runs.wedge.test.tsx +0 -387
- package/src/agent-chat/composer.test.tsx +0 -924
- package/src/agent-chat/relative-time.test.ts +0 -95
- package/src/agent-chat/thread-feed-row.test.tsx +0 -510
- package/src/agent-chat/thread-feed.test.tsx +0 -241
- package/src/agent-chat/thread-message.test.tsx +0 -1285
- package/src/agent-chat/thread-workspace.test.tsx +0 -169
- package/src/agent-chat/tool-chip.test.tsx +0 -139
- package/src/agent-chat/virtualize.type-guard.test.ts +0 -49
- package/src/charts/cursor/resolve.test.ts +0 -151
- package/src/charts/cursor/store.test.ts +0 -64
- package/src/charts/kinds/BandStrip.test.tsx +0 -282
- package/src/charts/kinds/Bars.test.tsx +0 -183
- package/src/charts/kinds/DualPanel.test.tsx +0 -527
- package/src/charts/kinds/MirroredBars.test.tsx +0 -232
- package/src/charts/kinds/MultiLine.test.tsx +0 -218
- package/src/charts/kinds/StackedArea.test.tsx +0 -114
- package/src/charts/kinds/ZonedLine.test.tsx +0 -147
- package/src/charts/layout/auto-margin.test.ts +0 -42
- package/src/charts/primitives/CartesianChart.test.tsx +0 -647
- package/src/charts/primitives/ChartCard.test.tsx +0 -66
- package/src/charts/primitives/ChartFrame.test.tsx +0 -142
- package/src/charts/primitives/ChartLegend.test.tsx +0 -78
- package/src/charts/primitives/ChartTooltip.test.tsx +0 -44
- package/src/charts/primitives/XZoneRects.test.tsx +0 -123
- package/src/charts/series.test.ts +0 -112
- package/src/charts/utils/domain.test.ts +0 -54
- package/src/charts/utils/measure-text.test.ts +0 -36
- package/src/cli/check-coverage.test.ts +0 -297
- package/src/cli/check-theme.test.ts +0 -837
- package/src/cli/help.test.ts +0 -170
- package/src/cli/init-sync.test.ts +0 -343
- package/src/cli/placement-engine.test.ts +0 -298
- package/src/cli/shipped-versions.test.ts +0 -83
- package/src/cli/tarball-parity.test.ts +0 -44
- package/src/cli/template-format.test.ts +0 -64
- package/src/cli/template-ledger.test.ts +0 -219
- package/src/cli/tokens-css.test.ts +0 -249
- package/src/cli/toolchain-wiring.test.ts +0 -1358
- package/src/cli/waiver-audit.test.ts +0 -215
- package/src/content/article-actions.test.ts +0 -78
- package/src/content/article-model.test.ts +0 -119
- package/src/content/block-split.test.ts +0 -75
- package/src/content/heading-components.test.tsx +0 -65
- package/src/content/markdown.test.tsx +0 -603
- package/src/content/prose.module.css.test.ts +0 -39
- package/src/content/sanitize.test.ts +0 -659
- package/src/content/slug.test.ts +0 -62
- package/src/controls/actions.test.tsx +0 -252
- package/src/controls/actions.type-guard.test.ts +0 -63
- package/src/controls/control-group.test.tsx +0 -229
- package/src/controls/controls.router.test.tsx +0 -637
- package/src/controls/filter-set.test.tsx +0 -472
- package/src/controls/peer-boundary.test.ts +0 -85
- package/src/controls/props-contract.test.tsx +0 -106
- package/src/controls/sync-button.test.tsx +0 -183
- package/src/dashboard/query-state.test.tsx +0 -152
- package/src/dashboard/settings-section.test.tsx +0 -56
- package/src/dashboard/stat-card.test.tsx +0 -154
- package/src/data/data-table.test.tsx +0 -434
- package/src/guard/check-source.test.ts +0 -3355
- package/src/guard/grace.test.ts +0 -149
- package/src/guard/guard-hook.test.ts +0 -203
- package/src/provider/index.test.tsx +0 -101
- package/src/provider/lab-theme.test.ts +0 -147
- package/src/query/error-message.test.ts +0 -67
- package/src/router-tanstack/multi-search-param-store.test.ts +0 -124
- package/src/router-tanstack/nav.test.ts +0 -111
- package/src/router-tanstack/search-param-store.test.ts +0 -135
- package/src/router-tanstack/search-store.router.test.tsx +0 -661
- package/src/router-tanstack/search-store.test.ts +0 -418
- package/src/router-tanstack/use-nav.test.tsx +0 -187
- package/src/section/section.test.tsx +0 -204
- package/src/shell/app-mobile-nav.test.tsx +0 -403
- package/src/shell/app-sidebar.test.tsx +0 -509
- package/src/shell/index.test.tsx +0 -428
- package/src/shell/mobile-nav-model.test.ts +0 -517
- package/src/shell/page-bar.test.tsx +0 -316
- package/src/state/fields.test.tsx +0 -258
- package/src/styles.floor.test.ts +0 -36
- package/src/theme/border-coverage.test.ts +0 -272
- package/src/theme/contrast.test.ts +0 -354
- package/src/theme/ctl-theme.test.tsx +0 -275
- package/src/theme/ctl-tier-coverage.test.ts +0 -170
- package/src/theme/density-option.test.ts +0 -96
- package/src/theme/density-relations.test.ts +0 -506
- package/src/theme/derive-theme.test.ts +0 -101
- package/src/theme/divider-law.test.ts +0 -259
- package/src/theme/fonts-option.test.ts +0 -75
- package/src/theme/icon-slot.test.tsx +0 -275
- package/src/theme/layout-rhythm-css.test.ts +0 -72
- package/src/theme/radius-option.test.ts +0 -86
- package/src/theme/radius.test.ts +0 -142
- package/src/theme/shadow-surfaces.test.ts +0 -488
- package/src/theme/spacing.test.ts +0 -495
- package/src/theme/use-basalt-spacing.test.tsx +0 -55
- package/src/theme-lab/derive-controls.test.ts +0 -94
- package/src/theme-lab/derive-state.test.ts +0 -71
- package/src/theme-lab/theme-lab.test.ts +0 -46
- package/src/tokens/build-fonts-css.test.ts +0 -52
- package/src/tokens/build-radius-css.test.ts +0 -25
- package/src/tokens/chart-margin.test.ts +0 -39
- package/src/tokens/density.test.ts +0 -259
- package/src/tokens/derive-radius.test.ts +0 -62
- package/src/tokens/derive.test.ts +0 -30
- package/src/tokens/palette.test.ts +0 -114
- package/src/tokens/text-scale.test.ts +0 -51
- package/src/vite-color-mix.test.ts +0 -46
- package/src/vite.test.ts +0 -423
- package/src/widget-header/delta-badge.test.tsx +0 -60
- package/src/widget-header/no-mantine.test.ts +0 -33
- package/src/widget-header/widget-header.test.tsx +0 -187
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
* overlays-mount — composable overlay mount for basalt-ui apps.
|
|
3
3
|
*
|
|
4
4
|
* `BasaltOverlays` bundles ModalsProvider, Spotlight, and Notifications into a single mount point.
|
|
5
|
-
* Put it inside BasaltProvider, before the router. It replaces the standalone
|
|
6
|
-
* from `basalt-ui/notifications` — do NOT mount both
|
|
7
|
-
* `<BasaltNotifications />` in the same tree (double-mount
|
|
5
|
+
* Put it inside BasaltProvider, before the router. It replaces the standalone
|
|
6
|
+
* `<BasaltNotifications />` from `basalt-ui/notifications` — do NOT mount both
|
|
7
|
+
* `<BasaltOverlays notifications />` and `<BasaltNotifications />` in the same tree (double-mount
|
|
8
|
+
* of `<Notifications />`).
|
|
9
|
+
*
|
|
10
|
+
* Every layer — ModalsProvider included — mounts as a SIBLING of `children`, never as a wrapper:
|
|
11
|
+
* see the comment in the component body (R1). `@mantine/modals`' imperative API (`modals.open*`,
|
|
12
|
+
* and so basalt's own `overlays.open`) is a window CustomEvent bus that ModalsProvider subscribes
|
|
13
|
+
* to, so nothing needs to be inside it; the one thing a sibling cannot serve is Mantine's
|
|
14
|
+
* `useModals()` context hook.
|
|
8
15
|
*
|
|
9
16
|
* Each overlay system is opt-in via props (all default to true). Use flags to disable layers the
|
|
10
17
|
* app does not need — e.g. a charts-only app that has no commands can set `spotlight={false}`.
|
|
@@ -55,8 +62,10 @@ import type { NotificationsProps } from '@mantine/notifications'
|
|
|
55
62
|
import type { SpotlightActionData } from '@mantine/spotlight'
|
|
56
63
|
import { runCommand } from './define-commands'
|
|
57
64
|
import type { CommandId } from './define-commands'
|
|
65
|
+
import { useModalsLayer } from './define-overlays'
|
|
58
66
|
import { toSpotlightActions } from './projectors'
|
|
59
67
|
import { useCommandHotkeys } from './useCommandHotkeys'
|
|
68
|
+
import { useNotificationsMountGuard } from '../notifications/mount-guard'
|
|
60
69
|
|
|
61
70
|
// ── Lazy @mantine/spotlight resolution (module-wide singleton) ────────────────
|
|
62
71
|
|
|
@@ -149,8 +158,9 @@ export type BasaltOverlaysProps = {
|
|
|
149
158
|
children: ReactNode
|
|
150
159
|
}
|
|
151
160
|
|
|
152
|
-
// ── Lazy ModalsProvider (falls back to
|
|
161
|
+
// ── Lazy ModalsProvider (falls back to rendering nothing) ─────────────────────
|
|
153
162
|
|
|
163
|
+
/** Missing-peer fallback. Mounted childless (see BasaltOverlays), so it renders nothing. */
|
|
154
164
|
function PassthroughFragment({ children }: ModalsProviderProps) {
|
|
155
165
|
return <>{children}</>
|
|
156
166
|
}
|
|
@@ -160,6 +170,7 @@ const LazyModalsProvider = lazy(() =>
|
|
|
160
170
|
.then((m) => ({ default: m.ModalsProvider }))
|
|
161
171
|
.catch(() => ({ default: PassthroughFragment })),
|
|
162
172
|
)
|
|
173
|
+
Object.assign(LazyModalsProvider, { displayName: 'LazyModalsProvider' })
|
|
163
174
|
|
|
164
175
|
// ── Lazy SpotlightMount (falls back to rendering nothing) ─────────────────────
|
|
165
176
|
|
|
@@ -215,6 +226,7 @@ const LazySpotlightMount = lazy<
|
|
|
215
226
|
})
|
|
216
227
|
.catch(() => ({ default: NullFallback })),
|
|
217
228
|
)
|
|
229
|
+
Object.assign(LazySpotlightMount, { displayName: 'LazySpotlightMount' })
|
|
218
230
|
|
|
219
231
|
// ── Lazy Notifications (falls back to rendering nothing) ──────────────────────
|
|
220
232
|
|
|
@@ -227,6 +239,29 @@ const LazyNotifications = lazy<ComponentType<NotificationsProps>>(() =>
|
|
|
227
239
|
.then((m) => ({ default: m.Notifications as ComponentType<NotificationsProps> }))
|
|
228
240
|
.catch(() => ({ default: NotificationsFallback })),
|
|
229
241
|
)
|
|
242
|
+
Object.assign(LazyNotifications, { displayName: 'LazyNotifications' })
|
|
243
|
+
|
|
244
|
+
// ── NotificationsLayer (runs the shared duplicate-mount guard, F15) ───────────
|
|
245
|
+
|
|
246
|
+
/** Wraps `LazyNotifications` so `useNotificationsMountGuard` only fires while this layer is
|
|
247
|
+
* actually enabled — a sibling of `BasaltNotifications` importing the SAME shared counter. */
|
|
248
|
+
function NotificationsLayer({
|
|
249
|
+
notificationsProps,
|
|
250
|
+
}: {
|
|
251
|
+
notificationsProps: Omit<NotificationsProps, 'children'> | undefined
|
|
252
|
+
}) {
|
|
253
|
+
useNotificationsMountGuard()
|
|
254
|
+
return (
|
|
255
|
+
<Suspense fallback={null}>
|
|
256
|
+
<LazyNotifications
|
|
257
|
+
position="bottom-right"
|
|
258
|
+
autoClose={4000}
|
|
259
|
+
limit={5}
|
|
260
|
+
{...notificationsProps}
|
|
261
|
+
/>
|
|
262
|
+
</Suspense>
|
|
263
|
+
)
|
|
264
|
+
}
|
|
230
265
|
|
|
231
266
|
// ── HotkeysMount (inner component — ensures hook is inside component tree) ────
|
|
232
267
|
|
|
@@ -239,9 +274,9 @@ function HotkeysMount() {
|
|
|
239
274
|
// ── BasaltOverlays ────────────────────────────────────────────────────────────
|
|
240
275
|
|
|
241
276
|
/**
|
|
242
|
-
* Composable overlay mount —
|
|
243
|
-
*
|
|
244
|
-
*
|
|
277
|
+
* Composable overlay mount — renders ModalsProvider, Spotlight and Notifications as siblings of
|
|
278
|
+
* `children`. All three layers are enabled by default; pass `false` to disable. A disabled layer's
|
|
279
|
+
* optional peer is never imported.
|
|
245
280
|
*
|
|
246
281
|
* Mount exactly ONE BasaltOverlays per app. Do NOT combine with a standalone
|
|
247
282
|
* `<BasaltNotifications />` from `basalt-ui/notifications` — that would double-mount
|
|
@@ -264,7 +299,20 @@ export function BasaltOverlays({
|
|
|
264
299
|
projectCommands = true,
|
|
265
300
|
children,
|
|
266
301
|
}: BasaltOverlaysProps) {
|
|
267
|
-
|
|
302
|
+
// Register the modals layer this mount serves, so `overlays.confirm` can reject with a named
|
|
303
|
+
// error instead of returning a promise nothing will ever settle (nothing subscribes to the modals
|
|
304
|
+
// event bus when no provider is up). With `modals={false}` nothing is registered here — a
|
|
305
|
+
// consumer mounting `<ModalsProvider>` themselves calls `registerModalsProvider()` instead.
|
|
306
|
+
useModalsLayer(enableModals)
|
|
307
|
+
|
|
308
|
+
// `children` sits OUTSIDE every Suspense boundary, and that is load-bearing (R1): React.lazy
|
|
309
|
+
// suspends on its first render even when the module is already warm, so a boundary wrapping the
|
|
310
|
+
// app defers the app's FIRST COMMIT past a microtask tick. TanStack Router's async loadMatches
|
|
311
|
+
// then resolves into that window and setStates onto the not-yet-mounted Transitioner fiber —
|
|
312
|
+
// "Can't perform a React state update on a component that hasn't mounted yet". The old shape
|
|
313
|
+
// also rendered `children` twice (once as the fallback, once resolved), running every effect in
|
|
314
|
+
// the app in both trees. Never put `children` under a lazy boundary here.
|
|
315
|
+
return (
|
|
268
316
|
<>
|
|
269
317
|
{enableSpotlight && (
|
|
270
318
|
<Suspense fallback={null}>
|
|
@@ -274,28 +322,14 @@ export function BasaltOverlays({
|
|
|
274
322
|
/>
|
|
275
323
|
</Suspense>
|
|
276
324
|
)}
|
|
277
|
-
{enableNotifications &&
|
|
325
|
+
{enableNotifications && <NotificationsLayer notificationsProps={notificationsProps} />}
|
|
326
|
+
{enableHotkeys && <HotkeysMount />}
|
|
327
|
+
{enableModals && (
|
|
278
328
|
<Suspense fallback={null}>
|
|
279
|
-
<
|
|
280
|
-
position="bottom-right"
|
|
281
|
-
autoClose={4000}
|
|
282
|
-
limit={5}
|
|
283
|
-
{...notificationsProps}
|
|
284
|
-
/>
|
|
329
|
+
<LazyModalsProvider />
|
|
285
330
|
</Suspense>
|
|
286
331
|
)}
|
|
287
|
-
{enableHotkeys && <HotkeysMount />}
|
|
288
332
|
{children}
|
|
289
333
|
</>
|
|
290
334
|
)
|
|
291
|
-
|
|
292
|
-
if (enableModals) {
|
|
293
|
-
return (
|
|
294
|
-
<Suspense fallback={<>{content}</>}>
|
|
295
|
-
<LazyModalsProvider>{content}</LazyModalsProvider>
|
|
296
|
-
</Suspense>
|
|
297
|
-
)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return <>{content}</>
|
|
301
335
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The message table (Blueprint audit §3). Every basalt diagnostic — thrown or logged — is built
|
|
3
|
+
* here, so the prefix, the `Component: …` shape and the em-dash-then-remedy rhythm are one decision
|
|
4
|
+
* instead of 60. It is the generalisation of `assertQueryStateLike`, which was the ONLY component
|
|
5
|
+
* in the library naming itself in its own failure (isomorphic finding F-ERR-1: the other 54 fail as
|
|
6
|
+
* raw `TypeError`s that `BasaltErrorBoundary` swallows into a blank subtree).
|
|
7
|
+
*
|
|
8
|
+
* Every builder returns a string; nothing here throws or logs. The caller decides which it is —
|
|
9
|
+
* `assertRequiredProps` throws, `useValidateProps` logs, the mount guards log.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** The one namespace every basalt message opens with. */
|
|
13
|
+
export const BASALT_PREFIX = '[basalt]'
|
|
14
|
+
|
|
15
|
+
function message(component: string, body: string): string {
|
|
16
|
+
return `${BASALT_PREFIX} ${component}: ${body}`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A prop the component reads into and cannot render without. This is the F-ERR-1 message: the
|
|
21
|
+
* component names itself and the prop, instead of the read landing as
|
|
22
|
+
* `undefined is not an object (evaluating 'field.use')`.
|
|
23
|
+
*/
|
|
24
|
+
export function requiredProp(component: string, prop: string, hint?: string): string {
|
|
25
|
+
return message(component, `prop "${prop}" is required${hint === undefined ? '.' : ` — ${hint}`}`)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A prop with a closed value set that got something outside it. */
|
|
29
|
+
export function oneOf(
|
|
30
|
+
component: string,
|
|
31
|
+
prop: string,
|
|
32
|
+
allowed: readonly string[],
|
|
33
|
+
got: unknown,
|
|
34
|
+
): string {
|
|
35
|
+
return message(
|
|
36
|
+
component,
|
|
37
|
+
`prop "${prop}" must be one of ${allowed.map((value) => `'${value}'`).join(' | ')} — ` +
|
|
38
|
+
`got ${JSON.stringify(got)}.`,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A prop still shipped and still working, with a named successor and the version it goes away in.
|
|
44
|
+
* Majors are banned here, so the deprecation notice IS the migration channel.
|
|
45
|
+
*/
|
|
46
|
+
export function deprecatedProp(
|
|
47
|
+
component: string,
|
|
48
|
+
oldProp: string,
|
|
49
|
+
newProp: string,
|
|
50
|
+
removeIn: string,
|
|
51
|
+
): string {
|
|
52
|
+
return message(
|
|
53
|
+
component,
|
|
54
|
+
`prop "${oldProp}" is deprecated — use "${newProp}" instead. "${oldProp}" is removed in ${removeIn}.`,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* An imperative call needs a layer that is not there — the optional peer is not installed, or the
|
|
60
|
+
* mount that subscribes to its event bus is disabled. Both halves are named because the remedy
|
|
61
|
+
* differs: install it, or stop turning it off.
|
|
62
|
+
*/
|
|
63
|
+
export function missingLayer(component: string, layer: string, remedy: string): string {
|
|
64
|
+
return message(component, `needs ${layer}, which is not available — ${remedy}.`)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** A single-mount component found a second instance alive (`BasaltProvider`, `Notifications`). */
|
|
68
|
+
export function duplicateMount(component: string): string {
|
|
69
|
+
return message(
|
|
70
|
+
component,
|
|
71
|
+
'more than one instance is mounted at once — mount exactly one, at the app root.',
|
|
72
|
+
)
|
|
73
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `common` — the prop, ref, message and validation primitives every basalt component shares.
|
|
3
|
+
*
|
|
4
|
+
* Not a published subpath: the pieces are re-exported from the root barrel (`.`) so a consumer has
|
|
5
|
+
* one import, and `src/surfaces.ts` stays the SSOT for real subpaths. The module is Mantine-free by
|
|
6
|
+
* rule (`.oxlintrc.json`) and by test (`boundary.test.ts`), so the Mantine-free half of the library
|
|
7
|
+
* may reach it too.
|
|
8
|
+
*/
|
|
9
|
+
export { type BasaltProps, type SlotClassNames, type SlotStylesProps } from './props'
|
|
10
|
+
export { type Tone, type ToneWithNeutral, type Tier, cx } from './props'
|
|
11
|
+
export { assignRef, mergeRefs } from './refs'
|
|
12
|
+
export {
|
|
13
|
+
BASALT_PREFIX,
|
|
14
|
+
requiredProp,
|
|
15
|
+
oneOf,
|
|
16
|
+
deprecatedProp,
|
|
17
|
+
duplicateMount,
|
|
18
|
+
missingLayer,
|
|
19
|
+
} from './errors'
|
|
20
|
+
export { useValidateProps, assertRequiredProps, resetValidatedProps } from './validate'
|
|
21
|
+
export { scrollParentOf, SCROLLPORT_ATTRIBUTE } from './scroll-parent'
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The prop vocabulary every basalt component shares (Blueprint audit §1, isomorphic finding C8).
|
|
3
|
+
*
|
|
4
|
+
* The finding this file answers: 98 of 123 exported components drop `className`, so a consumer who
|
|
5
|
+
* needs one margin has to fork the component. Fixing that per component is 79 edits; fixing it once
|
|
6
|
+
* here is one — every component's props type extends `BasaltProps`, and the root element takes
|
|
7
|
+
* `cx(classes.root, className)` plus `style`.
|
|
8
|
+
*
|
|
9
|
+
* **`className` + per-slot `classNames`, and nothing else.** No `styles` object, no `vars`: basalt
|
|
10
|
+
* does not spread `...rest` onto the DOM (which is why the harness saw zero unknown-attribute
|
|
11
|
+
* warnings), and a `styles`/`vars` surface would re-open the styling seam Mantine already owns for
|
|
12
|
+
* the primitives underneath. A composite that needs more than its root styled declares its SLOT
|
|
13
|
+
* NAMES in its own props type — `SlotStylesProps<'root' | 'header' | 'body'>` — so the slot set is
|
|
14
|
+
* a documented, compiler-checked union rather than an open record.
|
|
15
|
+
*
|
|
16
|
+
* This module is **Mantine-free and React-type-only** so `./charts` and `./tokens` may reach it
|
|
17
|
+
* without breaching the layer boundary (`common/boundary.test.ts` pins that, and `.oxlintrc.json`
|
|
18
|
+
* bans `@mantine/*` here the same way it does for `state`/`query`/`guard`).
|
|
19
|
+
*/
|
|
20
|
+
import type { CSSProperties } from 'react'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The base every basalt component accepts. `| undefined` is explicit on both members because
|
|
24
|
+
* `exactOptionalPropertyTypes` is on: a component destructuring `className` and forwarding it to a
|
|
25
|
+
* child would otherwise fail to type-check at every call site.
|
|
26
|
+
*/
|
|
27
|
+
export interface BasaltProps {
|
|
28
|
+
/** Appended to the root element's own class — never replaces it. */
|
|
29
|
+
readonly className?: string | undefined
|
|
30
|
+
/** Merged onto the root element's own inline style, if it has one. */
|
|
31
|
+
readonly style?: CSSProperties | undefined
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** One class per named slot. The slot union is the component's documented contract. */
|
|
35
|
+
export type SlotClassNames<S extends string> = Partial<Record<S, string>>
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The composite half of the contract: a container that paints more than one box publishes its slot
|
|
39
|
+
* names here. The set is small on purpose — `Section`, `StatCard`, `ChartCard`, `PageBar`,
|
|
40
|
+
* `PageAside`, `WidgetHeader`, `EmptyState`, `QueryState`, `BasaltDataTable`. A leaf takes
|
|
41
|
+
* `BasaltProps` alone.
|
|
42
|
+
*/
|
|
43
|
+
export interface SlotStylesProps<S extends string> {
|
|
44
|
+
readonly classNames?: SlotClassNames<S> | undefined
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The ONE status vocabulary (audit A13). Five forks exist today — `StatCardTone` and
|
|
49
|
+
* `SidebarBlockTone` are byte-identical to this, `CalloutKind` / `AccountBadgeTone` /
|
|
50
|
+
* `NotificationIntent` each differ — and they stay put for now: an adopter aliases its fork to this
|
|
51
|
+
* type, it does not get renamed out from under a consumer.
|
|
52
|
+
*/
|
|
53
|
+
export type Tone = 'good' | 'warn' | 'bad'
|
|
54
|
+
|
|
55
|
+
/** `Tone` plus the un-toned state — a badge or a block with nothing to say yet. */
|
|
56
|
+
export type ToneWithNeutral = Tone | 'neutral'
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The heading tier (`docs/CONTROLS-SPEC.md` §2.2). Re-exported from its owner rather than declared
|
|
60
|
+
* twice — `WidgetHeaderTier` stays the name on the public barrel; `Tier` is what `common`-aware
|
|
61
|
+
* code spells. Type-only, so this file emits no runtime edge into the Mantine-coupled half.
|
|
62
|
+
*/
|
|
63
|
+
export type { WidgetHeaderTier as Tier } from '../widget-header/widget-header'
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The class joiner. Replaces the `[a, b].filter(Boolean).join(' ')` spelled out in seven files
|
|
67
|
+
* today; falsy parts drop, so `cx(classes.root, open && classes.open, className)` is the idiom.
|
|
68
|
+
*/
|
|
69
|
+
export function cx(...parts: Array<string | false | null | undefined>): string {
|
|
70
|
+
return parts.filter((part): part is string => typeof part === 'string' && part !== '').join(' ')
|
|
71
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The query envelope every basalt container reads, and the ONE runtime assertion that stands in for
|
|
3
|
+
* the compiler over it.
|
|
4
|
+
*
|
|
5
|
+
* It lives in `common/` because two independent readers grew their own copy and the copies
|
|
6
|
+
* DISAGREED: `QueryState` (`dashboard/query-state.tsx`) checked the `data` key and that `refetch` is
|
|
7
|
+
* a function; `dataQueryBranch` (`data/query-branch.ts`) checked neither, so the table accepted a
|
|
8
|
+
* result whose Retry button did nothing. A validator that exists twice is a validator with two
|
|
9
|
+
* strictnesses, which is exactly the class of defect the assertion exists to catch.
|
|
10
|
+
*
|
|
11
|
+
* Mantine-free by construction (`common/boundary.test.ts`): types, a set and a throw.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The structural subset of a TanStack `UseQueryResult` these components read.
|
|
16
|
+
*
|
|
17
|
+
* Typed as a SUBSET rather than as `UseQueryResult<T>` on purpose: a composed, derived or
|
|
18
|
+
* hand-rolled result must be passable without a cast, and the components stay independent of which
|
|
19
|
+
* `@tanstack/react-query` major a consumer pins. This is NOT a claim that the root barrel is free of
|
|
20
|
+
* that package — `./connectivity` imports `onlineManager` as a value and is re-exported from
|
|
21
|
+
* `src/index.ts`. The cost of the subset is that the compiler stops policing the shape — which is
|
|
22
|
+
* why {@link assertQueryStateLike} checks it at runtime.
|
|
23
|
+
*/
|
|
24
|
+
export type QueryStateLike<TData> = {
|
|
25
|
+
data: TData | undefined
|
|
26
|
+
isError: boolean
|
|
27
|
+
error: unknown
|
|
28
|
+
fetchStatus: 'fetching' | 'paused' | 'idle'
|
|
29
|
+
refetch: () => unknown
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The three `fetchStatus` values a `UseQueryResult` can carry. */
|
|
33
|
+
export const FETCH_STATUSES: ReadonlySet<string> = new Set(['fetching', 'paused', 'idle'])
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* `QueryStateLike` is a structural subset, so TypeScript cannot protect a hand-composed result the
|
|
37
|
+
* way it protects a real `UseQueryResult` — and every field it drops fails SILENTLY in the exact
|
|
38
|
+
* direction these components exist to prevent. A missing `isError` renders "no data" over a 500. A
|
|
39
|
+
* misspelled `fetchStatus` never leaves the spinner. A missing `refetch` renders a Retry button that
|
|
40
|
+
* does nothing. Each of those is a false claim about the data, so it throws.
|
|
41
|
+
*
|
|
42
|
+
* `component` opens the message so the throw names the container that got the bad envelope —
|
|
43
|
+
* `QueryState`, `BasaltDataTable`, `BasaltVirtualList` all read the same shape.
|
|
44
|
+
*/
|
|
45
|
+
export function assertQueryStateLike(
|
|
46
|
+
component: string,
|
|
47
|
+
query: unknown,
|
|
48
|
+
): asserts query is QueryStateLike<unknown> {
|
|
49
|
+
const bad = (detail: string): never => {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`${component}: \`query\` ${detail}. It must carry { data, isError, error, fetchStatus, refetch } — ` +
|
|
52
|
+
'a TanStack UseQueryResult does; a hand-composed one must spell every field, because a ' +
|
|
53
|
+
'missing branch flag renders a false claim about the data instead of an error.',
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
if (query === null || typeof query !== 'object')
|
|
57
|
+
bad(`is ${query === null ? 'null' : typeof query}`)
|
|
58
|
+
const q = query as Record<string, unknown>
|
|
59
|
+
if (!('data' in q)) bad('has no `data` key')
|
|
60
|
+
if (typeof q['isError'] !== 'boolean') bad('has no boolean `isError`')
|
|
61
|
+
if (typeof q['fetchStatus'] !== 'string' || !FETCH_STATUSES.has(q['fetchStatus']))
|
|
62
|
+
bad(`has fetchStatus=${JSON.stringify(q['fetchStatus'])}, not 'fetching' | 'paused' | 'idle'`)
|
|
63
|
+
if (typeof q['refetch'] !== 'function') bad('has no `refetch()`')
|
|
64
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref plumbing for composites (Blueprint audit §2). React 19 made `ref` an ordinary prop, which
|
|
3
|
+
* removed `forwardRef` — it did NOT remove the need to merge: a component that both forwards its
|
|
4
|
+
* caller's ref and keeps its own (a measurement, a focus target) still has two refs and one node.
|
|
5
|
+
*
|
|
6
|
+
* The React 19 wrinkle these two functions exist to get right: a callback ref MAY return a cleanup
|
|
7
|
+
* function, and when it does React never calls it again with `null`. So merging cannot just fan out
|
|
8
|
+
* — it has to fan out the cleanups too, and null out the refs that returned none.
|
|
9
|
+
*/
|
|
10
|
+
import type { Ref, RefCallback } from 'react'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Writes `value` into one ref of either shape.
|
|
14
|
+
*
|
|
15
|
+
* @returns the callback ref's own cleanup when it returned one, else `undefined`.
|
|
16
|
+
*/
|
|
17
|
+
export function assignRef<T>(ref: Ref<T> | undefined, value: T | null): (() => void) | undefined {
|
|
18
|
+
if (ref === undefined || ref === null) return undefined
|
|
19
|
+
if (typeof ref === 'function') {
|
|
20
|
+
const cleanup = ref(value)
|
|
21
|
+
return typeof cleanup === 'function' ? cleanup : undefined
|
|
22
|
+
}
|
|
23
|
+
// `@types/react` 19 types `RefObject.current` as MUTABLE — the readonly `current` that forced a
|
|
24
|
+
// cast here was the React 18 `RefObject`, and `Ref<T>` now narrows to `RefObject<T | null>`.
|
|
25
|
+
ref.current = value
|
|
26
|
+
return undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Fans one node out to several refs.
|
|
31
|
+
*
|
|
32
|
+
* Returns a NEW function on every call, so a component that passes it straight to JSX re-attaches
|
|
33
|
+
* on every render — wrap it in `useCallback`/`useMemo` over the refs it merges when the node is
|
|
34
|
+
* expensive to re-attach.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const merged = useMemo(() => mergeRefs(ref, localRef), [ref])
|
|
38
|
+
* return <div ref={merged} />
|
|
39
|
+
*/
|
|
40
|
+
export function mergeRefs<T>(...refs: Array<Ref<T> | undefined>): RefCallback<T> {
|
|
41
|
+
return (value: T | null) => {
|
|
42
|
+
const cleanups = refs.map((ref) => assignRef(ref, value))
|
|
43
|
+
// No child returned a cleanup → stay on React's legacy path and let it call us with `null`.
|
|
44
|
+
if (cleanups.every((cleanup) => cleanup === undefined)) return undefined
|
|
45
|
+
// At least one did → React will call THIS instead of re-invoking with `null`, so the refs that
|
|
46
|
+
// returned no cleanup have to be cleared here or they keep pointing at a detached node.
|
|
47
|
+
return () => {
|
|
48
|
+
refs.forEach((ref, index) => {
|
|
49
|
+
const cleanup = cleanups[index]
|
|
50
|
+
if (cleanup !== undefined) {
|
|
51
|
+
cleanup()
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
assignRef(ref, null)
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `scrollParentOf` — which box actually scrolls `el`.
|
|
3
|
+
*
|
|
4
|
+
* Since `BasaltShell` made `AppShell.Main` the scrollport (`shell/app-main.module.css`), the
|
|
5
|
+
* document no longer scrolls inside a shell: `window.scrollY` is pinned at 0 and a `scroll`
|
|
6
|
+
* listener on `window` never fires. Everything in the package that reacted to page scroll had to
|
|
7
|
+
* stop asking the window and start asking whichever ancestor is really scrolling — and it has to
|
|
8
|
+
* keep working in a SHELL-LESS app, where the answer genuinely is the window.
|
|
9
|
+
*
|
|
10
|
+
* `null` IS the answer for "the document scrolls this", not a failure — callers listen on `window`
|
|
11
|
+
* and read `window.scrollY` in that case.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** The attribute `BasaltShell` puts on `AppShell.Main`. Also the public handle for a consumer. */
|
|
15
|
+
export const SCROLLPORT_ATTRIBUTE = 'data-basalt-scrollport'
|
|
16
|
+
|
|
17
|
+
function isScrollport(element: HTMLElement): boolean {
|
|
18
|
+
// The declared handle wins outright: Main is a scrollport by construction even on the frame where
|
|
19
|
+
// its content is short enough that `scrollHeight === clientHeight`.
|
|
20
|
+
if (element.hasAttribute(SCROLLPORT_ATTRIBUTE)) return true
|
|
21
|
+
const overflowY = getComputedStyle(element).overflowY
|
|
22
|
+
if (overflowY !== 'auto' && overflowY !== 'scroll') return false
|
|
23
|
+
return element.scrollHeight > element.clientHeight
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The nearest scrolling ANCESTOR of `el`, or `null` when the document is the scroller.
|
|
28
|
+
*
|
|
29
|
+
* `el` itself is never considered — the question is which box scrolls it, not whether it scrolls
|
|
30
|
+
* its own children. `<body>` and `<html>` are never returned either: an app that scrolls at the
|
|
31
|
+
* document level is exactly the `null` case.
|
|
32
|
+
*/
|
|
33
|
+
export function scrollParentOf(el: Element | null): HTMLElement | null {
|
|
34
|
+
if (el === null || typeof window === 'undefined') return null
|
|
35
|
+
const root = el.ownerDocument.documentElement
|
|
36
|
+
let node = el.parentElement
|
|
37
|
+
while (node !== null && node !== root && node !== el.ownerDocument.body) {
|
|
38
|
+
if (isScrollport(node)) return node
|
|
39
|
+
node = node.parentElement
|
|
40
|
+
}
|
|
41
|
+
return null
|
|
42
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prop validation, in the two shapes basalt actually needs (Blueprint audit §3, isomorphic finding
|
|
3
|
+
* F-ERR-1).
|
|
4
|
+
*
|
|
5
|
+
* The split is the design: a MISUSE that would crash anyway throws immediately with a written
|
|
6
|
+
* message (`assertRequiredProps`), while a misuse that merely renders something the caller did not
|
|
7
|
+
* mean warns once in dev and renders on (`useValidateProps`).
|
|
8
|
+
*/
|
|
9
|
+
import { useEffect } from 'react'
|
|
10
|
+
import { isDev } from '../utils/is-dev'
|
|
11
|
+
import { requiredProp } from './errors'
|
|
12
|
+
|
|
13
|
+
/** A check returns the message(s) it has, or nothing. `null`/`undefined` entries are ignored. */
|
|
14
|
+
type CheckResult = string | null | undefined | Array<string | null | undefined>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Module-level so the once-per-message promise survives a re-render, a remount, and a second
|
|
18
|
+
* instance of the same component. A dev warning is about the CODE, and printing it per render is
|
|
19
|
+
* how a real warning gets scrolled out of the console. Keyed by `component` + message, so two
|
|
20
|
+
* different faults in one component both get said.
|
|
21
|
+
*/
|
|
22
|
+
const reported = new Set<string>()
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Dev-only prop validation. `console.error`s each message ONCE per `(component, message)` pair, and
|
|
26
|
+
* is a no-op in production: `isDev()` reads `process.env.NODE_ENV`, which every bundler
|
|
27
|
+
* constant-folds, so the whole body disappears from a production build.
|
|
28
|
+
*
|
|
29
|
+
* **The dedup key is `${component} ${message}`, and nothing else** — not the instance, not the
|
|
30
|
+
* props. Two instances of one component producing the SAME message say it once between them, which
|
|
31
|
+
* is the intent (a dev warning is about the code). A caller that wants it said per instance has to
|
|
32
|
+
* embed the identifying context IN the message — the title, the persist key, the field name — the
|
|
33
|
+
* way `Section` writes `Section "<title>": …`. A message built from nothing instance-specific is a
|
|
34
|
+
* message the second faulty call site never gets.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* useValidateProps(
|
|
38
|
+
* 'Section',
|
|
39
|
+
* () => (persistKey !== undefined && !collapsible ? sectionPersistMessage : null),
|
|
40
|
+
* [persistKey, collapsible],
|
|
41
|
+
* )
|
|
42
|
+
*/
|
|
43
|
+
export function useValidateProps(
|
|
44
|
+
component: string,
|
|
45
|
+
check: () => CheckResult,
|
|
46
|
+
deps: unknown[],
|
|
47
|
+
): void {
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!isDev()) return
|
|
50
|
+
const result = check()
|
|
51
|
+
const messages = Array.isArray(result) ? result : [result]
|
|
52
|
+
for (const raw of messages) {
|
|
53
|
+
if (raw === null || raw === undefined) continue
|
|
54
|
+
const key = `${component} ${raw}`
|
|
55
|
+
if (reported.has(key)) continue
|
|
56
|
+
reported.add(key)
|
|
57
|
+
console.error(raw)
|
|
58
|
+
}
|
|
59
|
+
// The deps ARE the caller's contract: this hook cannot know what `check` closes over.
|
|
60
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps -- the caller owns the dep list
|
|
61
|
+
}, deps)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Test seam. The once-per-message Set is module state, so a suite has to be able to clear it. */
|
|
65
|
+
export function resetValidatedProps(): void {
|
|
66
|
+
reported.clear()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* THROWS on a missing required prop, in every build, before the component reads into it.
|
|
71
|
+
*
|
|
72
|
+
* This is the F-ERR-1 remedy, and the reason it is not dev-gated: the component was going to crash
|
|
73
|
+
* either way (`undefined is not an object (evaluating 'field.use')`), so the only thing in question
|
|
74
|
+
* is whether the stack reaching `BasaltErrorBoundary` names the component and the prop. It does
|
|
75
|
+
* now. A prop that is merely questionable belongs in `useValidateProps`, not here.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* assertRequiredProps('SelectFilter', props, ['field'])
|
|
79
|
+
*/
|
|
80
|
+
export function assertRequiredProps<P extends object>(
|
|
81
|
+
component: string,
|
|
82
|
+
props: P,
|
|
83
|
+
keys: ReadonlyArray<Extract<keyof P, string>>,
|
|
84
|
+
hints?: Partial<Record<Extract<keyof P, string>, string>>,
|
|
85
|
+
): void {
|
|
86
|
+
for (const key of keys) {
|
|
87
|
+
const value = (props as Record<string, unknown>)[key]
|
|
88
|
+
if (value !== undefined && value !== null) continue
|
|
89
|
+
const hint = hints?.[key]
|
|
90
|
+
throw new Error(
|
|
91
|
+
hint === undefined ? requiredProp(component, key) : requiredProp(component, key, hint),
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -16,10 +16,13 @@
|
|
|
16
16
|
import { ActionIcon, Badge, Divider, Group, Popover, Stack, Text } from '@mantine/core'
|
|
17
17
|
import { useDisclosure } from '@mantine/hooks'
|
|
18
18
|
import { useRef } from 'react'
|
|
19
|
+
import type { BasaltProps } from '../common/props'
|
|
19
20
|
import { alpha, VX } from '../tokens'
|
|
20
21
|
import { useConnectivity } from './use-connectivity'
|
|
21
22
|
import type { ConnectivityStatus } from './types'
|
|
22
23
|
|
|
24
|
+
export type ConnectivityIndicatorProps = BasaltProps
|
|
25
|
+
|
|
23
26
|
const HOVER_OPEN_DELAY = 150
|
|
24
27
|
const HOVER_CLOSE_DELAY = 200
|
|
25
28
|
|
|
@@ -180,7 +183,7 @@ const ICON_COLOR: Record<ConnectivityStatus, string> = {
|
|
|
180
183
|
* {...rest}
|
|
181
184
|
* />
|
|
182
185
|
*/
|
|
183
|
-
export function ConnectivityIndicator() {
|
|
186
|
+
export function ConnectivityIndicator({ className, style }: ConnectivityIndicatorProps = {}) {
|
|
184
187
|
const [opened, { open, toggle, close }] = useDisclosure(false)
|
|
185
188
|
const { status, details } = useConnectivity()
|
|
186
189
|
const statusCfg = STATUS_CONFIG[status]
|
|
@@ -215,6 +218,8 @@ export function ConnectivityIndicator() {
|
|
|
215
218
|
aria-label={statusCfg.label}
|
|
216
219
|
aria-expanded={opened}
|
|
217
220
|
aria-haspopup="dialog"
|
|
221
|
+
{...(className !== undefined && { className })}
|
|
222
|
+
{...(style !== undefined && { style })}
|
|
218
223
|
>
|
|
219
224
|
<WifiIcon />
|
|
220
225
|
</ActionIcon>
|
|
@@ -16,7 +16,10 @@ const SSR_SNAPSHOT: ConnectivitySnapshot = {
|
|
|
16
16
|
status: 'online',
|
|
17
17
|
details: {
|
|
18
18
|
browserOnline: true,
|
|
19
|
-
|
|
19
|
+
// Optimistic `true`, matching `browserOnline` — `onlineManager` is a module singleton so it is
|
|
20
|
+
// always readable, this is the same pre-hydration default as every other signal, never the
|
|
21
|
+
// "not mounted" case (see `ConnectivitySnapshot['details']['queryOnline']`'s JSDoc).
|
|
22
|
+
queryOnline: true,
|
|
20
23
|
sseOpen: null,
|
|
21
24
|
healthPassing: null,
|
|
22
25
|
},
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
export { ConnectivityProvider } from './connectivity-provider'
|
|
11
11
|
export { ConnectivityIndicator } from './connectivity-indicator'
|
|
12
|
+
export type { ConnectivityIndicatorProps } from './connectivity-indicator'
|
|
12
13
|
export { useConnectivity } from './use-connectivity'
|
|
13
14
|
export type {
|
|
14
15
|
ConnectivityStatus,
|
|
@@ -13,7 +13,10 @@ export type ConnectivitySnapshot = {
|
|
|
13
13
|
/** Per-signal breakdown for debugging / detailed indicators */
|
|
14
14
|
details: {
|
|
15
15
|
browserOnline: boolean // navigator.onLine
|
|
16
|
-
|
|
16
|
+
// React Query onlineManager — a module-level singleton, so it is always readable regardless of
|
|
17
|
+
// whether a QueryClient is mounted; never null on the client (the pre-hydration SSR snapshot
|
|
18
|
+
// reports an optimistic `true`, matching `browserOnline`, rather than an "unknown" null).
|
|
19
|
+
queryOnline: boolean
|
|
17
20
|
sseOpen: boolean | null // EventSource readyState === OPEN — null when no sseUrl configured
|
|
18
21
|
healthPassing: boolean | null // /health ping succeeded — null when no healthUrl configured
|
|
19
22
|
}
|
|
@@ -21,7 +24,7 @@ export type ConnectivitySnapshot = {
|
|
|
21
24
|
|
|
22
25
|
export type ConnectivityOverride = {
|
|
23
26
|
browserOnline?: boolean
|
|
24
|
-
queryOnline?: boolean
|
|
27
|
+
queryOnline?: boolean
|
|
25
28
|
sseOpen?: boolean | null
|
|
26
29
|
healthPassing?: boolean | null
|
|
27
30
|
}
|