basalt-ui 1.41.0 → 2.0.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 +46 -43
- package/CHANGELOG.md +542 -518
- package/MIGRATING.md +964 -37
- package/README.md +171 -366
- package/agent/rules/basalt-batteries.md +19 -74
- package/agent/rules/basalt-charts.md +21 -95
- package/agent/rules/basalt-controls.md +23 -131
- package/agent/rules/basalt-mantine.md +26 -99
- package/agent/rules/basalt-state.md +21 -103
- package/agent/rules/basalt-tokens.md +33 -114
- package/agent/skills/basalt-app/SKILL.md +229 -72
- package/agent/skills/basalt-charts/SKILL.md +23 -57
- package/agent/skills/basalt-design/SKILL.md +12 -70
- package/agent/templates/AGENTS-block.md.tpl +16 -26
- package/agent/templates/DESIGN.md.tpl +1 -1
- package/agent/templates/__root.tpl +9 -16
- package/agent/templates/main.tpl +21 -0
- package/agent/templates/nav.tpl +18 -0
- package/configs/oxlint-basalt.json +4 -10
- package/configs/oxlint-plugin.js +465 -844
- package/configs/oxlint-plugin.test.ts +661 -709
- package/configs/oxlint.json +10 -2
- package/dist/agent/ai-sdk-transport.d.ts +19 -7
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +10 -7
- package/dist/{agent-chat → agent/chat}/composer.d.ts +16 -16
- package/dist/agent/chat/composer.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/composer.js +10 -9
- package/dist/{agent-chat → agent/chat}/message-affordances.d.ts +7 -6
- package/dist/agent/chat/message-affordances.d.ts.map +1 -0
- package/dist/agent/chat/relative-time.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/thread-feed-row.d.ts +18 -16
- package/dist/agent/chat/thread-feed-row.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/thread-feed-row.js +12 -11
- package/dist/{agent-chat → agent/chat}/thread-feed.d.ts +8 -8
- package/dist/agent/chat/thread-feed.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/thread-feed.js +12 -10
- package/dist/{agent-chat → agent/chat}/thread-message.d.ts +12 -9
- package/dist/agent/chat/thread-message.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/thread-message.js +15 -13
- package/dist/{agent-chat → agent/chat}/thread-outcome-card.d.ts +2 -2
- package/dist/agent/chat/thread-outcome-card.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/thread-outcome-card.js +3 -3
- package/dist/{agent-chat → agent/chat}/tool-chip.d.ts +5 -5
- package/dist/agent/chat/tool-chip.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/tool-chip.js +4 -4
- package/dist/agent/chat/use-keyboard-inset.d.ts.map +1 -0
- package/dist/{agent-chat → agent/chat}/use-keyboard-inset.js +1 -1
- package/dist/{agent-chat → agent/chat}/virtualize.d.ts +7 -7
- package/dist/agent/chat/virtualize.d.ts.map +1 -0
- package/dist/agent/error.d.ts +31 -0
- package/dist/agent/error.d.ts.map +1 -0
- package/dist/agent/error.js +18 -0
- package/dist/agent/history.d.ts +2 -36
- package/dist/agent/history.d.ts.map +1 -1
- package/dist/agent/history.js +0 -32
- package/dist/agent/id.d.ts +4 -5
- package/dist/agent/id.d.ts.map +1 -1
- package/dist/agent/index.d.ts +19 -52
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +10 -32
- package/dist/agent/outcome.d.ts +3 -14
- package/dist/agent/outcome.d.ts.map +1 -1
- package/dist/agent/outcome.js +0 -30
- package/dist/agent/part-list.d.ts +3 -3
- package/dist/agent/part-list.d.ts.map +1 -1
- package/dist/agent/parts.d.ts +23 -24
- package/dist/agent/parts.d.ts.map +1 -1
- package/dist/agent/run-committer.d.ts +23 -0
- package/dist/agent/run-committer.d.ts.map +1 -0
- package/dist/agent/run-committer.js +41 -0
- package/dist/agent/run-records.d.ts +77 -0
- package/dist/agent/run-records.d.ts.map +1 -0
- package/dist/agent/run-records.js +69 -0
- package/dist/agent/thread.d.ts +23 -47
- package/dist/agent/thread.d.ts.map +1 -1
- package/dist/agent/thread.js +3 -134
- package/dist/agent/transport.d.ts +6 -69
- package/dist/agent/transport.d.ts.map +1 -1
- package/dist/agent/transport.js +0 -18
- package/dist/agent/use-agent-thread-runs.d.ts +63 -26
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.js +202 -66
- package/dist/charts/BandStrip.d.ts +46 -0
- package/dist/charts/BandStrip.d.ts.map +1 -0
- package/dist/charts/BandStrip.js +151 -0
- package/dist/charts/Bars.d.ts +19 -0
- package/dist/charts/Bars.d.ts.map +1 -0
- package/dist/charts/Bars.js +77 -0
- package/dist/charts/CartesianChart.d.ts +57 -0
- package/dist/charts/CartesianChart.d.ts.map +1 -0
- package/dist/charts/CartesianChart.js +121 -0
- package/dist/charts/ChartCard.d.ts +34 -0
- package/dist/charts/ChartCard.d.ts.map +1 -0
- package/dist/charts/ChartCard.js +115 -0
- package/dist/charts/Donut.d.ts +25 -0
- package/dist/charts/Donut.d.ts.map +1 -0
- package/dist/charts/Donut.js +191 -0
- package/dist/charts/DualPanel.d.ts +47 -0
- package/dist/charts/DualPanel.d.ts.map +1 -0
- package/dist/charts/DualPanel.js +214 -0
- package/dist/charts/Heatmap.d.ts +41 -0
- package/dist/charts/Heatmap.d.ts.map +1 -0
- package/dist/charts/Heatmap.js +216 -0
- package/dist/charts/Lines.d.ts +11 -0
- package/dist/charts/Lines.d.ts.map +1 -0
- package/dist/charts/Lines.js +114 -0
- package/dist/charts/MirroredBars.d.ts +44 -0
- package/dist/charts/MirroredBars.d.ts.map +1 -0
- package/dist/charts/MirroredBars.js +190 -0
- package/dist/charts/Sparkline.d.ts +22 -0
- package/dist/charts/Sparkline.d.ts.map +1 -0
- package/dist/charts/Sparkline.js +129 -0
- package/dist/charts/StackedArea.d.ts +15 -0
- package/dist/charts/StackedArea.d.ts.map +1 -0
- package/dist/charts/StackedArea.js +46 -0
- package/dist/charts/box.d.ts +38 -0
- package/dist/charts/box.d.ts.map +1 -0
- package/dist/charts/box.js +72 -0
- package/dist/charts/card-context.d.ts +3 -0
- package/dist/charts/card-context.d.ts.map +1 -0
- package/dist/charts/card-context.js +7 -0
- package/dist/charts/chart-box.module.css +64 -0
- package/{src/content/article-card.module.css.d.ts → dist/charts/chart-box.module.css.d.ts} +5 -9
- package/dist/charts/chart-card.module.css +25 -0
- package/dist/{dashboard/widget-grid.module.css.d.ts → charts/chart-card.module.css.d.ts} +1 -3
- package/dist/charts/chart-legend.module.css +38 -0
- package/{src/dashboard/widget-grid.module.css.d.ts → dist/charts/chart-legend.module.css.d.ts} +3 -3
- package/dist/charts/compile.d.ts +62 -0
- package/dist/charts/compile.d.ts.map +1 -0
- package/dist/charts/compile.js +386 -0
- package/dist/charts/cursor.d.ts +50 -0
- package/dist/charts/cursor.d.ts.map +1 -0
- package/dist/charts/cursor.js +157 -0
- package/dist/charts/curves.d.ts +12 -0
- package/dist/charts/curves.d.ts.map +1 -0
- package/dist/charts/curves.js +86 -0
- package/dist/charts/donut.module.css +54 -0
- package/dist/{content/article-card.module.css.d.ts → charts/donut.module.css.d.ts} +2 -9
- package/dist/charts/host.d.ts +17 -0
- package/dist/charts/host.d.ts.map +1 -0
- package/dist/charts/host.js +35 -0
- package/dist/charts/index.d.ts +18 -53
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +17 -189
- package/dist/charts/legend.d.ts +23 -0
- package/dist/charts/legend.d.ts.map +1 -0
- package/dist/charts/legend.js +160 -0
- package/dist/charts/marks.d.ts +25 -0
- package/dist/charts/marks.d.ts.map +1 -0
- package/dist/charts/marks.js +128 -0
- package/dist/charts/panel.d.ts +56 -0
- package/dist/charts/panel.d.ts.map +1 -0
- package/dist/charts/panel.js +123 -0
- package/dist/charts/scales.d.ts +44 -0
- package/dist/charts/scales.d.ts.map +1 -0
- package/dist/charts/scales.js +163 -0
- package/dist/charts/sizing.d.ts +12 -0
- package/dist/charts/sizing.d.ts.map +1 -0
- package/dist/charts/sizing.js +33 -0
- package/dist/charts/state.d.ts +17 -0
- package/dist/charts/state.d.ts.map +1 -0
- package/dist/charts/state.js +53 -0
- package/dist/charts/theme.d.ts +38 -19
- package/dist/charts/theme.d.ts.map +1 -1
- package/dist/charts/theme.js +48 -26
- package/dist/charts/types.d.ts +227 -0
- package/dist/charts/types.d.ts.map +1 -0
- package/dist/charts/types.js +4 -0
- package/dist/cli/audit-allows.d.ts +4 -17
- package/dist/cli/audit-allows.d.ts.map +1 -1
- package/dist/cli/config.d.ts +18 -43
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +6 -0
- package/dist/cli/doctor-upgrade.d.ts +43 -0
- package/dist/cli/doctor-upgrade.d.ts.map +1 -0
- package/dist/cli/doctor-upgrade.js +314 -0
- package/dist/cli/doctor.d.ts +14 -29
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +58 -9
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +2 -4
- package/dist/cli/index.d.ts +48 -172
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +39 -132
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +43 -37
- package/dist/cli/sync.d.ts +5 -21
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +4 -23
- package/dist/cli/tokens-css.d.ts +7 -28
- package/dist/cli/tokens-css.d.ts.map +1 -1
- package/dist/commands/ShortcutsHelp.d.ts.map +1 -1
- package/dist/commands/ShortcutsHelp.js +4 -5
- package/dist/commands/define-commands.d.ts +15 -31
- package/dist/commands/define-commands.d.ts.map +1 -1
- package/dist/commands/define-commands.js +1 -11
- package/dist/commands/define-overlays.d.ts +5 -19
- package/dist/commands/define-overlays.d.ts.map +1 -1
- package/dist/commands/define-overlays.js +3 -11
- package/dist/commands/index.d.ts +10 -40
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +9 -46
- package/dist/{notifications → commands/notifications}/bell.d.ts +1 -1
- package/dist/commands/notifications/bell.d.ts.map +1 -0
- package/dist/{notifications → commands/notifications}/center.d.ts +2 -2
- package/dist/commands/notifications/center.d.ts.map +1 -0
- package/dist/{notifications → commands/notifications}/center.js +2 -2
- package/dist/{notifications → commands/notifications}/define-notifications.d.ts +3 -3
- package/dist/commands/notifications/define-notifications.d.ts.map +1 -0
- package/dist/commands/notifications/notify.d.ts +44 -0
- package/dist/commands/notifications/notify.d.ts.map +1 -0
- package/dist/commands/notifications/notify.js +79 -0
- package/dist/{notifications → commands/notifications}/store.d.ts +2 -0
- package/dist/commands/notifications/store.d.ts.map +1 -0
- package/dist/{notifications → commands/notifications}/store.js +4 -0
- package/dist/commands/projectors.d.ts +1 -131
- package/dist/commands/projectors.d.ts.map +1 -1
- package/dist/commands/projectors.js +2 -73
- package/dist/commands/shell-bridge.d.ts +3 -3
- package/dist/commands/shortcut-format.d.ts +5 -4
- package/dist/commands/shortcut-format.d.ts.map +1 -1
- package/dist/common/errors.d.ts +3 -3
- package/dist/common/use-measured-widths.d.ts.map +1 -1
- package/dist/common/use-measured-widths.js +5 -3
- package/dist/common/validate.d.ts +2 -2
- package/dist/content/article-layout.d.ts.map +1 -1
- package/dist/content/article-layout.js +3 -3
- package/dist/content/article-model.d.ts +1 -46
- package/dist/content/article-model.d.ts.map +1 -1
- package/dist/content/article-model.js +1 -29
- package/dist/content/index.d.ts +11 -41
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +3 -35
- package/dist/content/markdown.d.ts +1 -1
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +1 -1
- package/dist/content/mermaid.d.ts.map +1 -1
- package/dist/content/mermaid.js +7 -7
- package/dist/content/slug.d.ts +1 -8
- package/dist/content/slug.d.ts.map +1 -1
- package/dist/content/slug.js +1 -8
- package/dist/content/url-hardening.d.ts +2 -2
- package/dist/content/url-hardening.d.ts.map +1 -1
- package/dist/content/url-hardening.js +2 -0
- package/dist/controls/actions.d.ts +16 -1
- package/dist/controls/actions.d.ts.map +1 -1
- package/dist/controls/enum-filter.d.ts +1 -1
- package/dist/controls/enum-filter.d.ts.map +1 -1
- package/dist/controls/filter-context.d.ts.map +1 -1
- package/dist/controls/filter-context.js +3 -1
- package/dist/controls/filter-set.js +4 -6
- package/dist/controls/form-layout.d.ts +1 -1
- package/dist/controls/form-layout.d.ts.map +1 -1
- package/dist/controls/form-layout.js +1 -1
- package/dist/controls/glyphs.d.ts +0 -2
- package/dist/controls/glyphs.d.ts.map +1 -1
- package/dist/controls/glyphs.js +0 -7
- package/dist/controls/index.d.ts +12 -17
- package/dist/controls/index.d.ts.map +1 -1
- package/dist/controls/index.js +5 -39
- package/dist/controls/multi-select-filter.d.ts +4 -3
- package/dist/controls/multi-select-filter.d.ts.map +1 -1
- package/dist/controls/number-filter.d.ts +4 -3
- package/dist/controls/number-filter.d.ts.map +1 -1
- package/dist/controls/number-filter.js +3 -1
- package/dist/controls/range-filter.d.ts +4 -3
- package/dist/controls/range-filter.d.ts.map +1 -1
- package/dist/controls/search-filter.d.ts +4 -3
- package/dist/controls/search-filter.d.ts.map +1 -1
- package/dist/controls/search-filter.js +19 -14
- package/dist/controls/select-filter.d.ts +4 -3
- package/dist/controls/select-filter.d.ts.map +1 -1
- package/dist/controls/sync-button.d.ts.map +1 -1
- package/dist/controls/sync-button.js +12 -15
- package/dist/controls/toggle-filter.d.ts +4 -3
- package/dist/controls/toggle-filter.d.ts.map +1 -1
- package/dist/controls/uncontrolled.d.ts +12 -0
- package/dist/controls/uncontrolled.d.ts.map +1 -0
- package/dist/controls/view-tabs.d.ts +2 -2
- package/dist/controls/view-tabs.d.ts.map +1 -1
- package/dist/controls-dates/index.d.ts +0 -1
- package/dist/controls-dates/index.d.ts.map +1 -1
- package/dist/dashboard/index.d.ts +7 -9
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +3 -23
- package/dist/dashboard/section.d.ts +4 -6
- package/dist/dashboard/section.d.ts.map +1 -1
- package/dist/dashboard/section.js +4 -10
- package/dist/dashboard/stat-card.d.ts +4 -4
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +3 -3
- package/dist/dashboard/widget-header.module.css +9 -7
- package/dist/dev-dock.d.ts.map +1 -1
- package/dist/dev-dock.js +6 -1
- package/dist/format/date.d.ts +0 -34
- package/dist/format/date.d.ts.map +1 -1
- package/dist/format/date.js +0 -54
- package/dist/format/index.d.ts +7 -22
- package/dist/format/index.d.ts.map +1 -1
- package/dist/format/index.js +2 -43
- package/dist/format/number.d.ts +3 -14
- package/dist/format/number.d.ts.map +1 -1
- package/dist/format/number.js +0 -13
- package/dist/format/shared.d.ts +2 -3
- package/dist/format/shared.d.ts.map +1 -1
- package/dist/forms/index.d.ts +0 -11
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +1 -14
- package/dist/guard/index.d.ts +6 -21
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +27 -115
- package/dist/guard/types.d.ts +7 -18
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +16 -48
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -117
- package/dist/provider/create-router.d.ts +44 -0
- package/dist/provider/create-router.d.ts.map +1 -0
- package/dist/provider/create-router.js +62 -0
- package/dist/provider/hotkeys.d.ts +8 -0
- package/dist/provider/hotkeys.d.ts.map +1 -0
- package/dist/provider/hotkeys.js +50 -0
- package/dist/provider/index.d.ts +33 -110
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +182 -82
- package/dist/provider/lab-theme.d.ts.map +1 -1
- package/dist/provider/route-transition.d.ts +76 -0
- package/dist/provider/route-transition.d.ts.map +1 -0
- package/dist/provider/route-transition.js +98 -0
- package/dist/provider/spotlight-actions.d.ts +10 -0
- package/dist/provider/spotlight-actions.d.ts.map +1 -0
- package/dist/provider/spotlight-actions.js +55 -0
- package/dist/provider/test-router.d.ts +6 -0
- package/dist/provider/test-router.d.ts.map +1 -0
- package/dist/provider/test-router.js +18 -0
- package/dist/query-client.d.ts +4 -20
- package/dist/query-client.d.ts.map +1 -1
- package/dist/query-client.js +2 -2
- package/dist/router-tanstack/index.d.ts +18 -64
- package/dist/router-tanstack/index.d.ts.map +1 -1
- package/dist/router-tanstack/index.js +2 -16
- package/dist/router-tanstack/nav.d.ts +12 -1
- package/dist/router-tanstack/nav.d.ts.map +1 -1
- package/dist/router-tanstack/nav.js +8 -1
- package/dist/router-tanstack/search-store.d.ts +1 -1
- package/dist/router-tanstack/search-store.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.d.ts +8 -9
- package/dist/router-tanstack/use-nav.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.js +20 -1
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +1 -1
- package/dist/shell/index.d.ts +31 -10
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +14 -3
- package/dist/shell/page-aside.d.ts +2 -2
- package/dist/shell/page-aside.d.ts.map +1 -1
- package/dist/shell/page-aside.js +31 -12
- package/dist/shell/page-bar.d.ts +2 -2
- package/dist/shell/page-bar.d.ts.map +1 -1
- package/dist/shell/page-bar.js +1 -1
- package/dist/state.d.ts +10 -12
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +4 -6
- package/dist/styles.css +107 -7
- package/dist/surfaces.d.ts +28 -103
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +54 -143
- package/dist/{data → table}/data-table-state.d.ts +1 -1
- package/dist/table/data-table-state.d.ts.map +1 -0
- package/dist/{data → table}/data-table-state.js +4 -3
- package/dist/{data → table}/data-table.d.ts +28 -49
- package/dist/table/data-table.d.ts.map +1 -0
- package/dist/{data → table}/data-table.js +74 -60
- package/dist/table/index.d.ts +18 -0
- package/dist/table/index.d.ts.map +1 -0
- package/dist/{data/table.js → table/index.js} +1 -1
- package/dist/table/query-branch.d.ts.map +1 -0
- package/dist/table/table-features.d.ts +69 -0
- package/dist/table/table-features.d.ts.map +1 -0
- package/dist/table/table-features.js +49 -0
- package/dist/telemetry.d.ts +77 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +33 -0
- package/dist/theme/index.d.ts +10 -21
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +3 -14
- package/dist/theme/theme-toggle.d.ts.map +1 -1
- package/dist/theme/theme-toggle.js +7 -33
- package/dist/theme/theme-toggle.module.css +30 -0
- package/dist/theme/theme-toggle.module.css.d.ts +10 -0
- package/dist/theme-lab/derive-controls.d.ts.map +1 -1
- package/dist/theme-lab/derive-controls.js +5 -3
- package/dist/theme-lab/derive-state.d.ts.map +1 -1
- package/dist/theme-lab/derive-state.js +2 -1
- package/dist/tokens/core.d.ts +360 -0
- package/dist/tokens/core.d.ts.map +1 -0
- package/dist/tokens/core.js +708 -0
- package/dist/tokens/derive.d.ts +1 -1
- package/dist/tokens/derive.d.ts.map +1 -1
- package/dist/tokens/index.d.ts +5 -373
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +8 -700
- package/dist/tokens/palette.d.ts +2 -6
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +1 -4
- package/dist/vite.d.ts +4 -3
- package/dist/vite.d.ts.map +1 -1
- package/llms.txt +43 -85
- package/package.json +80 -173
- package/src/agent/ai-sdk-transport.ts +57 -37
- package/src/{agent-chat → agent/chat}/composer.tsx +29 -30
- package/src/{agent-chat → agent/chat}/message-affordances.ts +8 -5
- package/src/{agent-chat → agent/chat}/thread-feed-row.tsx +30 -35
- package/src/{agent-chat → agent/chat}/thread-feed.tsx +40 -35
- package/src/{agent-chat → agent/chat}/thread-message.tsx +37 -35
- package/src/{agent-chat → agent/chat}/thread-outcome-card.tsx +5 -5
- package/src/{agent-chat → agent/chat}/tool-chip.tsx +12 -12
- package/src/{agent-chat → agent/chat}/use-keyboard-inset.ts +1 -1
- package/src/{agent-chat → agent/chat}/virtualize.ts +5 -5
- package/src/agent/error.ts +43 -0
- package/src/agent/history.ts +2 -107
- package/src/agent/id.ts +4 -5
- package/src/agent/index.ts +23 -112
- package/src/agent/outcome.ts +3 -56
- package/src/agent/part-list.tsx +3 -3
- package/src/agent/parts.ts +23 -22
- package/src/agent/run-committer.ts +64 -0
- package/src/agent/run-records.ts +147 -0
- package/src/agent/thread.ts +24 -231
- package/src/agent/transport.ts +6 -96
- package/src/agent/use-agent-thread-runs.ts +364 -199
- package/src/charts/BandStrip.tsx +276 -0
- package/src/charts/Bars.tsx +141 -0
- package/src/charts/CartesianChart.tsx +206 -0
- package/src/charts/ChartCard.tsx +178 -0
- package/src/charts/Donut.tsx +256 -0
- package/src/charts/DualPanel.tsx +326 -0
- package/src/charts/Heatmap.tsx +282 -0
- package/src/charts/Lines.tsx +151 -0
- package/src/charts/MirroredBars.tsx +303 -0
- package/src/charts/Sparkline.tsx +176 -0
- package/src/charts/StackedArea.tsx +80 -0
- package/src/charts/box.tsx +96 -0
- package/src/charts/card-context.ts +11 -0
- package/src/charts/chart-box.module.css +64 -0
- package/src/charts/chart-box.module.css.d.ts +12 -0
- package/src/charts/chart-card.module.css +25 -0
- package/src/charts/chart-card.module.css.d.ts +8 -0
- package/src/charts/chart-legend.module.css +38 -0
- package/src/charts/chart-legend.module.css.d.ts +10 -0
- package/src/charts/compile.ts +585 -0
- package/src/charts/cursor.ts +282 -0
- package/src/charts/curves.ts +111 -0
- package/src/charts/donut.module.css +54 -0
- package/src/charts/donut.module.css.d.ts +9 -0
- package/src/charts/host.tsx +60 -0
- package/src/charts/index.ts +41 -178
- package/src/charts/legend.tsx +204 -0
- package/src/charts/marks.ts +201 -0
- package/src/charts/panel.tsx +227 -0
- package/src/charts/scales.ts +237 -0
- package/src/charts/sizing.ts +47 -0
- package/src/charts/state.tsx +80 -0
- package/src/charts/theme.ts +65 -0
- package/src/charts/types.ts +242 -0
- package/src/cli/audit-allows.ts +8 -30
- package/src/cli/config.ts +26 -43
- package/src/cli/doctor-upgrade.ts +457 -0
- package/src/cli/doctor.ts +89 -72
- package/src/cli/help.ts +2 -4
- package/src/cli/index.ts +100 -384
- package/src/cli/init.ts +60 -51
- package/src/cli/sync.ts +13 -68
- package/src/cli/tokens-css.ts +7 -28
- package/src/commands/ShortcutsHelp.tsx +8 -9
- package/src/commands/define-commands.ts +16 -43
- package/src/commands/define-overlays.ts +12 -36
- package/src/commands/index.ts +11 -94
- package/src/{notifications → commands/notifications}/bell.tsx +2 -2
- package/src/{notifications → commands/notifications}/center.tsx +7 -5
- package/src/{notifications → commands/notifications}/define-notifications.ts +3 -3
- package/src/commands/notifications/notify.tsx +158 -0
- package/src/{notifications → commands/notifications}/store.ts +10 -2
- package/src/commands/projectors.ts +5 -225
- package/src/commands/shell-bridge.ts +5 -5
- package/src/commands/shortcut-format.ts +5 -4
- package/src/common/errors.ts +3 -3
- package/src/common/use-measured-widths.ts +6 -3
- package/src/common/validate.ts +2 -2
- package/src/content/article-layout.tsx +37 -38
- package/src/content/article-model.ts +1 -84
- package/src/content/index.ts +12 -83
- package/src/content/markdown.tsx +4 -3
- package/src/content/mermaid.tsx +9 -7
- package/src/content/slug.ts +1 -16
- package/src/content/url-hardening.ts +8 -2
- package/src/controls/actions.tsx +24 -1
- package/src/controls/enum-filter.tsx +1 -1
- package/src/controls/filter-context.tsx +3 -1
- package/src/controls/filter-set.tsx +5 -7
- package/src/controls/form-layout.tsx +2 -2
- package/src/controls/glyphs.tsx +0 -10
- package/src/controls/index.ts +13 -64
- package/src/controls/multi-select-filter.tsx +5 -4
- package/src/controls/number-filter.tsx +8 -4
- package/src/controls/range-filter.tsx +5 -4
- package/src/controls/search-filter.tsx +25 -19
- package/src/controls/select-filter.tsx +5 -4
- package/src/controls/sync-button.tsx +18 -20
- package/src/controls/toggle-filter.tsx +5 -4
- package/src/controls/uncontrolled.ts +12 -0
- package/src/controls/view-tabs.tsx +3 -3
- package/src/controls-dates/date-range-picker.tsx +1 -1
- package/src/controls-dates/index.ts +0 -1
- package/src/dashboard/index.ts +7 -48
- package/src/dashboard/section.tsx +11 -40
- package/src/dashboard/stat-card.tsx +14 -16
- package/src/dashboard/widget-header.module.css +9 -7
- package/src/dev-dock.tsx +14 -27
- package/src/format/date.ts +2 -92
- package/src/format/index.ts +7 -53
- package/src/format/number.ts +3 -26
- package/src/format/shared.ts +2 -3
- package/src/forms/index.ts +0 -23
- package/src/guard/index.ts +36 -191
- package/src/guard/types.ts +6 -19
- package/src/index.ts +30 -282
- package/src/provider/create-router.tsx +138 -0
- package/src/provider/hotkeys.ts +70 -0
- package/src/provider/index.tsx +260 -230
- package/src/provider/lab-theme.ts +3 -2
- package/src/provider/route-transition.ts +199 -0
- package/src/provider/spotlight-actions.tsx +69 -0
- package/src/provider/test-router.tsx +25 -0
- package/src/query-client.ts +4 -22
- package/src/router-tanstack/index.ts +18 -112
- package/src/router-tanstack/nav.ts +28 -2
- package/src/router-tanstack/search-store.ts +9 -2
- package/src/router-tanstack/use-nav.ts +47 -13
- package/src/shell/app-mobile-nav.tsx +3 -2
- package/src/shell/app-sidebar.tsx +1 -1
- package/src/shell/aside-docking.ts +1 -1
- package/src/shell/index.tsx +61 -20
- package/src/shell/page-aside.tsx +47 -23
- package/src/shell/page-bar.tsx +3 -3
- package/src/shell/page-title.tsx +1 -1
- package/src/state.ts +11 -37
- package/src/styles.css +107 -7
- package/src/surfaces.ts +56 -151
- package/src/{data → table}/data-table-state.ts +5 -4
- package/src/{data → table}/data-table.tsx +170 -161
- package/src/table/index.ts +18 -0
- package/src/table/table-features.ts +102 -0
- package/src/telemetry.ts +110 -0
- package/src/theme/index.ts +22 -47
- package/src/theme/theme-toggle.module.css +30 -0
- package/src/theme/theme-toggle.module.css.d.ts +10 -0
- package/src/theme/theme-toggle.tsx +15 -43
- package/src/theme-lab/derive-controls.tsx +5 -3
- package/src/theme-lab/derive-state.ts +2 -1
- package/src/tokens/core.ts +1163 -0
- package/src/tokens/derive.ts +1 -1
- package/src/tokens/index.ts +14 -1181
- package/src/tokens/palette.ts +3 -7
- package/src/vite.ts +3 -3
- package/agent/templates/query-client.ts.tpl +0 -26
- package/dist/agent/adapter.d.ts +0 -150
- package/dist/agent/adapter.d.ts.map +0 -1
- package/dist/agent/adapter.js +0 -482
- package/dist/agent/use-agent-stream.d.ts +0 -35
- package/dist/agent/use-agent-stream.d.ts.map +0 -1
- package/dist/agent/use-agent-stream.js +0 -59
- package/dist/agent-chat/composer.d.ts.map +0 -1
- package/dist/agent-chat/index.d.ts +0 -31
- package/dist/agent-chat/index.d.ts.map +0 -1
- package/dist/agent-chat/index.js +0 -19
- package/dist/agent-chat/message-affordances.d.ts.map +0 -1
- package/dist/agent-chat/relative-time.d.ts.map +0 -1
- package/dist/agent-chat/thread-detail-panel.d.ts +0 -28
- package/dist/agent-chat/thread-detail-panel.d.ts.map +0 -1
- package/dist/agent-chat/thread-detail-panel.js +0 -115
- package/dist/agent-chat/thread-feed-row.d.ts.map +0 -1
- package/dist/agent-chat/thread-feed.d.ts.map +0 -1
- package/dist/agent-chat/thread-message.d.ts.map +0 -1
- package/dist/agent-chat/thread-outcome-card.d.ts.map +0 -1
- package/dist/agent-chat/thread-workspace.d.ts +0 -44
- package/dist/agent-chat/thread-workspace.d.ts.map +0 -1
- package/dist/agent-chat/thread-workspace.js +0 -153
- package/dist/agent-chat/tool-chip.d.ts.map +0 -1
- package/dist/agent-chat/use-keyboard-inset.d.ts.map +0 -1
- package/dist/agent-chat/virtualize.d.ts.map +0 -1
- package/dist/charts/cursor/resolve.d.ts +0 -75
- package/dist/charts/cursor/resolve.d.ts.map +0 -1
- package/dist/charts/cursor/resolve.js +0 -91
- package/dist/charts/cursor/scope.d.ts +0 -20
- package/dist/charts/cursor/scope.d.ts.map +0 -1
- package/dist/charts/cursor/scope.js +0 -20
- package/dist/charts/cursor/store.d.ts +0 -35
- package/dist/charts/cursor/store.d.ts.map +0 -1
- package/dist/charts/cursor/store.js +0 -25
- package/dist/charts/cursor/touch-pin.d.ts +0 -45
- package/dist/charts/cursor/touch-pin.d.ts.map +0 -1
- package/dist/charts/cursor/touch-pin.js +0 -79
- package/dist/charts/hooks/use-discrete-cursor.d.ts +0 -66
- package/dist/charts/hooks/use-discrete-cursor.d.ts.map +0 -1
- package/dist/charts/hooks/use-discrete-cursor.js +0 -198
- package/dist/charts/hooks/use-hysteresis.d.ts +0 -18
- package/dist/charts/hooks/use-hysteresis.d.ts.map +0 -1
- package/dist/charts/hooks/use-hysteresis.js +0 -12
- package/dist/charts/hooks/useBandPlot.d.ts +0 -145
- package/dist/charts/hooks/useBandPlot.d.ts.map +0 -1
- package/dist/charts/hooks/useBandPlot.js +0 -178
- package/dist/charts/hooks/useChartCursor.d.ts +0 -75
- package/dist/charts/hooks/useChartCursor.d.ts.map +0 -1
- package/dist/charts/hooks/useChartCursor.js +0 -200
- package/dist/charts/hooks/useChartSize.d.ts +0 -29
- package/dist/charts/hooks/useChartSize.d.ts.map +0 -1
- package/dist/charts/hooks/useChartSize.js +0 -8
- package/dist/charts/kinds/BandStrip.d.ts +0 -132
- package/dist/charts/kinds/BandStrip.d.ts.map +0 -1
- package/dist/charts/kinds/BandStrip.js +0 -241
- package/dist/charts/kinds/Bars.d.ts +0 -141
- package/dist/charts/kinds/Bars.d.ts.map +0 -1
- package/dist/charts/kinds/Bars.js +0 -343
- package/dist/charts/kinds/Donut.d.ts +0 -77
- package/dist/charts/kinds/Donut.d.ts.map +0 -1
- package/dist/charts/kinds/Donut.js +0 -245
- package/dist/charts/kinds/DualPanel.d.ts +0 -111
- package/dist/charts/kinds/DualPanel.d.ts.map +0 -1
- package/dist/charts/kinds/DualPanel.js +0 -471
- package/dist/charts/kinds/Heatmap.d.ts +0 -85
- package/dist/charts/kinds/Heatmap.d.ts.map +0 -1
- package/dist/charts/kinds/Heatmap.js +0 -243
- package/dist/charts/kinds/MirroredBars.d.ts +0 -98
- package/dist/charts/kinds/MirroredBars.d.ts.map +0 -1
- package/dist/charts/kinds/MirroredBars.js +0 -292
- package/dist/charts/kinds/MultiLine.d.ts +0 -87
- package/dist/charts/kinds/MultiLine.d.ts.map +0 -1
- package/dist/charts/kinds/MultiLine.js +0 -176
- package/dist/charts/kinds/StackedArea.d.ts +0 -73
- package/dist/charts/kinds/StackedArea.d.ts.map +0 -1
- package/dist/charts/kinds/StackedArea.js +0 -135
- package/dist/charts/kinds/ZonedLine.d.ts +0 -97
- package/dist/charts/kinds/ZonedLine.d.ts.map +0 -1
- package/dist/charts/kinds/ZonedLine.js +0 -155
- package/dist/charts/kinds/band-chrome.d.ts +0 -31
- package/dist/charts/kinds/band-chrome.d.ts.map +0 -1
- package/dist/charts/kinds/band-chrome.js +0 -71
- package/dist/charts/kinds/donut-layout.d.ts +0 -47
- package/dist/charts/kinds/donut-layout.d.ts.map +0 -1
- package/dist/charts/kinds/donut-layout.js +0 -52
- package/dist/charts/layout/auto-margin.d.ts +0 -122
- package/dist/charts/layout/auto-margin.d.ts.map +0 -1
- package/dist/charts/layout/auto-margin.js +0 -81
- package/dist/charts/layout/end-labels.d.ts +0 -64
- package/dist/charts/layout/end-labels.d.ts.map +0 -1
- package/dist/charts/layout/end-labels.js +0 -76
- package/dist/charts/layout/log-ticks.d.ts +0 -27
- package/dist/charts/layout/log-ticks.d.ts.map +0 -1
- package/dist/charts/layout/log-ticks.js +0 -42
- package/dist/charts/primitives/AreaGradient.d.ts +0 -18
- package/dist/charts/primitives/AreaGradient.d.ts.map +0 -1
- package/dist/charts/primitives/AreaGradient.js +0 -13
- package/dist/charts/primitives/Axes.d.ts +0 -83
- package/dist/charts/primitives/Axes.d.ts.map +0 -1
- package/dist/charts/primitives/Axes.js +0 -168
- package/dist/charts/primitives/CartesianChart.d.ts +0 -257
- package/dist/charts/primitives/CartesianChart.d.ts.map +0 -1
- package/dist/charts/primitives/CartesianChart.js +0 -549
- package/dist/charts/primitives/ChartCard.d.ts +0 -66
- package/dist/charts/primitives/ChartCard.d.ts.map +0 -1
- package/dist/charts/primitives/ChartCard.js +0 -143
- package/dist/charts/primitives/ChartFrame.d.ts +0 -156
- package/dist/charts/primitives/ChartFrame.d.ts.map +0 -1
- package/dist/charts/primitives/ChartFrame.js +0 -241
- package/dist/charts/primitives/ChartLegend.d.ts +0 -67
- package/dist/charts/primitives/ChartLegend.d.ts.map +0 -1
- package/dist/charts/primitives/ChartLegend.js +0 -292
- package/dist/charts/primitives/ChartPending.d.ts +0 -113
- package/dist/charts/primitives/ChartPending.d.ts.map +0 -1
- package/dist/charts/primitives/ChartPending.js +0 -117
- package/dist/charts/primitives/ChartTooltip.d.ts +0 -59
- package/dist/charts/primitives/ChartTooltip.d.ts.map +0 -1
- package/dist/charts/primitives/ChartTooltip.js +0 -197
- package/dist/charts/primitives/Crosshair.d.ts +0 -26
- package/dist/charts/primitives/Crosshair.d.ts.map +0 -1
- package/dist/charts/primitives/Crosshair.js +0 -23
- package/dist/charts/primitives/HatchPattern.d.ts +0 -31
- package/dist/charts/primitives/HatchPattern.d.ts.map +0 -1
- package/dist/charts/primitives/HatchPattern.js +0 -31
- package/dist/charts/primitives/HoverOverlay.d.ts +0 -45
- package/dist/charts/primitives/HoverOverlay.d.ts.map +0 -1
- package/dist/charts/primitives/HoverOverlay.js +0 -72
- package/dist/charts/primitives/HoverOverlay.module.css +0 -13
- package/dist/charts/primitives/HoverOverlay.module.css.d.ts +0 -8
- package/dist/charts/primitives/XZoneRects.d.ts +0 -54
- package/dist/charts/primitives/XZoneRects.d.ts.map +0 -1
- package/dist/charts/primitives/XZoneRects.js +0 -65
- package/dist/charts/primitives/ZoneRects.d.ts +0 -38
- package/dist/charts/primitives/ZoneRects.d.ts.map +0 -1
- package/dist/charts/primitives/ZoneRects.js +0 -30
- package/dist/charts/primitives/chart-card-context.d.ts +0 -33
- package/dist/charts/primitives/chart-card-context.d.ts.map +0 -1
- package/dist/charts/primitives/chart-card-context.js +0 -18
- package/dist/charts/primitives/chart-frame-layout.d.ts +0 -185
- package/dist/charts/primitives/chart-frame-layout.d.ts.map +0 -1
- package/dist/charts/primitives/chart-frame-layout.js +0 -175
- package/dist/charts/primitives/chart-layout.d.ts +0 -112
- package/dist/charts/primitives/chart-layout.d.ts.map +0 -1
- package/dist/charts/primitives/chart-layout.js +0 -175
- package/dist/charts/primitives/chart-tier.d.ts +0 -16
- package/dist/charts/primitives/chart-tier.d.ts.map +0 -1
- package/dist/charts/primitives/chart-tier.js +0 -44
- package/dist/charts/primitives/legend-disclosure.d.ts +0 -27
- package/dist/charts/primitives/legend-disclosure.d.ts.map +0 -1
- package/dist/charts/primitives/legend-disclosure.js +0 -153
- package/dist/charts/series.d.ts +0 -189
- package/dist/charts/series.d.ts.map +0 -1
- package/dist/charts/series.js +0 -84
- package/dist/charts/sparklines/BarSparkline.d.ts +0 -37
- package/dist/charts/sparklines/BarSparkline.d.ts.map +0 -1
- package/dist/charts/sparklines/BarSparkline.js +0 -53
- package/dist/charts/sparklines/LineSparkline.d.ts +0 -15
- package/dist/charts/sparklines/LineSparkline.d.ts.map +0 -1
- package/dist/charts/sparklines/LineSparkline.js +0 -51
- package/dist/charts/sparklines/index.d.ts +0 -3
- package/dist/charts/sparklines/index.d.ts.map +0 -1
- package/dist/charts/sparklines/index.js +0 -6
- package/dist/charts/utils/domain.d.ts +0 -35
- package/dist/charts/utils/domain.d.ts.map +0 -1
- package/dist/charts/utils/domain.js +0 -12
- package/dist/charts/utils/format.d.ts +0 -8
- package/dist/charts/utils/format.d.ts.map +0 -1
- package/dist/charts/utils/format.js +0 -20
- package/dist/charts/utils/measure-text.d.ts +0 -25
- package/dist/charts/utils/measure-text.d.ts.map +0 -1
- package/dist/charts/utils/measure-text.js +0 -64
- package/dist/charts/utils/ticks.d.ts +0 -103
- package/dist/charts/utils/ticks.d.ts.map +0 -1
- package/dist/charts/utils/ticks.js +0 -92
- package/dist/commands/overlays-mount.d.ts +0 -122
- package/dist/commands/overlays-mount.d.ts.map +0 -1
- package/dist/commands/overlays-mount.js +0 -125
- package/dist/commands/useCommandHotkeys.d.ts +0 -14
- package/dist/commands/useCommandHotkeys.d.ts.map +0 -1
- package/dist/commands/useCommandHotkeys.js +0 -45
- package/dist/content/article-actions.d.ts +0 -39
- package/dist/content/article-actions.d.ts.map +0 -1
- package/dist/content/article-actions.js +0 -28
- package/dist/content/article-card.d.ts +0 -58
- package/dist/content/article-card.d.ts.map +0 -1
- package/dist/content/article-card.js +0 -79
- package/dist/content/article-card.module.css +0 -111
- package/dist/content/mdx.d.ts +0 -20
- package/dist/content/mdx.d.ts.map +0 -1
- package/dist/content/mdx.js +0 -64
- package/dist/controls/compare-filter.d.ts +0 -42
- package/dist/controls/compare-filter.d.ts.map +0 -1
- package/dist/controls/compare-filter.js +0 -38
- package/dist/controls/slider-control.d.ts +0 -36
- package/dist/controls/slider-control.d.ts.map +0 -1
- package/dist/controls/slider-control.js +0 -64
- package/dist/dashboard/widget-grid.d.ts +0 -27
- package/dist/dashboard/widget-grid.d.ts.map +0 -1
- package/dist/dashboard/widget-grid.js +0 -40
- package/dist/dashboard/widget-grid.module.css +0 -69
- package/dist/data/data-table-state.d.ts.map +0 -1
- package/dist/data/data-table.d.ts.map +0 -1
- package/dist/data/query-branch.d.ts.map +0 -1
- package/dist/data/table.d.ts +0 -24
- package/dist/data/table.d.ts.map +0 -1
- package/dist/data/virtual-list.d.ts +0 -133
- package/dist/data/virtual-list.d.ts.map +0 -1
- package/dist/data/virtual-list.js +0 -157
- package/dist/data/virtual.d.ts +0 -21
- package/dist/data/virtual.d.ts.map +0 -1
- package/dist/data/virtual.js +0 -4
- package/dist/forms/FormErrorSummary.d.ts +0 -30
- package/dist/forms/FormErrorSummary.d.ts.map +0 -1
- package/dist/forms/FormErrorSummary.js +0 -30
- package/dist/forms/use-field-array.d.ts +0 -60
- package/dist/forms/use-field-array.d.ts.map +0 -1
- package/dist/forms/use-field-array.js +0 -20
- package/dist/forms/use-form-draft.d.ts +0 -76
- package/dist/forms/use-form-draft.d.ts.map +0 -1
- package/dist/forms/use-form-draft.js +0 -92
- package/dist/forms/use-form-submit.d.ts +0 -88
- package/dist/forms/use-form-submit.d.ts.map +0 -1
- package/dist/forms/use-form-submit.js +0 -63
- package/dist/notifications/bell.d.ts.map +0 -1
- package/dist/notifications/center.d.ts.map +0 -1
- package/dist/notifications/define-notifications.d.ts.map +0 -1
- package/dist/notifications/index.d.ts +0 -40
- package/dist/notifications/index.d.ts.map +0 -1
- package/dist/notifications/index.js +0 -54
- package/dist/notifications/mount-guard.d.ts +0 -8
- package/dist/notifications/mount-guard.d.ts.map +0 -1
- package/dist/notifications/mount-guard.js +0 -18
- package/dist/notifications/notify.d.ts +0 -149
- package/dist/notifications/notify.d.ts.map +0 -1
- package/dist/notifications/notify.js +0 -171
- package/dist/notifications/store.d.ts.map +0 -1
- package/dist/provider/connectivity-indicator.d.ts +0 -13
- package/dist/provider/connectivity-indicator.d.ts.map +0 -1
- package/dist/provider/connectivity-indicator.js +0 -205
- package/dist/provider/connectivity-provider.d.ts +0 -7
- package/dist/provider/connectivity-provider.d.ts.map +0 -1
- package/dist/provider/connectivity-provider.js +0 -128
- package/dist/provider/connectivity-types.d.ts +0 -36
- package/dist/provider/connectivity-types.d.ts.map +0 -1
- package/dist/provider/use-connectivity.d.ts +0 -3
- package/dist/provider/use-connectivity.d.ts.map +0 -1
- package/dist/provider/use-connectivity.js +0 -14
- package/dist/query-devtools.d.ts +0 -21
- package/dist/query-devtools.d.ts.map +0 -1
- package/dist/query-devtools.js +0 -13
- package/src/agent/adapter.ts +0 -945
- package/src/agent/use-agent-stream.ts +0 -154
- package/src/agent-chat/index.ts +0 -54
- package/src/agent-chat/thread-detail-panel.tsx +0 -201
- package/src/agent-chat/thread-workspace.tsx +0 -279
- package/src/charts/cursor/resolve.ts +0 -198
- package/src/charts/cursor/scope.tsx +0 -35
- package/src/charts/cursor/store.ts +0 -58
- package/src/charts/cursor/touch-pin.ts +0 -138
- package/src/charts/hooks/use-discrete-cursor.ts +0 -335
- package/src/charts/hooks/use-hysteresis.ts +0 -26
- package/src/charts/hooks/useBandPlot.ts +0 -383
- package/src/charts/hooks/useChartCursor.ts +0 -367
- package/src/charts/hooks/useChartSize.ts +0 -35
- package/src/charts/kinds/BandStrip.tsx +0 -449
- package/src/charts/kinds/Bars.tsx +0 -589
- package/src/charts/kinds/Donut.tsx +0 -368
- package/src/charts/kinds/DualPanel.tsx +0 -712
- package/src/charts/kinds/Heatmap.tsx +0 -396
- package/src/charts/kinds/MirroredBars.tsx +0 -469
- package/src/charts/kinds/MultiLine.tsx +0 -322
- package/src/charts/kinds/StackedArea.tsx +0 -267
- package/src/charts/kinds/ZonedLine.tsx +0 -301
- package/src/charts/kinds/band-chrome.tsx +0 -91
- package/src/charts/kinds/donut-layout.ts +0 -82
- package/src/charts/layout/auto-margin.ts +0 -242
- package/src/charts/layout/end-labels.ts +0 -135
- package/src/charts/layout/log-ticks.ts +0 -90
- package/src/charts/primitives/AreaGradient.tsx +0 -26
- package/src/charts/primitives/Axes.tsx +0 -271
- package/src/charts/primitives/CartesianChart.tsx +0 -1002
- package/src/charts/primitives/ChartCard.tsx +0 -280
- package/src/charts/primitives/ChartFrame.tsx +0 -493
- package/src/charts/primitives/ChartLegend.tsx +0 -422
- package/src/charts/primitives/ChartPending.tsx +0 -243
- package/src/charts/primitives/ChartTooltip.tsx +0 -265
- package/src/charts/primitives/Crosshair.tsx +0 -43
- package/src/charts/primitives/HatchPattern.tsx +0 -55
- package/src/charts/primitives/HoverOverlay.module.css +0 -13
- package/src/charts/primitives/HoverOverlay.module.css.d.ts +0 -8
- package/src/charts/primitives/HoverOverlay.tsx +0 -109
- package/src/charts/primitives/XZoneRects.tsx +0 -132
- package/src/charts/primitives/ZoneRects.tsx +0 -67
- package/src/charts/primitives/chart-card-context.ts +0 -46
- package/src/charts/primitives/chart-frame-layout.ts +0 -430
- package/src/charts/primitives/chart-layout.ts +0 -318
- package/src/charts/primitives/chart-tier.tsx +0 -76
- package/src/charts/primitives/legend-disclosure.tsx +0 -178
- package/src/charts/series.ts +0 -276
- package/src/charts/sparklines/BarSparkline.tsx +0 -94
- package/src/charts/sparklines/LineSparkline.tsx +0 -71
- package/src/charts/sparklines/index.ts +0 -2
- package/src/charts/theme.tsx +0 -53
- package/src/charts/utils/domain.ts +0 -41
- package/src/charts/utils/format.ts +0 -19
- package/src/charts/utils/measure-text.ts +0 -109
- package/src/charts/utils/ticks.ts +0 -239
- package/src/commands/overlays-mount.tsx +0 -333
- package/src/commands/useCommandHotkeys.ts +0 -114
- package/src/content/article-actions.ts +0 -72
- package/src/content/article-card.module.css +0 -111
- package/src/content/article-card.tsx +0 -174
- package/src/content/mdx.tsx +0 -127
- package/src/controls/compare-filter.tsx +0 -81
- package/src/controls/slider-control.tsx +0 -159
- package/src/dashboard/widget-grid.module.css +0 -69
- package/src/dashboard/widget-grid.tsx +0 -146
- package/src/data/table.ts +0 -39
- package/src/data/virtual-list.tsx +0 -356
- package/src/data/virtual.ts +0 -26
- package/src/forms/FormErrorSummary.tsx +0 -71
- package/src/forms/use-field-array.ts +0 -94
- package/src/forms/use-form-draft.ts +0 -262
- package/src/forms/use-form-submit.ts +0 -199
- package/src/notifications/index.ts +0 -88
- package/src/notifications/mount-guard.ts +0 -38
- package/src/notifications/notify.tsx +0 -379
- package/src/provider/connectivity-indicator.tsx +0 -267
- package/src/provider/connectivity-provider.tsx +0 -189
- package/src/provider/connectivity-types.ts +0 -42
- package/src/provider/use-connectivity.ts +0 -26
- package/src/query-devtools.tsx +0 -40
- /package/dist/{agent-chat → agent/chat}/message-affordances.js +0 -0
- /package/dist/{agent-chat → agent/chat}/relative-time.d.ts +0 -0
- /package/dist/{agent-chat → agent/chat}/relative-time.js +0 -0
- /package/dist/{agent-chat → agent/chat}/use-keyboard-inset.d.ts +0 -0
- /package/dist/{agent-chat → agent/chat}/virtualize.js +0 -0
- /package/dist/{notifications → commands/notifications}/bell.js +0 -0
- /package/dist/{notifications → commands/notifications}/define-notifications.js +0 -0
- /package/dist/{provider/connectivity-types.js → controls/uncontrolled.js} +0 -0
- /package/dist/{data → table}/data-table.module.css +0 -0
- /package/dist/{data → table}/data-table.module.css.d.ts +0 -0
- /package/dist/{data → table}/query-branch.d.ts +0 -0
- /package/dist/{data → table}/query-branch.js +0 -0
- /package/src/{agent-chat → agent/chat}/relative-time.ts +0 -0
- /package/src/{data → table}/data-table.module.css +0 -0
- /package/src/{data → table}/data-table.module.css.d.ts +0 -0
- /package/src/{data → table}/query-branch.ts +0 -0
|
@@ -0,0 +1,1163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mantine-free token + palette layer.
|
|
3
|
+
*
|
|
4
|
+
* This module is PURE DATA + string helpers — ZERO `@mantine/*` imports (lint-enforced).
|
|
5
|
+
* Colors are CSS custom properties under the `--vx-*` prefix (do NOT rename the prefix).
|
|
6
|
+
* They resolve per color scheme in CSS, so `VX.*` works in components AND in non-component
|
|
7
|
+
* files. Apply opacity via `alpha(token, a)` (never raw `rgba()`) so the hue keeps resolving.
|
|
8
|
+
*
|
|
9
|
+
* Grounded in argo `packages/charts/src/{tokens,palette,theme-vars,utils/color}.ts`.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
buildPaletteData,
|
|
14
|
+
RADIUS,
|
|
15
|
+
RADIUS_STEP,
|
|
16
|
+
ROW_LINE_HEIGHT,
|
|
17
|
+
SHADOW,
|
|
18
|
+
SPACE,
|
|
19
|
+
SPACE_SCALE,
|
|
20
|
+
SPACE_STEP,
|
|
21
|
+
} from './palette'
|
|
22
|
+
import type { PaletteData, RadiusValues, SpaceValues } from './palette'
|
|
23
|
+
import { SIZE_CLASSES, sizeClassMaxEm } from './size-classes'
|
|
24
|
+
import { HIT_COARSE, HIT_FINE } from '../common/hit-floor'
|
|
25
|
+
import { BASALT_VX_FAMILIES } from '../common/vx-families'
|
|
26
|
+
import { vxFamilyOf } from '../common/vx-family'
|
|
27
|
+
|
|
28
|
+
// The raw hue families + pair-picker — the building blocks a consumer's series module composes
|
|
29
|
+
// (`hrv: p(BP.blue)`). The doctrine sends every consumer to `basalt-ui/tokens`, so they are public
|
|
30
|
+
// surface, not palette internals; dropping them from the public barrel (`./index`) hard-fails the
|
|
31
|
+
// consumer's build (1.0.0 bug, pinned by scripts/export-surface.json).
|
|
32
|
+
export { BP, p } from './palette'
|
|
33
|
+
|
|
34
|
+
// The six-knob derive engine — the generator behind the shipped default palette. Internal: the
|
|
35
|
+
// public barrel (`./index`) does not re-export it; a consumer retunes the palette identity via
|
|
36
|
+
// `createBasaltTheme(overrides, { derive })` (see `../theme`) without hand-picking hexes, and
|
|
37
|
+
// reaches a derived palette through that, not by building `--vx-*` CSS for a custom config directly.
|
|
38
|
+
export { DEFAULT_DERIVE_CONFIG, deriveTokens, resolveDeriveConfig } from './derive'
|
|
39
|
+
export type { DeriveConfig, DerivedPalette } from './derive'
|
|
40
|
+
|
|
41
|
+
// The radius analog of the derive engine — the law behind `createBasaltTheme(overrides, { radius })`
|
|
42
|
+
// (see `../theme`). `RADIUS`/`RADIUS_STEP` stay internal to the theme layer; a consumer retunes the
|
|
43
|
+
// two anchors through `createBasaltTheme`, not by calling `deriveRadius` directly (it is exposed for
|
|
44
|
+
// the law itself to be inspectable/testable, same rationale as `deriveTokens`).
|
|
45
|
+
export { deriveRadius } from './palette'
|
|
46
|
+
export type { RadiusValues } from './palette'
|
|
47
|
+
|
|
48
|
+
// The density analog of the derive engine — the law behind `createBasaltTheme(overrides, {
|
|
49
|
+
// density })` (see `../theme`). `SPACE`/`SPACE_SCALE`/`SPACE_STEP`/`ROW_LINE_HEIGHT` stay internal
|
|
50
|
+
// to the theme layer; a consumer retunes them through `createBasaltTheme`, not by calling
|
|
51
|
+
// `deriveSpacing` directly (it is exposed for the law itself to be inspectable/testable, same
|
|
52
|
+
// rationale as `deriveRadius`).
|
|
53
|
+
export { deriveSpacing } from './palette'
|
|
54
|
+
export type { SpaceValues } from './palette'
|
|
55
|
+
|
|
56
|
+
// The two responsive tables — MIGRATING recipes and the raw-breakpoint guard messages send
|
|
57
|
+
// consumers here for them; `migrating-imports.test.ts` pins that every documented import resolves.
|
|
58
|
+
export {
|
|
59
|
+
CONTAINER_CLASSES,
|
|
60
|
+
CONTAINER_GRID_BREAKPOINTS,
|
|
61
|
+
CONTAINER_KEYS,
|
|
62
|
+
resolveContainerClass,
|
|
63
|
+
SIZE_CLASSES,
|
|
64
|
+
} from './size-classes'
|
|
65
|
+
export type { ContainerClass } from './size-classes'
|
|
66
|
+
|
|
67
|
+
/** A per-theme color pair: a hue keeps its identity but shifts shade across schemes. */
|
|
68
|
+
export type ColorPair = { light: string; dark: string }
|
|
69
|
+
|
|
70
|
+
/** A map of token name → per-theme color pair (the input shape for series/group builders). */
|
|
71
|
+
export type SeriesMap = Record<string, ColorPair>
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Apply opacity to any palette token, theme-aware. Use instead of raw `rgba()` so the
|
|
75
|
+
* underlying hue still resolves per color scheme.
|
|
76
|
+
*
|
|
77
|
+
* alpha(VX.neutral, 0.5) // muted hairline
|
|
78
|
+
* alpha(VX.status.warn, 0.1) // zone-band fill
|
|
79
|
+
*/
|
|
80
|
+
export const alpha = (token: string, a: number): string =>
|
|
81
|
+
`color-mix(in srgb, ${token} ${Math.round(a * 100)}%, transparent)`
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* VX tokens — `var(--vx-*)` string refs + non-color sizing constants. Colors resolve per
|
|
85
|
+
* color scheme in CSS, so `VX.*` works in components AND in non-component files. Never
|
|
86
|
+
* reference raw hex in chart files — use `VX.*` / `alpha()`.
|
|
87
|
+
*
|
|
88
|
+
* The framework ships ONLY generic primitives — no domain `VX.series` tree (apps rebuild
|
|
89
|
+
* that with `seriesTokens` / `groupTokens` against their own series maps).
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* The type scale — the ONE owned ladder, in px.
|
|
93
|
+
*
|
|
94
|
+
* Type is a token axis like color / spacing / radius / motion: a single edit point, never a
|
|
95
|
+
* hardcoded literal at a call site. Every font-size in the framework resolves to a step here.
|
|
96
|
+
*
|
|
97
|
+
* Two representations are DERIVED from this one object, so they cannot drift:
|
|
98
|
+
* • `VX.text.*` — plain numbers, for inline `style` objects and visx SVG props (React appends
|
|
99
|
+
* `px`; SVG presentation attributes can't resolve `var()`, so a ref string would break charts).
|
|
100
|
+
* • `--vx-text-*` — the CSS-var form (`11px`, …), for CSS modules and the Mantine theme.
|
|
101
|
+
*
|
|
102
|
+
* The Mantine theme additionally re-expresses the ladder through Mantine's `rem()` (see
|
|
103
|
+
* `theme/index.ts`), so the component surface scales with the user's browser font-size AND with
|
|
104
|
+
* `--mantine-scale`. `md` is the body step; `lg` is pinned at exactly 16px because it doubles as
|
|
105
|
+
* the iOS input floor (see the `styles.css` floor — Safari zooms the viewport on focus below 16px).
|
|
106
|
+
*
|
|
107
|
+
* ## Adding a rung
|
|
108
|
+
*
|
|
109
|
+
* The ladder is hand-tuned per ROLE, not generated — but it is not arbitrary either, and the
|
|
110
|
+
* constraint is what keeps a "just add the size I need" request from dissolving it. Every adjacent
|
|
111
|
+
* pair sits between **1.06× and 1.17×**, so a new rung must too:
|
|
112
|
+
*
|
|
113
|
+
* • Below the range, two rungs are visually the same size and the ladder stops being a choice —
|
|
114
|
+
* the guard would then report a size for which two tokens are equally "right".
|
|
115
|
+
* • Above it, the jump reads as a different type system rather than the next step of this one.
|
|
116
|
+
*
|
|
117
|
+
* That test is what admitted `nano` (11/10 = 1.10) and `display` (30/26 = 1.154, the second-widest
|
|
118
|
+
* step, which is the shape a display tier is supposed to have), and what rejected a 20px rung
|
|
119
|
+
* between `xl` (18) and `h2` (21): 21/20 = 1.05 is below the floor, and `h2` is already 1px away
|
|
120
|
+
* from any 20px site. A size the ladder declines to grow a rung for is a size that should snap to
|
|
121
|
+
* its nearest step — not a `theme-allow`.
|
|
122
|
+
*
|
|
123
|
+
* A rung is also a ROLE, not just a number. `nano` and `display` are both deliberately named for
|
|
124
|
+
* where they belong (a label engraved inside a drawn object; a numeral read from across a room)
|
|
125
|
+
* rather than for a position, because the failure mode of a bare `xxs`/`xxl` is that it becomes the
|
|
126
|
+
* escape hatch for every size the ladder was meant to prevent.
|
|
127
|
+
*/
|
|
128
|
+
const TEXT = {
|
|
129
|
+
nano: 10, // engraved/graphic label INSIDE a drawn object (a plate face, a dial, a chip) — never UI copy or prose
|
|
130
|
+
micro: 11, // mono uppercase micro-label (table th, Menu.Label, sidebar/section headers, axis ticks)
|
|
131
|
+
xs: 12.5, // delta badges, tooltip meta, dense chrome, StatCard labels
|
|
132
|
+
sm: 13.5, // table/stat numerals, chart tooltip, legend
|
|
133
|
+
md: 15, // BODY — nav rows, menu items, timeline, labels, prose; chart/card titles
|
|
134
|
+
lg: 16, // breadcrumb current — ALSO the iOS input floor (do not lower)
|
|
135
|
+
xl: 18, // section titles
|
|
136
|
+
h2: 21, // article-density Prose h2 (docs/CONTENT-SPEC.md §5)
|
|
137
|
+
kpi: 24, // the StatCard hero numeral (density pass: 31 → 24, tighter/less shouty)
|
|
138
|
+
h1: 26, // article-density Prose h1 (docs/CONTENT-SPEC.md §5)
|
|
139
|
+
display: 30, // a numeral read at arm's length (a keypad readout, a timer, a kiosk figure) — not a heading
|
|
140
|
+
} as const
|
|
141
|
+
|
|
142
|
+
export const VX = {
|
|
143
|
+
// Non-color sizing constants
|
|
144
|
+
// Stroke WEIGHTS, not spacing — deliberately fixed, never density-tracking (see
|
|
145
|
+
// `SPACE_STEP_BASE`'s "charts" group doc in tokens/palette.ts).
|
|
146
|
+
lineWidth: 2.5,
|
|
147
|
+
line2Width: 2,
|
|
148
|
+
axisFont: TEXT.micro,
|
|
149
|
+
// A discrete visual footprint (not a stroke weight), so — unlike `lineWidth`/`line2Width` above —
|
|
150
|
+
// it DOES track density; single-sourced from `SPACE_STEP.chartDotR` (see that constant's doc).
|
|
151
|
+
dotR: SPACE_STEP.chartDotR,
|
|
152
|
+
// The ONE dashed pattern — plotted stroke, legend swatch, tooltip swatch all read this.
|
|
153
|
+
dashArray: '6 4' as const,
|
|
154
|
+
// Legend layout — single-sourced from `SPACE_STEP.chartLegendGap` (density-tracking; see that
|
|
155
|
+
// constant's doc). Still a raw number here (not `var()`) — the chart legend applies it via inline
|
|
156
|
+
// `style`, and this is the one static (level-0) value; `createBasaltTheme({ density })` has no
|
|
157
|
+
// wiring into chart render props yet, so this number does NOT move live with the knob (same
|
|
158
|
+
// "dev slider/production JS defaultProps" gap as Timeline's `bulletSize` — see `deriveSpacing`'s
|
|
159
|
+
// doc in tokens/palette.ts).
|
|
160
|
+
legendGap: SPACE_STEP.chartLegendGap,
|
|
161
|
+
legendFontSize: TEXT.sm,
|
|
162
|
+
|
|
163
|
+
// The type scale (px numbers — see TEXT above). Use in inline styles and visx SVG props;
|
|
164
|
+
// use `var(--vx-text-*)` in CSS modules.
|
|
165
|
+
text: TEXT,
|
|
166
|
+
|
|
167
|
+
// Single source for the card corner radius — shared by the Mantine-free ChartCard and the
|
|
168
|
+
// Mantine chrome (Card/Paper resolve to this SAME token). One knob, so cards never diverge.
|
|
169
|
+
radiusCard: 'var(--vx-radius-card)',
|
|
170
|
+
// Single source for the control corner radius (inputs, search, buttons, segmented track).
|
|
171
|
+
radiusCtrl: 'var(--vx-radius-ctrl)',
|
|
172
|
+
// Fully-rounded pill affordance (scroll-to-bottom button, chips) — fixed, does not track the
|
|
173
|
+
// radius knob (see `RADIUS_STEP.pill`'s doc in `tokens/palette.ts`).
|
|
174
|
+
radiusPill: 'var(--vx-radius-pill)',
|
|
175
|
+
// The pointer-tier hit floor: 44px under `(pointer: coarse)` (WCAG 2.5.5), 24px otherwise
|
|
176
|
+
// (2.5.8). Density-exempt; `[data-basalt-hit]::after` in `styles.css` reads it.
|
|
177
|
+
hit: 'var(--vx-hit)',
|
|
178
|
+
|
|
179
|
+
// Controls tier sizing (`docs/CONTROLS-SPEC.md` §5) — `var()` refs onto the density-tracking
|
|
180
|
+
// `--vx-space-*` declarations `spaceDecls` emits above (same ref pattern as `radiusCard`/
|
|
181
|
+
// `radiusCtrl`), so a home/control reads ONE source for its tier height whether it's Mantine
|
|
182
|
+
// chrome (`cssVariablesResolver`/`CTL_THEME`) or a Mantine-free composed layout.
|
|
183
|
+
space: {
|
|
184
|
+
controlHeightTag: 'var(--vx-space-control-height-tag)',
|
|
185
|
+
controlHeightWidget: 'var(--vx-space-control-height-widget)',
|
|
186
|
+
controlHeightCtl: 'var(--vx-space-control-height-ctl)',
|
|
187
|
+
pageBarRowHeight: 'var(--vx-space-page-bar-row-height)',
|
|
188
|
+
sectionHeaderHeight: 'var(--vx-space-section-header-height)',
|
|
189
|
+
widgetHeaderHeight: 'var(--vx-space-widget-header-height)',
|
|
190
|
+
sidebarBlockRowHeight: 'var(--vx-space-sidebar-block-row-height)',
|
|
191
|
+
controlGap: 'var(--vx-space-control-gap)',
|
|
192
|
+
sheetRowHeight: 'var(--vx-space-sheet-row-height)',
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
// Secondary-line color (back-compat alias; now theme-aware via --vx-line2)
|
|
196
|
+
line2Dark: 'var(--vx-line2)',
|
|
197
|
+
|
|
198
|
+
// Semantic fills — consistent opacity across all charts
|
|
199
|
+
good: 'var(--vx-good)',
|
|
200
|
+
goodSoft: 'var(--vx-good-soft)',
|
|
201
|
+
bad: 'var(--vx-bad)',
|
|
202
|
+
warn: 'var(--vx-warn)',
|
|
203
|
+
goodSolid: 'var(--vx-good-solid)',
|
|
204
|
+
badSolid: 'var(--vx-bad-solid)',
|
|
205
|
+
warnSolid: 'var(--vx-warn-solid)',
|
|
206
|
+
|
|
207
|
+
// Reference/dashed lines for thresholds
|
|
208
|
+
goodRef: 'var(--vx-good-ref)',
|
|
209
|
+
badRef: 'var(--vx-bad-ref)',
|
|
210
|
+
warnRef: 'var(--vx-warn-ref)',
|
|
211
|
+
|
|
212
|
+
// Neutral primary line/text color — the default for single-series, no-signal marks
|
|
213
|
+
// ("white/gray per theme"). Same value as the NEUTRAL.line pair.
|
|
214
|
+
line: 'var(--vx-line)',
|
|
215
|
+
line2: 'var(--vx-line2)',
|
|
216
|
+
|
|
217
|
+
// Axis label + axis stroke colors (theme-aware). Exposed as flat refs so a bespoke chart that
|
|
218
|
+
// renders raw <text> labels or axis lines (without the Axis* primitives) needs no hook.
|
|
219
|
+
axis: 'var(--vx-axis)',
|
|
220
|
+
axisStroke: 'var(--vx-axis-stroke)',
|
|
221
|
+
|
|
222
|
+
// Grid, hover, legend
|
|
223
|
+
grid: 'var(--vx-grid)',
|
|
224
|
+
crosshair: 'var(--vx-crosshair)',
|
|
225
|
+
dotStroke: 'var(--vx-dot-stroke)',
|
|
226
|
+
legendText: 'var(--vx-legend-text)',
|
|
227
|
+
|
|
228
|
+
// Tooltip chrome — muted (secondary) text inside a bespoke tooltip. The other tooltip vars
|
|
229
|
+
// (bg/text/border/shadow) reach the engine tooltip as `--ts-chart-tooltip-*` (`charts/theme.ts`);
|
|
230
|
+
// this one is flattened onto `VX` too because bespoke-tooltip authors reached for `VX.muted` (the
|
|
231
|
+
// general ink-ramp muted) instead and got the wrong token — same pattern as `VX.muted` below.
|
|
232
|
+
tooltipMuted: 'var(--vx-tooltip-muted)',
|
|
233
|
+
|
|
234
|
+
// Base neutral for hairlines / muted text / overlays — apply opacity via alpha()
|
|
235
|
+
neutral: 'var(--vx-neutral)',
|
|
236
|
+
|
|
237
|
+
// Ink text ramp (docs/DESIGN-SPEC.md §2) — primary/emphasis/secondary/tertiary body text.
|
|
238
|
+
ink: 'var(--vx-ink)',
|
|
239
|
+
ink2: 'var(--vx-ink2)',
|
|
240
|
+
muted: 'var(--vx-muted)',
|
|
241
|
+
faint: 'var(--vx-faint)',
|
|
242
|
+
|
|
243
|
+
// The accent as INK — primary series, active-nav icon, links, focus rings. Read against the PAGE,
|
|
244
|
+
// so it inverts across schemes (light on dark, deep on light).
|
|
245
|
+
accent: 'var(--vx-accent)',
|
|
246
|
+
accentHover: 'var(--vx-accent-hover)',
|
|
247
|
+
// The accent as SURFACE — a filled control that carries a label. Squeezed between white-text
|
|
248
|
+
// contrast and page contrast, so it is the same hex in both schemes (see ACCENT in palette.ts).
|
|
249
|
+
// Mantine's `--mantine-color-<primary>-filled` is bridged onto this, so it drives ALL filled
|
|
250
|
+
// chrome; a raw `--vx-accent` fill would be unreadable on dark. Fills use THIS, never `accent`.
|
|
251
|
+
accentFill: 'var(--vx-accent-fill)',
|
|
252
|
+
accentFillHover: 'var(--vx-accent-fill-hover)',
|
|
253
|
+
onAccent: 'var(--vx-on-accent)',
|
|
254
|
+
|
|
255
|
+
// Layout separators (header bottom rule, sidebar child indent) — distinct from `surface.border`.
|
|
256
|
+
divider: 'var(--vx-divider)',
|
|
257
|
+
|
|
258
|
+
// Depth shadows — a whisper shadow + a 1px ring baked into the value (never a `border` prop).
|
|
259
|
+
shadowCard: 'var(--vx-shadow-card)',
|
|
260
|
+
shadowCtrl: 'var(--vx-shadow-ctrl)',
|
|
261
|
+
// Raised interactive controls — drop + a 1px INSET edge, the one depth every raised Button/
|
|
262
|
+
// ActionIcon variant shares (works over a fill, a tint or a panel alike; see SHADOW.raised).
|
|
263
|
+
shadowRaised: 'var(--vx-shadow-raised)',
|
|
264
|
+
// Floating-layer elevation (menus, popovers, tooltips, modals, drawers) — a real drop shadow.
|
|
265
|
+
shadowOverlay: 'var(--vx-shadow-overlay)',
|
|
266
|
+
|
|
267
|
+
// App surfaces (cards, borders) — shared with the Mantine chrome
|
|
268
|
+
surface: {
|
|
269
|
+
bg: 'var(--vx-surface-bg)',
|
|
270
|
+
panel: 'var(--vx-surface-panel)',
|
|
271
|
+
panelHover: 'var(--vx-surface-panel-hover)',
|
|
272
|
+
elevated: 'var(--vx-surface-elevated)',
|
|
273
|
+
subtle: 'var(--vx-surface-subtle)',
|
|
274
|
+
overlay: 'var(--vx-surface-overlay)', // floating layer (menus, popovers, modals, drawers)
|
|
275
|
+
field: 'var(--vx-surface-field)', // input field surface (slightly inset on a panel)
|
|
276
|
+
border: 'var(--vx-surface-border)', // "line" — strong border
|
|
277
|
+
hairline: 'var(--vx-surface-hairline)', // card ring only
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
// Score / zone status scale (excellent → poor)
|
|
281
|
+
status: {
|
|
282
|
+
excellent: 'var(--vx-status-excellent)',
|
|
283
|
+
good: 'var(--vx-status-good)',
|
|
284
|
+
warn: 'var(--vx-status-warn)',
|
|
285
|
+
bad: 'var(--vx-status-bad)',
|
|
286
|
+
neutral: 'var(--vx-status-neutral)',
|
|
287
|
+
},
|
|
288
|
+
|
|
289
|
+
// Shared sizing — single-sourced from the `SPACE_STEP` chart-margin steps (density-tracking; same
|
|
290
|
+
// static-value/no-live-wiring note as `legendGap` above).
|
|
291
|
+
margin: {
|
|
292
|
+
top: SPACE_STEP.chartMarginTop,
|
|
293
|
+
right: SPACE_STEP.chartMarginRight,
|
|
294
|
+
bottom: SPACE_STEP.chartMarginBottom,
|
|
295
|
+
left: SPACE_STEP.chartMarginLeft,
|
|
296
|
+
},
|
|
297
|
+
minPxPerTick: 55,
|
|
298
|
+
/**
|
|
299
|
+
* Floor on a chart's plot rect height, in px (the 1.x chart frame). A legend wrapping to five rows at
|
|
300
|
+
* phone width used to eat a fixed `height={240}` toward zero and the plot simply stopped
|
|
301
|
+
* rendering — the plot never shrinks past this, the frame grows instead (or, under `fill`, the
|
|
302
|
+
* legend rolls up).
|
|
303
|
+
*/
|
|
304
|
+
minPlotHeight: 120,
|
|
305
|
+
/** Every floating chart overlay portalled to `document.body` — a pinned tooltip, the legend's
|
|
306
|
+
* `All N` disclosure and its backdrop — shares one stacking value, so they always stack the same
|
|
307
|
+
* way relative to page chrome and to each other. */
|
|
308
|
+
zIndexFloating: 9999,
|
|
309
|
+
} as const
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Layout breakpoints, in px, for the places CSS cannot read a custom property.
|
|
313
|
+
*
|
|
314
|
+
* A `@media` query's condition is resolved before custom properties exist, so
|
|
315
|
+
* `@media (max-width: var(--x))` is invalid CSS — a stylesheet with a responsive rule has no
|
|
316
|
+
* choice but to write the number. This constant is the other half of that literal: the CSS states
|
|
317
|
+
* the number and names the token beside it, and a test asserts the two agree
|
|
318
|
+
* (`content/article-layout.breakpoint.test.ts`, the same "literal must match the token" idiom as
|
|
319
|
+
* `styles.floor.test.ts`).
|
|
320
|
+
*
|
|
321
|
+
* Only breakpoints that are genuinely a CSS-authored `@media` belong here. A component that can
|
|
322
|
+
* measure its own box uses the measurement instead (`CONTAINER_CLASSES`), and Mantine chrome uses
|
|
323
|
+
* `theme.breakpoints`.
|
|
324
|
+
*/
|
|
325
|
+
export const BREAKPOINTS = {
|
|
326
|
+
/**
|
|
327
|
+
* `content/article-layout.module.css` — below this the TOC rail is dropped and the article
|
|
328
|
+
* collapses to a single centred column. Well above the `sm` (52.5em/840px) shell breakpoint on
|
|
329
|
+
* purpose: the rail needs the prose measure PLUS its own width plus the column gap, which runs
|
|
330
|
+
* out long before the shell goes mobile.
|
|
331
|
+
*/
|
|
332
|
+
article: 1200,
|
|
333
|
+
} as const
|
|
334
|
+
|
|
335
|
+
type Side = 'light' | 'dark'
|
|
336
|
+
|
|
337
|
+
/** A CSS declaration line for a single `--vx-*` custom property. */
|
|
338
|
+
const decl = (name: string, value: string): string => ` --vx-${name}: ${value};`
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* A px number expressed as the plain rem STRING literal (16px base: `pxRem(6)` → `'0.375rem'`) —
|
|
342
|
+
* NOT Mantine's own `rem()` helper, which instead emits a `calc(...)` expression bound to
|
|
343
|
+
* `--mantine-scale` (a different value; that scaling happens at the Mantine-coupled call site
|
|
344
|
+
* instead — see `theme/index.ts`'s `Input.extend` `vars` for why `--vx-space-input-height` needs
|
|
345
|
+
* both halves). The SINGLE source for this conversion — `theme/index.ts` imports this instead of
|
|
346
|
+
* keeping its own copy, so the radius/spacing size-scale steps and this module's own rem-emitting
|
|
347
|
+
* vars (`--vx-space-input-height`) can never compute the conversion two different ways.
|
|
348
|
+
*/
|
|
349
|
+
export function pxRem(px: number): string {
|
|
350
|
+
return `${px / 16}rem`
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/** Emit one prefixed group of pairs for a given scheme side. */
|
|
354
|
+
const groupSide = (prefix: string, map: SeriesMap, side: Side): string =>
|
|
355
|
+
Object.entries(map)
|
|
356
|
+
.map(([key, pair]) => decl(`${prefix}${key}`, pair[side]))
|
|
357
|
+
.join('\n')
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* The 16 deprecated camelCase aliases for `frameworkPrimitives`' per-scheme canonicals, each
|
|
361
|
+
* defined as `var(--vx-<canonical-kebab-name>)` so it can never drift from the value above it.
|
|
362
|
+
* Emitted as its own commented, trailing group (never interleaved with the canonicals) — gated by
|
|
363
|
+
* {@link BuildPaletteOpts.legacyAliases}, default on. See that option's doc for the migration
|
|
364
|
+
* rationale (1.4.0 kebab-case normalization).
|
|
365
|
+
*/
|
|
366
|
+
function frameworkPrimitivesAliases(): string {
|
|
367
|
+
return [
|
|
368
|
+
' /* Deprecated camelCase aliases — removed in a future minor; migrate to the kebab names above. */',
|
|
369
|
+
decl('goodSolid', 'var(--vx-good-solid)'),
|
|
370
|
+
decl('badSolid', 'var(--vx-bad-solid)'),
|
|
371
|
+
decl('warnSolid', 'var(--vx-warn-solid)'),
|
|
372
|
+
decl('axisStroke', 'var(--vx-axis-stroke)'),
|
|
373
|
+
decl('dotStroke', 'var(--vx-dot-stroke)'),
|
|
374
|
+
decl('tooltipBg', 'var(--vx-tooltip-bg)'),
|
|
375
|
+
decl('tooltipText', 'var(--vx-tooltip-text)'),
|
|
376
|
+
decl('tooltipMuted', 'var(--vx-tooltip-muted)'),
|
|
377
|
+
decl('tooltipBorder', 'var(--vx-tooltip-border)'),
|
|
378
|
+
decl('tooltipShadow', 'var(--vx-tooltip-shadow)'),
|
|
379
|
+
decl('legendText', 'var(--vx-legend-text)'),
|
|
380
|
+
decl('accentHover', 'var(--vx-accent-hover)'),
|
|
381
|
+
decl('accentFill', 'var(--vx-accent-fill)'),
|
|
382
|
+
decl('accentFillHover', 'var(--vx-accent-fill-hover)'),
|
|
383
|
+
decl('onAccent', 'var(--vx-on-accent)'),
|
|
384
|
+
decl('surface-panelHover', 'var(--vx-surface-panel-hover)'),
|
|
385
|
+
].join('\n')
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Built-in framework primitives for a given scheme side — STATUS group, semantic solids,
|
|
390
|
+
* neutral line/axis/grid/tooltip chrome, legend text, and the surface ramp. Domain series
|
|
391
|
+
* (SERIES/ACTIVITY/USAGE) are NOT shipped — apps append them via `opts.groups`.
|
|
392
|
+
*/
|
|
393
|
+
function frameworkPrimitives(side: Side, data: PaletteData, legacyAliases: boolean): string {
|
|
394
|
+
const n = data.NEUTRAL
|
|
395
|
+
const s = data.SEMANTIC
|
|
396
|
+
const su = data.SURFACE
|
|
397
|
+
const ink = data.INK
|
|
398
|
+
const ac = data.ACCENT
|
|
399
|
+
const canonical = [
|
|
400
|
+
groupSide('status-', data.STATUS as SeriesMap, side),
|
|
401
|
+
decl('good-solid', s.good[side]),
|
|
402
|
+
decl('bad-solid', s.bad[side]),
|
|
403
|
+
decl('warn-solid', s.warn[side]),
|
|
404
|
+
decl('neutral', n.neutral[side]),
|
|
405
|
+
decl('line', n.line[side]),
|
|
406
|
+
decl('line2', n.line2[side]),
|
|
407
|
+
decl('axis', n.axis[side]),
|
|
408
|
+
decl('axis-stroke', n.axisStroke[side]),
|
|
409
|
+
decl('grid', n.grid[side]),
|
|
410
|
+
decl('crosshair', n.crosshair[side]),
|
|
411
|
+
decl('dot-stroke', n.dotStroke[side]),
|
|
412
|
+
decl('tooltip-bg', n.tooltipBg[side]),
|
|
413
|
+
decl('tooltip-text', n.tooltipText[side]),
|
|
414
|
+
decl('tooltip-muted', n.tooltipMuted[side]),
|
|
415
|
+
decl('tooltip-border', n.tooltipBorder[side]),
|
|
416
|
+
decl('tooltip-shadow', n.tooltipShadow[side]),
|
|
417
|
+
decl('legend-text', n.legendText[side]),
|
|
418
|
+
decl('ink', ink.ink[side]),
|
|
419
|
+
decl('ink2', ink.ink2[side]),
|
|
420
|
+
decl('muted', ink.muted[side]),
|
|
421
|
+
decl('faint', ink.faint[side]),
|
|
422
|
+
decl('accent', ac.accent[side]),
|
|
423
|
+
decl('accent-hover', ac.accentHover[side]),
|
|
424
|
+
decl('accent-fill', ac.accentFill[side]),
|
|
425
|
+
decl('accent-fill-hover', ac.accentFillHover[side]),
|
|
426
|
+
decl('on-accent', ac.onAccent[side]),
|
|
427
|
+
decl('divider', su.divider[side]),
|
|
428
|
+
decl('shadow-card', SHADOW.card[side]),
|
|
429
|
+
decl('shadow-ctrl', SHADOW.ctrl[side]),
|
|
430
|
+
decl('shadow-raised', SHADOW.raised[side]),
|
|
431
|
+
decl('shadow-overlay', SHADOW.overlay[side]),
|
|
432
|
+
decl('surface-bg', su.bg[side]),
|
|
433
|
+
decl('surface-panel', su.panel[side]),
|
|
434
|
+
decl('surface-panel-hover', su.panelHover[side]),
|
|
435
|
+
decl('surface-elevated', su.elevated[side]),
|
|
436
|
+
decl('surface-subtle', su.subtle[side]),
|
|
437
|
+
decl('surface-overlay', su.overlay[side]),
|
|
438
|
+
decl('surface-field', su.field[side]),
|
|
439
|
+
decl('surface-border', su.border[side]),
|
|
440
|
+
decl('surface-hairline', su.hairline[side]),
|
|
441
|
+
].join('\n')
|
|
442
|
+
return legacyAliases ? `${canonical}\n${frameworkPrimitivesAliases()}` : canonical
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* The `--vx-space-*` declaration list for a resolved {@link SpaceValues} — every anchor and one-off
|
|
447
|
+
* that has at least one real `var()` consumer, plus the row line-height. Shared by
|
|
448
|
+
* `frameworkDerived` (emits the shipped defaults unconditionally, called with `DEFAULT_SPACE_
|
|
449
|
+
* VALUES`) and {@link buildDensityCss} (emits an OVERRIDING block for a retuned density level), so
|
|
450
|
+
* the two lists can never drift apart — mirrors `frameworkDerived`'s own single-source reasoning for
|
|
451
|
+
* the radii.
|
|
452
|
+
*
|
|
453
|
+
* The nine controls-tier anchors/one-offs (`controlHeightTag`/`Widget`/`Ctl`,
|
|
454
|
+
* `pageBarRowHeight`, `sectionHeaderHeight`, `widgetHeaderHeight`, `sidebarBlockRowHeight`,
|
|
455
|
+
* `controlGap`, `sheetRowHeight` — `docs/CONTROLS-SPEC.md` §5) are a DELIBERATE exception to the
|
|
456
|
+
* "has at least one real consumer today" rule below: `theme/ctl-theme.tsx`'s `CTL_THEME` and the
|
|
457
|
+
* `cssVariablesResolver`'s `-ctl`/`-icon` var sets consume the four control-height anchors this
|
|
458
|
+
* commit; `PageBar`/`WidgetHeader`/the sidebar blocks (wave 3/4) consume the six one-offs. Emitted
|
|
459
|
+
* now, ahead of that second wave, rather than left as JS-only — unlike the seventeen genuinely
|
|
460
|
+
* dead-weight keys below, these are forward-declared framework surface, not vestigial.
|
|
461
|
+
*
|
|
462
|
+
* `SPACE_FIXED` (Timeline `lineWidth`, 1px borders, the ReadingProgress bar height, SegmentedControl's
|
|
463
|
+
* `segmentedTrackInset`) is deliberately NEVER part of this list — it never moves, so a var would
|
|
464
|
+
* only invite someone to think it does.
|
|
465
|
+
*
|
|
466
|
+
* Deliberately DOES NOT emit a var for every `SpaceValues` number — `space.scale.*` (the generic
|
|
467
|
+
* Mantine spacing scale) and seventeen `space.step.*` keys have ZERO `var()` consumers anywhere in
|
|
468
|
+
* the framework or its tests beyond the CSS-emission test itself. Each is read straight off the
|
|
469
|
+
* resolved `SpaceValues` as a JS NUMBER instead, in one of three ways:
|
|
470
|
+
* `{timelineBullet,progressBarSize}` are Mantine `defaultProps` (`theme/index.ts`'s Timeline/
|
|
471
|
+
* Progress); `{sidebarAccountMenuWidth,sidebarSettingsMenuWidth,mobileNavMenuWidth,
|
|
472
|
+
* appShellHeaderHeight,appShellNavbarWidth,appShellNavbarRailWidth,appShellAsideWidth,
|
|
473
|
+
* appShellAsideRailWidth,
|
|
474
|
+
* mobileNavBarHeight}` are numeric Mantine component props (Menu `width`, AppShell `header`/
|
|
475
|
+
* `navbar`/`footer`); and `{chartLegendGap,chartMarginTop,chartMarginRight,
|
|
476
|
+
* chartMarginBottom,chartMarginLeft,chartDotR}` are visx SVG props via
|
|
477
|
+
* `VX.legendGap`/`VX.margin`/`VX.dotR` in this file's own `VX` object. The full list is locked
|
|
478
|
+
* against the `SpaceValues` key set by `tokens/density.test.ts`'s declaration-set test, so adding a
|
|
479
|
+
* one-off silently omits nothing. A `--vx-space-*` declaration for any of them would be dead weight
|
|
480
|
+
* that only looked like the fix for
|
|
481
|
+
* the dev-slider/production gap those JS reads actually have (see `deriveSpacing`'s JSDoc in
|
|
482
|
+
* `tokens/palette.ts` for the real scope of that gap — it is materially bigger than "a var these
|
|
483
|
+
* numbers could round-trip through"). `theme.spacing` (the generic scale, JS) already resolves
|
|
484
|
+
* through `--mantine-spacing-*` on the PRODUCTION `createBasaltTheme({ density })` path
|
|
485
|
+
* (`theme/index.ts`'s `buildTheme`), so nothing downstream of the generic scale actually needed
|
|
486
|
+
* `--vx-space-scale-*` either — deleted along with the rest rather than kept as an unread alias.
|
|
487
|
+
*/
|
|
488
|
+
function spaceDecls(space: SpaceValues): string[] {
|
|
489
|
+
return [
|
|
490
|
+
decl('space-row-inset-x', `${space.anchors.rowInsetX}px`),
|
|
491
|
+
decl('space-row-inset-y', `${space.anchors.rowInsetY}px`),
|
|
492
|
+
// Additive law, not the multiplier — see `deriveSpacing`'s doc in `tokens/palette.ts`. No unit:
|
|
493
|
+
// `line-height` is a unitless CSS value.
|
|
494
|
+
decl('space-row-line-height', `${space.rowLineHeight}`),
|
|
495
|
+
// A `size: 'md'` Input's resolved height. Mantine's own `--input-height-md` is
|
|
496
|
+
// `calc(2.625rem * var(--mantine-scale))` (BOTH `styles.css` and `styles.layer.css`, verified
|
|
497
|
+
// in the installed package) — REM-relative to the root font size AND scale-aware, not a flat
|
|
498
|
+
// px. Emitting this in REM (via `pxRem`, not a bare `${…}px`) preserves the rem half; the
|
|
499
|
+
// `* var(--mantine-scale))` half is reconstructed at the Mantine-coupled call site
|
|
500
|
+
// (`theme/index.ts`'s `Input.extend` `vars`, which wraps this var in the matching `calc(...)`)
|
|
501
|
+
// — this module stays Mantine-free, so it cannot reference `--mantine-scale` itself. Flattening
|
|
502
|
+
// either half into a flat px would desync input height from the user's root font size (an
|
|
503
|
+
// accessibility regression) and from Mantine's global `--mantine-scale` knob.
|
|
504
|
+
decl('space-input-height', pxRem(space.anchors.inputHeight)),
|
|
505
|
+
// A `size: 'md'` Button's/ActionIcon's resolved height — SAME rem-plus-scale reasoning and
|
|
506
|
+
// reconstruction as `space-input-height` above (`theme/index.ts`'s `Button.extend`/
|
|
507
|
+
// `ActionIcon.extend` `vars`), single-sourced from the SAME `controlHeight` anchor
|
|
508
|
+
// `space-input-height` reads from (`SPACE_ANCHORS_BASE`'s doc in `tokens/palette.ts`).
|
|
509
|
+
decl('space-control-height', pxRem(space.anchors.controlHeight)),
|
|
510
|
+
// Controls tier heights (`docs/CONTROLS-SPEC.md` §5) — same rem-plus-`--mantine-scale`
|
|
511
|
+
// reconstruction as `space-input-height`/`space-control-height` above; `theme/ctl-theme.tsx`'s
|
|
512
|
+
// `CTL_THEME` and the `cssVariablesResolver`'s `-ctl`/`-icon` var sets both wrap these in the
|
|
513
|
+
// matching `calc(... * var(--mantine-scale))`.
|
|
514
|
+
decl('space-control-height-tag', pxRem(space.anchors.controlHeightTag)),
|
|
515
|
+
decl('space-control-height-widget', pxRem(space.anchors.controlHeightWidget)),
|
|
516
|
+
decl('space-control-height-ctl', pxRem(space.anchors.controlHeightCtl)),
|
|
517
|
+
decl('space-stack-xs', `${space.anchors.stackXs}px`),
|
|
518
|
+
decl('space-stack-sm', `${space.anchors.stackSm}px`),
|
|
519
|
+
decl('space-stack-md', `${space.anchors.stackMd}px`),
|
|
520
|
+
decl('space-stack-lg', `${space.anchors.stackLg}px`),
|
|
521
|
+
decl('space-stack-xl', `${space.anchors.stackXl}px`),
|
|
522
|
+
// The CSS-module spacing sweep's one-offs (docs/STATUS.md) — same single-source reasoning,
|
|
523
|
+
// grouped to match `SPACE_STEP_BASE`'s own grouping in tokens/palette.ts.
|
|
524
|
+
// ONE value at every viewport since 1.26.0 — the AppShell header is a single
|
|
525
|
+
// `appShellHeaderHeight` row (law C14), so the `-mobile` override of the old Decision-3
|
|
526
|
+
// responsive pair is gone.
|
|
527
|
+
decl('space-sticky-header-clearance', `${space.step.stickyHeaderClearance}px`),
|
|
528
|
+
decl('space-nav-icon-gap', `${space.step.navIconGap}px`),
|
|
529
|
+
decl('space-sidebar-region-gap', `${space.step.sidebarRegionGap}px`),
|
|
530
|
+
decl('space-prose-quote-inset-y', `${space.step.proseQuoteInsetY}px`),
|
|
531
|
+
decl('space-prose-quote-indent', `${space.step.proseQuoteIndent}px`),
|
|
532
|
+
decl('space-prose-inline-code-inset-y', `${space.step.proseInlineCodeInsetY}px`),
|
|
533
|
+
decl('space-prose-inline-code-inset-x', `${space.step.proseInlineCodeInsetX}px`),
|
|
534
|
+
decl('space-prose-code-block-inset-y', `${space.step.proseCodeBlockInsetY}px`),
|
|
535
|
+
decl('space-prose-code-block-inset-x', `${space.step.proseCodeBlockInsetX}px`),
|
|
536
|
+
decl('space-prose-heading-anchor-gap', `${space.step.proseHeadingAnchorGap}px`),
|
|
537
|
+
decl('space-prose-table-cell-inset-y', `${space.step.proseTableCellInsetY}px`),
|
|
538
|
+
decl('space-prose-table-cell-inset-x', `${space.step.proseTableCellInsetX}px`),
|
|
539
|
+
decl('space-prose-chat-list-gap-bottom', `${space.step.proseChatListGapBottom}px`),
|
|
540
|
+
decl('space-prose-chat-list-indent', `${space.step.proseChatListIndent}px`),
|
|
541
|
+
decl('space-prose-chat-list-item-gap', `${space.step.proseChatListItemGap}px`),
|
|
542
|
+
decl('space-prose-chat-nested-list-gap', `${space.step.proseChatNestedListGap}px`),
|
|
543
|
+
decl('space-prose-chat-heading-gap-top', `${space.step.proseChatHeadingGapTop}px`),
|
|
544
|
+
decl('space-prose-chat-heading-gap-bottom', `${space.step.proseChatHeadingGapBottom}px`),
|
|
545
|
+
decl('space-prose-article-paragraph-gap', `${space.step.proseArticleParagraphGap}px`),
|
|
546
|
+
decl('space-prose-article-list-gap-top', `${space.step.proseArticleListGapTop}px`),
|
|
547
|
+
decl('space-prose-article-list-gap-bottom', `${space.step.proseArticleListGapBottom}px`),
|
|
548
|
+
decl('space-prose-article-list-indent', `${space.step.proseArticleListIndent}px`),
|
|
549
|
+
decl('space-prose-article-h1-gap-top', `${space.step.proseArticleH1GapTop}px`),
|
|
550
|
+
decl('space-prose-article-h1-gap-bottom', `${space.step.proseArticleH1GapBottom}px`),
|
|
551
|
+
decl('space-prose-article-heading-gap-top', `${space.step.proseArticleHeadingGapTop}px`),
|
|
552
|
+
decl('space-prose-article-heading-gap-bottom', `${space.step.proseArticleHeadingGapBottom}px`),
|
|
553
|
+
decl('space-prose-article-h2-rule-gap', `${space.step.proseArticleH2RuleGap}px`),
|
|
554
|
+
decl('space-prose-article-block-gap', `${space.step.proseArticleBlockGap}px`),
|
|
555
|
+
decl('space-article-column-gap', `${space.step.articleColumnGap}px`),
|
|
556
|
+
decl('space-article-toc-rail-width', `${space.step.articleTocRailWidth}px`),
|
|
557
|
+
decl('space-article-header-gap', `${space.step.articleHeaderGap}px`),
|
|
558
|
+
decl('space-article-header-padding-bottom', `${space.step.articleHeaderPaddingBottom}px`),
|
|
559
|
+
decl('space-article-header-margin-bottom', `${space.step.articleHeaderMarginBottom}px`),
|
|
560
|
+
decl('space-article-meta-row-gap', `${space.step.articleMetaRowGap}px`),
|
|
561
|
+
decl('space-article-footer-gap', `${space.step.articleFooterGap}px`),
|
|
562
|
+
decl('space-article-footer-margin-top', `${space.step.articleFooterMarginTop}px`),
|
|
563
|
+
decl('space-article-footer-padding-top', `${space.step.articleFooterPaddingTop}px`),
|
|
564
|
+
decl('space-article-nav-target-gap', `${space.step.articleNavTargetGap}px`),
|
|
565
|
+
decl('space-code-block-header-gap', `${space.step.codeBlockHeaderGap}px`),
|
|
566
|
+
decl('space-code-block-header-inset-y', `${space.step.codeBlockHeaderInsetY}px`),
|
|
567
|
+
decl('space-code-block-header-inset-right', `${space.step.codeBlockHeaderInsetRight}px`),
|
|
568
|
+
decl('space-code-block-content-inset-x', `${space.step.codeBlockContentInsetX}px`),
|
|
569
|
+
decl('space-code-block-header-right-gap', `${space.step.codeBlockHeaderRightGap}px`),
|
|
570
|
+
decl('space-code-block-body-inset-y', `${space.step.codeBlockBodyInsetY}px`),
|
|
571
|
+
decl('space-code-block-floating-copy-offset', `${space.step.codeBlockFloatingCopyOffset}px`),
|
|
572
|
+
decl('space-callout-inset-y', `${space.step.calloutInsetY}px`),
|
|
573
|
+
decl('space-callout-inset-x', `${space.step.calloutInsetX}px`),
|
|
574
|
+
decl('space-callout-title-row-gap', `${space.step.calloutTitleRowGap}px`),
|
|
575
|
+
decl('space-toc-root-gap', `${space.step.tocRootGap}px`),
|
|
576
|
+
decl('space-toc-link-inset-y', `${space.step.tocLinkInsetY}px`),
|
|
577
|
+
decl('space-toc-link-indent', `${space.step.tocLinkIndent}px`),
|
|
578
|
+
decl('space-toc-sub-indent', `${space.step.tocSubIndent}px`),
|
|
579
|
+
decl('space-article-card-tags-gap', `${space.step.articleCardTagsGap}px`),
|
|
580
|
+
decl('space-article-card-tag-inset-y', `${space.step.articleCardTagInsetY}px`),
|
|
581
|
+
decl('space-article-card-tag-inset-x', `${space.step.articleCardTagInsetX}px`),
|
|
582
|
+
decl('space-article-card-meta-gap-top', `${space.step.articleCardMetaGapTop}px`),
|
|
583
|
+
decl('space-guide-body-gap-bottom', `${space.step.guideBodyGapBottom}px`),
|
|
584
|
+
decl('space-guide-footer-gap-top', `${space.step.guideFooterGapTop}px`),
|
|
585
|
+
decl('space-guide-footer-inset-top', `${space.step.guideFooterInsetTop}px`),
|
|
586
|
+
decl('space-sidebar-search-gap', `${space.step.sidebarSearchGap}px`),
|
|
587
|
+
decl('space-sidebar-search-trigger-height', `${space.step.sidebarSearchTriggerHeight}px`),
|
|
588
|
+
decl('space-settings-row-inset-y', `${space.step.settingsRowInsetY}px`),
|
|
589
|
+
decl('space-settings-row-gap', `${space.step.settingsRowGap}px`),
|
|
590
|
+
decl('space-mermaid-container-inset', `${space.step.mermaidContainerInset}px`),
|
|
591
|
+
decl('space-sidebar-brand-inset-x', `${space.step.sidebarBrandInsetX}px`),
|
|
592
|
+
decl('space-sidebar-section-gap', `${space.step.sidebarSectionGap}px`),
|
|
593
|
+
decl('space-sidebar-account-inset-top', `${space.step.sidebarAccountInsetTop}px`),
|
|
594
|
+
decl('space-sidebar-account-inset-x', `${space.step.sidebarAccountInsetX}px`),
|
|
595
|
+
decl('space-sidebar-account-inset-bottom', `${space.step.sidebarAccountInsetBottom}px`),
|
|
596
|
+
decl('space-sidebar-avatar-size', `${space.step.sidebarAvatarSize}px`),
|
|
597
|
+
decl('space-sidebar-section-label-gap', `${space.step.sidebarSectionLabelGap}px`),
|
|
598
|
+
decl('space-sidebar-child-list-gap-top', `${space.step.sidebarChildListGapTop}px`),
|
|
599
|
+
decl('space-sidebar-child-list-gap-bottom', `${space.step.sidebarChildListGapBottom}px`),
|
|
600
|
+
decl('space-sidebar-child-list-indent', `${space.step.sidebarChildListIndent}px`),
|
|
601
|
+
decl('space-sidebar-child-row-inset-y', `${space.step.sidebarChildRowInsetY}px`),
|
|
602
|
+
decl('space-sidebar-child-row-indent', `${space.step.sidebarChildRowIndent}px`),
|
|
603
|
+
// The page gutter — the ONE `appShell*` dimension that IS emitted, against the JS-number-only
|
|
604
|
+
// rule its five neighbours follow (see the note at the bottom of this list). It earns the
|
|
605
|
+
// exception because it is the most visible spacing number the framework ships — every page's
|
|
606
|
+
// left edge — and it was, until now, the one number the `--vx-*` layer did not expose at all, so
|
|
607
|
+
// a consumer retuning its identity through `createBasaltTheme` could not reach it and had to
|
|
608
|
+
// reach past the token layer into `AppShell.Main`'s own styles. Emitted in PLAIN PX, like every
|
|
609
|
+
// other inset/gap in this list and unlike the `pxRem` heights above it: the rem-plus-
|
|
610
|
+
// `var(--mantine-scale)` reconstruction exists so a CONTROL's box tracks the root font size and
|
|
611
|
+
// Mantine's global scale knob; a page gutter is a layout margin against a viewport, not a box
|
|
612
|
+
// sized to text, so scaling it with the font would make a large-type user's content column
|
|
613
|
+
// narrower rather than more legible.
|
|
614
|
+
decl('space-app-shell-inset', `${space.step.appShellInset}px`),
|
|
615
|
+
decl('space-app-shell-inset-mobile', `${space.step.appShellInsetMobile}px`),
|
|
616
|
+
// The header's breadcrumb floor — emitted for the same reason as the gutter pair above it and
|
|
617
|
+
// not for the JS-number reason its `appShell*` neighbours below are withheld for: this one has
|
|
618
|
+
// a real CSS consumer (`shell/app-header.module.css`'s `.lead`), which is the whole test this
|
|
619
|
+
// list applies. Plain px, like every other layout dimension here.
|
|
620
|
+
decl('space-app-shell-header-lead-min', `${space.step.appShellHeaderLeadMin}px`),
|
|
621
|
+
decl('space-mobile-nav-tab-gap', `${space.step.mobileNavTabGap}px`),
|
|
622
|
+
decl('space-mobile-nav-icon-size', `${space.step.mobileNavIconSize}px`),
|
|
623
|
+
decl('space-mobile-nav-tab-inset-y', `${space.step.mobileNavTabInsetY}px`),
|
|
624
|
+
decl('space-mobile-nav-tab-inset-x', `${space.step.mobileNavTabInsetX}px`),
|
|
625
|
+
decl('space-mobile-nav-row-height', `${space.step.mobileNavRowHeight}px`),
|
|
626
|
+
decl('space-agent-rail-inset-x', `${space.step.agentRailInsetX}px`),
|
|
627
|
+
decl('space-agent-part-gap-top', `${space.step.agentPartGapTop}px`),
|
|
628
|
+
decl('space-agent-code-inset', `${space.step.agentCodeInset}px`),
|
|
629
|
+
decl('space-agent-error-inset-y', `${space.step.agentErrorInsetY}px`),
|
|
630
|
+
decl('space-agent-error-inset-x', `${space.step.agentErrorInsetX}px`),
|
|
631
|
+
decl('space-agent-scroll-button-gap-top', `${space.step.agentScrollButtonGapTop}px`),
|
|
632
|
+
decl('space-agent-message-inset-y', `${space.step.agentMessageInsetY}px`),
|
|
633
|
+
decl('space-agent-message-inset-x', `${space.step.agentMessageInsetX}px`),
|
|
634
|
+
decl('space-agent-transcript-inset', `${space.step.agentTranscriptInset}px`),
|
|
635
|
+
decl('space-badge-inset-y', `${space.step.badgeInsetY}px`),
|
|
636
|
+
decl('space-badge-inset-x', `${space.step.badgeInsetX}px`),
|
|
637
|
+
decl('space-stat-card-gap', `${space.step.statCardGap}px`),
|
|
638
|
+
// The card/section inset ladder — the three values `spaceMobileDecls` below re-points at `< sm`
|
|
639
|
+
// (see its doc for where the law lives and why it lives there).
|
|
640
|
+
decl('space-card-inset-y', `${space.step.cardInsetY}px`),
|
|
641
|
+
decl('space-card-inset-x', `${space.step.cardInsetX}px`),
|
|
642
|
+
decl('space-section-gap', `${space.step.sectionGap}px`),
|
|
643
|
+
decl('space-virtual-row-inset-y', `${space.step.virtualRowInsetY}px`),
|
|
644
|
+
decl('space-virtual-row-inset-x', `${space.step.virtualRowInsetX}px`),
|
|
645
|
+
// Controls tier row/gap heights (`docs/CONTROLS-SPEC.md` §5) — the current commit's consumers
|
|
646
|
+
// are `theme/ctl-theme.tsx` (`--vx-space-control-gap`) and the wave-3/4 homes (`PageBar`,
|
|
647
|
+
// `WidgetHeader`, sidebar blocks, the mobile `Filters (n)` sheet) landing next.
|
|
648
|
+
decl('space-page-bar-row-height', pxRem(space.step.pageBarRowHeight)),
|
|
649
|
+
decl('space-section-header-height', pxRem(space.step.sectionHeaderHeight)),
|
|
650
|
+
decl('space-widget-header-height', pxRem(space.step.widgetHeaderHeight)),
|
|
651
|
+
decl('space-sidebar-block-row-height', pxRem(space.step.sidebarBlockRowHeight)),
|
|
652
|
+
decl('space-control-gap', `${space.step.controlGap}px`),
|
|
653
|
+
decl('space-sheet-row-height', pxRem(space.step.sheetRowHeight)),
|
|
654
|
+
// `chartLegendGap`/`chartMarginTop`/`chartMarginRight`/`chartMarginBottom`/`chartMarginLeft`/
|
|
655
|
+
// `chartDotR`/`progressBarSize`/`timelineBullet` are DELIBERATELY absent — see this function's
|
|
656
|
+
// doc for why (JS-number-only consumers, zero `var()` reads). `appShellHeaderHeight`/
|
|
657
|
+
// `appShellNavbarWidth`/`appShellNavbarRailWidth`/`appShellAsideWidth`/`appShellAsideRailWidth`
|
|
658
|
+
// join that list — but NOT `appShellInset`/`appShellInsetMobile`/`appShellHeaderLeadMin`, which
|
|
659
|
+
// are emitted above and carry their own reason for the exception —
|
|
660
|
+
// `shell/index.tsx` reads all five as JS numbers via `useBasaltSpacing()` (Mantine's `AppShell`
|
|
661
|
+
// `header`/`navbar`/`aside` props take numbers, not `var()` strings), so a `--vx-space-app-shell-*`
|
|
662
|
+
// decl here would have had zero consumers, framework-wide, the same dead-weight shape this function's
|
|
663
|
+
// doc already calls out for the chart/Progress/Timeline group. `sidebarAccountMenuWidth`/
|
|
664
|
+
// `sidebarSettingsMenuWidth` join it too — `app-sidebar-account.tsx`/`app-sidebar.tsx` read both
|
|
665
|
+
// as JS numbers via `useBasaltSpacing()` (Mantine's `<Menu width={…}>` also takes a number).
|
|
666
|
+
]
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* The `--vx-space-*` names that survive `only: 'core'` — DERIVED from the `SPACE` anchor keys, never
|
|
671
|
+
* hand-listed, so a new `SPACE_STEP` one-off is excluded the moment it is added and a renamed anchor
|
|
672
|
+
* follows automatically. `SPACE` is the generic ladder (the stack rhythm, the two control heights,
|
|
673
|
+
* the row insets); everything else `spaceDecls` emits is named for a basalt COMPONENT and is dead
|
|
674
|
+
* weight outside this framework — including `--vx-space-row-line-height`, which is the NavLink row's
|
|
675
|
+
* line-height rather than a general anchor and so is (deliberately) in neither set.
|
|
676
|
+
*/
|
|
677
|
+
const CORE_SPACE_VARS = new Set(
|
|
678
|
+
Object.keys(SPACE).map((key) => `space-${key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`),
|
|
679
|
+
)
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Does this `spaceDecls` line declare a core anchor? The name is read back out of the emitted line
|
|
683
|
+
* because {@link decl} is the single formatter for every one of them — the shape is fixed at one
|
|
684
|
+
* call site, so parsing it cannot drift, whereas tagging 104 declarations by hand could.
|
|
685
|
+
*/
|
|
686
|
+
function isCoreSpaceDecl(line: string): boolean {
|
|
687
|
+
const name = /^ {2}--vx-([\w-]+):/.exec(line)?.[1]
|
|
688
|
+
return name !== undefined && CORE_SPACE_VARS.has(name)
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/** The shipped, level-0 spacing values — `frameworkDerived`'s `spaceDecls(...)` call below. No
|
|
692
|
+
* `createBasaltTheme({ density })` retuning applies here; that path calls `buildDensityCss` with a
|
|
693
|
+
* different resolved {@link SpaceValues} instead (see `../theme` and `../provider`). */
|
|
694
|
+
const DEFAULT_SPACE_VALUES: SpaceValues = {
|
|
695
|
+
anchors: SPACE,
|
|
696
|
+
scale: SPACE_SCALE,
|
|
697
|
+
step: SPACE_STEP,
|
|
698
|
+
rowLineHeight: ROW_LINE_HEIGHT,
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* The 16 deprecated camelCase aliases for `frameworkDerived`'s theme-independent (`:root`)
|
|
703
|
+
* canonicals — the 12 `fill-hover-<family>` fills plus `good-soft`/`good-ref`/`bad-ref`/`warn-ref`.
|
|
704
|
+
* Each is a `var(--vx-<canonical-kebab-name>)` ref so it can never drift. Emitted as its own
|
|
705
|
+
* commented, trailing group — gated by {@link BuildPaletteOpts.legacyAliases}, default on.
|
|
706
|
+
*/
|
|
707
|
+
function frameworkDerivedAliases(data: PaletteData): string {
|
|
708
|
+
return [
|
|
709
|
+
' /* Deprecated camelCase aliases — removed in a future minor; migrate to the kebab names above. */',
|
|
710
|
+
...Object.keys(data.FILL).map((name) =>
|
|
711
|
+
decl(`fillHover-${name}`, `var(--vx-fill-hover-${name})`),
|
|
712
|
+
),
|
|
713
|
+
decl('goodSoft', 'var(--vx-good-soft)'),
|
|
714
|
+
decl('goodRef', 'var(--vx-good-ref)'),
|
|
715
|
+
decl('badRef', 'var(--vx-bad-ref)'),
|
|
716
|
+
decl('warnRef', 'var(--vx-warn-ref)'),
|
|
717
|
+
].join('\n')
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Theme-independent scalars + semantic fills, defined once on `:root`.
|
|
722
|
+
*
|
|
723
|
+
* Area-gradient strength is a global knob (the theme lab overrides these two on `:root`
|
|
724
|
+
* to retune every line-area fill live). 0%/0% disables gradients app-wide.
|
|
725
|
+
*/
|
|
726
|
+
function frameworkDerived(data: PaletteData, only: 'core' | 'all', legacyAliases: boolean): string {
|
|
727
|
+
const space = spaceDecls(DEFAULT_SPACE_VALUES)
|
|
728
|
+
const canonical = [
|
|
729
|
+
decl('radius-card', `${RADIUS.card}px`),
|
|
730
|
+
decl('radius-ctrl', `${RADIUS.ctrl}px`),
|
|
731
|
+
// The two offset tiers (SegmentedControl indicator/Kbd/Code, Progress/scale-sm) — added so a
|
|
732
|
+
// component's inline `styles`/`style` can read the SAME source as `RADIUS_STEP.tight`/`.fine`
|
|
733
|
+
// instead of a hand-typed literal (see `theme/index.ts`'s component sweep).
|
|
734
|
+
decl('radius-tight', `${RADIUS_STEP.tight}px`),
|
|
735
|
+
decl('radius-fine', `${RADIUS_STEP.fine}px`),
|
|
736
|
+
// The floating tier (Modal/Tooltip/Popover/Notification, content code/mermaid blocks).
|
|
737
|
+
decl('radius-floating', `${RADIUS_STEP.floating}px`),
|
|
738
|
+
// The pill affordance (scroll-to-bottom button, chips) — fixed, level-invariant, so it lives
|
|
739
|
+
// only in this static block, never in `buildRadiusCss`'s dynamic override (see
|
|
740
|
+
// `RADIUS_STEP.pill`'s doc).
|
|
741
|
+
decl('radius-pill', `${RADIUS_STEP.pill}px`),
|
|
742
|
+
// The pointer tier's fine default — density-EXEMPT, so it lives only in this static block
|
|
743
|
+
// (same law as `radius-pill` above). `coarseHitBlock` re-points it to 44px.
|
|
744
|
+
decl('hit', `${HIT_FINE}px`),
|
|
745
|
+
...(only === 'core' ? space.filter(isCoreSpaceDecl) : space),
|
|
746
|
+
// Article-density Prose measure (docs/CONTENT-SPEC.md §5) — theme-independent, like the radii.
|
|
747
|
+
decl('prose-measure', '72ch'),
|
|
748
|
+
// The fill band (see FILL in palette.ts). Emitted on `:root`, NOT per scheme — a filled surface
|
|
749
|
+
// is the same hex in both, which is the whole point: it is squeezed between its white label and
|
|
750
|
+
// the page behind it, and only one luminance band satisfies both on both pages.
|
|
751
|
+
...Object.entries(data.FILL).map(([name, hex]) => decl(`fill-${name}`, hex)),
|
|
752
|
+
// Hover is DERIVED from the fill, so retuning a fill (in the theme lab, or here) carries its
|
|
753
|
+
// hover along instead of leaving a stale pair. 88% of the fill over black lands ~0.128 luminance:
|
|
754
|
+
// a visible press-darkening that still clears AA for the white label (~5.9:1).
|
|
755
|
+
...Object.keys(data.FILL).map((name) =>
|
|
756
|
+
decl(`fill-hover-${name}`, `color-mix(in srgb, var(--vx-fill-${name}) 88%, #000)`),
|
|
757
|
+
),
|
|
758
|
+
// The type scale, emitted from the SAME `TEXT` object `VX.text` reads — CSS modules and the
|
|
759
|
+
// Mantine theme consume these; inline styles / visx read the numbers. One ladder, two forms.
|
|
760
|
+
...Object.entries(TEXT).map(([step, px]) => decl(`text-${step}`, `${px}px`)),
|
|
761
|
+
decl('area-top', '22%'),
|
|
762
|
+
decl('area-bottom', '1%'),
|
|
763
|
+
decl('good', 'color-mix(in srgb, var(--vx-good-solid) 18%, transparent)'),
|
|
764
|
+
decl('good-soft', 'color-mix(in srgb, var(--vx-good-solid) 8%, transparent)'),
|
|
765
|
+
decl('bad', 'color-mix(in srgb, var(--vx-bad-solid) 18%, transparent)'),
|
|
766
|
+
decl('warn', 'color-mix(in srgb, var(--vx-warn-solid) 8%, transparent)'),
|
|
767
|
+
decl('good-ref', 'color-mix(in srgb, var(--vx-good-solid) 30%, transparent)'),
|
|
768
|
+
decl('bad-ref', 'color-mix(in srgb, var(--vx-bad-solid) 30%, transparent)'),
|
|
769
|
+
decl('warn-ref', 'color-mix(in srgb, var(--vx-warn-solid) 20%, transparent)'),
|
|
770
|
+
].join('\n')
|
|
771
|
+
return legacyAliases ? `${canonical}\n${frameworkDerivedAliases(data)}` : canonical
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Throw on a consumer series/group name inside a basalt-owned `--vx-*` family (`surface`, `space`,
|
|
776
|
+
* `ink`, …): `check-theme`'s `unknown-vx-token` judges every name there against what basalt emits,
|
|
777
|
+
* which is sound only while no consumer REF points there. Dev builds only (the call sits behind a
|
|
778
|
+
* literal NODE_ENV read); `unknown-vx-token` left the grace ledger at 1.36.0, which is when this
|
|
779
|
+
* went from a once-per-name warning to a throw. The families are the guard's own generated
|
|
780
|
+
* `BASALT_VX_FAMILIES`. Checked on the refs, not in `buildPaletteCss`, which runs on every first
|
|
781
|
+
* paint.
|
|
782
|
+
*/
|
|
783
|
+
function assertConsumerVxName(name: string): void {
|
|
784
|
+
const family = vxFamilyOf(name)
|
|
785
|
+
if (!BASALT_VX_FAMILIES.includes(family)) return
|
|
786
|
+
throw new Error(
|
|
787
|
+
`[basalt] ${name} is inside basalt's own --vx-${family} family — name your series group something basalt does not own (groupTokens('app', …)).`,
|
|
788
|
+
)
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Wrap a map of `{ name: ColorPair }` into `var(--vx-<prefix><name>)` token refs — the runtime
|
|
793
|
+
* companion to `buildPaletteCss`. Lets a consumer define its own series and read stable refs.
|
|
794
|
+
*
|
|
795
|
+
* Returns an exact-keyed object: the return type mirrors the keys of the input map, so a renamed
|
|
796
|
+
* or removed key becomes a tsc error rather than silently widening to `Record<string, string>`.
|
|
797
|
+
*/
|
|
798
|
+
export function seriesTokens<const T extends SeriesMap>(
|
|
799
|
+
map: T,
|
|
800
|
+
prefix = '',
|
|
801
|
+
): { [K in keyof T]: string } {
|
|
802
|
+
const out = {} as { [K in keyof T]: string }
|
|
803
|
+
for (const key of Object.keys(map) as (keyof T)[]) {
|
|
804
|
+
// Literal read at the branch, so a production bundle drops the check (common/dev-gate.test.ts).
|
|
805
|
+
if (process.env.NODE_ENV !== 'production') assertConsumerVxName(`--vx-${prefix}${String(key)}`)
|
|
806
|
+
out[key] = `var(--vx-${prefix}${String(key)})`
|
|
807
|
+
}
|
|
808
|
+
return out
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Define a named series map. Identity passthrough — gives consumers a typed authoring entry
|
|
813
|
+
* point and preserves the exact literal keys of the input (const-generic so callers get back T,
|
|
814
|
+
* not the widened SeriesMap, enabling downstream exact-key checks in groupTokens / seriesTokens).
|
|
815
|
+
*/
|
|
816
|
+
export function defineSeries<const T extends SeriesMap>(map: T): T {
|
|
817
|
+
return map
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/** Runtime key of the {@link SeriesGroup} brand. */
|
|
821
|
+
const SERIES_GROUP: unique symbol = Symbol('basalt.series-group')
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* The brand `groupTokens` puts on its return value. `BuildPaletteOpts.groups` takes these, so the
|
|
825
|
+
* `${name}-` key that emits the variables and the one that references them come from one call and
|
|
826
|
+
* cannot be spelled two ways.
|
|
827
|
+
*/
|
|
828
|
+
export type SeriesGroup = {
|
|
829
|
+
readonly [SERIES_GROUP]: { readonly prefix: string; readonly map: SeriesMap }
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Build a single namespaced group's token refs (`var(--vx-<name>-<key>)`).
|
|
834
|
+
*
|
|
835
|
+
* Returns an exact-keyed object matching the keys of `map` — a stale or renamed key is a tsc
|
|
836
|
+
* error at the call site rather than a silent `Record<string, string>` widening.
|
|
837
|
+
*/
|
|
838
|
+
export function groupTokens<const T extends SeriesMap>(
|
|
839
|
+
name: string,
|
|
840
|
+
map: T,
|
|
841
|
+
): { [K in keyof T]: string } & SeriesGroup {
|
|
842
|
+
const refs = seriesTokens(map, `${name}-`)
|
|
843
|
+
// Non-enumerable, symbol-keyed: a series key can never collide with the brand, and
|
|
844
|
+
// `Object.keys(refs)` still lists exactly the series.
|
|
845
|
+
Object.defineProperty(refs, SERIES_GROUP, { value: { prefix: `${name}-`, map } })
|
|
846
|
+
return refs as { [K in keyof T]: string } & SeriesGroup
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* The attribute + values the per-scheme blocks key off. Defaults reproduce Mantine's own toggle
|
|
851
|
+
* (`data-mantine-color-scheme` = `dark` / `light`), so a consumer only names the axis it differs
|
|
852
|
+
* on. Supplying this object at all switches the emitter onto the framework-neutral selector shape
|
|
853
|
+
* — see {@link BuildPaletteOpts.scheme}.
|
|
854
|
+
*/
|
|
855
|
+
export type ColorSchemeSelector = {
|
|
856
|
+
attribute?: string
|
|
857
|
+
darkValue?: string
|
|
858
|
+
lightValue?: string
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/** Options for {@link buildPaletteCss}. */
|
|
862
|
+
export type BuildPaletteOpts = {
|
|
863
|
+
/** Extra named series maps to emit under the given prefixes (each one is the return value of `groupTokens`). */
|
|
864
|
+
groups?: readonly SeriesGroup[]
|
|
865
|
+
/** Theme-independent derived declarations (gradients, semantic fills) emitted once on `:root`. */
|
|
866
|
+
derived?: string[]
|
|
867
|
+
/**
|
|
868
|
+
* Attribute + values the per-scheme blocks key off — for a consumer whose scheme toggle is not
|
|
869
|
+
* Mantine's (a static site on `data-theme`, say). Default: Mantine's own
|
|
870
|
+
* `data-mantine-color-scheme` = `dark` / `light`.
|
|
871
|
+
*
|
|
872
|
+
* Setting ANY of `scheme` / `defaultScheme` / `mediaFallback` moves the emitter off the legacy
|
|
873
|
+
* `html[…]` selector onto `:root[…]`. That is deliberate and load-bearing, NOT cosmetic:
|
|
874
|
+
*
|
|
875
|
+
* `:root[data-theme='dark']` 0-2-0 ← what this path emits
|
|
876
|
+
* `html[data-theme='dark']` 0-1-1
|
|
877
|
+
* `[data-theme='dark']` 0-1-0 ← same as a bare `:root`, so source order decides
|
|
878
|
+
*
|
|
879
|
+
* A light-default site whose own `:root` block happens to come last would beat the third form
|
|
880
|
+
* outright — dark mode silently does nothing. `:root[…]` sits above both a bare `:root` and
|
|
881
|
+
* `html[…]`, and carries no assumption about the element the attribute lands on.
|
|
882
|
+
*
|
|
883
|
+
* The no-options path keeps emitting `html[data-mantine-color-scheme='…']` verbatim, because a
|
|
884
|
+
* basalt consumer may already override `--vx-*` under that exact selector — raising basalt's own
|
|
885
|
+
* specificity would silently win over their override.
|
|
886
|
+
*/
|
|
887
|
+
scheme?: ColorSchemeSelector
|
|
888
|
+
/**
|
|
889
|
+
* Which scheme rides along on the bare `:root` block — the one that applies when the attribute
|
|
890
|
+
* is absent. Default: `'dark'` (the framework's own default scheme).
|
|
891
|
+
*
|
|
892
|
+
* `'none'` emits no bare-`:root` primitives at all: each scheme gets only its attribute block,
|
|
893
|
+
* and an unattributed document falls back to the theme-independent scalars alone. Pair it with
|
|
894
|
+
* `mediaFallback` unless the consumer always sets the attribute.
|
|
895
|
+
*/
|
|
896
|
+
defaultScheme?: 'dark' | 'light' | 'none'
|
|
897
|
+
/**
|
|
898
|
+
* Also emit an `@media (prefers-color-scheme: …)` block for every scheme that is not the bare
|
|
899
|
+
* `:root` default, so a document with no attribute set follows the OS. Default: `false`.
|
|
900
|
+
*
|
|
901
|
+
* The block is a bare `:root` (0-1-0), so an explicit attribute block (0-2-0) always wins over
|
|
902
|
+
* it regardless of source order — the OS preference is a fallback, never an override.
|
|
903
|
+
*/
|
|
904
|
+
mediaFallback?: boolean
|
|
905
|
+
/**
|
|
906
|
+
* How much of the SPACING set to emit. Default: `'all'` (every one of the 108 `--vx-space-*`
|
|
907
|
+
* declarations the framework's own components read).
|
|
908
|
+
*
|
|
909
|
+
* `'core'` keeps the 9 generic anchors — the stack rhythm, the two control heights, the row
|
|
910
|
+
* insets — and drops the 99 named for a specific basalt component
|
|
911
|
+
* (`--vx-space-agent-transcript-inset`, `--vx-space-toc-sub-indent`, …), taking the emitted set
|
|
912
|
+
* from 204 variables to 105. Nothing outside basalt's own React components reads those, so a
|
|
913
|
+
* framework-free consumer is carrying them for nothing.
|
|
914
|
+
*
|
|
915
|
+
* This is a SPACING filter only: color, radius, shadow, type and status variables are identical
|
|
916
|
+
* in both modes. The partition is derived from the `SPACE` key set rather than a maintained list
|
|
917
|
+
* — see {@link CORE_SPACE_VARS}.
|
|
918
|
+
*/
|
|
919
|
+
only?: 'core' | 'all'
|
|
920
|
+
/**
|
|
921
|
+
* Whether to also emit the 32 deprecated camelCase aliases (`--vx-accentFill`, `--vx-tooltipBg`,
|
|
922
|
+
* `--vx-fillHover-gray`, …) alongside the canonical kebab-case names the 1.4.0 normalization
|
|
923
|
+
* introduced. Default: `true`, so an existing consumer's hand-written CSS referencing a
|
|
924
|
+
* camelCase name keeps resolving. Each alias is defined as `var(--vx-<canonical>)` — it can
|
|
925
|
+
* never drift from the value it aliases. Pass `false` once every reference in your own code has
|
|
926
|
+
* migrated to the kebab names to drop the extra 32 lines.
|
|
927
|
+
*/
|
|
928
|
+
legacyAliases?: boolean
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/** Mantine's own color-scheme attribute — the default {@link ColorSchemeSelector.attribute}. */
|
|
932
|
+
const MANTINE_SCHEME_ATTRIBUTE = 'data-mantine-color-scheme'
|
|
933
|
+
|
|
934
|
+
/** Indent an already-2-space-indented declaration block one level deeper (for `@media` nesting). */
|
|
935
|
+
const indent = (block: string): string =>
|
|
936
|
+
block
|
|
937
|
+
.split('\n')
|
|
938
|
+
.map((line) => (line === '' ? line : ` ${line}`))
|
|
939
|
+
.join('\n')
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* The `< sm` breakpoint, written the way a stylesheet has to write it — the SAME literal every
|
|
943
|
+
* basalt CSS module spells (`shell/app-header.module.css`, `dashboard/section.module.css`, …), and
|
|
944
|
+
* for the same reason `BREAKPOINTS` above exists: a `@media` condition is resolved before custom
|
|
945
|
+
* properties exist, so the number cannot be a `var()`. Held here as a constant rather than inlined
|
|
946
|
+
* so the emitter and the modules can be grepped as one set.
|
|
947
|
+
*/
|
|
948
|
+
const MOBILE_MEDIA = `@media (max-width: ${sizeClassMaxEm(SIZE_CLASSES.medium)})`
|
|
949
|
+
|
|
950
|
+
const coarseHitBlock = `@media (pointer: coarse) {\n :root {\n --vx-hit: ${HIT_COARSE}px;\n }\n}`
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* The MOBILE INSET LADDER, and this function is its ONE home — framework-wide, not per module.
|
|
954
|
+
*
|
|
955
|
+
* The problem it answers: the desktop-shell pass took the page gutter from 20 to 8 below `sm`
|
|
956
|
+
* (`appShellInsetMobile`), and the card ladder INSIDE that gutter never moved — card insets stayed
|
|
957
|
+
* `xs`/`sm` and a `Section`'s gaps stayed `stackMd` at every width — so a 390px phone still read
|
|
958
|
+
* "content spacing too big" after the gutter fix. Two rungs close it: the card's horizontal inset
|
|
959
|
+
* steps `sm` -> `xs`, and the Section's gap steps `stackMd` -> `stackSm`.
|
|
960
|
+
*
|
|
961
|
+
* Why it lives HERE and not in the three CSS files that consume it: two of those three sites are
|
|
962
|
+
* INLINE styles in TSX (`dashboard/stat-card.tsx`, `charts/primitives/ChartCard.tsx`), and an
|
|
963
|
+
* inline style cannot carry a media query at all. The only surface that reaches all three is a
|
|
964
|
+
* custom property whose VALUE moves at the breakpoint, and the only stylesheet guaranteed present
|
|
965
|
+
* wherever those components render is this one — `BasaltProvider` injects `buildPaletteCss()`, and
|
|
966
|
+
* a component's own CSS module is loaded only if a bundler kept that module. So the law is one
|
|
967
|
+
* `@media` block emitted beside the base declarations it overrides, and every consuming site is a
|
|
968
|
+
* plain `var()` read with no breakpoint knowledge. A media query copied into three files (or into
|
|
969
|
+
* one component stylesheet reaching for `:global(:root)`) was the alternative, and it fails the
|
|
970
|
+
* same way twice: three copies drift, and one copy in a tree-shakeable module is a law that
|
|
971
|
+
* sometimes does not ship.
|
|
972
|
+
*
|
|
973
|
+
* This does NOT make the token layer responsive in general. It stays what `BREAKPOINTS`'s doc says
|
|
974
|
+
* it is — the layer that owns the NUMBER a media query has to write — and this is the one law whose
|
|
975
|
+
* consuming sites cannot write that query themselves. A dimension whose consumer is a CSS module
|
|
976
|
+
* keeps making the choice in that module (`appShellInset`/`appShellInsetMobile` still do).
|
|
977
|
+
*/
|
|
978
|
+
function spaceMobileDecls(space: SpaceValues): string[] {
|
|
979
|
+
return [
|
|
980
|
+
decl('space-card-inset-x', `${space.scale.xs}px`),
|
|
981
|
+
decl('space-section-gap', `${space.anchors.stackSm}px`),
|
|
982
|
+
]
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/** {@link spaceMobileDecls} as the `@media` block that overrides the base `:root` declarations —
|
|
986
|
+
* same specificity, later in source order, so it wins below `sm` and nowhere else. */
|
|
987
|
+
function mobileLadderBlock(space: SpaceValues): string {
|
|
988
|
+
return `${MOBILE_MEDIA} {\n :root {\n${indent(spaceMobileDecls(space).join('\n'))}\n }\n}`
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Emit the `--vx-*` stylesheet: a `:root` block of theme-independent scalars, then the
|
|
993
|
+
* dark (default) and light primitive blocks under `html[data-mantine-color-scheme='…']`.
|
|
994
|
+
*
|
|
995
|
+
* The framework chrome (STATUS/SEMANTIC/SURFACE pairs + the framework DERIVED defaults) is
|
|
996
|
+
* built in, so an empty `buildPaletteCss()` already emits every framework var. Consumer
|
|
997
|
+
* `opts.groups` / `opts.derived` append on top (e.g. argo's domain SERIES/ACTIVITY/USAGE).
|
|
998
|
+
*
|
|
999
|
+
* `data` defaults to the static, shipped palette (`buildPaletteData()` at `DEFAULT_DERIVE_CONFIG`)
|
|
1000
|
+
* — pass the result of `buildPaletteData(config)` to emit CSS for a retuned derive config instead
|
|
1001
|
+
* (this is how `BasaltProvider` follows `createBasaltTheme`'s `{ derive }` option; see `../theme`
|
|
1002
|
+
* and `../provider`).
|
|
1003
|
+
*
|
|
1004
|
+
* Dark is the default (`:root`) since the framework defaults to dark; the
|
|
1005
|
+
* `[data-mantine-color-scheme]` selectors track Mantine's toggle on `<html>`.
|
|
1006
|
+
*
|
|
1007
|
+
* A non-Mantine consumer retargets all three of those choices — the attribute, which scheme rides
|
|
1008
|
+
* the bare `:root`, and whether the OS preference is honoured — via `opts.scheme` /
|
|
1009
|
+
* `opts.defaultScheme` / `opts.mediaFallback`. Setting any of them also moves the per-scheme
|
|
1010
|
+
* selector from `html[…]` to the framework-neutral, higher-specificity `:root[…]`; see
|
|
1011
|
+
* `BuildPaletteOpts.scheme` for why that is not cosmetic. With none of them set the output is
|
|
1012
|
+
* byte-identical to what the framework has always emitted (pinned by
|
|
1013
|
+
* `tests/palette-css.test.ts`).
|
|
1014
|
+
*/
|
|
1015
|
+
export function buildPaletteCss(
|
|
1016
|
+
opts: BuildPaletteOpts = {},
|
|
1017
|
+
data: PaletteData = buildPaletteData(),
|
|
1018
|
+
): string {
|
|
1019
|
+
const groups = opts.groups ?? []
|
|
1020
|
+
const legacyAliases = opts.legacyAliases ?? true
|
|
1021
|
+
const only = opts.only ?? 'all'
|
|
1022
|
+
const extraDerived = (opts.derived ?? []).map((d) => ` ${d}`).join('\n')
|
|
1023
|
+
const derivedBlock = frameworkDerived(data, only, legacyAliases)
|
|
1024
|
+
const derived = extraDerived ? `${derivedBlock}\n${extraDerived}` : derivedBlock
|
|
1025
|
+
const side = (s: Side): string => {
|
|
1026
|
+
const extra = groups
|
|
1027
|
+
.map((group) => groupSide(group[SERIES_GROUP].prefix, group[SERIES_GROUP].map, s))
|
|
1028
|
+
.join('\n')
|
|
1029
|
+
const framework = frameworkPrimitives(s, data, legacyAliases)
|
|
1030
|
+
return extra ? `${framework}\n${extra}` : framework
|
|
1031
|
+
}
|
|
1032
|
+
// The scalars, then the ONE `@media` block that re-points two of them below `sm` (see
|
|
1033
|
+
// `spaceMobileDecls`). Dropped under `only: 'core'` for the same reason the declarations it
|
|
1034
|
+
// overrides are: both vars are component-named one-offs, not `SPACE` anchors, so a core-only
|
|
1035
|
+
// consumer never receives the base pair the block exists to override.
|
|
1036
|
+
const rootBlock =
|
|
1037
|
+
only === 'core'
|
|
1038
|
+
? `:root {\n${derived}\n}\n${coarseHitBlock}`
|
|
1039
|
+
: `:root {\n${derived}\n}\n${mobileLadderBlock(DEFAULT_SPACE_VALUES)}\n${coarseHitBlock}`
|
|
1040
|
+
|
|
1041
|
+
// The legacy shape — kept verbatim, and only reachable when the caller asked for nothing.
|
|
1042
|
+
if (opts.scheme === undefined && opts.defaultScheme === undefined && !opts.mediaFallback) {
|
|
1043
|
+
return `${rootBlock}
|
|
1044
|
+
:root,
|
|
1045
|
+
html[data-mantine-color-scheme='dark'] {
|
|
1046
|
+
${side('dark')}
|
|
1047
|
+
}
|
|
1048
|
+
html[data-mantine-color-scheme='light'] {
|
|
1049
|
+
${side('light')}
|
|
1050
|
+
}`
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
const attribute = opts.scheme?.attribute ?? MANTINE_SCHEME_ATTRIBUTE
|
|
1054
|
+
const value: Record<Side, string> = {
|
|
1055
|
+
dark: opts.scheme?.darkValue ?? 'dark',
|
|
1056
|
+
light: opts.scheme?.lightValue ?? 'light',
|
|
1057
|
+
}
|
|
1058
|
+
const defaultScheme = opts.defaultScheme ?? 'dark'
|
|
1059
|
+
// Default scheme first, so its attribute block can absorb the bare `:root` instead of repeating
|
|
1060
|
+
// ~40 declarations; `'none'` keeps the framework's dark-then-light order.
|
|
1061
|
+
const order: Side[] = defaultScheme === 'light' ? ['light', 'dark'] : ['dark', 'light']
|
|
1062
|
+
|
|
1063
|
+
const blocks = [rootBlock]
|
|
1064
|
+
for (const s of order) {
|
|
1065
|
+
const selector =
|
|
1066
|
+
s === defaultScheme
|
|
1067
|
+
? `:root,\n:root[${attribute}='${value[s]}']`
|
|
1068
|
+
: `:root[${attribute}='${value[s]}']`
|
|
1069
|
+
// The OS fallback for a scheme goes immediately before that scheme's own attribute block. It is
|
|
1070
|
+
// a bare `:root` (0-1-0), so the attribute block (0-2-0) outranks it on specificity rather than
|
|
1071
|
+
// on order — an explicit toggle always beats the OS preference, and the OS preference always
|
|
1072
|
+
// beats the hardcoded default that a bare `:root` above it carries.
|
|
1073
|
+
if (opts.mediaFallback === true && s !== defaultScheme) {
|
|
1074
|
+
blocks.push(`@media (prefers-color-scheme: ${s}) {\n :root {\n${indent(side(s))}\n }\n}`)
|
|
1075
|
+
}
|
|
1076
|
+
blocks.push(`${selector} {\n${side(s)}\n}`)
|
|
1077
|
+
}
|
|
1078
|
+
return blocks.join('\n')
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* The `fonts` option's resolved shape — a full CSS font-family stack string per slot (with its own
|
|
1083
|
+
* fallback chain), riding the `--basalt-font-sans/head/mono` override seam `styles.css` ships
|
|
1084
|
+
* fallbacks for. Omitted keys keep the shipped fallback untouched. Lives here (not in `../theme`,
|
|
1085
|
+
* which only re-exports the type) because its builder `buildFontsCss` below is a pure, Mantine-free
|
|
1086
|
+
* string builder that belongs in the tokens layer — see `../theme`'s
|
|
1087
|
+
* `CreateBasaltThemeOptions.fonts` for the production entry point that sets it.
|
|
1088
|
+
*/
|
|
1089
|
+
export type BasaltFontsConfig = {
|
|
1090
|
+
sans?: string
|
|
1091
|
+
head?: string
|
|
1092
|
+
mono?: string
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/** `{ basaltFonts key → --basalt-font-* var name }` — the one place the mapping is spelled out. */
|
|
1096
|
+
const FONT_VAR_NAMES = {
|
|
1097
|
+
sans: '--basalt-font-sans',
|
|
1098
|
+
head: '--basalt-font-head',
|
|
1099
|
+
mono: '--basalt-font-mono',
|
|
1100
|
+
} as const satisfies Record<keyof BasaltFontsConfig, string>
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Build the `:root` block of `--basalt-font-*` declarations for a resolved `basaltFonts` config —
|
|
1104
|
+
* only for the keys the consumer actually set (`createBasaltTheme(overrides, { fonts })`); an
|
|
1105
|
+
* omitted key keeps the shipped `styles.css` fallback chain untouched. Empty string when `fonts` is
|
|
1106
|
+
* absent or every key is omitted, so callers can unconditionally concatenate the result. Internal
|
|
1107
|
+
* (not on the `basalt-ui/tokens` barrel) — `BasaltProvider`'s bridge (`../provider`) calls this
|
|
1108
|
+
* directly to append declarations to its injected `<style>`.
|
|
1109
|
+
*/
|
|
1110
|
+
export function buildFontsCss(fonts: BasaltFontsConfig | undefined): string {
|
|
1111
|
+
if (!fonts) return ''
|
|
1112
|
+
const decls = (Object.keys(FONT_VAR_NAMES) as (keyof BasaltFontsConfig)[])
|
|
1113
|
+
.filter((key) => fonts[key] !== undefined)
|
|
1114
|
+
.map((key) => {
|
|
1115
|
+
const value = fonts[key] as string
|
|
1116
|
+
// A font stack is a plain declaration value — `{`/`}`/`;`/comment openers would let a
|
|
1117
|
+
// config string break out of the emitted `<style>` declaration. Throw, don't sanitize,
|
|
1118
|
+
// per the repo's validation convention (see `deriveTokens`'s accent-hex assert).
|
|
1119
|
+
if (/[{};]|\/\*/.test(value)) {
|
|
1120
|
+
throw new Error(
|
|
1121
|
+
`Invalid fonts.${key}: a font-family stack must not contain "{", "}", ";" or "/*" — got ${JSON.stringify(value)}`,
|
|
1122
|
+
)
|
|
1123
|
+
}
|
|
1124
|
+
return ` ${FONT_VAR_NAMES[key]}: ${value};`
|
|
1125
|
+
})
|
|
1126
|
+
if (decls.length === 0) return ''
|
|
1127
|
+
return `:root {\n${decls.join('\n')}\n}`
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Build the `:root` block of overriding `--vx-radius-*` declarations for a resolved
|
|
1132
|
+
* `basaltRadius` value (`createBasaltTheme(overrides, { radius })`) — analog of {@link buildFontsCss}.
|
|
1133
|
+
* Empty string when `radius` is absent (the default level-0 path never sets `theme.other.basaltRadius`
|
|
1134
|
+
* in the first place), so callers can unconditionally concatenate the result. Internal, like
|
|
1135
|
+
* `buildFontsCss` above.
|
|
1136
|
+
*/
|
|
1137
|
+
export function buildRadiusCss(radius: RadiusValues | undefined): string {
|
|
1138
|
+
if (!radius) return ''
|
|
1139
|
+
return `:root {
|
|
1140
|
+
--vx-radius-card: ${radius.card}px;
|
|
1141
|
+
--vx-radius-ctrl: ${radius.ctrl}px;
|
|
1142
|
+
--vx-radius-tight: ${radius.tight}px;
|
|
1143
|
+
--vx-radius-fine: ${radius.fine}px;
|
|
1144
|
+
--vx-radius-floating: ${radius.floating}px;
|
|
1145
|
+
}`
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* Build the `:root` block of overriding `--vx-space-*` declarations for a resolved `basaltDensity`
|
|
1150
|
+
* value (`createBasaltTheme(overrides, { density })`) — analog of {@link buildRadiusCss}, reusing
|
|
1151
|
+
* the SAME `spaceDecls` list `frameworkDerived` emits the shipped defaults from (so the two can
|
|
1152
|
+
* never drift). Empty string when `space` is absent (the default level-0 path never sets
|
|
1153
|
+
* `theme.other.basaltDensity` in the first place), so callers can unconditionally concatenate the
|
|
1154
|
+
* result. Importable from `basalt-ui/tokens`, same SSR/custom-injection use as `buildRadiusCss`
|
|
1155
|
+
* above.
|
|
1156
|
+
*/
|
|
1157
|
+
export function buildDensityCss(space: SpaceValues | undefined): string {
|
|
1158
|
+
if (!space) return ''
|
|
1159
|
+
// The `< sm` ladder rides along, at the retuned level — without it a phone at `density: 2` would
|
|
1160
|
+
// take the level-0 mobile inset from the static stylesheet and the level-2 base from this one,
|
|
1161
|
+
// which is the only way the two rungs of one ladder could ever come from different levels.
|
|
1162
|
+
return `:root {\n${spaceDecls(space).join('\n')}\n}\n${mobileLadderBlock(space)}`
|
|
1163
|
+
}
|