basalt-ui 1.28.0 → 1.29.1
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 +12 -19
- package/CHANGELOG.md +23 -0
- package/MIGRATING.md +171 -7
- package/README.md +66 -105
- package/agent/rules/basalt-batteries.md +60 -183
- package/agent/rules/basalt-charts.md +56 -75
- package/agent/rules/basalt-controls.md +38 -69
- package/agent/rules/basalt-mantine.md +58 -103
- package/agent/rules/basalt-state.md +42 -60
- package/agent/rules/basalt-tokens.md +46 -67
- package/agent/skills/basalt-app/SKILL.md +2 -0
- package/agent/templates/CLAUDE-block.md.tpl +14 -14
- package/agent/templates/query-client.ts.tpl +1 -1
- package/configs/oxlint-plugin.js +84 -254
- package/configs/oxlint-plugin.test.ts +23 -266
- package/configs/oxlint.json +0 -2
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +7 -4
- package/dist/agent/coalesce.js +1 -1
- package/dist/agent/merge.js +1 -1
- package/dist/agent/transport.d.ts +13 -2
- package/dist/agent/transport.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.d.ts +12 -1
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.js +20 -6
- package/dist/agent-chat/index.d.ts +1 -1
- package/dist/agent-chat/index.d.ts.map +1 -1
- package/dist/agent-chat/relative-time.js +1 -1
- package/dist/agent-chat/thread-detail-panel.js +1 -1
- package/dist/agent-chat/thread-feed-row.d.ts +32 -7
- package/dist/agent-chat/thread-feed-row.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed-row.js +121 -86
- package/dist/agent-chat/thread-feed.d.ts +11 -1
- package/dist/agent-chat/thread-feed.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed.js +10 -6
- package/dist/agent-chat/thread-message.js +1 -1
- package/dist/agent-chat/virtualize.d.ts +39 -0
- package/dist/agent-chat/virtualize.d.ts.map +1 -1
- package/dist/agent-chat/virtualize.js +15 -0
- package/dist/charts/index.d.ts +3 -3
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +8 -4
- package/dist/charts/kinds/BandStrip.js +1 -1
- package/dist/charts/kinds/Bars.d.ts +1 -3
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.js +1 -1
- package/dist/charts/kinds/DualPanel.d.ts +3 -1
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.js +1 -1
- package/dist/charts/kinds/StackedArea.js +1 -1
- package/dist/charts/kinds/ZonedLine.d.ts +1 -3
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/charts/primitives/Axes.d.ts +21 -2
- package/dist/charts/primitives/Axes.d.ts.map +1 -1
- package/dist/charts/primitives/Axes.js +34 -2
- package/dist/charts/primitives/ChartCard.d.ts +20 -4
- package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.js +62 -33
- package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
- package/dist/charts/primitives/ChartFrame.js +8 -1
- package/dist/charts/primitives/ChartPending.d.ts +12 -6
- package/dist/charts/primitives/ChartPending.d.ts.map +1 -1
- package/dist/charts/primitives/ChartPending.js +1 -1
- package/dist/charts/utils/format.d.ts +5 -92
- package/dist/charts/utils/format.d.ts.map +1 -1
- package/dist/charts/utils/format.js +10 -80
- package/dist/cli/audit-allows.d.ts +24 -0
- package/dist/cli/audit-allows.d.ts.map +1 -0
- package/dist/cli/audit-allows.js +240 -0
- package/dist/cli/check-theme.d.ts +10 -0
- package/dist/cli/check-theme.d.ts.map +1 -0
- package/dist/cli/check-theme.js +139 -0
- package/dist/cli/doctor.d.ts +47 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +197 -0
- package/dist/cli/guard-hook.d.ts +9 -0
- package/dist/cli/guard-hook.d.ts.map +1 -0
- package/dist/cli/guard-hook.js +93 -0
- package/dist/cli/help.d.ts +9 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +53 -0
- package/dist/cli/index.d.ts +360 -270
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +85 -1901
- package/dist/cli/init.d.ts +4 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +165 -0
- package/dist/cli/sync.d.ts +43 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +206 -0
- package/dist/cli/tokens-css.d.ts +51 -0
- package/dist/cli/tokens-css.d.ts.map +1 -0
- package/dist/cli/tokens-css.js +165 -0
- package/dist/commands/define-commands.js +1 -1
- package/dist/commands/define-overlays.js +1 -1
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +6 -0
- package/dist/commands/overlays-mount.d.ts +7 -9
- package/dist/commands/overlays-mount.d.ts.map +1 -1
- package/dist/commands/shell-bridge.d.ts +57 -0
- package/dist/commands/shell-bridge.d.ts.map +1 -0
- package/dist/commands/shell-bridge.js +32 -0
- package/dist/common/errors.d.ts +35 -0
- package/dist/common/errors.d.ts.map +1 -1
- package/dist/common/errors.js +29 -1
- package/dist/common/index.d.ts +2 -0
- package/dist/common/index.d.ts.map +1 -1
- package/dist/common/index.js +6 -0
- package/dist/common/is-dev.d.ts.map +1 -0
- package/dist/{motion/index.d.ts → common/motion.d.ts} +1 -1
- package/dist/common/motion.d.ts.map +1 -0
- package/dist/common/props.d.ts +1 -1
- package/dist/common/props.d.ts.map +1 -1
- package/dist/common/validate.js +1 -1
- package/dist/content/markdown.d.ts +3 -4
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +1 -4
- package/dist/controls/actions.d.ts +1 -1
- package/dist/controls/actions.d.ts.map +1 -1
- package/dist/controls/panel-row.js +1 -1
- package/dist/controls/range-filter.js +1 -1
- package/dist/dashboard/delta-badge.d.ts +18 -10
- package/dist/dashboard/delta-badge.d.ts.map +1 -1
- package/dist/dashboard/delta-badge.js +33 -1
- package/dist/dashboard/empty-state.d.ts +1 -4
- package/dist/dashboard/empty-state.d.ts.map +1 -1
- package/dist/dashboard/empty-state.js +1 -2
- package/dist/dashboard/index.d.ts +4 -2
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +7 -1
- package/dist/dashboard/query-state.d.ts +4 -13
- package/dist/dashboard/query-state.d.ts.map +1 -1
- package/dist/dashboard/query-state.js +4 -7
- package/dist/{section → dashboard}/section.d.ts +2 -2
- package/dist/{section → dashboard}/section.d.ts.map +1 -1
- package/dist/{section → dashboard}/section.js +2 -2
- package/dist/dashboard/settings-section.d.ts +1 -1
- package/dist/dashboard/settings-section.d.ts.map +1 -1
- package/dist/dashboard/settings-section.js +1 -1
- package/dist/dashboard/stat-card.d.ts +1 -1
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +1 -1
- package/dist/dashboard/widget-header.d.ts.map +1 -0
- package/dist/data/data-table.js +2 -2
- package/dist/data/table.d.ts +1 -1
- package/dist/data/table.d.ts.map +1 -1
- package/dist/data/table.js +2 -16
- package/dist/data/virtual.d.ts +3 -3
- package/dist/dev-dock.d.ts +26 -0
- package/dist/dev-dock.d.ts.map +1 -0
- package/dist/dev-dock.js +85 -0
- package/dist/format/date.d.ts +62 -0
- package/dist/format/date.d.ts.map +1 -0
- package/dist/format/date.js +106 -0
- package/dist/format/index.d.ts +39 -0
- package/dist/format/index.d.ts.map +1 -0
- package/dist/format/index.js +54 -0
- package/dist/format/measure.d.ts +15 -0
- package/dist/format/measure.d.ts.map +1 -0
- package/dist/format/measure.js +16 -0
- package/dist/format/number.d.ts +69 -0
- package/dist/format/number.d.ts.map +1 -0
- package/dist/format/number.js +62 -0
- package/dist/format/shared.d.ts +27 -0
- package/dist/format/shared.d.ts.map +1 -0
- package/dist/format/shared.js +29 -0
- package/dist/forms/field.d.ts +4 -20
- package/dist/forms/field.d.ts.map +1 -1
- package/dist/forms/field.js +0 -4
- package/dist/forms/form-layout.d.ts +1 -1
- package/dist/forms/form-layout.d.ts.map +1 -1
- package/dist/forms/form-layout.js +1 -1
- package/dist/forms/index.d.ts +1 -1
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +1 -2
- package/dist/forms/use-form-submit.d.ts +1 -1
- package/dist/forms/use-form-submit.js +1 -1
- package/dist/guard/index.d.ts +2 -9
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +53 -32
- package/dist/guard/types.d.ts +8 -10
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +16 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -29
- package/dist/notifications/index.d.ts +5 -5
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +0 -2
- package/dist/notifications/mount-guard.d.ts.map +1 -1
- package/dist/notifications/mount-guard.js +2 -2
- package/dist/provider/connectivity-indicator.d.ts.map +1 -0
- package/dist/{connectivity → provider}/connectivity-provider.d.ts +1 -1
- package/dist/provider/connectivity-provider.d.ts.map +1 -0
- package/dist/{connectivity/types.d.ts → provider/connectivity-types.d.ts} +1 -1
- package/dist/provider/connectivity-types.d.ts.map +1 -0
- package/dist/provider/error-fallback.module.css +21 -0
- package/dist/provider/error-fallback.module.css.d.ts +9 -0
- package/dist/provider/index.d.ts +20 -36
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +42 -32
- package/dist/provider/lab-theme.js +1 -1
- package/dist/provider/use-connectivity.d.ts +3 -0
- package/dist/provider/use-connectivity.d.ts.map +1 -0
- package/dist/query-client.d.ts +67 -0
- package/dist/query-client.d.ts.map +1 -0
- package/dist/query-client.js +35 -0
- package/dist/{query/devtools.d.ts → query-devtools.d.ts} +2 -2
- package/dist/query-devtools.d.ts.map +1 -0
- package/dist/register.d.ts +17 -3
- package/dist/register.d.ts.map +1 -1
- package/dist/router-tanstack/index.d.ts +4 -7
- package/dist/router-tanstack/index.d.ts.map +1 -1
- package/dist/router-tanstack/index.js +1 -9
- package/dist/router-tanstack/nav.d.ts +1 -1
- package/dist/router-tanstack/nav.d.ts.map +1 -1
- package/dist/router-tanstack/search-store.d.ts +3 -6
- package/dist/router-tanstack/search-store.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.d.ts +1 -1
- package/dist/router-tanstack/use-nav.d.ts.map +1 -1
- package/dist/shell/app-breadcrumbs.d.ts +1 -1
- package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
- package/dist/shell/app-main.module.css +11 -0
- package/dist/shell/app-mobile-nav.d.ts +1 -1
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +24 -2
- package/dist/shell/app-sidebar.d.ts +1 -1
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +31 -2
- package/dist/shell/app-sidebar.module.css +10 -0
- package/dist/shell/index.d.ts +10 -4
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +13 -17
- package/dist/shell/mobile-nav-model.d.ts +1 -1
- package/dist/shell/mobile-nav-model.d.ts.map +1 -1
- package/dist/{nav/types.d.ts → shell/nav-types.d.ts} +1 -1
- package/dist/shell/nav-types.d.ts.map +1 -0
- package/dist/shell/page-aside.d.ts.map +1 -1
- package/dist/shell/page-aside.js +2 -29
- package/dist/shell/page-title.d.ts +14 -0
- package/dist/shell/page-title.d.ts.map +1 -0
- package/dist/shell/page-title.js +25 -0
- package/dist/shell/page-title.module.css +33 -0
- package/dist/shell/page-title.module.css.d.ts +11 -0
- package/dist/shell/sidebar-block-model.d.ts +1 -1
- package/dist/shell/sidebar-block-model.d.ts.map +1 -1
- package/dist/shell/sidebar-blocks.d.ts +1 -1
- package/dist/shell/sidebar-blocks.d.ts.map +1 -1
- package/dist/shell/use-breakpoint.d.ts +11 -0
- package/dist/shell/use-breakpoint.d.ts.map +1 -0
- package/dist/shell/use-breakpoint.js +33 -0
- package/dist/state/fields.d.ts +3 -19
- package/dist/state/fields.d.ts.map +1 -1
- package/dist/state/fields.js +6 -16
- package/dist/styles.css +36 -0
- package/dist/surfaces.d.ts +18 -41
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +48 -60
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/{theme-toggle/index.d.ts → theme/theme-toggle.d.ts} +1 -1
- package/dist/theme/theme-toggle.d.ts.map +1 -0
- package/dist/{theme-toggle/index.js → theme/theme-toggle.js} +1 -1
- package/dist/tokens/index.d.ts +1 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +10 -0
- package/dist/tokens/palette.d.ts +12 -0
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +13 -1
- package/dist/tokens.css +1 -0
- package/llms.txt +9 -24
- package/package.json +12 -16
- package/src/agent/ai-sdk-transport.ts +11 -4
- package/src/agent/coalesce.ts +1 -1
- package/src/agent/merge.ts +1 -1
- package/src/agent/transport.ts +15 -2
- package/src/agent/use-agent-thread-runs.ts +65 -15
- package/src/agent-chat/index.ts +6 -4
- package/src/agent-chat/relative-time.ts +1 -1
- package/src/agent-chat/thread-detail-panel.tsx +1 -1
- package/src/agent-chat/thread-feed-row.tsx +105 -30
- package/src/agent-chat/thread-feed.tsx +51 -25
- package/src/agent-chat/thread-message.tsx +1 -1
- package/src/agent-chat/virtualize.ts +48 -0
- package/src/charts/index.ts +7 -10
- package/src/charts/kinds/BandStrip.tsx +1 -1
- package/src/charts/kinds/Bars.tsx +2 -5
- package/src/charts/kinds/DualPanel.tsx +4 -3
- package/src/charts/kinds/StackedArea.tsx +1 -1
- package/src/charts/kinds/ZonedLine.tsx +1 -4
- package/src/charts/primitives/Axes.tsx +49 -0
- package/src/charts/primitives/ChartCard.tsx +49 -6
- package/src/charts/primitives/ChartFrame.tsx +5 -1
- package/src/charts/primitives/ChartPending.tsx +14 -8
- package/src/charts/utils/format.ts +17 -186
- package/src/cli/audit-allows.ts +371 -0
- package/src/cli/check-theme.ts +197 -0
- package/src/cli/doctor.ts +331 -0
- package/src/cli/guard-hook.ts +115 -0
- package/src/cli/help.ts +101 -0
- package/src/cli/index.ts +269 -3439
- package/src/cli/init.ts +247 -0
- package/src/cli/sync.ts +324 -0
- package/src/cli/tokens-css.ts +252 -0
- package/src/commands/define-commands.ts +1 -1
- package/src/commands/define-overlays.ts +1 -1
- package/src/commands/index.ts +10 -1
- package/src/commands/overlays-mount.tsx +8 -10
- package/src/commands/shell-bridge.ts +86 -0
- package/src/common/errors.ts +70 -0
- package/src/common/index.ts +2 -0
- package/src/common/props.ts +1 -1
- package/src/common/validate.ts +1 -1
- package/src/content/markdown.tsx +4 -8
- package/src/controls/actions.tsx +1 -1
- package/src/controls/panel-row.tsx +1 -1
- package/src/controls/range-filter.tsx +1 -1
- package/src/dashboard/delta-badge.tsx +74 -7
- package/src/dashboard/empty-state.tsx +2 -6
- package/src/dashboard/index.ts +11 -2
- package/src/dashboard/query-state.tsx +5 -18
- package/src/{section → dashboard}/section.tsx +4 -4
- package/src/dashboard/settings-section.tsx +2 -2
- package/src/dashboard/stat-card.tsx +2 -2
- package/src/data/data-table.tsx +3 -3
- package/src/data/table.ts +6 -25
- package/src/data/virtual-list.tsx +1 -1
- package/src/data/virtual.ts +3 -3
- package/src/dev-dock.tsx +162 -0
- package/src/format/date.ts +184 -0
- package/src/format/index.ts +69 -0
- package/src/format/measure.ts +31 -0
- package/src/format/number.ts +129 -0
- package/src/format/shared.ts +63 -0
- package/src/forms/field.ts +4 -24
- package/src/forms/form-layout.tsx +2 -2
- package/src/forms/index.ts +1 -2
- package/src/forms/use-form-submit.ts +2 -2
- package/src/guard/index.ts +80 -69
- package/src/guard/types.ts +7 -10
- package/src/index.ts +38 -29
- package/src/notifications/index.ts +5 -7
- package/src/notifications/mount-guard.ts +7 -9
- package/src/{connectivity → provider}/connectivity-indicator.tsx +1 -1
- package/src/{connectivity → provider}/connectivity-provider.tsx +1 -1
- package/src/provider/error-fallback.module.css +21 -0
- package/src/provider/error-fallback.module.css.d.ts +9 -0
- package/src/provider/index.tsx +71 -71
- package/src/provider/lab-theme.ts +1 -1
- package/src/{connectivity → provider}/use-connectivity.ts +3 -3
- package/src/query-client.ts +105 -0
- package/src/{query/devtools.tsx → query-devtools.tsx} +5 -4
- package/src/register.ts +20 -4
- package/src/router-tanstack/index.ts +4 -15
- package/src/router-tanstack/nav.ts +1 -1
- package/src/router-tanstack/search-store.ts +3 -4
- package/src/router-tanstack/use-nav.ts +1 -1
- package/src/shell/app-breadcrumbs.tsx +1 -1
- package/src/shell/app-main.module.css +11 -0
- package/src/shell/app-mobile-nav.tsx +28 -1
- package/src/shell/app-sidebar.module.css +10 -0
- package/src/shell/app-sidebar.tsx +31 -2
- package/src/shell/index.tsx +23 -28
- package/src/shell/mobile-nav-model.ts +1 -1
- package/src/shell/page-aside.tsx +2 -52
- package/src/shell/page-title.module.css +33 -0
- package/src/shell/page-title.module.css.d.ts +11 -0
- package/src/shell/page-title.tsx +57 -0
- package/src/shell/sidebar-block-model.ts +1 -1
- package/src/shell/sidebar-blocks.tsx +1 -1
- package/src/shell/use-breakpoint.ts +73 -0
- package/src/state/fields.ts +7 -43
- package/src/styles.css +36 -0
- package/src/surfaces.ts +47 -61
- package/src/theme/index.ts +7 -0
- package/src/{theme-toggle/index.tsx → theme/theme-toggle.tsx} +1 -1
- package/src/tokens/index.ts +10 -0
- package/src/tokens/palette.ts +12 -0
- package/dist/connectivity/connectivity-indicator.d.ts.map +0 -1
- package/dist/connectivity/connectivity-provider.d.ts.map +0 -1
- package/dist/connectivity/index.d.ts +0 -14
- package/dist/connectivity/index.d.ts.map +0 -1
- package/dist/connectivity/index.js +0 -8
- package/dist/connectivity/types.d.ts.map +0 -1
- package/dist/connectivity/use-connectivity.d.ts +0 -3
- package/dist/connectivity/use-connectivity.d.ts.map +0 -1
- package/dist/data/index.d.ts +0 -38
- package/dist/data/index.d.ts.map +0 -1
- package/dist/data/index.js +0 -24
- package/dist/motion/index.d.ts.map +0 -1
- package/dist/nav/types.d.ts.map +0 -1
- package/dist/notifications/overlay.d.ts +0 -20
- package/dist/notifications/overlay.d.ts.map +0 -1
- package/dist/notifications/overlay.js +0 -14
- package/dist/query/devtools.d.ts.map +0 -1
- package/dist/query/error-message.d.ts +0 -41
- package/dist/query/error-message.d.ts.map +0 -1
- package/dist/query/error-message.js +0 -30
- package/dist/query/index.d.ts +0 -47
- package/dist/query/index.d.ts.map +0 -1
- package/dist/query/index.js +0 -56
- package/dist/router-tanstack/field.d.ts +0 -14
- package/dist/router-tanstack/field.d.ts.map +0 -1
- package/dist/router-tanstack/field.js +0 -4
- package/dist/router-tanstack/multi-search-param-store.d.ts +0 -43
- package/dist/router-tanstack/multi-search-param-store.d.ts.map +0 -1
- package/dist/router-tanstack/multi-search-param-store.js +0 -30
- package/dist/router-tanstack/search-param-store.d.ts +0 -42
- package/dist/router-tanstack/search-param-store.d.ts.map +0 -1
- package/dist/router-tanstack/search-param-store.js +0 -25
- package/dist/section/index.d.ts +0 -2
- package/dist/section/index.d.ts.map +0 -1
- package/dist/section/index.js +0 -4
- package/dist/theme-toggle/index.d.ts.map +0 -1
- package/dist/utils/is-dev.d.ts.map +0 -1
- package/dist/widget-header/delta-badge.d.ts +0 -19
- package/dist/widget-header/delta-badge.d.ts.map +0 -1
- package/dist/widget-header/delta-badge.js +0 -36
- package/dist/widget-header/index.d.ts +0 -3
- package/dist/widget-header/index.d.ts.map +0 -1
- package/dist/widget-header/index.js +0 -8
- package/dist/widget-header/widget-header.d.ts.map +0 -1
- package/src/connectivity/index.ts +0 -19
- package/src/data/index.ts +0 -69
- package/src/notifications/overlay.tsx +0 -66
- package/src/query/error-message.ts +0 -70
- package/src/query/index.ts +0 -97
- package/src/router-tanstack/field.ts +0 -36
- package/src/router-tanstack/multi-search-param-store.ts +0 -106
- package/src/router-tanstack/search-param-store.ts +0 -100
- package/src/section/index.ts +0 -1
- package/src/widget-header/delta-badge.tsx +0 -77
- package/src/widget-header/index.ts +0 -10
- /package/dist/{utils → common}/is-dev.d.ts +0 -0
- /package/dist/{utils → common}/is-dev.js +0 -0
- /package/dist/{motion/index.js → common/motion.js} +0 -0
- /package/dist/{section → dashboard}/section.module.css +0 -0
- /package/dist/{section → dashboard}/section.module.css.d.ts +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.d.ts +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.js +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.module.css +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.module.css.d.ts +0 -0
- /package/dist/{connectivity → provider}/connectivity-indicator.d.ts +0 -0
- /package/dist/{connectivity → provider}/connectivity-indicator.js +0 -0
- /package/dist/{connectivity → provider}/connectivity-provider.js +0 -0
- /package/dist/{connectivity/types.js → provider/connectivity-types.js} +0 -0
- /package/dist/{connectivity → provider}/use-connectivity.js +0 -0
- /package/dist/{query/devtools.js → query-devtools.js} +0 -0
- /package/dist/{nav/types.js → shell/nav-types.js} +0 -0
- /package/src/{utils → common}/is-dev.ts +0 -0
- /package/src/{motion/index.ts → common/motion.ts} +0 -0
- /package/src/{section → dashboard}/section.module.css +0 -0
- /package/src/{section → dashboard}/section.module.css.d.ts +0 -0
- /package/src/{widget-header → dashboard}/widget-header.module.css +0 -0
- /package/src/{widget-header → dashboard}/widget-header.module.css.d.ts +0 -0
- /package/src/{widget-header → dashboard}/widget-header.tsx +0 -0
- /package/src/{connectivity/types.ts → provider/connectivity-types.ts} +0 -0
- /package/src/{nav/types.ts → shell/nav-types.ts} +0 -0
|
@@ -23,10 +23,11 @@ import { AnimatePresence, motion } from 'motion/react'
|
|
|
23
23
|
import type { JSX, ReactNode } from 'react'
|
|
24
24
|
import { useEffect, useState } from 'react'
|
|
25
25
|
import type { AgentThread } from '../agent'
|
|
26
|
+
import { BasaltStickToBottom } from '../agent'
|
|
26
27
|
import { cx } from '../common/props'
|
|
27
28
|
import type { BasaltProps } from '../common/props'
|
|
28
29
|
import { assertRequiredProps } from '../common/validate'
|
|
29
|
-
import { MOTION_SPRING } from '../motion'
|
|
30
|
+
import { MOTION_SPRING } from '../common/motion'
|
|
30
31
|
import type { ComposerSubmit } from './composer'
|
|
31
32
|
import { ThreadFeedRow } from './thread-feed-row'
|
|
32
33
|
import { ThreadOutcomeCard } from './thread-outcome-card'
|
|
@@ -69,6 +70,16 @@ export type ThreadFeedProps = BasaltProps & {
|
|
|
69
70
|
* (`onStop`/`liveParts`/`liveStatus`) the built-in `'inline'` row doesn't expose; see `variant`
|
|
70
71
|
* and `onSend`. */
|
|
71
72
|
readonly renderRow?: (thread: AgentThread) => ReactNode
|
|
73
|
+
/**
|
|
74
|
+
* Scroll anchor. `'start'` (default) is today's top-anchored `ScrollArea` feed, unchanged.
|
|
75
|
+
* `'end'` anchors the feed's growth to the BOTTOM instead — a `BasaltStickToBottom` scroll node
|
|
76
|
+
* (auto-follows the live turn, same container `ThreadDetailPanel` uses) rather than `ScrollArea`,
|
|
77
|
+
* with the row stack `justify`-ed to the end and grown to the full height so a short feed still
|
|
78
|
+
* sits at the bottom rather than floating at the top. This is what a bottom-anchored chat feed
|
|
79
|
+
* (argo's hermes-chat S15 — oldest→newest top→bottom, pinned last, `renderRow`-driven) needs
|
|
80
|
+
* instead of hand-rolling its own scroll shell around `renderRow`.
|
|
81
|
+
*/
|
|
82
|
+
readonly anchor?: 'start' | 'end'
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
function defaultRow(
|
|
@@ -116,6 +127,7 @@ export function ThreadFeed({
|
|
|
116
127
|
variant = 'outcome',
|
|
117
128
|
onSend,
|
|
118
129
|
renderRow,
|
|
130
|
+
anchor = 'start',
|
|
119
131
|
className,
|
|
120
132
|
style,
|
|
121
133
|
}: ThreadFeedProps): JSX.Element {
|
|
@@ -153,36 +165,50 @@ export function ThreadFeed({
|
|
|
153
165
|
? renderRow(thread)
|
|
154
166
|
: defaultRow(thread, variant, activeId, collapsedId, handleInlineToggle, onSelect, onSend)
|
|
155
167
|
|
|
156
|
-
|
|
168
|
+
// B5: `anchor="end"` grows the stack to the full scroll height and pins its content to the
|
|
169
|
+
// bottom, so a feed with only a couple of threads still sits flush against the composer instead
|
|
170
|
+
// of floating at the top of an otherwise-empty ScrollArea.
|
|
171
|
+
const stackAnchorProps = anchor === 'end' ? { justify: 'flex-end' as const, mih: '100%' } : {}
|
|
172
|
+
|
|
173
|
+
const list = reduceMotion ? (
|
|
174
|
+
<Stack gap="sm" p="sm" {...stackAnchorProps}>
|
|
175
|
+
{threads.map((thread) => (
|
|
176
|
+
<Box key={thread.id}>{rowFor(thread)}</Box>
|
|
177
|
+
))}
|
|
178
|
+
</Stack>
|
|
179
|
+
) : (
|
|
180
|
+
<Stack gap="sm" p="sm" {...stackAnchorProps}>
|
|
181
|
+
<AnimatePresence mode="popLayout" initial={false}>
|
|
182
|
+
{threads.map((thread) => (
|
|
183
|
+
<motion.div
|
|
184
|
+
key={thread.id}
|
|
185
|
+
layout
|
|
186
|
+
initial={{ opacity: 0, y: -8 }}
|
|
187
|
+
animate={{ opacity: 1, y: 0 }}
|
|
188
|
+
exit={{ opacity: 0, scale: 0.97 }}
|
|
189
|
+
transition={MOTION_SPRING}
|
|
190
|
+
>
|
|
191
|
+
{rowFor(thread)}
|
|
192
|
+
</motion.div>
|
|
193
|
+
))}
|
|
194
|
+
</AnimatePresence>
|
|
195
|
+
</Stack>
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
// `anchor="end"`: a `BasaltStickToBottom` scroll node instead of `ScrollArea` — it owns an
|
|
199
|
+
// initial scroll-to-end on mount and auto-follows appended content (the live turn), which a
|
|
200
|
+
// plain `ScrollArea` has no notion of.
|
|
201
|
+
if (anchor === 'end') {
|
|
157
202
|
return (
|
|
158
|
-
<
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
<Box key={thread.id}>{rowFor(thread)}</Box>
|
|
162
|
-
))}
|
|
163
|
-
</Stack>
|
|
164
|
-
</ScrollArea>
|
|
203
|
+
<BasaltStickToBottom className={cx(className)} style={{ height: '100%', ...style }}>
|
|
204
|
+
{list}
|
|
205
|
+
</BasaltStickToBottom>
|
|
165
206
|
)
|
|
166
207
|
}
|
|
167
208
|
|
|
168
209
|
return (
|
|
169
210
|
<ScrollArea className={cx(className)} style={{ height: '100%', ...style }}>
|
|
170
|
-
|
|
171
|
-
<AnimatePresence mode="popLayout" initial={false}>
|
|
172
|
-
{threads.map((thread) => (
|
|
173
|
-
<motion.div
|
|
174
|
-
key={thread.id}
|
|
175
|
-
layout
|
|
176
|
-
initial={{ opacity: 0, y: -8 }}
|
|
177
|
-
animate={{ opacity: 1, y: 0 }}
|
|
178
|
-
exit={{ opacity: 0, scale: 0.97 }}
|
|
179
|
-
transition={MOTION_SPRING}
|
|
180
|
-
>
|
|
181
|
-
{rowFor(thread)}
|
|
182
|
-
</motion.div>
|
|
183
|
-
))}
|
|
184
|
-
</AnimatePresence>
|
|
185
|
-
</Stack>
|
|
211
|
+
{list}
|
|
186
212
|
</ScrollArea>
|
|
187
213
|
)
|
|
188
214
|
}
|
|
@@ -60,7 +60,7 @@ import { formatRelativeTime } from './relative-time'
|
|
|
60
60
|
import { ToolChip } from './tool-chip'
|
|
61
61
|
import { resolveVirtualize } from './virtualize'
|
|
62
62
|
import type { VirtualizeOptions, VirtualizeProps } from './virtualize'
|
|
63
|
-
import { isDev } from '../
|
|
63
|
+
import { isDev } from '../common/is-dev'
|
|
64
64
|
|
|
65
65
|
/** The mono, uppercase, letter-spaced micro-label idiom (docs/DESIGN-SPEC.md §3) — shared by the
|
|
66
66
|
* transcript's role labels and the reasoning/tool-call headers below. */
|
|
@@ -112,6 +112,54 @@ export type ResolvedVirtualize = {
|
|
|
112
112
|
readonly height: number | string
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* `ThreadFeedRow`'s OWN height contract (B3) — a strict superset of {@link VirtualizeProps} that
|
|
117
|
+
* additionally allows `height` WITHOUT `virtualize`. This is deliberately NOT a widening of
|
|
118
|
+
* `VirtualizeProps` itself (see `virtualize.type-guard.test.ts`, which pins that union rejecting
|
|
119
|
+
* `{ height }` with no `virtualize`): the two `height` modes mean different things and route to
|
|
120
|
+
* different DOM. `virtualize: true|VirtualizeOptions` + `height` still hands the row's transcript a
|
|
121
|
+
* fixed-size scroll container `@tanstack/react-virtual` owns and measures (unchanged, forwarded to
|
|
122
|
+
* `ThreadTranscript` via `resolveVirtualize`). `height` ALONE — no `virtualize` — wraps the row's
|
|
123
|
+
* TRANSCRIPT in a fixed-height `BasaltStickToBottom` (the same auto-follow-the-live-turn container
|
|
124
|
+
* `ThreadDetailPanel` already uses), leaving the composer outside/below it: a bounded, scrolling
|
|
125
|
+
* row for a thread the caller does not want to virtualize (argo's hermes-chat S7 — a 480px
|
|
126
|
+
* transcript body with inner scroll, no `@tanstack/react-virtual` peer installed).
|
|
127
|
+
*/
|
|
128
|
+
export type RowHeightProps =
|
|
129
|
+
| { readonly virtualize?: false; readonly height?: number | string }
|
|
130
|
+
| { readonly virtualize: true | VirtualizeOptions; readonly height: number | string }
|
|
131
|
+
|
|
132
|
+
/** The resolved shape of {@link RowHeightProps} — exactly one of the three row body layouts. */
|
|
133
|
+
export type ResolvedRowHeight =
|
|
134
|
+
| { readonly kind: 'virtualized'; readonly virtualize: ResolvedVirtualize }
|
|
135
|
+
| { readonly kind: 'bounded'; readonly height: number | string }
|
|
136
|
+
| { readonly kind: 'content-sized' }
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The single narrowing point `ThreadFeedRow` resolves {@link RowHeightProps} through — mirrors
|
|
140
|
+
* {@link resolveVirtualize}'s role for `VirtualizeProps`, extended with the `'bounded'` branch B3
|
|
141
|
+
* adds. Runtime-checked rather than routed through `resolveVirtualize` itself: `RowHeightProps`'
|
|
142
|
+
* inactive branch relaxes `height` from `never` to `number | string | undefined`, which is NOT
|
|
143
|
+
* structurally assignable to `VirtualizeProps` (by design — see this type's own doc), so the two
|
|
144
|
+
* resolvers stay independent rather than one calling the other with a cast.
|
|
145
|
+
*/
|
|
146
|
+
export function resolveRowHeight(props: RowHeightProps): ResolvedRowHeight {
|
|
147
|
+
const { virtualize, height } = props
|
|
148
|
+
if (virtualize === true || (typeof virtualize === 'object' && virtualize !== null)) {
|
|
149
|
+
// The union guarantees `height` is present on this branch — see resolveVirtualize's own doc
|
|
150
|
+
// for why the pairing is re-stated here instead of narrowed automatically.
|
|
151
|
+
return {
|
|
152
|
+
kind: 'virtualized',
|
|
153
|
+
virtualize: {
|
|
154
|
+
options: virtualize === true ? {} : virtualize,
|
|
155
|
+
height: height as number | string,
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (height !== undefined) return { kind: 'bounded', height }
|
|
160
|
+
return { kind: 'content-sized' }
|
|
161
|
+
}
|
|
162
|
+
|
|
115
163
|
/**
|
|
116
164
|
* Narrows a `VirtualizeProps` pair once, centrally: `null` when virtualization is off, otherwise
|
|
117
165
|
* the options object (normalizing the bare `virtualize: true` shorthand to `{}`) alongside the
|
package/src/charts/index.ts
CHANGED
|
@@ -101,7 +101,12 @@ export {
|
|
|
101
101
|
TooltipRow,
|
|
102
102
|
TooltipBody,
|
|
103
103
|
} from './primitives/ChartTooltip'
|
|
104
|
-
export {
|
|
104
|
+
export {
|
|
105
|
+
AxisBottomDate,
|
|
106
|
+
AxisBottomNumeric,
|
|
107
|
+
AxisLeftNumeric,
|
|
108
|
+
AxisRightNumeric,
|
|
109
|
+
} from './primitives/Axes'
|
|
105
110
|
export { HoverOverlay } from './primitives/HoverOverlay'
|
|
106
111
|
export { ZoneRects, type ZoneSpec } from './primitives/ZoneRects'
|
|
107
112
|
export { XZoneRects, type XZoneSpec } from './primitives/XZoneRects'
|
|
@@ -139,19 +144,11 @@ export { measureText, maxTextWidth } from './utils/measure-text'
|
|
|
139
144
|
export {
|
|
140
145
|
ZonedLine,
|
|
141
146
|
type ZonedLineProps,
|
|
142
|
-
type ZonedLineZone,
|
|
143
147
|
type ZonedLineThreshold,
|
|
144
148
|
type ZonedLineRefLine,
|
|
145
149
|
} from './kinds/ZonedLine'
|
|
146
150
|
|
|
147
|
-
export {
|
|
148
|
-
Bars,
|
|
149
|
-
type BarsProps,
|
|
150
|
-
type BarsBar,
|
|
151
|
-
type BarsLine,
|
|
152
|
-
type BarsZone,
|
|
153
|
-
type BarsRefLine,
|
|
154
|
-
} from './kinds/Bars'
|
|
151
|
+
export { Bars, type BarsProps, type BarsBar, type BarsLine, type BarsRefLine } from './kinds/Bars'
|
|
155
152
|
|
|
156
153
|
export { StackedArea, type StackedAreaProps } from './kinds/StackedArea'
|
|
157
154
|
export { Donut, type DonutProps, type DonutDatum } from './kinds/Donut'
|
|
@@ -22,7 +22,7 @@ import { HoverOverlay } from '../primitives/HoverOverlay'
|
|
|
22
22
|
import type { ChartState } from '../primitives/ChartPending'
|
|
23
23
|
import type { ChartLegendConfig, SeriesStyle } from '../series'
|
|
24
24
|
import { fmtAxisDate } from '../utils/format'
|
|
25
|
-
import { isDev } from '../../
|
|
25
|
+
import { isDev } from '../../common/is-dev'
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* A state a strip can draw. Extends `SeriesStyle` rather than `ChartSeries` because a band has no
|
|
@@ -12,7 +12,7 @@ import type { ChartState } from '../primitives/ChartPending'
|
|
|
12
12
|
import { curveFor, LINE_OVERLAY_STROKE_WIDTH } from '../series'
|
|
13
13
|
import type { ChartLegendConfig, ChartSeries, SeriesCurve } from '../series'
|
|
14
14
|
import { padAutoLower } from '../utils/domain'
|
|
15
|
-
import { isDev } from '../../
|
|
15
|
+
import { isDev } from '../../common/is-dev'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* `T = unknown` is load-bearing, not a shortcut: it keeps a consumer's existing
|
|
@@ -55,9 +55,6 @@ export type BarsLine<T = unknown> = {
|
|
|
55
55
|
curve?: SeriesCurve
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
/** @deprecated Use ZoneSpec from primitives/ZoneRects. Kept as an alias. */
|
|
59
|
-
export type BarsZone = ZoneSpec
|
|
60
|
-
|
|
61
58
|
export type BarsRefLine = {
|
|
62
59
|
value: number
|
|
63
60
|
color: string
|
|
@@ -84,7 +81,7 @@ export type BarsProps<T> = BasaltProps & {
|
|
|
84
81
|
lines?: BarsLine<T>[]
|
|
85
82
|
|
|
86
83
|
/** Horizontal value-range overlays (target zones, optimal bands). */
|
|
87
|
-
zones?:
|
|
84
|
+
zones?: ZoneSpec[]
|
|
88
85
|
/** Dashed/solid horizontal reference lines. */
|
|
89
86
|
refLines?: BarsRefLine[]
|
|
90
87
|
|
|
@@ -49,8 +49,9 @@ export type DualPanelProps<T> = BasaltProps & {
|
|
|
49
49
|
series: ChartSeries<T>[]
|
|
50
50
|
/** Top-pane y-domain. Default 'auto' (computed from all top lines, padded). */
|
|
51
51
|
topYDomain?: [number, number] | 'auto'
|
|
52
|
-
/** Shade the band between two top lines (by key)
|
|
53
|
-
|
|
52
|
+
/** Shade the band between two top lines (by key). `aboveFill` colors the side where `to` runs
|
|
53
|
+
* above `from` (e.g. a "bad" red) — omitted, both sides share `fill` (today's behaviour). */
|
|
54
|
+
fillBetween?: { from: string; to: string; fill: string; aboveFill?: string }
|
|
54
55
|
/** Horizontal reference lines on the top pane. Solid by default; set dashed: true for a dashed line. */
|
|
55
56
|
topRefLines?: { value: number; color: string; dashed?: boolean }[]
|
|
56
57
|
/** Horizontal value-range bands on the top pane. */
|
|
@@ -512,7 +513,7 @@ function DualPanelPlot<T>(props: DualPanelPlotProps<T>) {
|
|
|
512
513
|
clipBelowTo={topH}
|
|
513
514
|
curve={fillCurve}
|
|
514
515
|
belowAreaProps={{ fill: fillBetween.fill }}
|
|
515
|
-
aboveAreaProps={{ fill: fillBetween.fill }}
|
|
516
|
+
aboveAreaProps={{ fill: fillBetween.aboveFill ?? fillBetween.fill }}
|
|
516
517
|
/>
|
|
517
518
|
)}
|
|
518
519
|
|
|
@@ -8,7 +8,7 @@ import type { AxisConfig, PlotContext } from '../primitives/CartesianChart'
|
|
|
8
8
|
import type { ChartState } from '../primitives/ChartPending'
|
|
9
9
|
import { curveFor } from '../series'
|
|
10
10
|
import type { ChartLegendConfig, ChartSeries } from '../series'
|
|
11
|
-
import { isDev } from '../../
|
|
11
|
+
import { isDev } from '../../common/is-dev'
|
|
12
12
|
|
|
13
13
|
export type StackedAreaProps<T> = BasaltProps & {
|
|
14
14
|
data: T[]
|
|
@@ -14,9 +14,6 @@ import { curveFor, definedOn, LINE_OVERLAY_STROKE_WIDTH, toPlotPoint } from '../
|
|
|
14
14
|
import type { ChartLegendConfig, ChartSeries } from '../series'
|
|
15
15
|
import { VX } from '../../tokens'
|
|
16
16
|
|
|
17
|
-
/** @deprecated Use ZoneSpec from primitives/ZoneRects. Kept as an alias for back-compat. */
|
|
18
|
-
export type ZonedLineZone = ZoneSpec
|
|
19
|
-
|
|
20
17
|
/** Semi-transparent fill above (or below) a threshold value, tracking the line. */
|
|
21
18
|
export type ZonedLineThreshold = {
|
|
22
19
|
value: number
|
|
@@ -46,7 +43,7 @@ export type ZonedLineProps<T> = BasaltProps & {
|
|
|
46
43
|
/** Y-axis. Collapses the old `yDomain` / `yAutoMaxFloor` / `yAutoMinCeil` / `yAutoPad` /
|
|
47
44
|
* `numTicksY` / `formatYTick` prop soup into one object. */
|
|
48
45
|
y?: AxisConfig<T>
|
|
49
|
-
zones?:
|
|
46
|
+
zones?: ZoneSpec[]
|
|
50
47
|
/** Vertical x-range overlays (time windows), rendered behind the line. Bounds are `getX`
|
|
51
48
|
* domain keys. */
|
|
52
49
|
xZones?: XZoneSpec[]
|
|
@@ -20,10 +20,13 @@ export function AxisLeftNumeric({
|
|
|
20
20
|
scale,
|
|
21
21
|
numTicks = 5,
|
|
22
22
|
tickFormat,
|
|
23
|
+
tickValues,
|
|
23
24
|
}: {
|
|
24
25
|
scale: AxisScale
|
|
25
26
|
numTicks?: number
|
|
26
27
|
tickFormat?: TickFormatter<number>
|
|
28
|
+
/** Exact tick positions (e.g. a compass axis at 0/90/180/270). Overrides `numTicks`. */
|
|
29
|
+
tickValues?: readonly number[]
|
|
27
30
|
}) {
|
|
28
31
|
const { axisFont } = useChartTierMetrics()
|
|
29
32
|
return (
|
|
@@ -31,6 +34,7 @@ export function AxisLeftNumeric({
|
|
|
31
34
|
scale={scale}
|
|
32
35
|
numTicks={numTicks}
|
|
33
36
|
{...(tickFormat !== undefined && { tickFormat })}
|
|
37
|
+
{...(tickValues !== undefined && { tickValues: [...tickValues] })}
|
|
34
38
|
tickLabelProps={{
|
|
35
39
|
fill: VX.faint,
|
|
36
40
|
fontFamily: TICK_FONT_FAMILY,
|
|
@@ -49,12 +53,15 @@ export function AxisRightNumeric({
|
|
|
49
53
|
left,
|
|
50
54
|
numTicks = 5,
|
|
51
55
|
tickFormat,
|
|
56
|
+
tickValues,
|
|
52
57
|
}: {
|
|
53
58
|
scale: AxisScale
|
|
54
59
|
/** Left offset inside the Group (typically xMax). Required since AxisRight needs positioning. */
|
|
55
60
|
left: number
|
|
56
61
|
numTicks?: number
|
|
57
62
|
tickFormat?: TickFormatter<number>
|
|
63
|
+
/** Exact tick positions (e.g. a compass axis at 0/90/180/270). Overrides `numTicks`. */
|
|
64
|
+
tickValues?: readonly number[]
|
|
58
65
|
}) {
|
|
59
66
|
const { axisFont } = useChartTierMetrics()
|
|
60
67
|
return (
|
|
@@ -63,6 +70,7 @@ export function AxisRightNumeric({
|
|
|
63
70
|
scale={scale}
|
|
64
71
|
numTicks={numTicks}
|
|
65
72
|
{...(tickFormat !== undefined && { tickFormat })}
|
|
73
|
+
{...(tickValues !== undefined && { tickValues: [...tickValues] })}
|
|
66
74
|
tickLabelProps={{
|
|
67
75
|
fill: VX.faint,
|
|
68
76
|
fontFamily: TICK_FONT_FAMILY,
|
|
@@ -75,6 +83,47 @@ export function AxisRightNumeric({
|
|
|
75
83
|
)
|
|
76
84
|
}
|
|
77
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Themed bottom numeric axis — the numeric twin of {@link AxisLeftNumeric}, for a plot whose x is
|
|
88
|
+
* a continuous number rather than a date/category (e.g. `sky-panorama.tsx`'s azimuth 0–360°,
|
|
89
|
+
* `docs/CHARTS-SPEC.md` issue #52). Exists so a bespoke continuous-x plot — declared exempt from
|
|
90
|
+
* `CartesianChart` by a `theme-allow-file hand-rolled-plot` waiver, since the point-scale x axis
|
|
91
|
+
* that primitive builds cannot represent one — stops re-implementing tick text/color/font by hand.
|
|
92
|
+
*/
|
|
93
|
+
export function AxisBottomNumeric({
|
|
94
|
+
scale,
|
|
95
|
+
top,
|
|
96
|
+
numTicks = 5,
|
|
97
|
+
tickFormat,
|
|
98
|
+
tickValues,
|
|
99
|
+
}: {
|
|
100
|
+
scale: AxisScale
|
|
101
|
+
top: number
|
|
102
|
+
numTicks?: number
|
|
103
|
+
tickFormat?: TickFormatter<number>
|
|
104
|
+
/** Exact tick positions (e.g. a compass axis at 0/90/180/270). Overrides `numTicks`. */
|
|
105
|
+
tickValues?: readonly number[]
|
|
106
|
+
}) {
|
|
107
|
+
const { axisFont } = useChartTierMetrics()
|
|
108
|
+
return (
|
|
109
|
+
<AxisBottom
|
|
110
|
+
top={top}
|
|
111
|
+
scale={scale}
|
|
112
|
+
numTicks={numTicks}
|
|
113
|
+
{...(tickFormat !== undefined && { tickFormat })}
|
|
114
|
+
{...(tickValues !== undefined && { tickValues: [...tickValues] })}
|
|
115
|
+
tickLabelProps={{
|
|
116
|
+
fill: VX.faint,
|
|
117
|
+
fontFamily: TICK_FONT_FAMILY,
|
|
118
|
+
fontSize: axisFont,
|
|
119
|
+
textAnchor: 'middle',
|
|
120
|
+
}}
|
|
121
|
+
stroke={VX.surface.border}
|
|
122
|
+
tickStroke={VX.surface.border}
|
|
123
|
+
/>
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
78
127
|
/**
|
|
79
128
|
* Nudge a rotated tick label back onto its tick. Both are the d3 idiom for the angle: a 45° label
|
|
80
129
|
* hangs from the tick's lower-left, a 90° one is centred on the tick's vertical line.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* tier="widget"` title row (icon/info/value/delta/count/actions) plus an optional subtitle, over a
|
|
4
4
|
* clipped chart body. Do not wrap visx charts in bare divs.
|
|
5
5
|
*
|
|
6
|
-
* `WidgetHeader` lives in `src/
|
|
6
|
+
* `WidgetHeader` lives in `src/dashboard/` and is itself Mantine-free, so composing it here
|
|
7
7
|
* keeps `./charts` resolving with no `@mantine/*` installed (`check-dist-layering.mjs`,
|
|
8
8
|
* `basalt/token-layer-boundary`). The `actions` slot cannot mount `CtlSlot` (Mantine-coupled) for
|
|
9
9
|
* the same reason — it carries only `data-basalt-tier="widget"`; a basalt control placed there
|
|
@@ -16,8 +16,10 @@ import type { CSSProperties, ReactNode } from 'react'
|
|
|
16
16
|
import { cx } from '../../common/props'
|
|
17
17
|
import type { BasaltProps, SlotStylesProps } from '../../common/props'
|
|
18
18
|
import { VX } from '../../tokens'
|
|
19
|
-
import { WidgetHeader } from '../../widget-header'
|
|
20
|
-
import type { DeltaPolarity } from '../../
|
|
19
|
+
import { WidgetHeader } from '../../dashboard/widget-header'
|
|
20
|
+
import type { DeltaPolarity } from '../../dashboard/delta-badge'
|
|
21
|
+
import { ChartEmpty, ChartError, ChartPending, resolveChartState } from './ChartPending'
|
|
22
|
+
import type { ChartState } from './ChartPending'
|
|
21
23
|
|
|
22
24
|
// Surfaces resolve per theme via CSS vars, so the styles are static (no useMemo/isDark).
|
|
23
25
|
// Depth = `shadow-card` (a whisper shadow + a 1px ring baked into the same value), never a
|
|
@@ -99,7 +101,22 @@ export type ChartCardProps = BasaltProps &
|
|
|
99
101
|
count?: number
|
|
100
102
|
/** Right-aligned slot — carries `data-basalt-tier="widget"` (no `CtlSlot`; see module doc). */
|
|
101
103
|
actions?: ReactNode
|
|
102
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Any resolved state (pending → error → empty, same precedence `resolveChartState` gives
|
|
106
|
+
* every chart kind) REPLACES `children` with its placeholder at `placeholderHeight` — the
|
|
107
|
+
* header still renders unchanged, so a card's title never reflows through the pending → drawn
|
|
108
|
+
* transition. `state={{}}` (or an all-falsy state) renders `children`, same as omitting the
|
|
109
|
+
* prop.
|
|
110
|
+
*/
|
|
111
|
+
state?: ChartState
|
|
112
|
+
/** Body height while a placeholder shows. Default 240 (`ChartFrame`'s own default height). */
|
|
113
|
+
placeholderHeight?: number
|
|
114
|
+
/** Affordance under a pending/empty/error label — a retry button, a "clear filters" link.
|
|
115
|
+
* Forwarded to whichever placeholder resolves. */
|
|
116
|
+
stateAction?: ReactNode
|
|
117
|
+
/** Optional so a title-less pending card can BE a route's `<Suspense>` fallback
|
|
118
|
+
* (`<ChartCard state={{ pending: true }} placeholderHeight={320} />`, no `children` at all). */
|
|
119
|
+
children?: ReactNode
|
|
103
120
|
}
|
|
104
121
|
|
|
105
122
|
export function ChartCard({
|
|
@@ -113,11 +130,15 @@ export function ChartCard({
|
|
|
113
130
|
deltaPolarity,
|
|
114
131
|
count,
|
|
115
132
|
actions,
|
|
133
|
+
state,
|
|
134
|
+
placeholderHeight = 240,
|
|
135
|
+
stateAction,
|
|
116
136
|
className,
|
|
117
137
|
classNames,
|
|
118
138
|
style,
|
|
119
139
|
children,
|
|
120
140
|
}: ChartCardProps) {
|
|
141
|
+
const resolvedState = resolveChartState({ ...(state !== undefined && { state }) })
|
|
121
142
|
const hasHeader =
|
|
122
143
|
title !== undefined ||
|
|
123
144
|
info !== undefined ||
|
|
@@ -127,7 +148,11 @@ export function ChartCard({
|
|
|
127
148
|
count !== undefined
|
|
128
149
|
|
|
129
150
|
return (
|
|
130
|
-
<div
|
|
151
|
+
<div
|
|
152
|
+
className={cx(classNames?.root, className)}
|
|
153
|
+
style={{ ...cardStyle, ...style }}
|
|
154
|
+
{...(resolvedState === 'pending' && { 'aria-busy': 'true' })}
|
|
155
|
+
>
|
|
131
156
|
{hasHeader && (
|
|
132
157
|
<div
|
|
133
158
|
{...(classNames?.header !== undefined && { className: classNames.header })}
|
|
@@ -154,7 +179,25 @@ export function ChartCard({
|
|
|
154
179
|
{...(classNames?.body !== undefined && { className: classNames.body })}
|
|
155
180
|
style={bodyClipStyle}
|
|
156
181
|
>
|
|
157
|
-
{
|
|
182
|
+
{resolvedState === 'pending' ? (
|
|
183
|
+
<ChartPending width="100%" height={placeholderHeight} />
|
|
184
|
+
) : resolvedState === 'error' ? (
|
|
185
|
+
<ChartError
|
|
186
|
+
width="100%"
|
|
187
|
+
height={placeholderHeight}
|
|
188
|
+
error={state?.error}
|
|
189
|
+
action={stateAction}
|
|
190
|
+
/>
|
|
191
|
+
) : resolvedState === 'empty' ? (
|
|
192
|
+
<ChartEmpty
|
|
193
|
+
width="100%"
|
|
194
|
+
height={placeholderHeight}
|
|
195
|
+
{...(typeof state?.empty === 'string' && { label: state.empty })}
|
|
196
|
+
action={stateAction}
|
|
197
|
+
/>
|
|
198
|
+
) : (
|
|
199
|
+
children
|
|
200
|
+
)}
|
|
158
201
|
</div>
|
|
159
202
|
</div>
|
|
160
203
|
)
|
|
@@ -283,7 +283,11 @@ export function ChartFrame({
|
|
|
283
283
|
) : resolvedState === 'error' ? (
|
|
284
284
|
<ChartError width={plot.width} height={plot.height} error={state?.error} />
|
|
285
285
|
) : resolvedState === 'empty' ? (
|
|
286
|
-
<ChartEmpty
|
|
286
|
+
<ChartEmpty
|
|
287
|
+
width={plot.width}
|
|
288
|
+
height={plot.height}
|
|
289
|
+
{...(typeof state?.empty === 'string' && { label: state.empty })}
|
|
290
|
+
/>
|
|
287
291
|
) : (
|
|
288
292
|
children({ ...plot, hidden })
|
|
289
293
|
))}
|
|
@@ -3,12 +3,14 @@ import type { BasaltProps } from '../../common/props'
|
|
|
3
3
|
import { VX } from '../../tokens'
|
|
4
4
|
|
|
5
5
|
export type ChartCenterProps = BasaltProps & {
|
|
6
|
-
|
|
6
|
+
/** A block body (a title-less pending `ChartCard`, a non-`ChartFrame` body) has no measured
|
|
7
|
+
* plot width to reserve — `'100%'` fills its container instead of a pixel figure. */
|
|
8
|
+
width: number | string
|
|
7
9
|
height: number
|
|
8
10
|
children: ReactNode
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
const centerStyle = (width: number, height: number): CSSProperties => ({
|
|
13
|
+
const centerStyle = (width: number | string, height: number): CSSProperties => ({
|
|
12
14
|
width,
|
|
13
15
|
height,
|
|
14
16
|
display: 'flex',
|
|
@@ -40,7 +42,7 @@ export function ChartCenter({
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export type ChartPendingProps = BasaltProps & {
|
|
43
|
-
width: number
|
|
45
|
+
width: number | string
|
|
44
46
|
height: number
|
|
45
47
|
/** Default `'Loading…'`. */
|
|
46
48
|
label?: string
|
|
@@ -113,8 +115,12 @@ export type ChartState = {
|
|
|
113
115
|
pending?: boolean
|
|
114
116
|
/** Truthy = the query failed. Any thrown value; an `Error`'s `message` is used as the label. */
|
|
115
117
|
error?: unknown
|
|
116
|
-
/**
|
|
117
|
-
|
|
118
|
+
/**
|
|
119
|
+
* The query resolved and there is genuinely nothing to plot. `true`, or the empty label
|
|
120
|
+
* itself — a string is truthy AND the copy `ChartEmpty` paints, so a consumer with its own
|
|
121
|
+
* "No data" wording never needs a ternary around the placeholder.
|
|
122
|
+
*/
|
|
123
|
+
empty?: boolean | string
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
/** Which placeholder {@link ChartState} resolves to, or `null` to draw the chart. */
|
|
@@ -132,12 +138,12 @@ export function resolveChartState(input: {
|
|
|
132
138
|
const { state, isPending } = input
|
|
133
139
|
if (isPending === true || state?.pending === true) return 'pending'
|
|
134
140
|
if (state?.error !== undefined && state.error !== null && state.error !== false) return 'error'
|
|
135
|
-
if (state?.empty
|
|
141
|
+
if (state?.empty) return 'empty'
|
|
136
142
|
return null
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
export type ChartEmptyProps = BasaltProps & {
|
|
140
|
-
width: number
|
|
146
|
+
width: number | string
|
|
141
147
|
height: number
|
|
142
148
|
/** Default `'No data'`. */
|
|
143
149
|
label?: string
|
|
@@ -188,7 +194,7 @@ export function ChartEmpty({
|
|
|
188
194
|
}
|
|
189
195
|
|
|
190
196
|
export type ChartErrorProps = BasaltProps & {
|
|
191
|
-
width: number
|
|
197
|
+
width: number | string
|
|
192
198
|
height: number
|
|
193
199
|
/** Overrides the text outright. Omitted, an `Error`'s own `message` is used, else
|
|
194
200
|
* `'Could not load chart'` — a failure never borrows the empty state's copy. */
|