basalt-ui 1.25.0 → 1.27.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 +26 -0
- package/MIGRATING.md +815 -23
- package/README.md +45 -32
- package/agent/rules/basalt-batteries.md +205 -0
- package/agent/rules/basalt-charts.md +125 -555
- package/agent/rules/basalt-controls.md +160 -0
- package/agent/rules/basalt-mantine.md +146 -439
- package/agent/rules/basalt-state.md +118 -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 +1465 -36
- package/configs/oxlint-plugin.test.ts +1190 -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 +39 -0
- package/dist/controls/enum-filter.d.ts.map +1 -0
- package/dist/controls/enum-filter.js +93 -0
- package/dist/controls/filter-context.d.ts +60 -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 +20 -0
- package/dist/controls/index.d.ts.map +1 -0
- package/dist/controls/index.js +46 -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/number-filter.d.ts +26 -0
- package/dist/controls/number-filter.d.ts.map +1 -0
- package/dist/controls/number-filter.js +143 -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 +43 -0
- package/dist/controls/range-filter.d.ts.map +1 -0
- package/dist/controls/range-filter.js +135 -0
- package/dist/controls/range-filter.type-guard.test.d.ts +2 -0
- package/dist/controls/range-filter.type-guard.test.d.ts.map +1 -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/index.d.ts +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +3 -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 +95 -9
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +108 -49
- package/dist/dashboard/stat-card.module.css +153 -0
- package/dist/dashboard/stat-card.module.css.d.ts +15 -0
- package/dist/data/data-table.d.ts +37 -15
- package/dist/data/data-table.d.ts.map +1 -1
- package/dist/data/data-table.js +96 -58
- 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 +78 -7
- package/dist/guard/types.d.ts +3 -3
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +13 -3
- 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 +84 -0
- package/dist/router-tanstack/search-store.d.ts.map +1 -0
- package/dist/router-tanstack/search-store.js +271 -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 +565 -0
- package/dist/state/fields.d.ts.map +1 -0
- package/dist/state/fields.js +405 -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 +60 -0
- package/dist/state/persisted.d.ts.map +1 -0
- package/dist/state/persisted.js +123 -0
- package/dist/state/persisted.test.d.ts +2 -0
- package/dist/state/persisted.test.d.ts.map +1 -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 +156 -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 +67 -0
- package/dist/widget-header/widget-header.d.ts.map +1 -0
- package/dist/widget-header/widget-header.js +89 -0
- package/dist/widget-header/widget-header.module.css +350 -0
- package/dist/widget-header/widget-header.module.css.d.ts +25 -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 +1053 -0
- package/src/controls/enum-filter.tsx +170 -0
- package/src/controls/filter-context.tsx +158 -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 +49 -0
- package/src/controls/multi-select-filter.tsx +140 -0
- package/src/controls/number-filter.tsx +291 -0
- package/src/controls/peer-boundary.test.ts +85 -0
- package/src/controls/props-contract.test.tsx +137 -0
- package/src/controls/range-filter.tsx +237 -0
- package/src/controls/range-filter.type-guard.test.tsx +122 -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/index.ts +6 -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 +153 -0
- package/src/dashboard/stat-card.module.css.d.ts +15 -0
- package/src/dashboard/stat-card.test.tsx +298 -1
- package/src/dashboard/stat-card.tsx +289 -67
- package/src/data/data-table.test.tsx +96 -11
- package/src/data/data-table.tsx +228 -84
- package/src/guard/check-source.test.ts +159 -13
- package/src/guard/grace.test.ts +158 -0
- package/src/guard/index.ts +185 -29
- package/src/guard/types.ts +4 -2
- package/src/index.ts +51 -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 +35 -0
- package/src/router-tanstack/index.ts +28 -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 +882 -0
- package/src/router-tanstack/search-store.test.ts +578 -0
- package/src/router-tanstack/search-store.ts +546 -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 +512 -0
- package/src/state/fields.ts +1150 -0
- package/src/state/persisted.test.ts +91 -0
- package/src/state/persisted.ts +261 -0
- package/src/state.ts +52 -240
- package/src/styles.css +13 -0
- package/src/surfaces.ts +204 -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 +350 -0
- package/src/widget-header/widget-header.module.css.d.ts +25 -0
- package/src/widget-header/widget-header.test.tsx +187 -0
- package/src/widget-header/widget-header.tsx +213 -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 -329
- 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/src/surfaces.ts
CHANGED
|
@@ -9,26 +9,61 @@ import type { GuardKind } from './guard/types'
|
|
|
9
9
|
|
|
10
10
|
// ── Scalar types ──────────────────────────────────────────────────────────────────────────────────
|
|
11
11
|
|
|
12
|
-
/** The
|
|
12
|
+
/** The 6 on-disk rule names (agent/rules/basalt-{name}.md — the set-equality target).
|
|
13
|
+
*
|
|
14
|
+
* One rule file per DOCTRINE, not per subpath: `state` also owns the router bridge's placement law
|
|
15
|
+
* (the two were one argument split across two files), and `batteries` owns every adapter surface
|
|
16
|
+
* whose doctrine is "use the shipped thing" — query, forms, notifications, commands, data, content,
|
|
17
|
+
* agent and the app-global layer. Thirteen files carried 4,177 lines, 55% of it with no guard
|
|
18
|
+
* behind it and the identity paragraph restated six times (`docs/CONTROLS-SPEC.md` §7).
|
|
13
19
|
*
|
|
14
20
|
* @example
|
|
15
21
|
* const r: RuleName = 'tokens' // ok
|
|
16
22
|
* // const bad: RuleName = 'overlays' // tsc error — not in the union
|
|
17
23
|
*/
|
|
18
|
-
export type RuleName =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
export type RuleName = 'tokens' | 'charts' | 'mantine' | 'state' | 'controls' | 'batteries'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Every rule the shipped oxlint JS plugin registers (`configs/oxlint-plugin.js` → `rules`), as one
|
|
28
|
+
* literal union AND one runtime list — the type and the list are the same declaration, so they
|
|
29
|
+
* cannot drift from each other. What they CAN drift from is the plugin itself, which this module
|
|
30
|
+
* must not import (it is a standalone `.js` loaded through `jsPlugins` out of a consumer's
|
|
31
|
+
* node_modules, and `surfaces.ts` is dependency-free by contract). `oxlint-plugin.test.ts` closes
|
|
32
|
+
* that gap: it asserts this list is EXACTLY the plugin's own rule keys, and `check-coverage`
|
|
33
|
+
* asserts every id here maps to exactly one surface.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const id: PluginRuleId = 'hand-rolled-filter' // ok
|
|
37
|
+
* // const bad: PluginRuleId = 'hand-rolled-filters' // tsc error
|
|
38
|
+
*/
|
|
39
|
+
export const PLUGIN_RULE_ID_LIST = [
|
|
40
|
+
'no-raw-font-size',
|
|
41
|
+
'raw-size-literal',
|
|
42
|
+
'card-inset',
|
|
43
|
+
'chart-in-raw-surface',
|
|
44
|
+
'hand-rolled-plot',
|
|
45
|
+
'chart-legend-literal',
|
|
46
|
+
'shadow-basalt-export',
|
|
47
|
+
'hand-rolled-shell',
|
|
48
|
+
'raw-scroll-container',
|
|
49
|
+
'hand-rolled-filter',
|
|
50
|
+
'control-outside-home',
|
|
51
|
+
'control-size-literal',
|
|
52
|
+
'page-bar-budget',
|
|
53
|
+
'in-body-page-title',
|
|
54
|
+
'responsive-twin',
|
|
55
|
+
'search-literal-link',
|
|
56
|
+
'use-search-from-literal',
|
|
57
|
+
'visx-boundary',
|
|
58
|
+
'visx-tooltip',
|
|
59
|
+
'token-layer-boundary',
|
|
60
|
+
'agent-resume-guard',
|
|
61
|
+
'agent-no-raw-usechat',
|
|
62
|
+
'ai-sdk-major',
|
|
63
|
+
] as const
|
|
64
|
+
|
|
65
|
+
/** One registered oxlint plugin rule id — the literal union of {@link PLUGIN_RULE_ID_LIST}. */
|
|
66
|
+
export type PluginRuleId = (typeof PLUGIN_RULE_ID_LIST)[number]
|
|
32
67
|
|
|
33
68
|
/** The 3 shipped skill names (agent/skills/basalt-{name}/SKILL.md, placed into a consumer's
|
|
34
69
|
* .claude/skills/ by `basalt-ui init`/`sync` — the same managed path the rules take).
|
|
@@ -112,15 +147,33 @@ type BaseSurface = {
|
|
|
112
147
|
*
|
|
113
148
|
* @example
|
|
114
149
|
* const s: DoctrineSpec = { kind: 'doctrine', layer: 'headless', rule: 'tokens',
|
|
115
|
-
* skill: ['basalt-design'], guardKinds: ['raw-hex'],
|
|
150
|
+
* skill: ['basalt-design'], guardKinds: ['raw-hex'], pluginRules: ['no-raw-font-size'],
|
|
151
|
+
* forbiddenImports: [] }
|
|
116
152
|
*/
|
|
117
153
|
export type DoctrineSpec = BaseSurface & {
|
|
118
154
|
readonly kind: 'doctrine'
|
|
119
155
|
readonly rule: RuleName
|
|
120
156
|
/** A LIST (skill↔surface is many-to-one — basalt-design covers tokens AND mantine AND state). */
|
|
121
157
|
readonly skill: readonly SkillName[]
|
|
122
|
-
/** Required, but [] is legal for advisory surfaces (
|
|
158
|
+
/** Required, but [] is legal for advisory surfaces (the batteries: rule only, no guard). */
|
|
123
159
|
readonly guardKinds: readonly GuardKind[]
|
|
160
|
+
/**
|
|
161
|
+
* The oxlint plugin rules this surface's doctrine is enforced by — the AST half of the same seam
|
|
162
|
+
* `guardKinds` covers with text scans. Required (`[]` is legal, and says "no AST rule guards
|
|
163
|
+
* this"), because the ABSENCE of the field is what let the generated coverage headers claim a
|
|
164
|
+
* rule was "backed by" a guard kind while the plugin rule doing the real work went unnamed (D8).
|
|
165
|
+
*
|
|
166
|
+
* Every id in {@link PLUGIN_RULE_ID_LIST} maps to EXACTLY ONE surface — asserted by
|
|
167
|
+
* `check-coverage` and by `oxlint-plugin.test.ts`, so a new plugin rule cannot ship without a
|
|
168
|
+
* home, and one rule cannot be counted as coverage for two surfaces.
|
|
169
|
+
*/
|
|
170
|
+
readonly pluginRules: readonly PluginRuleId[]
|
|
171
|
+
/**
|
|
172
|
+
* Laws this surface states but nothing enforces — printed under `not guarded:` in the generated
|
|
173
|
+
* `<!-- basalt:coverage -->` header. The honest half of the block: claiming coverage that does
|
|
174
|
+
* not exist is D8, and the only way a reader can tell is if the doc says so itself.
|
|
175
|
+
*/
|
|
176
|
+
readonly advisoryLaws?: readonly string[]
|
|
124
177
|
}
|
|
125
178
|
|
|
126
179
|
/**
|
|
@@ -136,6 +189,8 @@ export type ToolingSpec = BaseSurface & {
|
|
|
136
189
|
readonly rule?: never
|
|
137
190
|
readonly skill?: never
|
|
138
191
|
readonly guardKinds?: never
|
|
192
|
+
readonly pluginRules?: never
|
|
193
|
+
readonly advisoryLaws?: never
|
|
139
194
|
}
|
|
140
195
|
|
|
141
196
|
/** The discriminated union — the SURFACES registry value type. */
|
|
@@ -192,9 +247,29 @@ export const SURFACES = {
|
|
|
192
247
|
'raw-form-control',
|
|
193
248
|
'sub-16-input-font',
|
|
194
249
|
'mantine-shade-index',
|
|
250
|
+
// The text lane of the kinds whose remedy IS a Mantine primitive or a Mantine-owned prop:
|
|
251
|
+
// C8's page title (same id as the plugin rule, so one annotation waives both lanes), the
|
|
252
|
+
// spacing props, and the layout primitives an inline `display`/raw element replaces.
|
|
253
|
+
'in-body-page-title',
|
|
254
|
+
'raw-spacing',
|
|
255
|
+
'inline-spacing',
|
|
256
|
+
'inline-display',
|
|
257
|
+
'raw-html-layout',
|
|
258
|
+
'hidden-inline-style',
|
|
259
|
+
],
|
|
260
|
+
// The chrome half of the plugin: the shell, the card idiom, the page title and the scroll
|
|
261
|
+
// doctrine. `hand-rolled-shell` sits here rather than on a shell-shaped surface because
|
|
262
|
+
// `BasaltShell` IS the root barrel's promise (docs/CONTROLS-SPEC.md §6 wave 6).
|
|
263
|
+
pluginRules: [
|
|
264
|
+
'hand-rolled-shell',
|
|
265
|
+
'card-inset',
|
|
266
|
+
'in-body-page-title',
|
|
267
|
+
'raw-scroll-container',
|
|
268
|
+
'page-bar-budget',
|
|
269
|
+
'shadow-basalt-export',
|
|
195
270
|
],
|
|
196
271
|
description:
|
|
197
|
-
'BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone)',
|
|
272
|
+
'BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, PageBar, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, WidgetHeader, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone)',
|
|
198
273
|
optionalPeers: [
|
|
199
274
|
'react-markdown',
|
|
200
275
|
'remark-gfm',
|
|
@@ -210,7 +285,20 @@ export const SURFACES = {
|
|
|
210
285
|
layer: 'headless',
|
|
211
286
|
rule: 'charts',
|
|
212
287
|
skill: ['basalt-charts'],
|
|
213
|
-
guardKinds: [
|
|
288
|
+
guardKinds: [
|
|
289
|
+
'raw-hex',
|
|
290
|
+
'raw-color-fn',
|
|
291
|
+
'raw-visx-axis',
|
|
292
|
+
'unframed-chart',
|
|
293
|
+
'chart-missing-aria-label',
|
|
294
|
+
],
|
|
295
|
+
pluginRules: [
|
|
296
|
+
'hand-rolled-plot',
|
|
297
|
+
'chart-legend-literal',
|
|
298
|
+
'chart-in-raw-surface',
|
|
299
|
+
'visx-boundary',
|
|
300
|
+
'visx-tooltip',
|
|
301
|
+
],
|
|
214
302
|
description:
|
|
215
303
|
'CartesianChart + visx chart primitives, kinds, sparklines, hooks, and token re-exports (Mantine-free)',
|
|
216
304
|
globs: {
|
|
@@ -229,7 +317,28 @@ export const SURFACES = {
|
|
|
229
317
|
layer: 'headless',
|
|
230
318
|
rule: 'tokens',
|
|
231
319
|
skill: ['basalt-design', 'basalt-charts'],
|
|
232
|
-
guardKinds: [
|
|
320
|
+
guardKinds: [
|
|
321
|
+
'raw-hex',
|
|
322
|
+
'raw-color-fn',
|
|
323
|
+
'off-identity-accent',
|
|
324
|
+
'off-system-surface-var',
|
|
325
|
+
// The rest of the value lane: every kind whose remedy is a `--vx-*` token or a theme knob,
|
|
326
|
+
// in TSX and in kebab CSS alike.
|
|
327
|
+
'raw-font-family',
|
|
328
|
+
'raw-radius',
|
|
329
|
+
'raw-surface',
|
|
330
|
+
'inline-font-size',
|
|
331
|
+
'css-raw-surface',
|
|
332
|
+
'surface-shadow-override',
|
|
333
|
+
// Not a token kind — the kind that judges the ANNOTATION rather than the code. It lands here
|
|
334
|
+
// because `agent/rules/basalt-tokens.md` is where the `theme-allow` grammar is documented
|
|
335
|
+
// (said once, on purpose), so this is the header that must name its enforcement.
|
|
336
|
+
'theme-allow-unscoped',
|
|
337
|
+
],
|
|
338
|
+
// The type-scale rules live with the tokens, not with `.`: both police a value that left the
|
|
339
|
+
// `--vx-*` system, which is this surface's whole subject. `token-layer-boundary` is the
|
|
340
|
+
// repo-local-only rule that keeps the layer upstream of Mantine (see below).
|
|
341
|
+
pluginRules: ['no-raw-font-size', 'raw-size-literal', 'token-layer-boundary'],
|
|
233
342
|
description:
|
|
234
343
|
'VX token refs, buildPaletteCss, defineSeries, seriesTokens, groupTokens, alpha (Mantine-free)',
|
|
235
344
|
globs: {
|
|
@@ -269,9 +378,10 @@ export const SURFACES = {
|
|
|
269
378
|
'./query': {
|
|
270
379
|
kind: 'doctrine',
|
|
271
380
|
layer: 'headless',
|
|
272
|
-
rule: '
|
|
381
|
+
rule: 'batteries',
|
|
273
382
|
skill: ['basalt-app'],
|
|
274
383
|
guardKinds: [],
|
|
384
|
+
pluginRules: [],
|
|
275
385
|
description: 'createBasaltQueryClient, transport-agnostic unwrap, lazy BasaltQueryDevtools',
|
|
276
386
|
optionalPeers: ['@tanstack/react-query-devtools'],
|
|
277
387
|
globs: {
|
|
@@ -284,11 +394,13 @@ export const SURFACES = {
|
|
|
284
394
|
'./router-tanstack': {
|
|
285
395
|
kind: 'doctrine',
|
|
286
396
|
layer: 'headless',
|
|
287
|
-
rule: '
|
|
397
|
+
rule: 'state',
|
|
288
398
|
skill: ['basalt-app'],
|
|
289
399
|
guardKinds: [],
|
|
400
|
+
// Law C10 — a nav link's `search` and a reader's `from` are both this bridge's contract.
|
|
401
|
+
pluginRules: ['search-literal-link', 'use-search-from-literal'],
|
|
290
402
|
description:
|
|
291
|
-
'TanStack Router bridge: defineNav/navGroup/navTarget (one typed nav definition) + useNav (sections + mobileNav, spread onto BasaltShell) + useBasaltNav (active route) + useRouterBreadcrumbs +
|
|
403
|
+
'TanStack Router bridge: defineNav/navGroup/navTarget (one typed nav definition) + useNav (sections + mobileNav, spread onto BasaltShell) + useBasaltNav (active route) + useRouterBreadcrumbs + createSearchStore (typed URL > localStorage > fallback store over field.enum/multi/range/number/boolean/string; deprecated createSearchParamStore/createMultiSearchParamStore wrappers until 1.29.0)',
|
|
292
404
|
optionalPeers: ['@tanstack/react-router'],
|
|
293
405
|
globs: {
|
|
294
406
|
shipped: [],
|
|
@@ -300,9 +412,10 @@ export const SURFACES = {
|
|
|
300
412
|
'./forms': {
|
|
301
413
|
kind: 'doctrine',
|
|
302
414
|
layer: 'mantine-coupled',
|
|
303
|
-
rule: '
|
|
415
|
+
rule: 'batteries',
|
|
304
416
|
skill: ['basalt-design'],
|
|
305
417
|
guardKinds: [],
|
|
418
|
+
pluginRules: [],
|
|
306
419
|
description:
|
|
307
420
|
'Mantine form adapter: useBasaltForm, field, FormErrorSummary, useFormDraft (Standard Schema)',
|
|
308
421
|
optionalPeers: ['@mantine/form'],
|
|
@@ -311,9 +424,10 @@ export const SURFACES = {
|
|
|
311
424
|
'./notifications': {
|
|
312
425
|
kind: 'doctrine',
|
|
313
426
|
layer: 'mantine-coupled',
|
|
314
|
-
rule: '
|
|
427
|
+
rule: 'batteries',
|
|
315
428
|
skill: ['basalt-app'],
|
|
316
429
|
guardKinds: [],
|
|
430
|
+
pluginRules: [],
|
|
317
431
|
description:
|
|
318
432
|
'Mantine notifications: notify helpers, typed registry, persisted history, NotificationBell, NotificationCenter',
|
|
319
433
|
optionalPeers: ['@mantine/notifications'],
|
|
@@ -322,9 +436,10 @@ export const SURFACES = {
|
|
|
322
436
|
'./commands': {
|
|
323
437
|
kind: 'doctrine',
|
|
324
438
|
layer: 'mantine-coupled',
|
|
325
|
-
rule: '
|
|
439
|
+
rule: 'batteries',
|
|
326
440
|
skill: ['basalt-app'],
|
|
327
441
|
guardKinds: [],
|
|
442
|
+
pluginRules: [],
|
|
328
443
|
description:
|
|
329
444
|
'typed command bus + overlay controller, toSpotlightActions, ShortcutsHelp, BasaltOverlays',
|
|
330
445
|
optionalPeers: ['@mantine/spotlight', '@mantine/modals', '@tanstack/react-hotkeys'],
|
|
@@ -333,9 +448,10 @@ export const SURFACES = {
|
|
|
333
448
|
'./data': {
|
|
334
449
|
kind: 'doctrine',
|
|
335
450
|
layer: 'mantine-coupled',
|
|
336
|
-
rule: '
|
|
451
|
+
rule: 'batteries',
|
|
337
452
|
skill: ['basalt-design'],
|
|
338
453
|
guardKinds: [],
|
|
454
|
+
pluginRules: [],
|
|
339
455
|
description:
|
|
340
456
|
'Convenience barrel pulling both TanStack Table + Virtual peer groups: BasaltDataTable, BasaltVirtualList (Mantine-rendered) — prefer ./data/table or ./data/virtual for per-feature opt-in',
|
|
341
457
|
optionalPeers: ['@tanstack/react-table', '@tanstack/react-virtual'],
|
|
@@ -344,9 +460,10 @@ export const SURFACES = {
|
|
|
344
460
|
'./data/table': {
|
|
345
461
|
kind: 'doctrine',
|
|
346
462
|
layer: 'mantine-coupled',
|
|
347
|
-
rule: '
|
|
463
|
+
rule: 'batteries',
|
|
348
464
|
skill: ['basalt-design'],
|
|
349
465
|
guardKinds: [],
|
|
466
|
+
pluginRules: [],
|
|
350
467
|
description:
|
|
351
468
|
'BasaltDataTable: a sortable data table over TanStack Table, rendered with Mantine (Mantine-rendered)',
|
|
352
469
|
optionalPeers: ['@tanstack/react-table'],
|
|
@@ -355,9 +472,10 @@ export const SURFACES = {
|
|
|
355
472
|
'./data/virtual': {
|
|
356
473
|
kind: 'doctrine',
|
|
357
474
|
layer: 'mantine-coupled',
|
|
358
|
-
rule: '
|
|
475
|
+
rule: 'batteries',
|
|
359
476
|
skill: ['basalt-design'],
|
|
360
477
|
guardKinds: [],
|
|
478
|
+
pluginRules: [],
|
|
361
479
|
description:
|
|
362
480
|
'BasaltVirtualList: a windowed virtual list over TanStack Virtual, rendered with Mantine (Mantine-rendered)',
|
|
363
481
|
optionalPeers: ['@tanstack/react-virtual'],
|
|
@@ -366,9 +484,11 @@ export const SURFACES = {
|
|
|
366
484
|
'./agent': {
|
|
367
485
|
kind: 'doctrine',
|
|
368
486
|
layer: 'headless',
|
|
369
|
-
rule: '
|
|
487
|
+
rule: 'batteries',
|
|
370
488
|
skill: ['basalt-app'],
|
|
371
489
|
guardKinds: [],
|
|
490
|
+
// The three agent-chat correctness rules — they honour `basalt-agent-allow`, not `theme-allow`.
|
|
491
|
+
pluginRules: ['agent-resume-guard', 'agent-no-raw-usechat', 'ai-sdk-major'],
|
|
372
492
|
description:
|
|
373
493
|
'Headless streaming-chat layer: useAgentStream, aiSdkTransport (recommended default) + edenTransport, isResumable/ResumableAgentTransport (stream-resumption seam), PartList, coalesceParts, the ForeignPart/definePartRenderers/narrowAgentPart open part-registry seam, plus the multi-thread createThreadsStore + useAgentThreadRuns + outcome-resolver seam (Mantine-free)',
|
|
374
494
|
optionalPeers: ['ai', 'use-stick-to-bottom'],
|
|
@@ -382,9 +502,10 @@ export const SURFACES = {
|
|
|
382
502
|
'./agent-chat': {
|
|
383
503
|
kind: 'doctrine',
|
|
384
504
|
layer: 'mantine-coupled',
|
|
385
|
-
rule: '
|
|
505
|
+
rule: 'batteries',
|
|
386
506
|
skill: ['basalt-app'],
|
|
387
507
|
guardKinds: [],
|
|
508
|
+
pluginRules: [],
|
|
388
509
|
description:
|
|
389
510
|
'Mantine-styled thread-chat components over basalt-ui/agent: ThreadWorkspace, ThreadFeed (variant/renderRow), ThreadFeedRow (inline-expanding Slack row, lazily mounted + kept mounted), ThreadOutcomeCard, ThreadDetailPanel, Composer, ThreadTranscript (open part-renderer registry via its renderers/fallbackRenderer props, per-message MessageAffordances, groupConsecutive, and an optional virtualize/height windowing mode whose VirtualizeOptions carry overscan/estimateSize/initialScroll — a virtualized transcript opens scrolled to the newest message unless initialScroll is "start"), threadPartRenderers, ToolChip (Mantine-coupled). motion is required, not optional — ThreadFeed/ThreadDetailPanel import motion/react eagerly, so this subpath fails to resolve without it installed even though peerDependenciesMeta marks it optional (npm has no per-subpath optionality). remend is genuinely optional here — ThreadTranscript reaches it only through the lazy dynamic import() inside content/markdown.tsx, and @tanstack/react-virtual the same way through the lazy import() behind ThreadTranscript virtualize (absent peer degrades to an unwindowed, height-bound pane).',
|
|
390
511
|
optionalPeers: [
|
|
@@ -405,11 +526,12 @@ export const SURFACES = {
|
|
|
405
526
|
'./content': {
|
|
406
527
|
kind: 'doctrine',
|
|
407
528
|
layer: 'mantine-coupled',
|
|
408
|
-
rule: '
|
|
529
|
+
rule: 'batteries',
|
|
409
530
|
skill: ['basalt-design'],
|
|
410
531
|
guardKinds: [],
|
|
532
|
+
pluginRules: [],
|
|
411
533
|
description:
|
|
412
|
-
'Prose (article/chat typography), CodeBlock (shiki, optional peer), Callout, TableOfContents, ReadingProgress, Markdown (react-markdown + remark-gfm, optional peers; `streaming` is a rendering mode ONLY — `contentTrust` is the independent security input, and any surface rendering agent/model output must pin `contentTrust="untrusted"`, the sole input to the image-origin allowlist; a `fenceRenderers` registry — settledOnly/FenceRenderer/FenceRenderers/FenceRenderContext; `sanitizeSchema`, an additions-only SanitizeSchemaExtension merged over BASALT_SANITIZE_SCHEMA via mergeSanitizeSchema; the remend streaming-repair pass is now a lazy optional peer), MermaidDiagram (beautiful-mermaid, optional peer), mdxComponents/createMdxComponents, ArticleLayout (docs-page frame), ArticleCard/ArticleGrid (overview cards), Article model (sortArticles/filterArticles/formatArticleDate),
|
|
534
|
+
'Prose (article/chat typography), CodeBlock (shiki, optional peer), Callout, TableOfContents, ReadingProgress, Markdown (react-markdown + remark-gfm, optional peers; `streaming` is a rendering mode ONLY — `contentTrust` is the independent security input, and any surface rendering agent/model output must pin `contentTrust="untrusted"`, the sole input to the image-origin allowlist; a `fenceRenderers` registry — settledOnly/FenceRenderer/FenceRenderers/FenceRenderContext; `sanitizeSchema`, an additions-only SanitizeSchemaExtension merged over BASALT_SANITIZE_SCHEMA via mergeSanitizeSchema; the remend streaming-repair pass is now a lazy optional peer), MermaidDiagram (beautiful-mermaid, optional peer), mdxComponents/createMdxComponents, ArticleLayout (docs-page frame), ArticleCard/ArticleGrid (overview cards), Article model (sortArticles/filterArticles/formatArticleDate), FilterSet/ViewTabs/MultiSelectFilter re-exported from ./controls (they replaced the controlled ArticleFilterBar), toArticleActions (Spotlight projector, @mantine/spotlight type-only), GuideLink/GuideDrawer (contextual-help drawer) — the content/prose surface',
|
|
413
535
|
optionalPeers: [
|
|
414
536
|
'shiki',
|
|
415
537
|
'@shikijs/langs',
|
|
@@ -423,14 +545,58 @@ export const SURFACES = {
|
|
|
423
545
|
],
|
|
424
546
|
forbiddenImports: [],
|
|
425
547
|
},
|
|
548
|
+
'./controls': {
|
|
549
|
+
kind: 'doctrine',
|
|
550
|
+
layer: 'mantine-coupled',
|
|
551
|
+
rule: 'controls',
|
|
552
|
+
skill: ['basalt-design'],
|
|
553
|
+
// The text lane of law C1 — the plugin's `control-outside-home` seen through a 12-line host-tag
|
|
554
|
+
// window, since a regex scan has no ancestry. Same law, same wave, same promotion.
|
|
555
|
+
guardKinds: ['raw-selection-control'],
|
|
556
|
+
// The control tier itself (laws C1/C3/C5/C9). `hand-rolled-filter`, `control-size-literal` and
|
|
557
|
+
// `responsive-twin` all ship `error`; `control-outside-home` is the one grace entry left in
|
|
558
|
+
// `PLUGIN_RULE_GRACE`, re-dated to 1.28.0 against the wave-7 measurement (see its `why`).
|
|
559
|
+
// The budget rules live on `.` with `PageBar` itself.
|
|
560
|
+
pluginRules: [
|
|
561
|
+
'hand-rolled-filter',
|
|
562
|
+
'control-outside-home',
|
|
563
|
+
'control-size-literal',
|
|
564
|
+
'responsive-twin',
|
|
565
|
+
],
|
|
566
|
+
// docs/CONTROLS-SPEC.md §6 "Honest coverage" — verbatim, because a generated header claiming
|
|
567
|
+
// otherwise is D8 again.
|
|
568
|
+
advisoryLaws: [
|
|
569
|
+
'C1 as a cross-file law (a control placed in one file, its home declared in another)',
|
|
570
|
+
'hand-rolled section headings (argo writes `<Text fw={600} size="sm">` + children, which no AST heuristic matches without false positives)',
|
|
571
|
+
'C11 — a table/list stating its count when it is not a BasaltDataTable',
|
|
572
|
+
'C12 — one shape for refresh/sync (SyncButton); only the alias table sees a renamed copy',
|
|
573
|
+
],
|
|
574
|
+
description:
|
|
575
|
+
'The control tier (docs/CONTROLS-SPEC.md §3): FilterSet (nowrap row + measured +N fold + the mobile Filters (n) sheet), RangeFilter/CompareFilter/SelectFilter/MultiSelectFilter/NumberFilter/SearchFilter/ToggleFilter (each bound to a FieldHandle — no value/onChange/size, law C2/C5; NumberFilter is the field.number lane, a radio list over `options` or a stepper without), ViewTabs, and the action/sync family (ActionGroup, OverflowMenu, SyncButton, BarAction/GlobalAction). Every control owns its own desktop/mobile swap in CSS (C9) and renders size="ctl" internally. Resolves and renders with NO @mantine/dates installed — the custom date picker is injected through RangeFilter.customPicker from ./controls-dates.',
|
|
576
|
+
optionalPeers: [],
|
|
577
|
+
forbiddenImports: [],
|
|
578
|
+
},
|
|
579
|
+
'./controls-dates': {
|
|
580
|
+
kind: 'doctrine',
|
|
581
|
+
layer: 'mantine-coupled',
|
|
582
|
+
rule: 'controls',
|
|
583
|
+
skill: ['basalt-design'],
|
|
584
|
+
guardKinds: [],
|
|
585
|
+
pluginRules: [],
|
|
586
|
+
description:
|
|
587
|
+
"DateRangePicker — the @mantine/dates implementation of RangeFilter's customPicker seam. Its own subpath because @mantine/dates is an optional peer and basaltViteConfig pre-bundles the whole @mantine scope, so a consumer without the peer (linewatch) must never resolve it: nothing under src/controls may import it, statically or lazily (docs/CONTROLS-SPEC.md §3).",
|
|
588
|
+
optionalPeers: ['@mantine/dates'],
|
|
589
|
+
forbiddenImports: [],
|
|
590
|
+
},
|
|
426
591
|
'./state': {
|
|
427
592
|
kind: 'doctrine',
|
|
428
593
|
layer: 'headless',
|
|
429
594
|
rule: 'state',
|
|
430
595
|
skill: ['basalt-design'],
|
|
431
596
|
guardKinds: ['localstorage-theme'],
|
|
597
|
+
pluginRules: [],
|
|
432
598
|
description:
|
|
433
|
-
'createPersistedState (versioned localStorage) +
|
|
599
|
+
'createPersistedState (versioned localStorage) + the store field vocabulary (field.enum/multi/range/number/boolean/string, FieldHandle, lanes) + createLocalStore, the router-free store — Mantine-free state primitives',
|
|
434
600
|
optionalPeers: [],
|
|
435
601
|
// Consumers import basalt-ui/state from node_modules (lint-ignored), so there is nothing to
|
|
436
602
|
// enforce consumer-side, and a shipped **/state* glob would wrongly hit consumers' own
|
|
@@ -449,6 +615,7 @@ export const SURFACES = {
|
|
|
449
615
|
rule: 'mantine',
|
|
450
616
|
skill: ['basalt-app'],
|
|
451
617
|
guardKinds: [],
|
|
618
|
+
pluginRules: [],
|
|
452
619
|
description:
|
|
453
620
|
'ConnectivityProvider (aggregates browser online/offline, React Query onlineManager, SSE, and health-check pings into one status), useConnectivity, and ConnectivityIndicator — auto-mounted by BasaltProvider',
|
|
454
621
|
optionalPeers: [],
|
|
@@ -490,9 +657,10 @@ export const SURFACES = {
|
|
|
490
657
|
// synthetic global app-wide ban layer — the src/**+app/** glob
|
|
491
658
|
kind: 'doctrine',
|
|
492
659
|
layer: 'app-global',
|
|
493
|
-
rule: '
|
|
660
|
+
rule: 'batteries',
|
|
494
661
|
skill: ['basalt-app'],
|
|
495
662
|
guardKinds: [],
|
|
663
|
+
pluginRules: [],
|
|
496
664
|
globs: {
|
|
497
665
|
// Shipped is a catch-all (not just src/**+app/**) so consumer code under components/, lib/,
|
|
498
666
|
// features/, etc. is also covered. The @visx/*-only-in-charts and Mantine-free charts/tokens
|
|
@@ -523,7 +691,7 @@ export const SURFACES = {
|
|
|
523
691
|
|
|
524
692
|
/**
|
|
525
693
|
* Derived, deduped set of doctrine rule names. Projection 1 of SURFACES.
|
|
526
|
-
* → ['mantine', 'charts', 'tokens', '
|
|
694
|
+
* → ['mantine', 'charts', 'tokens', 'batteries', 'state', 'controls'] (order is insertion order of Set)
|
|
527
695
|
*
|
|
528
696
|
* @example
|
|
529
697
|
* RULE_NAMES.includes('tokens') // true
|
|
@@ -204,7 +204,8 @@ html[data-mantine-color-scheme] .inputWrapper[data-variant='default']:not([data-
|
|
|
204
204
|
/*
|
|
205
205
|
* Reduced motion drops the fade, never the shadow: a static shadow is not motion, and removing it
|
|
206
206
|
* would strip the very hierarchy this pass exists to establish from the users who asked for less
|
|
207
|
-
* animation. `
|
|
207
|
+
* animation. `default`/`filled`/`light`/`outline`'s hover depth still lands — it just lands
|
|
208
|
+
* instantly. `subtle` stays flat regardless, as it does in every other state (see above).
|
|
208
209
|
*/
|
|
209
210
|
@media (prefers-reduced-motion: reduce) {
|
|
210
211
|
.buttonRoot,
|
|
@@ -282,3 +283,17 @@ html[data-mantine-color-scheme] .tabsRoot {
|
|
|
282
283
|
html .tableRoot {
|
|
283
284
|
--table-border-color: var(--vx-surface-hairline);
|
|
284
285
|
}
|
|
286
|
+
|
|
287
|
+
/*
|
|
288
|
+
* The LAST row's separator is dropped — exactly the rule (and exactly the reasoning) the Accordion
|
|
289
|
+
* above already carries: a separator BETWEEN items is information, and the same line drawn after the
|
|
290
|
+
* final item is an outer border pretending to be one. It mattered more once `BasaltDataTable`'s
|
|
291
|
+
* `withTableBorder` went to `false` by default, because the two used to sit on top of each other and
|
|
292
|
+
* the doubling hid which of them was drawing the line.
|
|
293
|
+
*
|
|
294
|
+
* Scoped to `tbody`: a `tfoot` (a totals row) is separated FROM the body by the rule above it, which
|
|
295
|
+
* is a between rule and stays.
|
|
296
|
+
*/
|
|
297
|
+
html .tableRoot tbody tr:last-of-type {
|
|
298
|
+
border-bottom: none;
|
|
299
|
+
}
|