basalt-ui 1.24.0 → 1.26.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 +8 -6
- package/CHANGELOG.md +25 -0
- package/MIGRATING.md +547 -21
- package/README.md +46 -33
- package/agent/rules/basalt-batteries.md +205 -0
- package/agent/rules/basalt-charts.md +125 -555
- package/agent/rules/basalt-controls.md +155 -0
- package/agent/rules/basalt-mantine.md +146 -439
- package/agent/rules/basalt-state.md +113 -96
- package/agent/rules/basalt-tokens.md +126 -288
- package/agent/skills/basalt-app/SKILL.md +70 -195
- package/agent/skills/basalt-charts/SKILL.md +54 -234
- package/agent/skills/basalt-design/SKILL.md +56 -248
- package/agent/templates/CLAUDE-block.md.tpl +31 -40
- package/agent/templates/DESIGN.md.tpl +22 -51
- package/configs/oxlint-plugin.js +1275 -31
- package/configs/oxlint-plugin.test.ts +947 -11
- package/configs/oxlint.json +11 -3
- package/dist/charts/cursor/resolve.d.ts +18 -0
- package/dist/charts/cursor/resolve.d.ts.map +1 -1
- package/dist/charts/cursor/resolve.js +15 -6
- package/dist/charts/cursor/scope.d.ts +6 -3
- package/dist/charts/cursor/scope.d.ts.map +1 -1
- package/dist/charts/cursor/store.d.ts +5 -1
- package/dist/charts/cursor/store.d.ts.map +1 -1
- package/dist/charts/cursor/store.js +4 -4
- package/dist/charts/hooks/useChartCursor.d.ts.map +1 -1
- package/dist/charts/hooks/useChartCursor.js +9 -8
- package/dist/charts/index.d.ts +2 -2
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.d.ts +34 -9
- package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.js +29 -114
- package/dist/charts/primitives/ChartCard.test.d.ts +2 -0
- package/dist/charts/primitives/ChartCard.test.d.ts.map +1 -0
- package/dist/charts/sparklines/BarSparkline.d.ts +26 -2
- package/dist/charts/sparklines/BarSparkline.d.ts.map +1 -1
- package/dist/charts/sparklines/BarSparkline.js +18 -4
- package/dist/cli/check-coverage.test.d.ts +2 -0
- package/dist/cli/check-coverage.test.d.ts.map +1 -0
- package/dist/cli/index.d.ts +67 -4
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +225 -7
- package/dist/connectivity/connectivity-indicator.d.ts +4 -1
- package/dist/connectivity/connectivity-indicator.d.ts.map +1 -1
- package/dist/connectivity/connectivity-indicator.js +1 -1
- package/dist/content/index.d.ts +5 -3
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +4 -2
- package/dist/content/prose.module.css +7 -28
- package/dist/controls/actions.d.ts +169 -0
- package/dist/controls/actions.d.ts.map +1 -0
- package/dist/controls/actions.js +287 -0
- package/dist/controls/actions.module.css +62 -0
- package/dist/controls/actions.module.css.d.ts +13 -0
- package/dist/controls/actions.test.d.ts +2 -0
- package/dist/controls/actions.test.d.ts.map +1 -0
- package/dist/controls/actions.type-guard.test.d.ts +2 -0
- package/dist/controls/actions.type-guard.test.d.ts.map +1 -0
- package/dist/controls/compare-filter.d.ts +41 -0
- package/dist/controls/compare-filter.d.ts.map +1 -0
- package/dist/controls/compare-filter.js +23 -0
- package/dist/controls/control-group.d.ts +19 -0
- package/dist/controls/control-group.d.ts.map +1 -0
- package/dist/controls/control-group.js +20 -0
- package/dist/controls/control-group.test.d.ts +2 -0
- package/dist/controls/control-group.test.d.ts.map +1 -0
- package/dist/controls/controls.module.css +542 -0
- package/dist/controls/controls.module.css.d.ts +35 -0
- package/dist/controls/controls.router.test.d.ts +2 -0
- package/dist/controls/controls.router.test.d.ts.map +1 -0
- package/dist/controls/enum-filter.d.ts +30 -0
- package/dist/controls/enum-filter.d.ts.map +1 -0
- package/dist/controls/enum-filter.js +91 -0
- package/dist/controls/filter-context.d.ts +55 -0
- package/dist/controls/filter-context.d.ts.map +1 -0
- package/dist/controls/filter-context.js +69 -0
- package/dist/controls/filter-pill.d.ts +28 -0
- package/dist/controls/filter-pill.d.ts.map +1 -0
- package/dist/controls/filter-pill.js +70 -0
- package/dist/controls/filter-set.d.ts +13 -0
- package/dist/controls/filter-set.d.ts.map +1 -0
- package/dist/controls/filter-set.js +125 -0
- package/dist/controls/filter-set.test.d.ts +2 -0
- package/dist/controls/filter-set.test.d.ts.map +1 -0
- package/dist/controls/filter-sheet.d.ts +117 -0
- package/dist/controls/filter-sheet.d.ts.map +1 -0
- package/dist/controls/filter-sheet.js +146 -0
- package/dist/controls/glyphs.d.ts +27 -0
- package/dist/controls/glyphs.d.ts.map +1 -0
- package/dist/controls/glyphs.js +49 -0
- package/dist/controls/index.d.ts +19 -0
- package/dist/controls/index.d.ts.map +1 -0
- package/dist/controls/index.js +44 -0
- package/dist/controls/multi-select-filter.d.ts +23 -0
- package/dist/controls/multi-select-filter.d.ts.map +1 -0
- package/dist/controls/multi-select-filter.js +89 -0
- package/dist/controls/peer-boundary.test.d.ts +2 -0
- package/dist/controls/peer-boundary.test.d.ts.map +1 -0
- package/dist/controls/props-contract.test.d.ts +2 -0
- package/dist/controls/props-contract.test.d.ts.map +1 -0
- package/dist/controls/range-filter.d.ts +29 -0
- package/dist/controls/range-filter.d.ts.map +1 -0
- package/dist/controls/range-filter.js +120 -0
- package/dist/controls/search-filter.d.ts +10 -0
- package/dist/controls/search-filter.d.ts.map +1 -0
- package/dist/controls/search-filter.js +81 -0
- package/dist/controls/select-filter.d.ts +74 -0
- package/dist/controls/select-filter.d.ts.map +1 -0
- package/dist/controls/select-filter.js +10 -0
- package/dist/controls/sync-button.d.ts +38 -0
- package/dist/controls/sync-button.d.ts.map +1 -0
- package/dist/controls/sync-button.js +119 -0
- package/dist/controls/sync-button.module.css +63 -0
- package/dist/controls/sync-button.module.css.d.ts +11 -0
- package/dist/controls/sync-button.test.d.ts +2 -0
- package/dist/controls/sync-button.test.d.ts.map +1 -0
- package/dist/controls/toggle-filter.d.ts +9 -0
- package/dist/controls/toggle-filter.d.ts.map +1 -0
- package/dist/controls/toggle-filter.js +42 -0
- package/dist/controls/view-tabs.d.ts +23 -0
- package/dist/controls/view-tabs.d.ts.map +1 -0
- package/dist/controls/view-tabs.js +59 -0
- package/dist/controls-dates/date-range-picker.d.ts +4 -0
- package/dist/controls-dates/date-range-picker.d.ts.map +1 -0
- package/dist/controls-dates/date-range-picker.js +18 -0
- package/dist/controls-dates/index.d.ts +9 -0
- package/dist/controls-dates/index.d.ts.map +1 -0
- package/dist/controls-dates/index.js +4 -0
- package/dist/dashboard/delta-badge.d.ts +6 -12
- package/dist/dashboard/delta-badge.d.ts.map +1 -1
- package/dist/dashboard/delta-badge.js +1 -50
- package/dist/dashboard/query-state.d.ts +1 -1
- package/dist/dashboard/settings-section.d.ts +6 -4
- package/dist/dashboard/settings-section.d.ts.map +1 -1
- package/dist/dashboard/settings-section.js +23 -16
- package/dist/dashboard/settings-section.module.css +10 -0
- package/dist/dashboard/settings-section.module.css.d.ts +1 -0
- package/dist/dashboard/settings-section.test.d.ts +2 -0
- package/dist/dashboard/settings-section.test.d.ts.map +1 -0
- package/dist/dashboard/stat-card.d.ts +44 -9
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +80 -48
- package/dist/dashboard/stat-card.module.css +82 -0
- package/dist/dashboard/stat-card.module.css.d.ts +11 -0
- package/dist/data/data-table.d.ts +102 -20
- package/dist/data/data-table.d.ts.map +1 -1
- package/dist/data/data-table.js +166 -65
- package/dist/data/table.d.ts +1 -1
- package/dist/data/table.d.ts.map +1 -1
- package/dist/guard/grace.test.d.ts +20 -0
- package/dist/guard/grace.test.d.ts.map +1 -0
- package/dist/guard/index.d.ts +66 -3
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +82 -7
- package/dist/guard/types.d.ts +3 -3
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -10
- package/dist/nav/types.d.ts +78 -2
- package/dist/nav/types.d.ts.map +1 -1
- package/dist/notifications/bell.d.ts +4 -1
- package/dist/notifications/bell.d.ts.map +1 -1
- package/dist/notifications/index.d.ts +1 -1
- package/dist/router-tanstack/field.d.ts +14 -0
- package/dist/router-tanstack/field.d.ts.map +1 -0
- package/dist/router-tanstack/field.js +4 -0
- package/dist/router-tanstack/index.d.ts +6 -2
- package/dist/router-tanstack/index.d.ts.map +1 -1
- package/dist/router-tanstack/index.js +4 -0
- package/dist/router-tanstack/multi-search-param-store.d.ts +4 -52
- package/dist/router-tanstack/multi-search-param-store.d.ts.map +1 -1
- package/dist/router-tanstack/multi-search-param-store.js +19 -27
- package/dist/router-tanstack/search-param-store.d.ts +3 -87
- package/dist/router-tanstack/search-param-store.d.ts.map +1 -1
- package/dist/router-tanstack/search-param-store.js +16 -45
- package/dist/router-tanstack/search-store.d.ts +81 -0
- package/dist/router-tanstack/search-store.d.ts.map +1 -0
- package/dist/router-tanstack/search-store.js +187 -0
- package/dist/router-tanstack/search-store.router.test.d.ts +2 -0
- package/dist/router-tanstack/search-store.router.test.d.ts.map +1 -0
- package/dist/router-tanstack/search-store.test.d.ts +2 -0
- package/dist/router-tanstack/search-store.test.d.ts.map +1 -0
- package/dist/router-tanstack/use-nav.d.ts +0 -2
- package/dist/router-tanstack/use-nav.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.js +34 -12
- package/dist/router-tanstack/use-nav.test.d.ts +2 -0
- package/dist/router-tanstack/use-nav.test.d.ts.map +1 -0
- package/dist/section/index.d.ts +2 -0
- package/dist/section/index.d.ts.map +1 -0
- package/dist/section/index.js +4 -0
- package/dist/section/section.d.ts +24 -0
- package/dist/section/section.d.ts.map +1 -0
- package/dist/section/section.js +126 -0
- package/dist/section/section.module.css +104 -0
- package/dist/section/section.module.css.d.ts +11 -0
- package/dist/section/section.test.d.ts +2 -0
- package/dist/section/section.test.d.ts.map +1 -0
- package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
- package/dist/shell/app-breadcrumbs.js +18 -15
- package/dist/shell/app-header.module.css +77 -37
- package/dist/shell/app-header.module.css.d.ts +2 -1
- package/dist/shell/app-mobile-nav.d.ts +9 -2
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +98 -11
- package/dist/shell/app-mobile-nav.module.css +8 -0
- package/dist/shell/app-mobile-nav.module.css.d.ts +1 -0
- package/dist/shell/app-sidebar.d.ts +55 -28
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +116 -67
- package/dist/shell/app-sidebar.module.css +303 -20
- package/dist/shell/app-sidebar.module.css.d.ts +19 -1
- package/dist/shell/index.d.ts +55 -21
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +40 -18
- package/dist/shell/mobile-nav-model.d.ts +13 -2
- package/dist/shell/mobile-nav-model.d.ts.map +1 -1
- package/dist/shell/mobile-nav-model.js +15 -1
- package/dist/shell/nav-count-badge.d.ts +1 -1
- package/dist/shell/page-bar.d.ts +51 -0
- package/dist/shell/page-bar.d.ts.map +1 -0
- package/dist/shell/page-bar.js +154 -0
- package/dist/shell/page-bar.module.css +178 -0
- package/dist/shell/page-bar.module.css.d.ts +17 -0
- package/dist/shell/page-bar.test.d.ts +2 -0
- package/dist/shell/page-bar.test.d.ts.map +1 -0
- package/dist/shell/sidebar-block-model.d.ts +48 -0
- package/dist/shell/sidebar-block-model.d.ts.map +1 -0
- package/dist/shell/sidebar-block-model.js +39 -0
- package/dist/shell/sidebar-blocks.d.ts +32 -0
- package/dist/shell/sidebar-blocks.d.ts.map +1 -0
- package/dist/shell/sidebar-blocks.js +169 -0
- package/dist/shell/sidebar-search.d.ts +13 -1
- package/dist/shell/sidebar-search.d.ts.map +1 -1
- package/dist/shell/sidebar-search.js +34 -1
- package/dist/shell/sidebar-search.module.css +26 -0
- package/dist/shell/sidebar-search.module.css.d.ts +2 -0
- package/dist/state/fields.d.ts +392 -0
- package/dist/state/fields.d.ts.map +1 -0
- package/dist/state/fields.js +369 -0
- package/dist/state/fields.test.d.ts +2 -0
- package/dist/state/fields.test.d.ts.map +1 -0
- package/dist/state/persisted.d.ts +48 -0
- package/dist/state/persisted.d.ts.map +1 -0
- package/dist/state/persisted.js +105 -0
- package/dist/state.d.ts +11 -56
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +14 -120
- package/dist/styles.css +13 -0
- package/dist/surfaces.d.ts +106 -24
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +155 -19
- package/dist/theme/controls.module.css +16 -1
- package/dist/theme/ctl-theme.d.ts +32 -0
- package/dist/theme/ctl-theme.d.ts.map +1 -0
- package/dist/theme/ctl-theme.js +54 -0
- package/dist/theme/ctl-theme.test.d.ts +2 -0
- package/dist/theme/ctl-theme.test.d.ts.map +1 -0
- package/dist/theme/ctl-tier-coverage.test.d.ts +2 -0
- package/dist/theme/ctl-tier-coverage.test.d.ts.map +1 -0
- package/dist/theme/divider-law.test.d.ts +2 -0
- package/dist/theme/divider-law.test.d.ts.map +1 -0
- package/dist/theme/icon-slot.d.ts +44 -0
- package/dist/theme/icon-slot.d.ts.map +1 -0
- package/dist/theme/icon-slot.js +21 -0
- package/dist/theme/icon-slot.module.css +47 -0
- package/dist/theme/icon-slot.module.css.d.ts +8 -0
- package/dist/theme/icon-slot.test.d.ts +2 -0
- package/dist/theme/icon-slot.test.d.ts.map +1 -0
- package/dist/theme/index.d.ts +1 -0
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +82 -5
- package/dist/theme/layout-rhythm-css.test.d.ts +2 -0
- package/dist/theme/layout-rhythm-css.test.d.ts.map +1 -0
- package/dist/theme/segmented-control.module.css +20 -0
- package/dist/theme/shadow-surfaces.test.d.ts.map +1 -1
- package/dist/tokens/index.d.ts +12 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +38 -8
- package/dist/tokens/palette.d.ts +97 -61
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +76 -38
- package/dist/tokens.css +10 -2
- package/dist/widget-header/delta-badge.d.ts +13 -0
- package/dist/widget-header/delta-badge.d.ts.map +1 -0
- package/dist/widget-header/delta-badge.js +29 -0
- package/dist/widget-header/delta-badge.test.d.ts +2 -0
- package/dist/widget-header/delta-badge.test.d.ts.map +1 -0
- package/dist/widget-header/index.d.ts +3 -0
- package/dist/widget-header/index.d.ts.map +1 -0
- package/dist/widget-header/index.js +6 -0
- package/dist/widget-header/no-mantine.test.d.ts +2 -0
- package/dist/widget-header/no-mantine.test.d.ts.map +1 -0
- package/dist/widget-header/widget-header.d.ts +37 -0
- package/dist/widget-header/widget-header.d.ts.map +1 -0
- package/dist/widget-header/widget-header.js +77 -0
- package/dist/widget-header/widget-header.module.css +335 -0
- package/dist/widget-header/widget-header.module.css.d.ts +24 -0
- package/dist/widget-header/widget-header.test.d.ts +2 -0
- package/dist/widget-header/widget-header.test.d.ts.map +1 -0
- package/llms.txt +30 -17
- package/package.json +14 -1
- package/src/charts/cursor/resolve.test.ts +29 -1
- package/src/charts/cursor/resolve.ts +38 -6
- package/src/charts/cursor/scope.tsx +6 -3
- package/src/charts/cursor/store.test.ts +19 -1
- package/src/charts/cursor/store.ts +10 -5
- package/src/charts/hooks/useChartCursor.ts +16 -8
- package/src/charts/index.ts +2 -2
- package/src/charts/primitives/CartesianChart.test.tsx +124 -0
- package/src/charts/primitives/ChartCard.test.tsx +66 -0
- package/src/charts/primitives/ChartCard.tsx +86 -146
- package/src/charts/sparklines/BarSparkline.tsx +43 -5
- package/src/cli/check-coverage.test.ts +297 -0
- package/src/cli/check-theme.test.ts +38 -14
- package/src/cli/index.ts +392 -16
- package/src/cli/init-sync.test.ts +97 -0
- package/src/connectivity/connectivity-indicator.tsx +16 -9
- package/src/content/index.ts +16 -3
- package/src/content/prose.module.css +7 -28
- package/src/content/prose.module.css.test.ts +8 -24
- package/src/controls/actions.module.css +62 -0
- package/src/controls/actions.module.css.d.ts +13 -0
- package/src/controls/actions.test.tsx +252 -0
- package/src/controls/actions.tsx +655 -0
- package/src/controls/actions.type-guard.test.ts +63 -0
- package/src/controls/compare-filter.tsx +64 -0
- package/src/controls/control-group.test.tsx +229 -0
- package/src/controls/control-group.tsx +63 -0
- package/src/controls/controls.module.css +542 -0
- package/src/controls/controls.module.css.d.ts +35 -0
- package/src/controls/controls.router.test.tsx +637 -0
- package/src/controls/enum-filter.tsx +159 -0
- package/src/controls/filter-context.tsx +153 -0
- package/src/controls/filter-pill.tsx +120 -0
- package/src/controls/filter-set.test.tsx +472 -0
- package/src/controls/filter-set.tsx +225 -0
- package/src/controls/filter-sheet.tsx +285 -0
- package/src/controls/glyphs.tsx +81 -0
- package/src/controls/index.ts +48 -0
- package/src/controls/multi-select-filter.tsx +140 -0
- package/src/controls/peer-boundary.test.ts +85 -0
- package/src/controls/props-contract.test.tsx +106 -0
- package/src/controls/range-filter.tsx +184 -0
- package/src/controls/search-filter.tsx +123 -0
- package/src/controls/select-filter.tsx +89 -0
- package/src/controls/sync-button.module.css +63 -0
- package/src/controls/sync-button.module.css.d.ts +11 -0
- package/src/controls/sync-button.test.tsx +183 -0
- package/src/controls/sync-button.tsx +197 -0
- package/src/controls/toggle-filter.tsx +60 -0
- package/src/controls/view-tabs.tsx +110 -0
- package/src/controls-dates/date-range-picker.tsx +42 -0
- package/src/controls-dates/index.ts +8 -0
- package/src/dashboard/delta-badge.tsx +4 -74
- package/src/dashboard/query-state.tsx +1 -1
- package/src/dashboard/settings-section.module.css +10 -0
- package/src/dashboard/settings-section.module.css.d.ts +1 -0
- package/src/dashboard/settings-section.test.tsx +56 -0
- package/src/dashboard/settings-section.tsx +33 -30
- package/src/dashboard/stat-card.module.css +82 -0
- package/src/dashboard/stat-card.module.css.d.ts +11 -0
- package/src/dashboard/stat-card.test.tsx +67 -1
- package/src/dashboard/stat-card.tsx +209 -68
- package/src/data/data-table.test.tsx +282 -6
- package/src/data/data-table.tsx +429 -94
- package/src/data/table.ts +2 -0
- package/src/guard/check-source.test.ts +126 -13
- package/src/guard/grace.test.ts +149 -0
- package/src/guard/index.ts +172 -29
- package/src/guard/types.ts +4 -2
- package/src/index.ts +46 -5
- package/src/nav/types.ts +84 -2
- package/src/notifications/bell.tsx +6 -3
- package/src/notifications/index.ts +1 -1
- package/src/router-tanstack/field.ts +31 -0
- package/src/router-tanstack/index.ts +24 -2
- package/src/router-tanstack/multi-search-param-store.test.ts +71 -3
- package/src/router-tanstack/multi-search-param-store.ts +46 -77
- package/src/router-tanstack/search-param-store.ts +42 -159
- package/src/router-tanstack/search-store.router.test.tsx +661 -0
- package/src/router-tanstack/search-store.test.ts +418 -0
- package/src/router-tanstack/search-store.ts +380 -0
- package/src/router-tanstack/use-nav.test.tsx +187 -0
- package/src/router-tanstack/use-nav.ts +72 -14
- package/src/section/index.ts +1 -0
- package/src/section/section.module.css +104 -0
- package/src/section/section.module.css.d.ts +11 -0
- package/src/section/section.test.tsx +204 -0
- package/src/section/section.tsx +220 -0
- package/src/shell/app-breadcrumbs.tsx +44 -31
- package/src/shell/app-header.module.css +77 -37
- package/src/shell/app-header.module.css.d.ts +2 -1
- package/src/shell/app-mobile-nav.module.css +8 -0
- package/src/shell/app-mobile-nav.module.css.d.ts +1 -0
- package/src/shell/app-mobile-nav.tsx +147 -8
- package/src/shell/app-sidebar-account.tsx +2 -2
- package/src/shell/app-sidebar.module.css +303 -20
- package/src/shell/app-sidebar.module.css.d.ts +19 -1
- package/src/shell/app-sidebar.test.tsx +456 -41
- package/src/shell/app-sidebar.tsx +276 -140
- package/src/shell/index.test.tsx +291 -5
- package/src/shell/index.tsx +137 -38
- package/src/shell/mobile-nav-model.test.ts +228 -7
- package/src/shell/mobile-nav-model.ts +53 -3
- package/src/shell/nav-count-badge.tsx +1 -1
- package/src/shell/page-bar.module.css +178 -0
- package/src/shell/page-bar.module.css.d.ts +17 -0
- package/src/shell/page-bar.test.tsx +316 -0
- package/src/shell/page-bar.tsx +315 -0
- package/src/shell/sidebar-block-model.ts +83 -0
- package/src/shell/sidebar-blocks.tsx +301 -0
- package/src/shell/sidebar-search.module.css +26 -0
- package/src/shell/sidebar-search.module.css.d.ts +2 -0
- package/src/shell/sidebar-search.tsx +71 -2
- package/src/state/fields.test.tsx +258 -0
- package/src/state/fields.ts +892 -0
- package/src/state/persisted.ts +211 -0
- package/src/state.ts +46 -240
- package/src/styles.css +13 -0
- package/src/surfaces.ts +203 -36
- package/src/theme/controls.module.css +16 -1
- package/src/theme/ctl-theme.test.tsx +275 -0
- package/src/theme/ctl-theme.tsx +138 -0
- package/src/theme/ctl-tier-coverage.test.ts +170 -0
- package/src/theme/density-relations.test.ts +106 -51
- package/src/theme/divider-law.test.ts +259 -0
- package/src/theme/icon-slot.module.css +47 -0
- package/src/theme/icon-slot.module.css.d.ts +8 -0
- package/src/theme/icon-slot.test.tsx +275 -0
- package/src/theme/icon-slot.tsx +59 -0
- package/src/theme/index.ts +165 -3
- package/src/theme/layout-rhythm-css.test.ts +72 -0
- package/src/theme/radius.test.ts +11 -1
- package/src/theme/segmented-control.module.css +20 -0
- package/src/theme/shadow-surfaces.test.ts +20 -7
- package/src/theme/spacing.test.ts +75 -27
- package/src/theme/use-basalt-spacing.ts +2 -2
- package/src/tokens/density.test.ts +7 -25
- package/src/tokens/index.ts +48 -8
- package/src/tokens/palette.ts +107 -73
- package/src/widget-header/delta-badge.test.tsx +60 -0
- package/src/widget-header/delta-badge.tsx +57 -0
- package/src/widget-header/index.ts +2 -0
- package/src/widget-header/no-mantine.test.ts +33 -0
- package/src/widget-header/widget-header.module.css +335 -0
- package/src/widget-header/widget-header.module.css.d.ts +24 -0
- package/src/widget-header/widget-header.test.tsx +187 -0
- package/src/widget-header/widget-header.tsx +168 -0
- package/agent/rules/basalt-agent.md +0 -452
- package/agent/rules/basalt-app.md +0 -246
- package/agent/rules/basalt-commands.md +0 -320
- package/agent/rules/basalt-content.md +0 -409
- package/agent/rules/basalt-data.md +0 -269
- package/agent/rules/basalt-forms.md +0 -186
- package/agent/rules/basalt-notifications.md +0 -264
- package/agent/rules/basalt-query.md +0 -187
- package/agent/rules/basalt-router.md +0 -336
- package/dist/content/article-filter-bar.d.ts +0 -40
- package/dist/content/article-filter-bar.d.ts.map +0 -1
- package/dist/content/article-filter-bar.js +0 -56
- package/dist/shell/page-header.d.ts +0 -13
- package/dist/shell/page-header.d.ts.map +0 -1
- package/dist/shell/page-header.js +0 -23
- package/src/content/article-filter-bar.tsx +0 -88
- package/src/shell/page-header.tsx +0 -35
package/configs/oxlint.json
CHANGED
|
@@ -27,11 +27,19 @@
|
|
|
27
27
|
"basalt/raw-size-literal": "error",
|
|
28
28
|
"basalt/card-inset": "error",
|
|
29
29
|
"basalt/chart-in-raw-surface": "error",
|
|
30
|
-
"basalt/hand-rolled-plot": "
|
|
31
|
-
"basalt/chart-legend-literal": "
|
|
30
|
+
"basalt/hand-rolled-plot": "error",
|
|
31
|
+
"basalt/chart-legend-literal": "error",
|
|
32
32
|
"basalt/shadow-basalt-export": "warn",
|
|
33
|
-
"basalt/hand-rolled-shell": "
|
|
33
|
+
"basalt/hand-rolled-shell": "error",
|
|
34
34
|
"basalt/raw-scroll-container": "error",
|
|
35
|
+
"basalt/hand-rolled-filter": "error",
|
|
36
|
+
"basalt/control-outside-home": "warn",
|
|
37
|
+
"basalt/control-size-literal": "warn",
|
|
38
|
+
"basalt/page-bar-budget": "error",
|
|
39
|
+
"basalt/in-body-page-title": "warn",
|
|
40
|
+
"basalt/responsive-twin": "warn",
|
|
41
|
+
"basalt/search-literal-link": "warn",
|
|
42
|
+
"basalt/use-search-from-literal": "warn",
|
|
35
43
|
"basalt/visx-boundary": "error",
|
|
36
44
|
"basalt/visx-tooltip": "error",
|
|
37
45
|
"basalt/agent-resume-guard": "error",
|
|
@@ -13,6 +13,24 @@
|
|
|
13
13
|
* since "nearest category" is meaningless.
|
|
14
14
|
*/
|
|
15
15
|
export declare function parseKey(key: string): number | null;
|
|
16
|
+
/** The x-domain families the shared cursor partitions on, derived from a chart's own keys — never
|
|
17
|
+
* a prop, never `ChartCursorScope`. A chart's kind is stamped on every broadcast it makes, and a
|
|
18
|
+
* receiving chart ignores any broadcast whose kind differs from its own — so a category chart can
|
|
19
|
+
* never be mistaken for a time chart just because both domains happen to parse. */
|
|
20
|
+
export type DomainKind = 'time' | 'linear' | 'band';
|
|
21
|
+
/**
|
|
22
|
+
* Classify a domain by the SAME parse precedence `parseKey` applies to each key, so a domain can
|
|
23
|
+
* never be classified one way and resolved another:
|
|
24
|
+
*
|
|
25
|
+
* - empty domain → `'band'` (nothing to share).
|
|
26
|
+
* - every key numeric (same test `parseKey` tries first) → `'linear'`.
|
|
27
|
+
* - otherwise every key `Date.parse`-able (same test `parseKey` falls back to) → `'time'`.
|
|
28
|
+
* - otherwise → `'band'` (categories, or a mixed domain).
|
|
29
|
+
*
|
|
30
|
+
* Ordering matters and mirrors `parseKey` exactly: a domain of bare years like `"2026"` is numeric
|
|
31
|
+
* FIRST, so it classifies `'linear'`, not `'time'`, even though every value is also a valid date.
|
|
32
|
+
*/
|
|
33
|
+
export declare function classifyDomain(keys: readonly string[]): DomainKind;
|
|
16
34
|
/**
|
|
17
35
|
* How a foreign key maps onto a chart's own points.
|
|
18
36
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/charts/cursor/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/charts/cursor/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGnD;AAED;;;mFAGmF;AACnF,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEnD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAKlE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAA;AAEpD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACrB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,mCAAmC;IACnC,MAAM,EAAE,CAAC,EAAE,CAAA;IACX,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,UAAU,EAAE,gBAAgB,CAAA;CAC7B,CAAA;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,EACxB,UAAU,GAAE,gBAA4B,GACvC,WAAW,CAAC,CAAC,CAAC,CA8BhB;AAoBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EACrB,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,gBAAmC,GAC9C,CAAC,GAAG,IAAI,CA0CV"}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
function isNumericString(key) {
|
|
2
|
+
return /^[-+]?\d*\.?\d+$/.test(key) && Number.isFinite(Number(key));
|
|
3
|
+
}
|
|
4
|
+
function isDateParseableString(key) {
|
|
5
|
+
return !Number.isNaN(Date.parse(key));
|
|
6
|
+
}
|
|
1
7
|
function parseKey(key) {
|
|
2
|
-
if (
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
if (isNumericString(key)) return Number(key);
|
|
9
|
+
return isDateParseableString(key) ? Date.parse(key) : null;
|
|
10
|
+
}
|
|
11
|
+
function classifyDomain(keys) {
|
|
12
|
+
if (keys.length === 0) return "band";
|
|
13
|
+
if (keys.every(isNumericString)) return "linear";
|
|
14
|
+
if (keys.every(isDateParseableString)) return "time";
|
|
15
|
+
return "band";
|
|
8
16
|
}
|
|
9
17
|
function buildDomainIndex(data, getKey, resolution = "nearest") {
|
|
10
18
|
const byKey = /* @__PURE__ */ new Map();
|
|
@@ -77,6 +85,7 @@ function resolveCursorPoint(index, key, resolution = index.resolution) {
|
|
|
77
85
|
}
|
|
78
86
|
export {
|
|
79
87
|
buildDomainIndex,
|
|
88
|
+
classifyDomain,
|
|
80
89
|
parseKey,
|
|
81
90
|
resolveCursorPoint
|
|
82
91
|
};
|
|
@@ -5,9 +5,12 @@ export type ChartCursorScopeProps = {
|
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
7
7
|
* ISOLATES its subtree onto a private cursor store — the inverse of the removed `ChartHoverSync`, which
|
|
8
|
-
* had to be mounted to enable sharing at all. Charts share a cursor by default now
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* had to be mounted to enable sharing at all. Charts share a cursor by default now, AND the shared
|
|
9
|
+
* cursor partitions automatically by x-domain kind (`DomainKind`, derived from each chart's own
|
|
10
|
+
* data in `useChartCursor`) — a categorical chart never follows a date chart just because both
|
|
11
|
+
* happen to be on the page, with nothing to configure. `ChartCursorScope` is no longer the tool for
|
|
12
|
+
* that case. What it is still for: isolating two charts that share the same domain KIND but are
|
|
13
|
+
* semantically unrelated — two different tenants' date ranges rendered side by side on one page.
|
|
11
14
|
*/
|
|
12
15
|
export declare function ChartCursorScope({ children }: ChartCursorScopeProps): import("react").JSX.Element;
|
|
13
16
|
/** The cursor store this chart belongs to — the nearest `ChartCursorScope`, else the global one. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../src/charts/cursor/scope.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAKvD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../src/charts/cursor/scope.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAKvD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,qBAAqB,+BAGnE;AAED,oGAAoG;AACpG,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED,mFAAmF;AACnF,wBAAgB,cAAc,IAAI,WAAW,CAG5C"}
|
|
@@ -11,16 +11,20 @@
|
|
|
11
11
|
* charts subscribed to it, instead of every descendant of a provider whose value object is new
|
|
12
12
|
* on each pointer frame.
|
|
13
13
|
*/
|
|
14
|
+
import type { DomainKind } from './resolve.js';
|
|
14
15
|
/** Broadcast cursor position: an opaque domain key plus the chart that owns it. */
|
|
15
16
|
export type CursorState = {
|
|
16
17
|
/** The hovered x-domain key (a date/category string), or null when nothing is hovered. */
|
|
17
18
|
key: string | null;
|
|
18
19
|
/** `chartId` of the chart the pointer is actually over — the one that owns the tooltip. */
|
|
19
20
|
source: string | null;
|
|
21
|
+
/** The broadcaster's own x-domain kind. `null` only in the empty state — the store itself does
|
|
22
|
+
* not police this, it just carries it; the partition is enforced by the reading hook. */
|
|
23
|
+
kind: DomainKind | null;
|
|
20
24
|
};
|
|
21
25
|
export type CursorStore = {
|
|
22
26
|
get: () => CursorState;
|
|
23
|
-
set: (key: string | null, source: string | null) => void;
|
|
27
|
+
set: (key: string | null, source: string | null, kind?: DomainKind | null) => void;
|
|
24
28
|
subscribe: (onChange: () => void) => () => void;
|
|
25
29
|
};
|
|
26
30
|
/** Stable identity for "nothing hovered" — also the SSR snapshot, so it must never be recreated. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/charts/cursor/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG;IACxB,0FAA0F;IAC1F,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,2FAA2F;IAC3F,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/charts/cursor/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG;IACxB,0FAA0F;IAC1F,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,2FAA2F;IAC3F,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;6FACyF;IACzF,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,WAAW,CAAA;IACtB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAClF,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;CAChD,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,YAAY,EAAE,WAAqD,CAAA;AAEhF,wBAAgB,iBAAiB,IAAI,WAAW,CAkB/C;AAED,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,EAAE,WAAiC,CAAA"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
const EMPTY_CURSOR = { key: null, source: null };
|
|
1
|
+
const EMPTY_CURSOR = { key: null, source: null, kind: null };
|
|
2
2
|
function createCursorStore() {
|
|
3
3
|
let state = EMPTY_CURSOR;
|
|
4
4
|
const listeners = /* @__PURE__ */ new Set();
|
|
5
5
|
return {
|
|
6
6
|
get: () => state,
|
|
7
|
-
set: (key, source) => {
|
|
8
|
-
if (state.key === key && state.source === source) return;
|
|
9
|
-
state = key === null && source === null ? EMPTY_CURSOR : { key, source };
|
|
7
|
+
set: (key, source, kind = null) => {
|
|
8
|
+
if (state.key === key && state.source === source && state.kind === kind) return;
|
|
9
|
+
state = key === null && source === null ? EMPTY_CURSOR : { key, source, kind };
|
|
10
10
|
for (const listener of listeners) listener();
|
|
11
11
|
},
|
|
12
12
|
subscribe: (onChange) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChartCursor.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useChartCursor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzD,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,kGAAkG;IAClG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;IACf,kGAAkG;IAClG,QAAQ,EAAE,OAAO,CAAA;IACjB,4EAA4E;IAC5E,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IAC5D,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IACzD,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAChC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,UAAU,EACV,UAAsB,GACvB,EAAE;IACD,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,gEAAgE;IAChE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAC9B,GAAG,WAAW,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"useChartCursor.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useChartCursor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzD,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,kGAAkG;IAClG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;IACf,kGAAkG;IAClG,QAAQ,EAAE,OAAO,CAAA;IACjB,4EAA4E;IAC5E,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IAC5D,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IACzD,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAChC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,UAAU,EACV,UAAsB,GACvB,EAAE;IACD,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,gEAAgE;IAChE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAC9B,GAAG,WAAW,CAAC,CAAC,CAAC,CA8HjB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { localPoint } from "@visx/event";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
-
import { buildDomainIndex, resolveCursorPoint } from "../cursor/resolve.js";
|
|
3
|
+
import { buildDomainIndex, classifyDomain, resolveCursorPoint } from "../cursor/resolve.js";
|
|
4
4
|
import { useCursorState, useCursorStore } from "../cursor/scope.js";
|
|
5
5
|
function useChartCursor({
|
|
6
6
|
data,
|
|
@@ -21,12 +21,13 @@ function useChartCursor({
|
|
|
21
21
|
() => buildDomainIndex(data, getKeyRef.current, resolution),
|
|
22
22
|
[data, resolution]
|
|
23
23
|
);
|
|
24
|
+
const kind = useMemo(() => classifyDomain(data.map((d) => getKeyRef.current(d))), [data]);
|
|
24
25
|
const frameRef = useRef(null);
|
|
25
26
|
const pendingRef = useRef(null);
|
|
26
27
|
useEffect(
|
|
27
28
|
() => () => {
|
|
28
29
|
if (frameRef.current !== null) cancelAnimationFrame(frameRef.current);
|
|
29
|
-
if (store.get().source === chartId) store.set(null, null);
|
|
30
|
+
if (store.get().source === chartId) store.set(null, null, null);
|
|
30
31
|
},
|
|
31
32
|
[store, chartId]
|
|
32
33
|
);
|
|
@@ -55,9 +56,9 @@ function useChartCursor({
|
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
scheduleAnchor({ x: event.clientX, y: event.clientY });
|
|
58
|
-
store.set(getKeyRef.current(closest), chartId);
|
|
59
|
+
store.set(getKeyRef.current(closest), chartId, kind);
|
|
59
60
|
},
|
|
60
|
-
[data, marginLeft, chartId, store, scheduleAnchor]
|
|
61
|
+
[data, marginLeft, chartId, store, scheduleAnchor, kind]
|
|
61
62
|
);
|
|
62
63
|
const clear = useCallback(() => {
|
|
63
64
|
if (frameRef.current !== null) {
|
|
@@ -66,7 +67,7 @@ function useChartCursor({
|
|
|
66
67
|
}
|
|
67
68
|
pendingRef.current = null;
|
|
68
69
|
setAnchor(null);
|
|
69
|
-
if (store.get().source === chartId) store.set(null, null);
|
|
70
|
+
if (store.get().source === chartId) store.set(null, null, null);
|
|
70
71
|
}, [store, chartId]);
|
|
71
72
|
const onKeyDown = useCallback(
|
|
72
73
|
(event) => {
|
|
@@ -88,11 +89,11 @@ function useChartCursor({
|
|
|
88
89
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
89
90
|
const x = xScaleRef.current(getKeyRef.current(next)) ?? 0;
|
|
90
91
|
scheduleAnchor({ x: rect.left + x, y: rect.top });
|
|
91
|
-
store.set(getKeyRef.current(next), chartId);
|
|
92
|
+
store.set(getKeyRef.current(next), chartId, kind);
|
|
92
93
|
},
|
|
93
|
-
[data, store, chartId, clear, scheduleAnchor]
|
|
94
|
+
[data, store, chartId, clear, scheduleAnchor, kind]
|
|
94
95
|
);
|
|
95
|
-
const point = cursor.key === null ? null : resolveCursorPoint(index, cursor.key);
|
|
96
|
+
const point = cursor.key === null || cursor.kind !== kind ? null : resolveCursorPoint(index, cursor.key);
|
|
96
97
|
return {
|
|
97
98
|
point,
|
|
98
99
|
isSource: cursor.source === chartId,
|
package/dist/charts/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export { ChartFrame, type ChartFrameProps, type ChartFrameLegend, type PlotRect,
|
|
|
21
21
|
export { ChartCenter, type ChartCenterProps, ChartPending, type ChartPendingProps, } from './primitives/ChartPending.js';
|
|
22
22
|
export { Crosshair, SeriesDot } from './primitives/Crosshair.js';
|
|
23
23
|
export { HatchPattern, hatchFill, hatchSizeFor } from './primitives/HatchPattern.js';
|
|
24
|
-
export { ChartCard } from './primitives/ChartCard.js';
|
|
24
|
+
export { ChartCard, type ChartCardProps } from './primitives/ChartCard.js';
|
|
25
25
|
export { ChartLegend, type LegendEntry } from './primitives/ChartLegend.js';
|
|
26
26
|
export { ChartTooltipFloat, TooltipHeader, TooltipRow, TooltipBody, } from './primitives/ChartTooltip.js';
|
|
27
27
|
export { AxisBottomDate, AxisLeftNumeric, AxisRightNumeric } from './primitives/Axes.js';
|
|
@@ -31,7 +31,7 @@ export { XZoneRects, type XZoneSpec } from './primitives/XZoneRects.js';
|
|
|
31
31
|
export { AreaGradient, areaFillUrl } from './primitives/AreaGradient.js';
|
|
32
32
|
export { useChartCursor, type ChartCursor, type CursorAnchor } from './hooks/useChartCursor.js';
|
|
33
33
|
export { foldBands, type BandFold, type BandTooltipConfig, type BandTooltipRowContext, } from './hooks/useBandPlot.js';
|
|
34
|
-
export type { CursorResolution } from './cursor/resolve.js';
|
|
34
|
+
export type { CursorResolution, DomainKind } from './cursor/resolve.js';
|
|
35
35
|
export { useChartSize, type UseChartSizeResult, type ChartSize } from './hooks/useChartSize.js';
|
|
36
36
|
export { fmtAxisDate, fmtTooltipDate } from './utils/format.js';
|
|
37
37
|
export { smartTicks, smartTicksEvery } from './utils/ticks.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EACL,EAAE,EACF,KAAK,EACL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,WAAW,GACjB,MAAM,WAAW,CAAA;AAGlB,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAG5C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC7F,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,UAAU,CAAA;AAGjB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,aAAa,GACd,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,YAAY,EACZ,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,39 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
1
|
/**
|
|
3
|
-
* Standard wrapper for every visx chart — card with
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Standard wrapper for every visx chart (docs/CONTROLS-SPEC.md §2.2) — card with a `WidgetHeader
|
|
3
|
+
* tier="widget"` title row (icon/info/value/delta/count/actions) plus an optional subtitle, over a
|
|
4
|
+
* clipped chart body. Do not wrap visx charts in bare divs.
|
|
5
|
+
*
|
|
6
|
+
* `WidgetHeader` lives in `src/widget-header/` and is itself Mantine-free, so composing it here
|
|
7
|
+
* keeps `./charts` resolving with no `@mantine/*` installed (`check-dist-layering.mjs`,
|
|
8
|
+
* `basalt/token-layer-boundary`). The `actions` slot cannot mount `CtlSlot` (Mantine-coupled) for
|
|
9
|
+
* the same reason — it carries only `data-basalt-tier="widget"`; a basalt control placed there
|
|
10
|
+
* sizes itself (`size="ctl"` internally), and a raw Mantine element is not auto-tiered.
|
|
11
|
+
*
|
|
12
|
+
* The header renders only when at least one of title/info/value/actions/icon/count is set — ending
|
|
13
|
+
* the `''`-as-hidden-header sentinel a consumer used to reach for otherwise.
|
|
6
14
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
15
|
+
import type { ReactNode } from 'react';
|
|
16
|
+
export type ChartCardProps = {
|
|
17
|
+
/** Optional — the header renders only when this or one of info/value/actions/icon/count is set. */
|
|
18
|
+
title?: string;
|
|
19
|
+
/** Optional leading icon, forwarded to `WidgetHeader`. */
|
|
20
|
+
icon?: ReactNode;
|
|
21
|
+
/** Optional muted line rendered below the title row — does NOT by itself trigger the header. */
|
|
9
22
|
subtitle?: string;
|
|
10
|
-
|
|
11
|
-
|
|
23
|
+
/** Renders `WidgetHeader`'s info glyph beside the title — a `More information` button whose
|
|
24
|
+
* bubble opens on hover, focus and click. Never part of the heading's accessible name. */
|
|
25
|
+
info?: string;
|
|
26
|
+
/** Pre-formatted metric value, on the hero-metric row with `delta`. */
|
|
27
|
+
value?: string;
|
|
28
|
+
/** Signed delta rendered via `DeltaBadge`, alongside `value`. */
|
|
29
|
+
delta?: number;
|
|
30
|
+
/** Comparison timeframe forwarded to `DeltaBadge` (e.g. `MoM`). */
|
|
31
|
+
deltaPeriod?: string;
|
|
32
|
+
/** Mono count tag after the title. */
|
|
33
|
+
count?: number;
|
|
34
|
+
/** Right-aligned slot — carries `data-basalt-tier="widget"` (no `CtlSlot`; see module doc). */
|
|
35
|
+
actions?: ReactNode;
|
|
12
36
|
children: ReactNode;
|
|
13
|
-
}
|
|
37
|
+
};
|
|
38
|
+
export declare function ChartCard({ title, icon, subtitle, info, value, delta, deltaPeriod, count, actions, children, }: ChartCardProps): import("react").JSX.Element;
|
|
14
39
|
//# sourceMappingURL=ChartCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartCard.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"ChartCard.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAuCrD,MAAM,MAAM,cAAc,GAAG;IAC3B,mGAAmG;IACnG,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;8FAC0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+FAA+F;IAC/F,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,EACL,WAAW,EACX,KAAK,EACL,OAAO,EACP,QAAQ,GACT,EAAE,cAAc,+BAgChB"}
|
|
@@ -1,76 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useId, useRef, useState } from "react";
|
|
3
2
|
import { VX } from "../../tokens/index.js";
|
|
4
|
-
|
|
5
|
-
position: "relative",
|
|
6
|
-
display: "inline-flex",
|
|
7
|
-
alignItems: "center",
|
|
8
|
-
marginLeft: 5
|
|
9
|
-
};
|
|
10
|
-
const infoTriggerStyle = {
|
|
11
|
-
appearance: "none",
|
|
12
|
-
background: "none",
|
|
13
|
-
border: "none",
|
|
14
|
-
padding: 0,
|
|
15
|
-
margin: 0,
|
|
16
|
-
cursor: "help",
|
|
17
|
-
display: "inline-flex",
|
|
18
|
-
alignItems: "center"
|
|
19
|
-
};
|
|
20
|
-
const bubbleStyle = {
|
|
21
|
-
position: "absolute",
|
|
22
|
-
top: "calc(100% + 7px)",
|
|
23
|
-
left: 0,
|
|
24
|
-
zIndex: 10,
|
|
25
|
-
maxWidth: 260,
|
|
26
|
-
width: "max-content",
|
|
27
|
-
padding: "7px 10px",
|
|
28
|
-
borderRadius: VX.radiusCard,
|
|
29
|
-
backgroundColor: VX.surface.panel,
|
|
30
|
-
boxShadow: VX.shadowCard,
|
|
31
|
-
color: VX.muted,
|
|
32
|
-
fontSize: VX.text.sm,
|
|
33
|
-
fontWeight: 400,
|
|
34
|
-
lineHeight: 1.4,
|
|
35
|
-
whiteSpace: "normal",
|
|
36
|
-
pointerEvents: "none"
|
|
37
|
-
};
|
|
38
|
-
function InfoIcon({ title }) {
|
|
39
|
-
const [open, setOpen] = useState(false);
|
|
40
|
-
const tipId = useId();
|
|
41
|
-
const triggerRef = useRef(null);
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
if (!open) return;
|
|
44
|
-
const handlePointerDown = (event) => {
|
|
45
|
-
if (triggerRef.current?.contains(event.target)) return;
|
|
46
|
-
setOpen(false);
|
|
47
|
-
};
|
|
48
|
-
document.addEventListener("pointerdown", handlePointerDown);
|
|
49
|
-
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
50
|
-
}, [open]);
|
|
51
|
-
return /* @__PURE__ */ jsxs("span", { style: infoWrapStyle, children: [
|
|
52
|
-
/* @__PURE__ */ jsx(
|
|
53
|
-
"button",
|
|
54
|
-
{
|
|
55
|
-
ref: triggerRef,
|
|
56
|
-
type: "button",
|
|
57
|
-
"aria-label": "More information",
|
|
58
|
-
"aria-describedby": open ? tipId : void 0,
|
|
59
|
-
onMouseEnter: () => setOpen(true),
|
|
60
|
-
onMouseLeave: () => setOpen(false),
|
|
61
|
-
onFocus: () => setOpen(true),
|
|
62
|
-
onBlur: () => setOpen(false),
|
|
63
|
-
onClick: () => setOpen(true),
|
|
64
|
-
onKeyDown: (event) => {
|
|
65
|
-
if (event.key === "Escape") setOpen(false);
|
|
66
|
-
},
|
|
67
|
-
style: { ...infoTriggerStyle, color: open ? VX.muted : VX.faint },
|
|
68
|
-
children: /* @__PURE__ */ jsx("svg", { width: 11, height: 11, viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm0 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3zm0 5a1 1 0 0 1 1 1v7a1 1 0 1 1-2 0v-7a1 1 0 0 1 1-1z" }) })
|
|
69
|
-
}
|
|
70
|
-
),
|
|
71
|
-
open && /* @__PURE__ */ jsx("span", { id: tipId, role: "tooltip", style: bubbleStyle, children: title })
|
|
72
|
-
] });
|
|
73
|
-
}
|
|
3
|
+
import { WidgetHeader } from "../../widget-header/index.js";
|
|
74
4
|
const cardStyle = {
|
|
75
5
|
borderRadius: VX.radiusCard,
|
|
76
6
|
boxShadow: VX.shadowCard,
|
|
@@ -85,57 +15,42 @@ const bodyClipStyle = {
|
|
|
85
15
|
borderBottomLeftRadius: VX.radiusCard,
|
|
86
16
|
borderBottomRightRadius: VX.radiusCard,
|
|
87
17
|
overflow: "hidden",
|
|
88
|
-
padding: "2px var(--mantine-spacing-sm, 0.
|
|
89
|
-
};
|
|
90
|
-
const headerStyle = {
|
|
91
|
-
display: "flex",
|
|
92
|
-
justifyContent: "space-between",
|
|
93
|
-
alignItems: "center",
|
|
94
|
-
// Card inset = spacing xs (vertical) / sm (horizontal). The `--mantine-spacing-*` vars carry
|
|
95
|
-
// basalt's OWNED scale (theme.spacing.xs 0.625rem / sm 0.75rem); the rem fallbacks keep a
|
|
96
|
-
// Mantine-free `./charts`-only consumer (no MantineProvider vars) padded identically. No
|
|
97
|
-
// header/body divider — the title block and the plot read as one continuous surface; a rule here
|
|
98
|
-
// only doubled the card's shadow-embedded ring and made the header feel heavier.
|
|
99
|
-
padding: "var(--mantine-spacing-xs, 0.625rem) var(--mantine-spacing-sm, 0.75rem) 4px"
|
|
100
|
-
};
|
|
101
|
-
const titleColumnStyle = {
|
|
102
|
-
display: "inline-flex",
|
|
103
|
-
flexDirection: "column",
|
|
104
|
-
lineHeight: 1.15
|
|
18
|
+
padding: "2px var(--mantine-spacing-sm, 0.8125rem) var(--mantine-spacing-xs, 0.6875rem)"
|
|
105
19
|
};
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
alignItems: "center",
|
|
109
|
-
fontFamily: "var(--basalt-font-head)",
|
|
110
|
-
fontStretch: "88%",
|
|
111
|
-
fontWeight: 550,
|
|
112
|
-
fontSize: VX.text.md,
|
|
113
|
-
color: VX.ink
|
|
114
|
-
};
|
|
115
|
-
const subtitleStyle = {
|
|
116
|
-
fontSize: VX.text.sm,
|
|
117
|
-
fontWeight: 400,
|
|
118
|
-
color: VX.muted,
|
|
119
|
-
marginTop: 1
|
|
20
|
+
const headerWrapStyle = {
|
|
21
|
+
padding: "var(--mantine-spacing-xs, 0.6875rem) var(--mantine-spacing-sm, 0.8125rem) 4px"
|
|
120
22
|
};
|
|
121
23
|
function ChartCard({
|
|
122
24
|
title,
|
|
25
|
+
icon,
|
|
123
26
|
subtitle,
|
|
124
|
-
|
|
125
|
-
|
|
27
|
+
info,
|
|
28
|
+
value,
|
|
29
|
+
delta,
|
|
30
|
+
deltaPeriod,
|
|
31
|
+
count,
|
|
32
|
+
actions,
|
|
126
33
|
children
|
|
127
34
|
}) {
|
|
35
|
+
const hasHeader = title !== void 0 || info !== void 0 || value !== void 0 || actions !== void 0 || icon !== void 0 || count !== void 0;
|
|
128
36
|
return /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
subtitle !== void 0 &&
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
37
|
+
hasHeader && /* @__PURE__ */ jsx("div", { style: headerWrapStyle, children: /* @__PURE__ */ jsx(
|
|
38
|
+
WidgetHeader,
|
|
39
|
+
{
|
|
40
|
+
tier: "widget",
|
|
41
|
+
title: title ?? "",
|
|
42
|
+
...icon !== void 0 && { icon },
|
|
43
|
+
...subtitle !== void 0 && { subtitle },
|
|
44
|
+
...info !== void 0 && { info },
|
|
45
|
+
...value !== void 0 && { value },
|
|
46
|
+
...delta !== void 0 && { delta },
|
|
47
|
+
...deltaPeriod !== void 0 && { deltaPeriod },
|
|
48
|
+
...count !== void 0 && { count },
|
|
49
|
+
...actions !== void 0 && {
|
|
50
|
+
actions: /* @__PURE__ */ jsx("span", { "data-basalt-tier": "widget", children: actions })
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
) }),
|
|
139
54
|
/* @__PURE__ */ jsx("div", { style: bodyClipStyle, children })
|
|
140
55
|
] });
|
|
141
56
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChartCard.test.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartCard.test.tsx"],"names":[],"mappings":""}
|
|
@@ -3,11 +3,35 @@ type BarSparklineProps = {
|
|
|
3
3
|
width: number;
|
|
4
4
|
height: number;
|
|
5
5
|
color?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Gap between two bars, in px. `1` is the shipped look; `2` at ~10 bars reads as a discrete series
|
|
8
|
+
* rather than a histogram, which is the KPI-card treatment.
|
|
9
|
+
*
|
|
10
|
+
* @default 1
|
|
11
|
+
*/
|
|
12
|
+
barGap?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Bar corner radius, in px. `0` is the shipped look.
|
|
15
|
+
*
|
|
16
|
+
* @default 0
|
|
17
|
+
*/
|
|
18
|
+
barRadius?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Paints the LAST bar in `emphasisColor` at full opacity — "this is where the series ends", the
|
|
21
|
+
* one reading a trend beside a KPI value is actually for. Off by default: a chart that means
|
|
22
|
+
* something by its final point must say so.
|
|
23
|
+
*
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
emphasizeLast?: boolean;
|
|
27
|
+
/** The emphasised bar's fill. @default `VX.accent` */
|
|
28
|
+
emphasisColor?: string;
|
|
6
29
|
/** Accessible text alternative, applied as `aria-label` (+ `role="img"`) on the `<svg>`. */
|
|
7
30
|
ariaLabel?: string;
|
|
8
31
|
};
|
|
9
32
|
/** Quiet inline bar trend — defaults to `VX.faint`, matching the sparkline family's restrained
|
|
10
|
-
* identity (docs/DESIGN-SPEC.md §5).
|
|
11
|
-
|
|
33
|
+
* identity (docs/DESIGN-SPEC.md §5). Every geometry option below defaults to the shipped look, so
|
|
34
|
+
* an existing call site renders byte-identically. */
|
|
35
|
+
export declare function BarSparkline({ data, width, height, color, barGap, barRadius, emphasizeLast, emphasisColor, ariaLabel, }: BarSparklineProps): import("react").JSX.Element;
|
|
12
36
|
export {};
|
|
13
37
|
//# sourceMappingURL=BarSparkline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BarSparkline.d.ts","sourceRoot":"","sources":["../../../src/charts/sparklines/BarSparkline.tsx"],"names":[],"mappings":"AAIA,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;
|
|
1
|
+
{"version":3,"file":"BarSparkline.d.ts","sourceRoot":"","sources":["../../../src/charts/sparklines/BarSparkline.tsx"],"names":[],"mappings":"AAIA,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;qDAEqD;AACrD,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,KAAK,EACL,MAAM,EACN,KAAK,EACL,MAAU,EACV,SAAa,EACb,aAAqB,EACrB,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+BAoCnB"}
|
|
@@ -2,8 +2,19 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { scaleLinear } from "@visx/scale";
|
|
3
3
|
import { useMemo } from "react";
|
|
4
4
|
import { VX } from "../../tokens/index.js";
|
|
5
|
-
function BarSparkline({
|
|
5
|
+
function BarSparkline({
|
|
6
|
+
data,
|
|
7
|
+
width,
|
|
8
|
+
height,
|
|
9
|
+
color,
|
|
10
|
+
barGap = 1,
|
|
11
|
+
barRadius = 0,
|
|
12
|
+
emphasizeLast = false,
|
|
13
|
+
emphasisColor,
|
|
14
|
+
ariaLabel
|
|
15
|
+
}) {
|
|
6
16
|
const fillColor = color ?? VX.faint;
|
|
17
|
+
const lastColor = emphasisColor ?? VX.accent;
|
|
7
18
|
const a11yProps = ariaLabel !== void 0 ? { role: "img", "aria-label": ariaLabel } : {};
|
|
8
19
|
const yScale = useMemo(() => {
|
|
9
20
|
const max = Math.max(...data.filter((v) => isFinite(v)), 1);
|
|
@@ -11,9 +22,11 @@ function BarSparkline({ data, width, height, color, ariaLabel }) {
|
|
|
11
22
|
}, [data, height]);
|
|
12
23
|
if (!data.length) return /* @__PURE__ */ jsx("svg", { width, height, ...a11yProps });
|
|
13
24
|
const step = width / data.length;
|
|
14
|
-
const barWidth = Math.max(step -
|
|
25
|
+
const barWidth = Math.max(step - barGap, 1);
|
|
26
|
+
const lastIndex = data.length - 1;
|
|
15
27
|
return /* @__PURE__ */ jsx("svg", { width, height, ...a11yProps, children: data.map((v, i) => {
|
|
16
28
|
const bh = Math.max(yScale(Math.max(v, 0)), 0);
|
|
29
|
+
const isLast = emphasizeLast && i === lastIndex;
|
|
17
30
|
return /* @__PURE__ */ jsx(
|
|
18
31
|
"rect",
|
|
19
32
|
{
|
|
@@ -21,8 +34,9 @@ function BarSparkline({ data, width, height, color, ariaLabel }) {
|
|
|
21
34
|
y: height - bh,
|
|
22
35
|
width: barWidth,
|
|
23
36
|
height: bh,
|
|
24
|
-
|
|
25
|
-
|
|
37
|
+
...barRadius > 0 && { rx: barRadius },
|
|
38
|
+
fill: isLast ? lastColor : fillColor,
|
|
39
|
+
fillOpacity: isLast ? 1 : 0.75
|
|
26
40
|
},
|
|
27
41
|
i
|
|
28
42
|
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-coverage.test.d.ts","sourceRoot":"","sources":["../../src/cli/check-coverage.test.ts"],"names":[],"mappings":""}
|