basalt-ui 1.27.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 +59 -0
- package/MIGRATING.md +613 -20
- package/README.md +33 -3
- package/agent/rules/basalt-batteries.md +25 -10
- package/agent/rules/basalt-controls.md +56 -31
- package/agent/rules/basalt-mantine.md +17 -6
- package/agent/rules/basalt-tokens.md +1 -1
- package/configs/oxlint-plugin.js +1056 -28
- package/configs/oxlint-plugin.test.ts +1066 -0
- package/configs/oxlint.json +7 -0
- 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 +3 -2
- package/dist/controls/enum-filter.d.ts.map +1 -1
- package/dist/controls/enum-filter.js +28 -13
- package/dist/controls/filter-context.d.ts +8 -4
- 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 +2 -0
- package/dist/controls/index.d.ts.map +1 -1
- package/dist/controls/index.js +4 -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 +122 -20
- package/dist/controls/number-filter.d.ts +7 -5
- package/dist/controls/number-filter.d.ts.map +1 -1
- package/dist/controls/number-filter.js +40 -11
- 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 +2 -1
- package/dist/controls/range-filter.d.ts.map +1 -1
- package/dist/controls/range-filter.js +57 -35
- 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 +25 -10
- 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 +28 -11
- 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 +7 -1
- 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 +44 -38
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +55 -42
- package/dist/dashboard/stat-card.module.css +46 -31
- package/dist/dashboard/stat-card.module.css.d.ts +1 -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 +384 -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.map +1 -1
- package/dist/guard/index.js +26 -6
- 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/search-store.d.ts.map +1 -1
- package/dist/router-tanstack/search-store.js +1 -1
- 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 +23 -3
- package/dist/state/fields.d.ts.map +1 -1
- package/dist/state/fields.js +13 -2
- 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.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 +42 -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 +69 -4
- package/dist/widget-header/widget-header.d.ts.map +1 -1
- package/dist/widget-header/widget-header.js +42 -27
- package/dist/widget-header/widget-header.module.css +72 -7
- 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 +32 -16
- package/src/controls/filter-context.tsx +14 -6
- 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 +7 -0
- package/src/controls/multi-select-filter.tsx +177 -27
- package/src/controls/number-filter.tsx +61 -23
- 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 +76 -39
- package/src/controls/search-filter.tsx +30 -12
- 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 +36 -16
- 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 +13 -1
- package/src/dashboard/query-state.tsx +154 -84
- package/src/dashboard/settings-section.tsx +87 -31
- package/src/dashboard/stat-card.module.css +46 -31
- package/src/dashboard/stat-card.module.css.d.ts +1 -0
- package/src/dashboard/stat-card.tsx +185 -127
- 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 +919 -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 +73 -18
- package/src/index.ts +74 -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 +1 -0
- package/src/router-tanstack/search-store.ts +3 -10
- 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 +43 -10
- package/src/state/persisted-or-local.ts +50 -0
- package/src/state.ts +0 -9
- package/src/surfaces.ts +42 -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 +72 -7
- package/src/widget-header/widget-header.tsx +150 -71
- 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/range-filter.type-guard.test.d.ts +0 -2
- package/dist/controls/range-filter.type-guard.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/state/persisted.test.d.ts +0 -2
- package/dist/state/persisted.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 -1053
- 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 -137
- package/src/controls/range-filter.type-guard.test.tsx +0 -122
- 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 -385
- package/src/data/data-table.test.tsx +0 -434
- package/src/guard/check-source.test.ts +0 -3388
- package/src/guard/grace.test.ts +0 -158
- 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 -882
- package/src/router-tanstack/search-store.test.ts +0 -578
- 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 -512
- package/src/state/persisted.test.ts +0 -91
- 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
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { curveMonotoneX } from '@visx/curve'
|
|
2
1
|
import { AreaClosed, LinePath } from '@visx/shape'
|
|
3
2
|
import { Threshold } from '@visx/threshold'
|
|
4
3
|
import { memo, useMemo } from 'react'
|
|
4
|
+
import { assertRequiredProps } from '../../common/validate'
|
|
5
|
+
import type { BasaltProps } from '../../common/props'
|
|
5
6
|
import type { CursorResolution } from '../cursor/resolve'
|
|
6
7
|
import { AreaGradient, areaFillUrl } from '../primitives/AreaGradient'
|
|
7
8
|
import type { CartesianTooltipConfig, AxisConfig, PlotContext } from '../primitives/CartesianChart'
|
|
8
9
|
import { CartesianChart } from '../primitives/CartesianChart'
|
|
9
10
|
import type { XZoneSpec } from '../primitives/XZoneRects'
|
|
10
11
|
import type { ZoneSpec } from '../primitives/ZoneRects'
|
|
11
|
-
import {
|
|
12
|
+
import type { ChartState } from '../primitives/ChartPending'
|
|
13
|
+
import { curveFor, definedOn, LINE_OVERLAY_STROKE_WIDTH, toPlotPoint } from '../series'
|
|
12
14
|
import type { ChartLegendConfig, ChartSeries } from '../series'
|
|
13
15
|
import { VX } from '../../tokens'
|
|
14
16
|
|
|
@@ -30,7 +32,7 @@ export type ZonedLineRefLine = {
|
|
|
30
32
|
dashed?: boolean
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
export type ZonedLineProps<T> = {
|
|
35
|
+
export type ZonedLineProps<T> = BasaltProps & {
|
|
34
36
|
data: T[]
|
|
35
37
|
/** Fixed height in pixels, forwarded to `CartesianChart`. Default 240. */
|
|
36
38
|
height?: number
|
|
@@ -58,6 +60,9 @@ export type ZonedLineProps<T> = {
|
|
|
58
60
|
xTickValues?: (keys: readonly string[], xMax: number) => readonly string[]
|
|
59
61
|
/** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
|
|
60
62
|
formatX?: (key: string) => string
|
|
63
|
+
/** Tilt the x tick labels 45° or 90°, or `0` to opt out of the phone tier's auto-rotation —
|
|
64
|
+
* see `CartesianChartProps.xLabelRotate`. */
|
|
65
|
+
xLabelRotate?: 0 | 45 | 90
|
|
61
66
|
/**
|
|
62
67
|
* How a sibling chart's broadcast cursor key resolves against this chart's points. Default
|
|
63
68
|
* `'nearest'`. Pass `'leading'` when `getX` returns a bucket's leading edge (a weekly series
|
|
@@ -81,21 +86,22 @@ export type ZonedLineProps<T> = {
|
|
|
81
86
|
ariaLabel?: string
|
|
82
87
|
/** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
83
88
|
isPending?: boolean
|
|
89
|
+
/** The three "nothing to draw" states in one prop — pending → error → empty. See
|
|
90
|
+
* `ChartState`; `isPending` stays a supported alias for `state={{ pending: true }}`. */
|
|
91
|
+
state?: ChartState
|
|
84
92
|
}
|
|
85
93
|
|
|
86
|
-
type
|
|
94
|
+
type Pt<T> = T & { __y: number | null }
|
|
87
95
|
|
|
88
|
-
/**
|
|
89
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Every row, in x order, with `__y: null` where the series reports no value. The null row STAYS in
|
|
98
|
+
* the array — see `MultiLine`'s `seriesPoints`: dropping it makes `LinePath`/`AreaClosed`/
|
|
99
|
+
* `Threshold` join straight across a coverage hole, drawing a measurement that was never taken.
|
|
100
|
+
* The shared `defined` guard below is what turns it back into a gap.
|
|
101
|
+
*/
|
|
102
|
+
function linePoints<T>(series: ChartSeries<T> | undefined, data: readonly T[]): Pt<T>[] {
|
|
90
103
|
if (!series) return []
|
|
91
|
-
|
|
92
|
-
for (const d of data) {
|
|
93
|
-
const y = series.getValue(d)
|
|
94
|
-
if (y !== null && y !== undefined && !Number.isNaN(y)) {
|
|
95
|
-
out.push(Object.assign({}, d, { __y: y }) as Valid<T>)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return out
|
|
104
|
+
return data.map((d) => Object.assign({}, d, { __y: toPlotPoint(series.getValue(d)) }) as Pt<T>)
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
/**
|
|
@@ -107,11 +113,15 @@ function validPoints<T>(series: ChartSeries<T> | undefined, data: readonly T[]):
|
|
|
107
113
|
* and the derived tooltip — this kind draws ONLY the marks (thresholds, area fill, and the line).
|
|
108
114
|
* Single-series, so the legend is optional in practice but present by default.
|
|
109
115
|
*
|
|
110
|
-
* X-axis is built from the full `data` array so the calendar is preserved even
|
|
111
|
-
*
|
|
112
|
-
*
|
|
116
|
+
* X-axis is built from the full `data` array so the calendar is preserved even when the series has
|
|
117
|
+
* nulls; the line, the area fill and the threshold fills all BREAK at a null point, leaving a real
|
|
118
|
+
* gap rather than interpolating across it.
|
|
113
119
|
*/
|
|
114
120
|
function ZonedLineInner<T>(props: ZonedLineProps<T>) {
|
|
121
|
+
// F-ERR-1: name the component and the prop. Without this a missing accessor surfaces
|
|
122
|
+
// from inside visx as `undefined is not a function`, which `BasaltErrorBoundary`
|
|
123
|
+
// swallows into a blank subtree that names nothing.
|
|
124
|
+
assertRequiredProps('ZonedLine', props, ['data', 'getX', 'series'])
|
|
115
125
|
const {
|
|
116
126
|
data,
|
|
117
127
|
chartId,
|
|
@@ -125,6 +135,7 @@ function ZonedLineInner<T>(props: ZonedLineProps<T>) {
|
|
|
125
135
|
xTicks,
|
|
126
136
|
xTickValues,
|
|
127
137
|
formatX,
|
|
138
|
+
xLabelRotate,
|
|
128
139
|
cursorResolution,
|
|
129
140
|
tooltip,
|
|
130
141
|
areaFill,
|
|
@@ -132,6 +143,9 @@ function ZonedLineInner<T>(props: ZonedLineProps<T>) {
|
|
|
132
143
|
legend,
|
|
133
144
|
ariaLabel,
|
|
134
145
|
isPending,
|
|
146
|
+
state,
|
|
147
|
+
className,
|
|
148
|
+
style,
|
|
135
149
|
} = props
|
|
136
150
|
|
|
137
151
|
// Default the line overlay to the redesign's 1.9px stroke (docs/DESIGN-SPEC.md §5) — applied
|
|
@@ -158,12 +172,16 @@ function ZonedLineInner<T>(props: ZonedLineProps<T>) {
|
|
|
158
172
|
{...(xTicks !== undefined && { xTicks })}
|
|
159
173
|
{...(xTickValues !== undefined && { xTickValues })}
|
|
160
174
|
{...(formatX !== undefined && { formatX })}
|
|
175
|
+
{...(xLabelRotate !== undefined && { xLabelRotate })}
|
|
161
176
|
{...(cursorResolution !== undefined && { cursorResolution })}
|
|
162
177
|
{...(tooltip !== undefined && { tooltip })}
|
|
163
178
|
{...(height !== undefined && { height })}
|
|
164
179
|
{...(legend !== undefined && { legend })}
|
|
165
180
|
{...(ariaLabel !== undefined && { ariaLabel })}
|
|
166
181
|
{...(isPending !== undefined && { isPending })}
|
|
182
|
+
{...(state !== undefined && { state })}
|
|
183
|
+
{...(className !== undefined && { className })}
|
|
184
|
+
{...(style !== undefined && { style })}
|
|
167
185
|
>
|
|
168
186
|
{(ctx: PlotContext<T>) => (
|
|
169
187
|
<ZonedLineMarks
|
|
@@ -197,7 +215,22 @@ function ZonedLineMarks<T>({
|
|
|
197
215
|
const primary = visible[0]
|
|
198
216
|
// Memoized: the shared cursor re-renders every chart on every pointer frame, and this both
|
|
199
217
|
// walks the full series and clones an object per point.
|
|
200
|
-
const
|
|
218
|
+
const pts = useMemo(() => linePoints(primary, data), [primary, data])
|
|
219
|
+
|
|
220
|
+
// ONE guard for all three shapes below, covering two absences. A null value is a documented GAP
|
|
221
|
+
// (`ChartSeries.getValue`), and a non-positive value on a log axis maps to NaN via `yScale` —
|
|
222
|
+
// without `defined` the first is drawn as an interpolated straight line across a coverage hole
|
|
223
|
+
// and the second emits a NaN path command, which per SVG error handling blanks the ENTIRE path
|
|
224
|
+
// from that point on.
|
|
225
|
+
const defined = definedOn(yScale)
|
|
226
|
+
// ONE curve for all three shapes: the threshold band, the area fill and the line are the SAME
|
|
227
|
+
// series drawn three ways, so a step line over a monotone fill would be two different readings
|
|
228
|
+
// of one measurement.
|
|
229
|
+
const curve = curveFor(primary?.curve)
|
|
230
|
+
// Never reached with a null `__y`: d3's line/area generators call the position accessors only
|
|
231
|
+
// for points `defined` accepted. The `NaN` floor is a type-level one, and it can never paint at
|
|
232
|
+
// zero the way a `?? 0` would.
|
|
233
|
+
const yOf = (d: Pt<T>) => yScale(d.__y ?? NaN)
|
|
201
234
|
|
|
202
235
|
// Area is opt-in: pass a color token to get a cohesive single-hue fill under the line.
|
|
203
236
|
// (A neutral fill under the neutral line just reads as grey haze, so there is no default-on.)
|
|
@@ -208,16 +241,17 @@ function ZonedLineMarks<T>({
|
|
|
208
241
|
return (
|
|
209
242
|
<>
|
|
210
243
|
{thresholds.map((t, i) => (
|
|
211
|
-
<Threshold<
|
|
244
|
+
<Threshold<Pt<T>>
|
|
212
245
|
key={`thr-${i}`}
|
|
213
246
|
id={`${chartId}-thr-${i}`}
|
|
214
|
-
data={
|
|
247
|
+
data={pts}
|
|
248
|
+
defined={defined}
|
|
215
249
|
x={(d) => xScale(getX(d)) ?? 0}
|
|
216
250
|
y0={() => yScale(t.value)}
|
|
217
|
-
y1={
|
|
251
|
+
y1={yOf}
|
|
218
252
|
clipAboveTo={0}
|
|
219
253
|
clipBelowTo={yMax}
|
|
220
|
-
curve={
|
|
254
|
+
curve={curve}
|
|
221
255
|
belowAreaProps={{ fill: t.side === 'above' ? t.fill : 'transparent' }}
|
|
222
256
|
aboveAreaProps={{ fill: t.side === 'below' ? t.fill : 'transparent' }}
|
|
223
257
|
/>
|
|
@@ -228,27 +262,29 @@ function ZonedLineMarks<T>({
|
|
|
228
262
|
<defs>
|
|
229
263
|
<AreaGradient id={areaId} color={areaColor} />
|
|
230
264
|
</defs>
|
|
231
|
-
<AreaClosed<
|
|
232
|
-
data={
|
|
265
|
+
<AreaClosed<Pt<T>>
|
|
266
|
+
data={pts}
|
|
267
|
+
defined={defined}
|
|
233
268
|
x={(d) => xScale(getX(d)) ?? 0}
|
|
234
|
-
y={
|
|
269
|
+
y={yOf}
|
|
235
270
|
yScale={yScale}
|
|
236
|
-
curve={
|
|
271
|
+
curve={curve}
|
|
237
272
|
fill={areaFillUrl(areaId)}
|
|
238
273
|
/>
|
|
239
274
|
</>
|
|
240
275
|
)}
|
|
241
276
|
|
|
242
277
|
{primary && (
|
|
243
|
-
<LinePath<
|
|
244
|
-
data={
|
|
278
|
+
<LinePath<Pt<T>>
|
|
279
|
+
data={pts}
|
|
280
|
+
defined={defined}
|
|
245
281
|
x={(d) => xScale(getX(d)) ?? 0}
|
|
246
|
-
y={
|
|
282
|
+
y={yOf}
|
|
247
283
|
stroke={primary.color}
|
|
248
284
|
strokeWidth={primary.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH}
|
|
249
285
|
strokeDasharray={primary.dash === 'dashed' ? VX.dashArray : undefined}
|
|
250
286
|
strokeOpacity={primary.strokeOpacity ?? 1}
|
|
251
|
-
curve={
|
|
287
|
+
curve={curve}
|
|
252
288
|
/>
|
|
253
289
|
)}
|
|
254
290
|
</>
|
|
@@ -259,4 +295,8 @@ function ZonedLineMarks<T>({
|
|
|
259
295
|
* Hand-memoized: React Compiler does not process the shipped dist, so the hot ZonedLine kind is
|
|
260
296
|
* wrapped in `React.memo` to retain the auto-memoization it had as source (parity with Bars).
|
|
261
297
|
*/
|
|
262
|
-
|
|
298
|
+
const ZonedLineMemo = memo(ZonedLineInner)
|
|
299
|
+
// Without it every kind reads as `Memo` in React DevTools (audit A16) — a profiler flame
|
|
300
|
+
// graph of nine identically-named nodes names nothing.
|
|
301
|
+
ZonedLineMemo.displayName = 'ZonedLine'
|
|
302
|
+
export const ZonedLine = ZonedLineMemo as typeof ZonedLineInner
|
|
@@ -13,6 +13,7 @@ import { scaleLinear } from '@visx/scale'
|
|
|
13
13
|
import { VX } from '../../tokens'
|
|
14
14
|
import type { ChartMargin } from '../../tokens'
|
|
15
15
|
import { maxTextWidth } from '../utils/measure-text'
|
|
16
|
+
import { logTickValues, niceLogDomain } from './log-ticks'
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Distance from the plot edge to the near edge of a tick LABEL: visx's default `tickLength` (8)
|
|
@@ -24,6 +25,95 @@ const AXIS_TICK_GAP = 12
|
|
|
24
25
|
/** Line box of a single-line tick label at `fontPx`. */
|
|
25
26
|
const lineHeight = (fontPx: number): number => Math.ceil(fontPx * 1.35)
|
|
26
27
|
|
|
28
|
+
/**
|
|
29
|
+
* The line box split at the baseline. Only the DESCENT falls below it and only the ASCENT reaches
|
|
30
|
+
* back over the anchor, and a rotated label needs the two apart — its box is measured from the
|
|
31
|
+
* baseline point the axis anchors it at, not from a centred line box. The two ratios sum to
|
|
32
|
+
* {@link lineHeight}'s 1.35em, so nothing moves for the unrotated case.
|
|
33
|
+
*/
|
|
34
|
+
const DESCENT_RATIO = 0.3
|
|
35
|
+
const descent = (fontPx: number): number => fontPx * DESCENT_RATIO
|
|
36
|
+
const ascent = (fontPx: number): number => lineHeight(fontPx) - descent(fontPx)
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* visx's own `tickLength` (`@visx/axis`'s `Axis` default) and the extra drop `Ticks` applies to a
|
|
40
|
+
* bottom-axis label — `to.y + max(10, fontSize)`. Together they are the distance from the axis LINE
|
|
41
|
+
* to the tick label's BASELINE, which is where a rotated label's box is measured from.
|
|
42
|
+
*/
|
|
43
|
+
const AXIS_TICK_LENGTH = 8
|
|
44
|
+
const VISX_MIN_LABEL_FONT = 10
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The `dx`/`dy` nudge `primitives/Axes.tsx` paints a rotated tick label through — the d3 idiom
|
|
48
|
+
* that puts a 45° label under its tick's lower-left and centres a 90° one on its vertical line.
|
|
49
|
+
*
|
|
50
|
+
* It lives HERE, and the axis imports it, because it is the one number that must be in both
|
|
51
|
+
* places: the nudge was applied at paint and absent from the measure, so §1's measured-equals-
|
|
52
|
+
* painted law broke in exactly the rotated case §8 introduced (the first label crossed the SVG's
|
|
53
|
+
* left edge by 3.2px at 390 and 5.7px at 320, and every rotated label's descender row sat on the
|
|
54
|
+
* bottom clip line). Move a value here and the gutter moves with it.
|
|
55
|
+
*/
|
|
56
|
+
export const ROTATED_LABEL_OFFSET: Record<45 | 90, { dx: number; dy: number }> = {
|
|
57
|
+
45: { dx: -6, dy: 2 },
|
|
58
|
+
90: { dx: -4, dy: 4 },
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Breathing room between a rotated label's painted box and the SVG's own clip edge. One px reads
|
|
62
|
+
* as flush; two is the smallest gap that reads as deliberate. */
|
|
63
|
+
const ROTATED_CLEARANCE = 2
|
|
64
|
+
|
|
65
|
+
const rotatedOffset = (rotate: number): { dx: number; dy: number } =>
|
|
66
|
+
ROTATED_LABEL_OFFSET[rotate as 45 | 90] ?? { dx: 0, dy: 0 }
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* How far a rotated x label reaches LEFT of the plot's left edge, and how far BELOW the axis line —
|
|
70
|
+
* measured from the baseline point the axis anchors it at, through the same `dx`/`dy` the axis
|
|
71
|
+
* paints it with.
|
|
72
|
+
*
|
|
73
|
+
* `AxisBottomDate` anchors a rotated label at its right edge (`textAnchor: 'end'`) and rotates it
|
|
74
|
+
* counter-clockwise about that point, so the string runs down-and-to-the-LEFT from the tick it
|
|
75
|
+
* belongs to. The FIRST tick sits at the plot's left edge, so its label hangs into the left gutter;
|
|
76
|
+
* the LAST row of glyphs hangs below the axis. Rotating the label's box about its anchor gives both
|
|
77
|
+
* extents exactly:
|
|
78
|
+
*
|
|
79
|
+
* - left = `cos θ · (width + ascent) − dx` — zero at 90°, where the string runs straight down.
|
|
80
|
+
* - below = `tickLength + max(10, fontPx) + dy + sin θ · width + cos θ · descent`.
|
|
81
|
+
*
|
|
82
|
+
* Both carry {@link ROTATED_CLEARANCE} so the painted box clears the SVG's clip rather than
|
|
83
|
+
* touching it.
|
|
84
|
+
*/
|
|
85
|
+
export function rotatedLabelExtents(input: {
|
|
86
|
+
/** Width of the widest x tick label, already measured at the painted font. */
|
|
87
|
+
labelWidth: number
|
|
88
|
+
fontPx: number
|
|
89
|
+
rotate: number
|
|
90
|
+
}): { left: number; below: number } {
|
|
91
|
+
const { labelWidth, fontPx, rotate } = input
|
|
92
|
+
if (rotate === 0) return { left: 0, below: 0 }
|
|
93
|
+
const radians = (rotate * Math.PI) / 180
|
|
94
|
+
const cos = Math.abs(Math.cos(radians))
|
|
95
|
+
const sin = Math.abs(Math.sin(radians))
|
|
96
|
+
const { dx, dy } = rotatedOffset(rotate)
|
|
97
|
+
return {
|
|
98
|
+
left: cos * (labelWidth + ascent(fontPx)) - dx + ROTATED_CLEARANCE,
|
|
99
|
+
below:
|
|
100
|
+
AXIS_TICK_LENGTH +
|
|
101
|
+
Math.max(VISX_MIN_LABEL_FONT, fontPx) +
|
|
102
|
+
dy +
|
|
103
|
+
sin * labelWidth +
|
|
104
|
+
cos * descent(fontPx) +
|
|
105
|
+
ROTATED_CLEARANCE,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The grouped-thousands default for a log axis with no explicit `format` — parity with the linear
|
|
111
|
+
* branch's own `probe.tickFormat(ticks)`, which already groups (`"100,000"`). Unbounded fraction
|
|
112
|
+
* digits (rather than `toLocaleString`'s default of 3) so a sub-unit log tick (`1e-7`) still prints
|
|
113
|
+
* its digits instead of truncating to `"0"`.
|
|
114
|
+
*/
|
|
115
|
+
const LOG_TICK_FORMAT = new Intl.NumberFormat('en-US', { maximumFractionDigits: 20 })
|
|
116
|
+
|
|
27
117
|
export type AutoMarginInput = {
|
|
28
118
|
/** Left-axis tick labels, already formatted. */
|
|
29
119
|
left?: readonly string[]
|
|
@@ -33,8 +123,16 @@ export type AutoMarginInput = {
|
|
|
33
123
|
bottom?: readonly string[]
|
|
34
124
|
/** Degrees of counter-clockwise rotation applied to the x tick labels. Default 0. */
|
|
35
125
|
rotate?: number
|
|
36
|
-
/** Tick-label font size. Default `VX.axisFont`.
|
|
126
|
+
/** Tick-label font size. Default `VX.axisFont`. A phone-tier chart passes its own smaller size
|
|
127
|
+
* (`chartTierMetrics().axisFont`) — the measured label must be the painted label. */
|
|
37
128
|
fontPx?: number
|
|
129
|
+
/**
|
|
130
|
+
* Per-side FLOORS. Default `VX.margin`. The phone tier passes its tightened set
|
|
131
|
+
* (`chartTierMetrics().margin`) so a static 44px left gutter does not spend an eighth of a 360px
|
|
132
|
+
* chart on a three-character label. The law itself does not move: a side may still only ever
|
|
133
|
+
* grow past its floor.
|
|
134
|
+
*/
|
|
135
|
+
floor?: ChartMargin
|
|
38
136
|
/** Explicit per-side overrides — applied LAST, so an escape hatch always wins. */
|
|
39
137
|
override?: Partial<ChartMargin>
|
|
40
138
|
}
|
|
@@ -42,44 +140,50 @@ export type AutoMarginInput = {
|
|
|
42
140
|
/**
|
|
43
141
|
* Resolve the four margins from measured labels.
|
|
44
142
|
*
|
|
45
|
-
* Law, per side:
|
|
46
|
-
* - `left` — widest left label + gap, floored at `VX.margin.left`.
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
143
|
+
* Law, per side (the floors are `VX.margin` by default; a tier may tighten them via `floor`):
|
|
144
|
+
* - `left` — widest left label + gap, floored at `VX.margin.left`. When the x labels are ROTATED
|
|
145
|
+
* they also reach into this gutter, so the left side additionally clears their leftward
|
|
146
|
+
* extent — see {@link rotatedLabelExtents}.
|
|
147
|
+
* - `right` — with a right axis: widest right label + gap. Without one, and the x labels are NOT
|
|
148
|
+
* rotated: half the widest x label, so the LAST x tick (centered on the plot's right edge)
|
|
149
|
+
* cannot clip. Without one AND rotated: nothing — a rotated label is anchored at its right edge
|
|
150
|
+
* (`textAnchor: 'end'`, same as {@link rotatedLabelExtents}), so it hangs left of its tick, not
|
|
151
|
+
* right, and reserving half its width would pad a side nothing paints into. Every case is
|
|
152
|
+
* floored at `VX.margin.right`.
|
|
153
|
+
* - `bottom` — one label line + gap; when ROTATED, the label's measured drop below the axis line
|
|
154
|
+
* ({@link rotatedLabelExtents}) instead. Floored at `VX.margin.bottom`.
|
|
52
155
|
* - `top` — `VX.margin.top`. Nothing measures into it; a chart that draws into the top gutter
|
|
53
156
|
* passes an override.
|
|
54
157
|
*/
|
|
55
158
|
export function autoMargin(input: AutoMarginInput = {}): ChartMargin {
|
|
56
159
|
const fontPx = input.fontPx ?? VX.axisFont
|
|
57
|
-
const { left = [], right = [], bottom = [], rotate = 0, override } = input
|
|
160
|
+
const { left = [], right = [], bottom = [], rotate = 0, floor = VX.margin, override } = input
|
|
58
161
|
|
|
59
162
|
const leftWidth = maxTextWidth(left, fontPx)
|
|
60
163
|
const rightWidth = maxTextWidth(right, fontPx)
|
|
61
164
|
const bottomWidth = maxTextWidth(bottom, fontPx)
|
|
62
165
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
: Math.ceil(
|
|
68
|
-
Math.abs(bottomWidth * Math.sin(radians)) +
|
|
69
|
-
Math.abs(lineHeight(fontPx) * Math.cos(radians)),
|
|
70
|
-
)
|
|
166
|
+
// Measured EXACTLY as painted: through the same `dx`/`dy` `primitives/Axes.tsx` nudges a rotated
|
|
167
|
+
// label by, and from the baseline the axis anchors it at.
|
|
168
|
+
const rotated = rotatedLabelExtents({ labelWidth: bottomWidth, fontPx, rotate })
|
|
169
|
+
const bottomExtent = rotate === 0 ? lineHeight(fontPx) + AXIS_TICK_GAP : rotated.below
|
|
71
170
|
|
|
72
171
|
return {
|
|
73
|
-
top: override?.top ??
|
|
172
|
+
top: override?.top ?? floor.top,
|
|
74
173
|
right:
|
|
75
174
|
override?.right ??
|
|
76
175
|
Math.ceil(
|
|
77
|
-
Math.max(
|
|
176
|
+
Math.max(
|
|
177
|
+
floor.right,
|
|
178
|
+
right.length > 0 ? rightWidth + AXIS_TICK_GAP : rotate === 0 ? bottomWidth / 2 : 0,
|
|
179
|
+
),
|
|
78
180
|
),
|
|
79
|
-
bottom: override?.bottom ?? Math.ceil(Math.max(
|
|
181
|
+
bottom: override?.bottom ?? Math.ceil(Math.max(floor.bottom, bottomExtent)),
|
|
80
182
|
left:
|
|
81
183
|
override?.left ??
|
|
82
|
-
Math.ceil(
|
|
184
|
+
Math.ceil(
|
|
185
|
+
Math.max(floor.left, left.length > 0 ? leftWidth + AXIS_TICK_GAP : 0, rotated.left),
|
|
186
|
+
),
|
|
83
187
|
}
|
|
84
188
|
}
|
|
85
189
|
|
|
@@ -99,7 +203,16 @@ export function probeAxisLabels(opts: {
|
|
|
99
203
|
format?: (v: number) => string
|
|
100
204
|
/** Must match the real scale's `nice` — niceing changes which ticks exist. */
|
|
101
205
|
nice?: boolean
|
|
206
|
+
/** `'log'` measures through {@link logTickValues} instead of a linear probe scale — the same
|
|
207
|
+
* helper the axis paints from (CHARTS-SPEC §1: measured labels == painted labels). Default
|
|
208
|
+
* `'linear'`. */
|
|
209
|
+
scale?: 'linear' | 'log'
|
|
102
210
|
}): { labels: string[]; format: (v: number) => string } {
|
|
211
|
+
if (opts.scale === 'log') {
|
|
212
|
+
const domain = opts.nice === true ? niceLogDomain(opts.domain) : opts.domain
|
|
213
|
+
const format = opts.format ?? ((v: number) => LOG_TICK_FORMAT.format(v))
|
|
214
|
+
return { labels: logTickValues(domain, opts.ticks).map(format), format }
|
|
215
|
+
}
|
|
103
216
|
const probe = scaleLinear<number>({
|
|
104
217
|
domain: opts.domain,
|
|
105
218
|
range: [1, 0],
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 1-2-5 mantissa tick law for a log axis (`docs/CHARTS-SPEC.md` §2).
|
|
3
|
+
*
|
|
4
|
+
* d3's own `scaleLog().ticks()` multiplies the mantissa density by the number of decades the
|
|
5
|
+
* domain spans, so a wide financial range (e.g. $10k–$300k) reads `$316,228 / $100,000 / $31,623 /
|
|
6
|
+
* $10,000` — every finance reference instead ticks a log price axis at `{1, 2, 5} × 10^n`
|
|
7
|
+
* (`$10,000 · $20,000 · $50,000 · $100,000`). Pure, no visx dependency, so both the measured
|
|
8
|
+
* (`probeAxisLabels`) and painted (`CartesianChart`) sides can share the exact same tick list.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Escalating mantissa sets: the strict {1, 2, 5} law first, then progressively denser sets used
|
|
13
|
+
* only when the stricter one leaves too few in-domain candidates to read — a short span (a
|
|
14
|
+
* one-year BTC window, say, $58k–$139k) collapses {1, 2, 5} to a single tick, which is
|
|
15
|
+
* unreadable. Each set is ascending and never crosses a decade boundary within itself
|
|
16
|
+
* (`9 × 10^k < 1 × 10^(k+1)`), so the flatMap output stays sorted with no explicit sort.
|
|
17
|
+
*/
|
|
18
|
+
const MANTISSA_SETS = [
|
|
19
|
+
[1, 2, 5],
|
|
20
|
+
[1, 1.5, 2, 3, 4, 5, 7],
|
|
21
|
+
[1, 1.5, 2, 2.5, 3, 4, 5, 6, 7, 8, 9],
|
|
22
|
+
] as const
|
|
23
|
+
|
|
24
|
+
/** Below this many in-domain candidates, escalate to the next denser mantissa set. */
|
|
25
|
+
const DENSIFY_BELOW = 4
|
|
26
|
+
|
|
27
|
+
/** Every base-10 exponent whose decade touches `[min, max]`. */
|
|
28
|
+
function decadeExponents(min: number, max: number): number[] {
|
|
29
|
+
const lo = Math.floor(Math.log10(min))
|
|
30
|
+
const hi = Math.ceil(Math.log10(max))
|
|
31
|
+
const exponents: number[] = []
|
|
32
|
+
for (let k = lo; k <= hi; k++) exponents.push(k)
|
|
33
|
+
return exponents
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Thin an ascending, over-budget value list toward `ticks`, keeping both extremes — a stride
|
|
38
|
+
* derived from the budget (`Math.ceil(length / ticks)`) rather than a fixed 2, so the result
|
|
39
|
+
* actually tracks `ticks` instead of only ever halving regardless of how far over budget the input
|
|
40
|
+
* is. May return one more than `ticks` when the last value doesn't land on the stride (an even
|
|
41
|
+
* decade count, say): keeping the axis's top labeled matters more than the exact count.
|
|
42
|
+
*/
|
|
43
|
+
function thinToBudget(values: number[], ticks: number): number[] {
|
|
44
|
+
if (values.length <= ticks) return values
|
|
45
|
+
const stride = Math.ceil(values.length / ticks)
|
|
46
|
+
const thinned = values.filter((_, i) => i % stride === 0)
|
|
47
|
+
const last = values[values.length - 1] as number
|
|
48
|
+
return thinned[thinned.length - 1] === last ? thinned : [...thinned, last]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Every `{1, 2, 5} × 10^k` value for every decade touching `[min, max]`, filtered to the domain —
|
|
53
|
+
* escalating through {@link MANTISSA_SETS} while a set leaves fewer than {@link DENSIFY_BELOW}
|
|
54
|
+
* candidates (a short span collapses the strict law to one tick). The exact same list is what
|
|
55
|
+
* `probeAxisLabels` measures and what `CartesianChart` paints, so the two can never disagree.
|
|
56
|
+
* An over-budget result collapses to whole decades only when the decades ALONE form a readable
|
|
57
|
+
* axis ({@link DENSIFY_BELOW}+ in-domain); otherwise it is thinned by a budget-derived stride
|
|
58
|
+
* (may exceed `ticks` by one — see {@link thinToBudget}). Collapsing to decades unconditionally
|
|
59
|
+
* is the bug this ordering exists to prevent: a 4-year BTC window ($15.5k–$139k) holds ONE whole
|
|
60
|
+
* decade, so the collapse produced a single-tick axis. Never returns a non-positive value; a
|
|
61
|
+
* non-positive or inverted domain (a log axis has no zero and no reversed extent) returns `[]`.
|
|
62
|
+
*/
|
|
63
|
+
export function logTickValues([min, max]: readonly [number, number], ticks: number): number[] {
|
|
64
|
+
if (min <= 0 || max <= 0 || min >= max) return []
|
|
65
|
+
|
|
66
|
+
const exponents = decadeExponents(min, max)
|
|
67
|
+
const inDomain = (v: number): boolean => v >= min && v <= max
|
|
68
|
+
const collect = (mantissas: readonly number[]): number[] =>
|
|
69
|
+
exponents.flatMap((k) => mantissas.map((m) => m * 10 ** k)).filter(inDomain)
|
|
70
|
+
|
|
71
|
+
let resolved: number[] = []
|
|
72
|
+
for (const mantissas of MANTISSA_SETS) {
|
|
73
|
+
resolved = collect(mantissas)
|
|
74
|
+
if (resolved.length >= DENSIFY_BELOW) break
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (resolved.length <= ticks) return resolved
|
|
78
|
+
|
|
79
|
+
const decades = exponents.map((k) => 10 ** k).filter(inDomain)
|
|
80
|
+
if (decades.length >= DENSIFY_BELOW) return thinToBudget(decades, ticks)
|
|
81
|
+
|
|
82
|
+
return thinToBudget(resolved, ticks)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Round a domain outward to the nearest enclosing power-of-10 bounds — the log analog of
|
|
86
|
+
* `scale.nice()`, used to keep `probeAxisLabels` (measurement) and the real niced scale
|
|
87
|
+
* (rendering) computing ticks from the same rounded domain. */
|
|
88
|
+
export function niceLogDomain([min, max]: readonly [number, number]): [number, number] {
|
|
89
|
+
return [10 ** Math.floor(Math.log10(min)), 10 ** Math.ceil(Math.log10(max))]
|
|
90
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { AxisBottom, AxisLeft, AxisRight } from '@visx/axis'
|
|
2
2
|
import type { AxisScale, TickFormatter } from '@visx/axis'
|
|
3
3
|
import { VX } from '../../tokens'
|
|
4
|
+
import { ROTATED_LABEL_OFFSET } from '../layout/auto-margin'
|
|
4
5
|
import { fmtAxisDate } from '../utils/format'
|
|
6
|
+
import { useChartTierMetrics } from './chart-tier'
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Tick label font — mono, per `docs/DESIGN-SPEC.md` §5 ("ticks mono 10.5px faint"). Not a `VX.*`
|
|
@@ -10,7 +12,10 @@ import { fmtAxisDate } from '../utils/format'
|
|
|
10
12
|
*/
|
|
11
13
|
const TICK_FONT_FAMILY = 'var(--basalt-font-mono)'
|
|
12
14
|
|
|
13
|
-
/** Themed left numeric axis — baked-in theme colors + font size.
|
|
15
|
+
/** Themed left numeric axis — baked-in theme colors + font size. The tick font tracks the ambient
|
|
16
|
+
* chart tier (`docs/CHARTS-SPEC.md` §8); a caller measuring its own gutter must measure at the
|
|
17
|
+
* SAME size (`chartTierMetrics().axisFont` into `autoMargin`'s `fontPx`), or the measured label
|
|
18
|
+
* and the painted one stop being the same string's width. */
|
|
14
19
|
export function AxisLeftNumeric({
|
|
15
20
|
scale,
|
|
16
21
|
numTicks = 5,
|
|
@@ -20,6 +25,7 @@ export function AxisLeftNumeric({
|
|
|
20
25
|
numTicks?: number
|
|
21
26
|
tickFormat?: TickFormatter<number>
|
|
22
27
|
}) {
|
|
28
|
+
const { axisFont } = useChartTierMetrics()
|
|
23
29
|
return (
|
|
24
30
|
<AxisLeft
|
|
25
31
|
scale={scale}
|
|
@@ -28,7 +34,7 @@ export function AxisLeftNumeric({
|
|
|
28
34
|
tickLabelProps={{
|
|
29
35
|
fill: VX.faint,
|
|
30
36
|
fontFamily: TICK_FONT_FAMILY,
|
|
31
|
-
fontSize:
|
|
37
|
+
fontSize: axisFont,
|
|
32
38
|
dx: -4,
|
|
33
39
|
}}
|
|
34
40
|
stroke={VX.surface.border}
|
|
@@ -50,6 +56,7 @@ export function AxisRightNumeric({
|
|
|
50
56
|
numTicks?: number
|
|
51
57
|
tickFormat?: TickFormatter<number>
|
|
52
58
|
}) {
|
|
59
|
+
const { axisFont } = useChartTierMetrics()
|
|
53
60
|
return (
|
|
54
61
|
<AxisRight
|
|
55
62
|
left={left}
|
|
@@ -59,7 +66,7 @@ export function AxisRightNumeric({
|
|
|
59
66
|
tickLabelProps={{
|
|
60
67
|
fill: VX.faint,
|
|
61
68
|
fontFamily: TICK_FONT_FAMILY,
|
|
62
|
-
fontSize:
|
|
69
|
+
fontSize: axisFont,
|
|
63
70
|
dx: 4,
|
|
64
71
|
}}
|
|
65
72
|
stroke={VX.surface.border}
|
|
@@ -68,12 +75,23 @@ export function AxisRightNumeric({
|
|
|
68
75
|
)
|
|
69
76
|
}
|
|
70
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Nudge a rotated tick label back onto its tick. Both are the d3 idiom for the angle: a 45° label
|
|
80
|
+
* hangs from the tick's lower-left, a 90° one is centred on the tick's vertical line.
|
|
81
|
+
*
|
|
82
|
+
* Imported, never re-declared: `autoMargin` measures the gutter THROUGH this same nudge
|
|
83
|
+
* (`rotatedLabelExtents`), and a second copy here is exactly how the painted label came to sit
|
|
84
|
+
* 6px left of the box the measurement had reserved (`docs/CHARTS-SPEC.md` §1).
|
|
85
|
+
*/
|
|
86
|
+
const ROTATED_OFFSET = ROTATED_LABEL_OFFSET
|
|
87
|
+
|
|
71
88
|
/** Themed bottom date axis — baked-in smartTicks + DD.MM formatting. */
|
|
72
89
|
export function AxisBottomDate({
|
|
73
90
|
scale,
|
|
74
91
|
top,
|
|
75
92
|
tickValues,
|
|
76
93
|
tickFormat = fmtAxisDate,
|
|
94
|
+
rotate,
|
|
77
95
|
}: {
|
|
78
96
|
scale: AxisScale
|
|
79
97
|
top: number
|
|
@@ -83,7 +101,15 @@ export function AxisBottomDate({
|
|
|
83
101
|
* tick to the same label.
|
|
84
102
|
*/
|
|
85
103
|
tickFormat?: TickFormatter<string>
|
|
104
|
+
/**
|
|
105
|
+
* Tilt each tick label counter-clockwise by 45° or 90°, anchored at its right edge — the answer
|
|
106
|
+
* to labels too wide to sit side by side. The caller owns the deepened bottom gutter it needs
|
|
107
|
+
* (`autoMargin({ rotate })`, `docs/CHARTS-SPEC.md` §1); this only paints them.
|
|
108
|
+
*/
|
|
109
|
+
rotate?: 45 | 90
|
|
86
110
|
}) {
|
|
111
|
+
const { axisFont } = useChartTierMetrics()
|
|
112
|
+
const rotated = rotate === undefined ? undefined : ROTATED_OFFSET[rotate]
|
|
87
113
|
return (
|
|
88
114
|
<AxisBottom
|
|
89
115
|
top={top}
|
|
@@ -93,8 +119,10 @@ export function AxisBottomDate({
|
|
|
93
119
|
tickLabelProps={{
|
|
94
120
|
fill: VX.faint,
|
|
95
121
|
fontFamily: TICK_FONT_FAMILY,
|
|
96
|
-
fontSize:
|
|
97
|
-
textAnchor: 'middle',
|
|
122
|
+
fontSize: axisFont,
|
|
123
|
+
textAnchor: rotated === undefined ? 'middle' : 'end',
|
|
124
|
+
...(rotate !== undefined && { angle: -rotate }),
|
|
125
|
+
...(rotated !== undefined && { dx: rotated.dx, dy: rotated.dy }),
|
|
98
126
|
}}
|
|
99
127
|
stroke={VX.surface.border}
|
|
100
128
|
tickStroke={VX.surface.border}
|