basalt-ui 1.41.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +46 -43
- package/CHANGELOG.md +535 -518
- package/MIGRATING.md +945 -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 +14 -43
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/doctor-upgrade.d.ts +31 -0
- package/dist/cli/doctor-upgrade.d.ts.map +1 -0
- package/dist/cli/doctor-upgrade.js +269 -0
- package/dist/cli/doctor.d.ts +13 -29
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +51 -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 +77 -170
- 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 +14 -43
- package/src/cli/doctor-upgrade.ts +392 -0
- package/src/cli/doctor.ts +81 -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
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import { VX } from '../../tokens'
|
|
2
|
-
import type { ChartTier } from '../primitives/chart-frame-layout'
|
|
3
|
-
import { maxTextWidth } from './measure-text'
|
|
4
|
-
|
|
5
|
-
/** The gap one x tick label wants from its neighbour, on top of its measured width. */
|
|
6
|
-
const X_TICK_LABEL_GAP = 8
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The horizontal room one x tick label needs: the widest string in `labels`, plus breathing space
|
|
10
|
-
* to its neighbour. Feeds `smartTicks`, which otherwise thinned the axis by a constant that knew
|
|
11
|
-
* nothing about what was actually painted (`docs/CHARTS-SPEC.md` §1). Shared by `CartesianChart`,
|
|
12
|
-
* `useBandPlot` and `DualPanel` — the three call sites that used to reimplement this formula.
|
|
13
|
-
*
|
|
14
|
-
* `fontPx` defaults to `VX.axisFont`; a phone-tier chart passes its own smaller tick font
|
|
15
|
-
* (`chartMetrics().axisFont`) so the spacing is derived from the size actually painted.
|
|
16
|
-
*/
|
|
17
|
-
export function xLabelPxFor(labels: string[], fontPx: number = VX.axisFont): number {
|
|
18
|
-
return maxTextWidth(labels, fontPx) + X_TICK_LABEL_GAP
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* The horizontal room one 45°-rotated x label takes: its projected box (`cos 45°` of the width plus
|
|
23
|
-
* one line box) plus the gap. A tilted label still competes with its neighbour for this much, so
|
|
24
|
-
* thinning by the bare `VX.minPxPerTick` floor let two of them touch as soon as the plot widened.
|
|
25
|
-
*/
|
|
26
|
-
export function rotatedXLabelPx(labels: string[], fontPx: number = VX.axisFont): number {
|
|
27
|
-
return (
|
|
28
|
-
Math.ceil(COS_45 * (maxTextWidth(labels, fontPx) + Math.ceil(fontPx * 1.35))) + X_TICK_LABEL_GAP
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Pick evenly-spaced tick values that fit the available width.
|
|
34
|
-
*
|
|
35
|
-
* `labelPx` is the width one formatted label actually needs (measured, plus the gap it wants from
|
|
36
|
-
* its neighbour) and REPLACES the `VX.minPxPerTick` constant whenever it is supplied, in either
|
|
37
|
-
* direction — a wide label needs more room than the constant assumed (a `formatX` returning
|
|
38
|
-
* `Mar 08 14:00` used to overlap at every width, the one side of the chart that did not follow
|
|
39
|
-
* §1's "measure what you paint" law), and a narrow one (single-digit band labels) can pack in
|
|
40
|
-
* MORE ticks than the constant would allow, which the floor used to suppress (R2C-11). Omit it and
|
|
41
|
-
* the constant is what governs, same as before.
|
|
42
|
-
*
|
|
43
|
-
* The final key is still appended when the step misses the last index — a thinned axis would
|
|
44
|
-
* otherwise paint no label at the right edge at all — but it no longer prints ON TOP of its
|
|
45
|
-
* neighbour. An appended tick lands a PARTIAL step from the last one on the grid, so at any tick
|
|
46
|
-
* count wide enough labels overlap there; measured at `/charts-stress` block (f1), `Mar 13 14:00`
|
|
47
|
-
* and `Mar 14 14:00` printed over each other at 1440px. When that gap is narrower than one label,
|
|
48
|
-
* the grid tick before it is dropped instead.
|
|
49
|
-
*
|
|
50
|
-
* `anchorTerminals` (default false) mirrors the SAME flag `autoMargin`/`Axes.tsx` take: when the
|
|
51
|
-
* axis anchors index 0 and the last index at their TEXT edge rather than their centre
|
|
52
|
-
* (`terminalAnchor`), each reaches a FULL label's width toward its neighbour instead of half, so
|
|
53
|
-
* the plain per-tick pitch above (sized for two centred labels) isn't enough at either boundary —
|
|
54
|
-
* `Bars` with 30 daily "Jan DD HH:MM" keys overlapped there at phone width even though the interior
|
|
55
|
-
* pitch was fine (R2C-6). The SAME rule then applies, symmetrically, to the tick right after
|
|
56
|
-
* index 0. 1.5× is a deliberately generous (cheap, simple) stand-in for "one label plus half a
|
|
57
|
-
* label" rather than measuring the split precisely; it's skipped when `labelPx` is only the bare
|
|
58
|
-
* `VX.minPxPerTick` floor, which has no relationship to how wide a label actually is. Index 0
|
|
59
|
-
* always survives (never the one dropped here) and `last` is always (re-)added below, so dropping
|
|
60
|
-
* any OTHER index never breaks the "at least 2 ticks" floor.
|
|
61
|
-
*/
|
|
62
|
-
export function smartTicks(
|
|
63
|
-
dates: string[],
|
|
64
|
-
xMax: number,
|
|
65
|
-
labelPx?: number,
|
|
66
|
-
anchorTerminals = false,
|
|
67
|
-
): string[] {
|
|
68
|
-
if (dates.length === 0) return []
|
|
69
|
-
// A non-positive `labelPx` (a caller's own arithmetic gone wrong, or an explicit 0) is not "no
|
|
70
|
-
// measurement" — `labelPx ?? VX.minPxPerTick` let it through as-is, and `xMax / 0` then floors
|
|
71
|
-
// `maxTicks` to `Infinity`, which used to make EVERY tick "fit" and skip thinning entirely.
|
|
72
|
-
const perTick = labelPx !== undefined && labelPx > 0 ? labelPx : VX.minPxPerTick
|
|
73
|
-
const maxTicks = Math.max(2, Math.floor(xMax / perTick))
|
|
74
|
-
const last = dates.length - 1
|
|
75
|
-
// `scalePoint({ padding: 0.5 })` spreads N points over `xMax`, so one index is `xMax / N` wide.
|
|
76
|
-
const pxPerIndex = dates.length > 0 ? xMax / dates.length : 0
|
|
77
|
-
// Only a REAL measured label (not the bare `VX.minPxPerTick` floor, which knows nothing about how
|
|
78
|
-
// wide a label actually is) earns the wider terminal clearance below.
|
|
79
|
-
const anchored = anchorTerminals && labelPx !== undefined && labelPx > 0
|
|
80
|
-
|
|
81
|
-
const keep = new Set<number>()
|
|
82
|
-
if (dates.length <= maxTicks) {
|
|
83
|
-
// Every date already fits with no thinning — round 3: this used to `return dates` here,
|
|
84
|
-
// skipping the terminal-clearance pass below entirely. A terminal-anchored label still reaches
|
|
85
|
-
// a FULL label's width toward its neighbour (not half, like a centred one), which the plain
|
|
86
|
-
// per-tick spacing above does not itself guarantee, so the same pass has to run here too.
|
|
87
|
-
for (let i = 0; i <= last; i += 1) keep.add(i)
|
|
88
|
-
} else {
|
|
89
|
-
const step = Math.ceil(dates.length / maxTicks)
|
|
90
|
-
for (let i = 0; i <= last; i += step) keep.add(i)
|
|
91
|
-
|
|
92
|
-
const BOUNDARY_FACTOR = 1.5
|
|
93
|
-
const boundaryPx = anchored ? perTick * BOUNDARY_FACTOR : perTick
|
|
94
|
-
// The final key is appended unconditionally, even when the step misses it — but only dropping
|
|
95
|
-
// the grid tick right before it when the two would otherwise sit closer than one tick's width.
|
|
96
|
-
// This is the "would an APPEND overlap" concern; it does nothing when the step already lands on
|
|
97
|
-
// `last` (nothing is being appended), which is the gap the anchored pass below closes.
|
|
98
|
-
const lastOnGrid = Math.floor(last / step) * step
|
|
99
|
-
if (lastOnGrid !== last) {
|
|
100
|
-
const gapPx = (last - lastOnGrid) * pxPerIndex
|
|
101
|
-
if (lastOnGrid > 0 && gapPx > 0 && gapPx < boundaryPx) keep.delete(lastOnGrid)
|
|
102
|
-
keep.add(last)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (anchored && keep.size > 1) {
|
|
107
|
-
const BOUNDARY_FACTOR = 1.5
|
|
108
|
-
const boundaryPx = perTick * BOUNDARY_FACTOR
|
|
109
|
-
// START: the kept index right after 0 needs a FULL label's clearance from it, not the plain
|
|
110
|
-
// per-tick pitch a centred label would settle for.
|
|
111
|
-
const sorted = [...keep].toSorted((a, b) => a - b)
|
|
112
|
-
const second = sorted[1]
|
|
113
|
-
if (second !== undefined && second !== last && second * pxPerIndex < boundaryPx) {
|
|
114
|
-
keep.delete(second)
|
|
115
|
-
}
|
|
116
|
-
// END: the same check, mirrored, against whatever is now the second-to-last kept index —
|
|
117
|
-
// computed AFTER the START drop above (not from the original grid), and unconditional of
|
|
118
|
-
// whether `last` was naturally on the grid or had to be appended (round 3's fix: previously this
|
|
119
|
-
// only ran inside the `lastOnGrid !== last` branch above, so a grid that already landed on
|
|
120
|
-
// `last` skipped it — the 13-dates/60px-label/260px-width counter-example this closes: step 4
|
|
121
|
-
// lands on index 12, leaving its neighbour at index 8 only 80px away, under the 90px a
|
|
122
|
-
// full-width terminal label needs).
|
|
123
|
-
const afterHead = [...keep].toSorted((a, b) => a - b)
|
|
124
|
-
const secondLast = afterHead[afterHead.length - 2]
|
|
125
|
-
if (
|
|
126
|
-
secondLast !== undefined &&
|
|
127
|
-
secondLast !== 0 &&
|
|
128
|
-
(last - secondLast) * pxPerIndex < boundaryPx
|
|
129
|
-
) {
|
|
130
|
-
keep.delete(secondLast)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return dates.filter((_, i) => keep.has(i))
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Which of a BAND axis's category labels may be painted so that no two neighbours overlap — the
|
|
139
|
-
* same measured law {@link smartTicks} applies to a point axis, for a chart that lays its labels
|
|
140
|
-
* out itself instead of through the `Axis*` primitives.
|
|
141
|
-
*
|
|
142
|
-
* `Heatmap` was the one kind rendering labels as plain `<text>`, and therefore the one kind exempt
|
|
143
|
-
* from §1's measured-margin law: it printed all 12 columns at 390px, ten of them overlapping. Here
|
|
144
|
-
* `bandPx` is the pitch between two neighbouring labels (a cell's width for columns, its height for
|
|
145
|
-
* rows) and `labelPx` the room one label needs ({@link xLabelPxFor} for a horizontal run, the line
|
|
146
|
-
* box for a vertical one); a label is kept every `ceil(labelPx / bandPx)` bands, so the gap between
|
|
147
|
-
* two painted labels is never narrower than one label.
|
|
148
|
-
*
|
|
149
|
-
* The first and last band always keep theirs — they are the two a reader orients from — and when
|
|
150
|
-
* the last one lands a partial step from the grid, the grid label before it is dropped rather than
|
|
151
|
-
* printed underneath, exactly as `smartTicks` does with its appended final tick.
|
|
152
|
-
*/
|
|
153
|
-
export function thinLabels(
|
|
154
|
-
labels: readonly string[],
|
|
155
|
-
bandPx: number,
|
|
156
|
-
labelPx: number,
|
|
157
|
-
): Set<number> {
|
|
158
|
-
const keep = new Set<number>()
|
|
159
|
-
const last = labels.length - 1
|
|
160
|
-
if (last < 0) return keep
|
|
161
|
-
keep.add(0)
|
|
162
|
-
if (last === 0) return keep
|
|
163
|
-
if (bandPx <= 0 || labelPx <= 0) {
|
|
164
|
-
keep.add(last)
|
|
165
|
-
return keep
|
|
166
|
-
}
|
|
167
|
-
const step = Math.max(1, Math.ceil(labelPx / bandPx))
|
|
168
|
-
for (let i = 0; i <= last; i += step) keep.add(i)
|
|
169
|
-
const lastOnGrid = Math.floor(last / step) * step
|
|
170
|
-
if (lastOnGrid !== last && lastOnGrid > 0 && (last - lastOnGrid) * bandPx < labelPx) {
|
|
171
|
-
keep.delete(lastOnGrid)
|
|
172
|
-
}
|
|
173
|
-
keep.add(last)
|
|
174
|
-
return keep
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** Variant of smartTicks that targets an exact tick count rather than deriving from width. */
|
|
178
|
-
export function smartTicksEvery(dates: string[], count: number): string[] {
|
|
179
|
-
if (dates.length === 0) return []
|
|
180
|
-
if (dates.length <= count) return dates
|
|
181
|
-
const step = Math.ceil(dates.length / count)
|
|
182
|
-
return dates.filter((_, i) => i % step === 0 || i === dates.length - 1)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* The fewest x ticks an axis may thin down to before rotating is the cheaper trade. Two ticks
|
|
187
|
-
* (`smartTicks`' own floor) is a labelled left edge and a labelled right edge and nothing to read
|
|
188
|
-
* between them — at that point the axis has stopped being an axis.
|
|
189
|
-
*/
|
|
190
|
-
const MIN_HORIZONTAL_TICKS = 3
|
|
191
|
-
|
|
192
|
-
/** Horizontal projection of a 45°-rotated label — `cos 45°`. A tilted label still competes for
|
|
193
|
-
* horizontal room, just for `0.71×` of it. */
|
|
194
|
-
const COS_45 = Math.SQRT1_2
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* The phone tier's default x-label rotation: 45° when the labels are so wide that fewer than
|
|
198
|
-
* {@link MIN_HORIZONTAL_TICKS} of them fit side by side, else none.
|
|
199
|
-
*
|
|
200
|
-
* `xLabelRotate` already existed as the answer to a `formatX` too wide to repeat horizontally
|
|
201
|
-
* (`docs/CHARTS-SPEC.md` §1) — it just had to be reached for by hand, per chart, by someone who
|
|
202
|
-
* had already seen it collide on a phone. This makes it the DEFAULT at phone width and only there:
|
|
203
|
-
* rotating trades horizontal crowding for bottom-gutter depth, which is the cheap axis on a narrow
|
|
204
|
-
* viewport and the expensive one on a wide screen that had room all along. Opt out with an
|
|
205
|
-
* explicit `xLabelRotate: 0`.
|
|
206
|
-
*
|
|
207
|
-
* Deliberately measured against the same `labelPx` `smartTicks` thins by, so the decision and the
|
|
208
|
-
* thinning cannot disagree about how wide a label is.
|
|
209
|
-
*
|
|
210
|
-
* **Wanting to rotate is not the same as rotating fitting.** A rotated label reaches into the LEFT
|
|
211
|
-
* gutter (`rotatedLabelExtents`), so rotating BUYS bottom-gutter depth and SPENDS plot width — and
|
|
212
|
-
* at a narrow enough box it spends more than it buys. `/charts-stress` block (f1) is the case:
|
|
213
|
-
* three clean horizontal labels at 390, and at 320 an auto-rotation that reached off the left edge
|
|
214
|
-
* and bought not one extra label for it. So the trade is CHECKED, not assumed. Pass `rotatedXMax`
|
|
215
|
-
* (the width left once `autoMargin({ rotate: 45 })` has taken its deeper left gutter) and the
|
|
216
|
-
* rotation is taken only when the rotated axis paints MORE labels than the flat one at its
|
|
217
|
-
* projected pitch (`labelPx · cos 45°`), and at least two of them. Otherwise the axis stays flat
|
|
218
|
-
* and `smartTicks` thins further — two readable horizontal labels beat two tilted ones in a
|
|
219
|
-
* narrower plot. Omit `rotatedXMax` and the check is skipped.
|
|
220
|
-
*/
|
|
221
|
-
export function autoXLabelRotate(input: {
|
|
222
|
-
tier: ChartTier
|
|
223
|
-
/** Plot width available to the x axis, from the UNROTATED margin. */
|
|
224
|
-
xMax: number
|
|
225
|
-
/** What one x label needs horizontally ({@link xLabelPxFor}). */
|
|
226
|
-
labelPx: number
|
|
227
|
-
/** Plot width that would REMAIN once the rotated margin takes its deeper left gutter
|
|
228
|
-
* (`autoMargin({ rotate: 45 })`). Omit to skip the fit check. */
|
|
229
|
-
rotatedXMax?: number
|
|
230
|
-
}): 0 | 45 {
|
|
231
|
-
const { tier, xMax, labelPx, rotatedXMax } = input
|
|
232
|
-
if (tier !== 'phone') return 0
|
|
233
|
-
if (labelPx <= 0 || xMax <= 0) return 0
|
|
234
|
-
const flatLabels = Math.floor(xMax / labelPx)
|
|
235
|
-
if (flatLabels >= MIN_HORIZONTAL_TICKS) return 0
|
|
236
|
-
if (rotatedXMax === undefined) return 45
|
|
237
|
-
const rotatedLabels = Math.floor(rotatedXMax / (labelPx * COS_45))
|
|
238
|
-
return rotatedLabels >= 2 && rotatedLabels > flatLabels ? 45 : 0
|
|
239
|
-
}
|
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* overlays-mount — composable overlay mount for basalt-ui apps.
|
|
3
|
-
*
|
|
4
|
-
* `BasaltOverlays` bundles ModalsProvider, Spotlight, and Notifications into a single mount point.
|
|
5
|
-
* Put it inside BasaltProvider, before the router. It is the ONLY notifications mount — the
|
|
6
|
-
* standalone `basalt-ui/notifications` overlay it superseded is gone (C1 consolidation); mounting
|
|
7
|
-
* a second, hand-rolled `<Notifications />` alongside `<BasaltOverlays notifications />` still
|
|
8
|
-
* double-mounts the overlay and is still wrong for the same reason.
|
|
9
|
-
*
|
|
10
|
-
* Every layer — ModalsProvider included — mounts as a SIBLING of `children`, never as a wrapper:
|
|
11
|
-
* see the comment in the component body (R1). `@mantine/modals`' imperative API (`modals.open*`,
|
|
12
|
-
* and so basalt's own `overlays.open`) is a window CustomEvent bus that ModalsProvider subscribes
|
|
13
|
-
* to, so nothing needs to be inside it; the one thing a sibling cannot serve is Mantine's
|
|
14
|
-
* `useModals()` context hook.
|
|
15
|
-
*
|
|
16
|
-
* Each overlay system is opt-in via props (all default to true). Use flags to disable layers the
|
|
17
|
-
* app does not need — e.g. a charts-only app that has no commands can set `spotlight={false}`.
|
|
18
|
-
* A disabled layer's optional peer is NEVER imported — each layer is lazy-loaded (React.lazy +
|
|
19
|
-
* dynamic import()) only when its flag is true, and degrades to a no-op fallback instead of
|
|
20
|
-
* crashing when the peer is absent.
|
|
21
|
-
*
|
|
22
|
-
* Optional peers required (only when the corresponding layer is enabled):
|
|
23
|
-
* @mantine/modals ^9.3.0 (for modals)
|
|
24
|
-
* @mantine/spotlight ^9.3.0 (for spotlight)
|
|
25
|
-
* @mantine/notifications ^9.3.0 (for notifications)
|
|
26
|
-
* @tanstack/react-hotkeys ^0.10.0 (optional — keybindings degrade to no-op when absent)
|
|
27
|
-
*
|
|
28
|
-
* Spotlight live store: BasaltOverlays uses a basalt-owned createSpotlight() store so the
|
|
29
|
-
* spotlight instance is separate from Mantine's default global. The store is created lazily (on
|
|
30
|
-
* first use, whether from mounting the spotlight layer or from calling openSpotlight()/
|
|
31
|
-
* closeSpotlight()) so @mantine/spotlight is never imported until actually needed. Import
|
|
32
|
-
* `basaltSpotlight` and call `basaltSpotlight.open()` / `basaltSpotlight.close()` from consumer
|
|
33
|
-
* code. The re-exported `openSpotlight` / `closeSpotlight` helpers delegate to this store.
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* // main.tsx — mount <BasaltOverlays>. Use the layered bundle — the unlayered one outranks
|
|
37
|
-
* // basalt's `@layer basalt` styles regardless of specificity:
|
|
38
|
-
* import { BasaltOverlays } from 'basalt-ui/commands'
|
|
39
|
-
* import '@mantine/spotlight/styles.layer.css'
|
|
40
|
-
*
|
|
41
|
-
* createRoot(root).render(
|
|
42
|
-
* <BasaltProvider>
|
|
43
|
-
* <BasaltOverlays>
|
|
44
|
-
* <App />
|
|
45
|
-
* </BasaltOverlays>
|
|
46
|
-
* </BasaltProvider>
|
|
47
|
-
* )
|
|
48
|
-
*
|
|
49
|
-
* // Disable spotlight for apps without commands — @mantine/spotlight is then never imported:
|
|
50
|
-
* <BasaltOverlays spotlight={false}>
|
|
51
|
-
* <App />
|
|
52
|
-
* </BasaltOverlays>
|
|
53
|
-
*
|
|
54
|
-
* // Open/close programmatically:
|
|
55
|
-
* import { openSpotlight, closeSpotlight } from 'basalt-ui/commands'
|
|
56
|
-
* openSpotlight()
|
|
57
|
-
*/
|
|
58
|
-
import type { ComponentType, ReactNode } from 'react'
|
|
59
|
-
import { lazy, Suspense } from 'react'
|
|
60
|
-
import type { ModalsProviderProps } from '@mantine/modals'
|
|
61
|
-
import type { NotificationsProps } from '@mantine/notifications'
|
|
62
|
-
import type { SpotlightActionData } from '@mantine/spotlight'
|
|
63
|
-
import { runCommand } from './define-commands'
|
|
64
|
-
import type { CommandId } from './define-commands'
|
|
65
|
-
import { useModalsLayer } from './define-overlays'
|
|
66
|
-
import { toSpotlightActions } from './projectors'
|
|
67
|
-
import { useCommandHotkeys } from './useCommandHotkeys'
|
|
68
|
-
import { useNotificationsMountGuard } from '../notifications/mount-guard'
|
|
69
|
-
|
|
70
|
-
// ── Lazy @mantine/spotlight resolution (module-wide singleton) ────────────────
|
|
71
|
-
|
|
72
|
-
type SpotlightModule = typeof import('@mantine/spotlight')
|
|
73
|
-
type SpotlightStore = ReturnType<SpotlightModule['createSpotlight']>[0]
|
|
74
|
-
type SpotlightActions = ReturnType<SpotlightModule['createSpotlight']>[1]
|
|
75
|
-
type SpotlightHandle = { store: SpotlightStore; actions: SpotlightActions }
|
|
76
|
-
|
|
77
|
-
let spotlightHandlePromise: Promise<SpotlightHandle | undefined> | undefined
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Lazily resolves @mantine/spotlight and creates the basalt-owned createSpotlight() store.
|
|
81
|
-
* Memoized module-wide so the spotlight layer's SpotlightMount and the openSpotlight/
|
|
82
|
-
* closeSpotlight helpers share one store instance. Resolves to undefined when the peer is
|
|
83
|
-
* absent — callers degrade to a no-op instead of crashing.
|
|
84
|
-
*/
|
|
85
|
-
function loadSpotlightHandle(): Promise<SpotlightHandle | undefined> {
|
|
86
|
-
spotlightHandlePromise ??= import('@mantine/spotlight')
|
|
87
|
-
.then(({ createSpotlight }) => {
|
|
88
|
-
const [store, actions] = createSpotlight()
|
|
89
|
-
return { store, actions }
|
|
90
|
-
})
|
|
91
|
-
.catch(() => undefined)
|
|
92
|
-
return spotlightHandlePromise
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ── basaltSpotlight singleton ─────────────────────────────────────────────────
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Basalt-owned Spotlight actions (open/close/toggle), backed by a lazily-created
|
|
99
|
-
* createSpotlight() store so @mantine/spotlight is only imported on first use.
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* import { basaltSpotlight } from 'basalt-ui/commands'
|
|
103
|
-
* basaltSpotlight.open()
|
|
104
|
-
*/
|
|
105
|
-
export const basaltSpotlight = {
|
|
106
|
-
open: (): void => {
|
|
107
|
-
void loadSpotlightHandle().then((handle) => handle?.actions.open())
|
|
108
|
-
},
|
|
109
|
-
close: (): void => {
|
|
110
|
-
void loadSpotlightHandle().then((handle) => handle?.actions.close())
|
|
111
|
-
},
|
|
112
|
-
toggle: (): void => {
|
|
113
|
-
void loadSpotlightHandle().then((handle) => handle?.actions.toggle())
|
|
114
|
-
},
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ── openSpotlight / closeSpotlight ────────────────────────────────────────────
|
|
118
|
-
|
|
119
|
-
/** Open the basalt Spotlight palette programmatically. */
|
|
120
|
-
export function openSpotlight(): void {
|
|
121
|
-
basaltSpotlight.open()
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Close the basalt Spotlight palette programmatically. */
|
|
125
|
-
export function closeSpotlight(): void {
|
|
126
|
-
basaltSpotlight.close()
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// ── BasaltOverlaysProps ───────────────────────────────────────────────────────
|
|
130
|
-
|
|
131
|
-
export type BasaltOverlaysProps = {
|
|
132
|
-
/** Mount @mantine/modals ModalsProvider. Default: true. */
|
|
133
|
-
modals?: boolean
|
|
134
|
-
/** Mount @mantine/spotlight Spotlight with mod+K shortcut. Default: true. */
|
|
135
|
-
spotlight?: boolean
|
|
136
|
-
/** Mount @mantine/notifications Notifications overlay. Default: true. */
|
|
137
|
-
notifications?: boolean
|
|
138
|
-
/**
|
|
139
|
-
* Activate @tanstack/react-hotkeys keybindings for all registered commands. Default: true.
|
|
140
|
-
* Degrades to no-op when @tanstack/react-hotkeys peer is absent — safe to leave enabled.
|
|
141
|
-
*/
|
|
142
|
-
hotkeys?: boolean
|
|
143
|
-
/** Override or extend the Notifications props (position, autoClose, limit, etc.). Defaults: position="bottom-right", autoClose=4000, limit=5. */
|
|
144
|
-
notificationsProps?: Omit<NotificationsProps, 'children'>
|
|
145
|
-
/**
|
|
146
|
-
* Extra Spotlight actions merged with the command-projected actions — e.g.
|
|
147
|
-
* toRouteActions(nav, { onNavigate }) for page navigation. Rendered BEFORE the command actions
|
|
148
|
-
* and grouped by each action's `group`. A static snapshot, same as the command projection.
|
|
149
|
-
*/
|
|
150
|
-
spotlightActions?: SpotlightActionData[]
|
|
151
|
-
/**
|
|
152
|
-
* Auto-project the registered command bus into Spotlight actions. Default: true. Set false when
|
|
153
|
-
* the app supplies the FULL action list itself via `spotlightActions` (e.g. to decorate commands
|
|
154
|
-
* with kind badges built from `toSpotlightActions()`) — this avoids the commands appearing twice.
|
|
155
|
-
*/
|
|
156
|
-
projectCommands?: boolean
|
|
157
|
-
/** App content (required). */
|
|
158
|
-
children: ReactNode
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// ── Lazy ModalsProvider (falls back to rendering nothing) ─────────────────────
|
|
162
|
-
|
|
163
|
-
/** Missing-peer fallback. Mounted childless (see BasaltOverlays), so it renders nothing. */
|
|
164
|
-
function PassthroughFragment({ children }: ModalsProviderProps) {
|
|
165
|
-
return <>{children}</>
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const LazyModalsProvider = lazy(() =>
|
|
169
|
-
import('@mantine/modals')
|
|
170
|
-
.then((m) => ({ default: m.ModalsProvider }))
|
|
171
|
-
.catch(() => ({ default: PassthroughFragment })),
|
|
172
|
-
)
|
|
173
|
-
Object.assign(LazyModalsProvider, { displayName: 'LazyModalsProvider' })
|
|
174
|
-
|
|
175
|
-
// ── Lazy SpotlightMount (falls back to rendering nothing) ─────────────────────
|
|
176
|
-
|
|
177
|
-
function NullFallback(): ReactNode {
|
|
178
|
-
return null
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Lazily resolves @mantine/spotlight and mounts Spotlight with a live-updating actions list
|
|
183
|
-
* synced to the command registry, sharing the store created by loadSpotlightHandle().
|
|
184
|
-
*
|
|
185
|
-
* Actions are a snapshot at render time — sufficient because commands are registered at module
|
|
186
|
-
* load before BasaltOverlays mounts. A future reactive stash can add a version counter here.
|
|
187
|
-
*/
|
|
188
|
-
const LazySpotlightMount = lazy<
|
|
189
|
-
ComponentType<{ extraActions?: SpotlightActionData[]; projectCommands?: boolean }>
|
|
190
|
-
>(() =>
|
|
191
|
-
Promise.all([import('@mantine/spotlight'), loadSpotlightHandle()])
|
|
192
|
-
.then(([{ Spotlight }, handle]) => {
|
|
193
|
-
if (handle === undefined) return { default: NullFallback }
|
|
194
|
-
// Re-bind as a fresh const so the non-undefined narrowing above survives into the
|
|
195
|
-
// nested closure below (TS does not carry a parameter narrowing into nested functions).
|
|
196
|
-
const spotlightHandle: SpotlightHandle = handle
|
|
197
|
-
|
|
198
|
-
function SpotlightMountInner({
|
|
199
|
-
extraActions,
|
|
200
|
-
projectCommands = true,
|
|
201
|
-
}: {
|
|
202
|
-
extraActions?: SpotlightActionData[]
|
|
203
|
-
projectCommands?: boolean
|
|
204
|
-
}): ReactNode {
|
|
205
|
-
const commandActions = projectCommands
|
|
206
|
-
? toSpotlightActions((id) => {
|
|
207
|
-
spotlightHandle.actions.close()
|
|
208
|
-
void runCommand(id as CommandId)
|
|
209
|
-
})
|
|
210
|
-
: []
|
|
211
|
-
const actions = [...(extraActions ?? []), ...commandActions]
|
|
212
|
-
|
|
213
|
-
// maxHeight bounds the results ScrollArea so the palette has ONE inner scroller — without it
|
|
214
|
-
// a long action list overflows the modal content box too, producing a double scrollbar.
|
|
215
|
-
return (
|
|
216
|
-
<Spotlight
|
|
217
|
-
store={spotlightHandle.store}
|
|
218
|
-
actions={actions}
|
|
219
|
-
shortcut="mod + K"
|
|
220
|
-
maxHeight={420}
|
|
221
|
-
/>
|
|
222
|
-
)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return { default: SpotlightMountInner }
|
|
226
|
-
})
|
|
227
|
-
.catch(() => ({ default: NullFallback })),
|
|
228
|
-
)
|
|
229
|
-
Object.assign(LazySpotlightMount, { displayName: 'LazySpotlightMount' })
|
|
230
|
-
|
|
231
|
-
// ── Lazy Notifications (falls back to rendering nothing) ──────────────────────
|
|
232
|
-
|
|
233
|
-
function NotificationsFallback(_props: NotificationsProps): ReactNode {
|
|
234
|
-
return null
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const LazyNotifications = lazy<ComponentType<NotificationsProps>>(() =>
|
|
238
|
-
import('@mantine/notifications')
|
|
239
|
-
.then((m) => ({ default: m.Notifications as ComponentType<NotificationsProps> }))
|
|
240
|
-
.catch(() => ({ default: NotificationsFallback })),
|
|
241
|
-
)
|
|
242
|
-
Object.assign(LazyNotifications, { displayName: 'LazyNotifications' })
|
|
243
|
-
|
|
244
|
-
// ── NotificationsLayer (runs the shared duplicate-mount guard, F15) ───────────
|
|
245
|
-
|
|
246
|
-
/** Wraps `LazyNotifications` so `useNotificationsMountGuard` only fires while this layer is
|
|
247
|
-
* actually enabled — the shared counter guards against any second `<Notifications />` mount. */
|
|
248
|
-
function NotificationsLayer({
|
|
249
|
-
notificationsProps,
|
|
250
|
-
}: {
|
|
251
|
-
notificationsProps: Omit<NotificationsProps, 'children'> | undefined
|
|
252
|
-
}) {
|
|
253
|
-
useNotificationsMountGuard()
|
|
254
|
-
return (
|
|
255
|
-
<Suspense fallback={null}>
|
|
256
|
-
<LazyNotifications
|
|
257
|
-
position="bottom-right"
|
|
258
|
-
autoClose={4000}
|
|
259
|
-
limit={5}
|
|
260
|
-
{...notificationsProps}
|
|
261
|
-
/>
|
|
262
|
-
</Suspense>
|
|
263
|
-
)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// ── HotkeysMount (inner component — ensures hook is inside component tree) ────
|
|
267
|
-
|
|
268
|
-
/** Mounts useCommandHotkeys inside the overlay tree. Graceful no-op when peer is absent. */
|
|
269
|
-
function HotkeysMount() {
|
|
270
|
-
useCommandHotkeys()
|
|
271
|
-
return null
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// ── BasaltOverlays ────────────────────────────────────────────────────────────
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Composable overlay mount — renders ModalsProvider, Spotlight and Notifications as siblings of
|
|
278
|
-
* `children`. All three layers are enabled by default; pass `false` to disable. A disabled layer's
|
|
279
|
-
* optional peer is never imported.
|
|
280
|
-
*
|
|
281
|
-
* Mount exactly ONE BasaltOverlays per app — a second instance double-mounts `<Notifications />`.
|
|
282
|
-
*
|
|
283
|
-
* @example
|
|
284
|
-
* <BasaltProvider>
|
|
285
|
-
* <BasaltOverlays>
|
|
286
|
-
* <RouterProvider router={router} />
|
|
287
|
-
* </BasaltOverlays>
|
|
288
|
-
* </BasaltProvider>
|
|
289
|
-
*/
|
|
290
|
-
export function BasaltOverlays({
|
|
291
|
-
modals: enableModals = true,
|
|
292
|
-
spotlight: enableSpotlight = true,
|
|
293
|
-
notifications: enableNotifications = true,
|
|
294
|
-
hotkeys: enableHotkeys = true,
|
|
295
|
-
notificationsProps,
|
|
296
|
-
spotlightActions,
|
|
297
|
-
projectCommands = true,
|
|
298
|
-
children,
|
|
299
|
-
}: BasaltOverlaysProps) {
|
|
300
|
-
// Register the modals layer this mount serves, so `overlays.confirm` can reject with a named
|
|
301
|
-
// error instead of returning a promise nothing will ever settle (nothing subscribes to the modals
|
|
302
|
-
// event bus when no provider is up). With `modals={false}` nothing is registered here — a
|
|
303
|
-
// consumer mounting `<ModalsProvider>` themselves calls `registerModalsProvider()` instead.
|
|
304
|
-
useModalsLayer(enableModals)
|
|
305
|
-
|
|
306
|
-
// `children` sits OUTSIDE every Suspense boundary, and that is load-bearing (R1): React.lazy
|
|
307
|
-
// suspends on its first render even when the module is already warm, so a boundary wrapping the
|
|
308
|
-
// app defers the app's FIRST COMMIT past a microtask tick. TanStack Router's async loadMatches
|
|
309
|
-
// then resolves into that window and setStates onto the not-yet-mounted Transitioner fiber —
|
|
310
|
-
// "Can't perform a React state update on a component that hasn't mounted yet". The old shape
|
|
311
|
-
// also rendered `children` twice (once as the fallback, once resolved), running every effect in
|
|
312
|
-
// the app in both trees. Never put `children` under a lazy boundary here.
|
|
313
|
-
return (
|
|
314
|
-
<>
|
|
315
|
-
{enableSpotlight && (
|
|
316
|
-
<Suspense fallback={null}>
|
|
317
|
-
<LazySpotlightMount
|
|
318
|
-
projectCommands={projectCommands}
|
|
319
|
-
{...(spotlightActions !== undefined && { extraActions: spotlightActions })}
|
|
320
|
-
/>
|
|
321
|
-
</Suspense>
|
|
322
|
-
)}
|
|
323
|
-
{enableNotifications && <NotificationsLayer notificationsProps={notificationsProps} />}
|
|
324
|
-
{enableHotkeys && <HotkeysMount />}
|
|
325
|
-
{enableModals && (
|
|
326
|
-
<Suspense fallback={null}>
|
|
327
|
-
<LazyModalsProvider />
|
|
328
|
-
</Suspense>
|
|
329
|
-
)}
|
|
330
|
-
{children}
|
|
331
|
-
</>
|
|
332
|
-
)
|
|
333
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useCommandHotkeys — binds the active command registry to keyboard shortcuts via
|
|
3
|
-
* @tanstack/react-hotkeys.
|
|
4
|
-
*
|
|
5
|
-
* OPTIONAL PEER: @tanstack/react-hotkeys is an optional peer dependency. This hook degrades
|
|
6
|
-
* gracefully to a no-op when the peer is absent — core imports cleanly with the peer missing.
|
|
7
|
-
*
|
|
8
|
-
* Implementation: uses dynamic import() inside useEffect to lazily resolve the optional peer.
|
|
9
|
-
* Registration is imperative via the `getHotkeyManager()` singleton (re-exported from
|
|
10
|
-
* @tanstack/react-hotkeys → @tanstack/hotkeys). Each effect run registers all shortcut commands
|
|
11
|
-
* and returns a cleanup that unregisters them. This is fully rules-of-hooks compliant and works
|
|
12
|
-
* in strict ESM environments (no require()).
|
|
13
|
-
*
|
|
14
|
-
* No HotkeysProvider is required — @tanstack/react-hotkeys uses a singleton HotkeyManager.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* // Typical placement — inside BasaltOverlays so keybindings are active whenever overlays mount:
|
|
18
|
-
* useCommandHotkeys()
|
|
19
|
-
*
|
|
20
|
-
* // Standalone consumer:
|
|
21
|
-
* import { useCommandHotkeys } from 'basalt-ui/commands'
|
|
22
|
-
* function App() {
|
|
23
|
-
* useCommandHotkeys()
|
|
24
|
-
* return <RouterProvider router={router} />
|
|
25
|
-
* }
|
|
26
|
-
*/
|
|
27
|
-
import { useEffect } from 'react'
|
|
28
|
-
import { getActiveCommands } from './define-commands'
|
|
29
|
-
|
|
30
|
-
// ── HotkeyManager peer types (erased at runtime) ──────────────────────────────
|
|
31
|
-
|
|
32
|
-
// We only import types here — the actual module is loaded dynamically inside useEffect.
|
|
33
|
-
// This keeps the module resolvable even when the peer is absent (no static import).
|
|
34
|
-
|
|
35
|
-
type HotkeyHandle = {
|
|
36
|
-
unregister: () => void
|
|
37
|
-
callback: (event: KeyboardEvent) => void
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
type HotkeyManagerType = {
|
|
41
|
-
register: (
|
|
42
|
-
hotkey: string,
|
|
43
|
-
callback: (event: KeyboardEvent) => void,
|
|
44
|
-
options?: { preventDefault?: boolean },
|
|
45
|
-
) => HotkeyHandle
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
type PeerModule = {
|
|
49
|
-
getHotkeyManager: () => HotkeyManagerType
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ── useCommandHotkeys ─────────────────────────────────────────────────────────
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Reads the active command registry and binds each command's `shortcut` to its `run()` via
|
|
56
|
-
* the @tanstack/react-hotkeys HotkeyManager singleton. Degrades to a no-op when the optional
|
|
57
|
-
* peer is absent.
|
|
58
|
-
*
|
|
59
|
-
* Registers on mount, unregisters on unmount. Re-runs whenever the effect deps change.
|
|
60
|
-
* Commands without a shortcut are skipped. Commands where `when()` returns false at press time
|
|
61
|
-
* are silently skipped (the binding stays registered; the when-gate fires in the callback).
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* useCommandHotkeys()
|
|
65
|
-
*/
|
|
66
|
-
export function useCommandHotkeys(): void {
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
let handles: HotkeyHandle[] = []
|
|
69
|
-
let cancelled = false
|
|
70
|
-
|
|
71
|
-
const bind = async (): Promise<void> => {
|
|
72
|
-
let peer: PeerModule
|
|
73
|
-
try {
|
|
74
|
-
peer = (await import('@tanstack/react-hotkeys')) as unknown as PeerModule
|
|
75
|
-
} catch {
|
|
76
|
-
// Peer absent — stay no-op.
|
|
77
|
-
return
|
|
78
|
-
}
|
|
79
|
-
if (cancelled) return
|
|
80
|
-
if (typeof peer.getHotkeyManager !== 'function') return
|
|
81
|
-
|
|
82
|
-
const manager = peer.getHotkeyManager()
|
|
83
|
-
const cmds = getActiveCommands()
|
|
84
|
-
|
|
85
|
-
for (const [, cmd] of Object.entries(cmds)) {
|
|
86
|
-
if (cmd.shortcut === undefined) continue
|
|
87
|
-
|
|
88
|
-
const handle = manager.register(
|
|
89
|
-
cmd.shortcut,
|
|
90
|
-
(event: KeyboardEvent) => {
|
|
91
|
-
// Respect the when() gate at execution time (not registration time)
|
|
92
|
-
if (cmd.when !== undefined && !cmd.when()) return
|
|
93
|
-
// Only prevent default when the command will actually run
|
|
94
|
-
event.preventDefault()
|
|
95
|
-
void cmd.run()
|
|
96
|
-
},
|
|
97
|
-
// preventDefault: false — we handle it manually above, gated on when()
|
|
98
|
-
{ preventDefault: false },
|
|
99
|
-
)
|
|
100
|
-
handles.push(handle)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
void bind()
|
|
105
|
-
|
|
106
|
-
return () => {
|
|
107
|
-
cancelled = true
|
|
108
|
-
for (const handle of handles) {
|
|
109
|
-
handle.unregister()
|
|
110
|
-
}
|
|
111
|
-
handles = []
|
|
112
|
-
}
|
|
113
|
-
}, [])
|
|
114
|
-
}
|