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
|
@@ -10,6 +10,7 @@ declare const classes: {
|
|
|
10
10
|
readonly brand: string
|
|
11
11
|
readonly brandLead: string
|
|
12
12
|
readonly brandName: string
|
|
13
|
+
readonly brandButton: string
|
|
13
14
|
readonly searchSlot: string
|
|
14
15
|
readonly navScroll: string
|
|
15
16
|
readonly navViewport: string
|
|
@@ -27,7 +28,24 @@ declare const classes: {
|
|
|
27
28
|
readonly sectionHeader: string
|
|
28
29
|
readonly subnavDropdown: string
|
|
29
30
|
readonly childList: string
|
|
30
|
-
readonly navExtra: string
|
|
31
31
|
readonly ghostIcon: string
|
|
32
|
+
readonly block: string
|
|
33
|
+
readonly blockHeader: string
|
|
34
|
+
readonly blockHeaderButton: string
|
|
35
|
+
readonly blockIcon: string
|
|
36
|
+
readonly blockDot: string
|
|
37
|
+
readonly blockItems: string
|
|
38
|
+
readonly blockRow: string
|
|
39
|
+
readonly blockRowStatic: string
|
|
40
|
+
readonly blockRowLabel: string
|
|
41
|
+
readonly blockRowMeta: string
|
|
42
|
+
readonly blockToneDot: string
|
|
43
|
+
readonly blockMore: string
|
|
44
|
+
readonly blockProgress: string
|
|
45
|
+
readonly blockProgressHead: string
|
|
46
|
+
readonly blockRing: string
|
|
47
|
+
readonly footerLinks: string
|
|
48
|
+
readonly footerIconSlot: string
|
|
49
|
+
readonly footerVersion: string
|
|
32
50
|
}
|
|
33
51
|
export default classes
|
package/dist/shell/index.d.ts
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import type { MouseEvent, ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
2
|
+
import type { GlobalAction } from '../controls/actions.js';
|
|
3
|
+
import type { AccountMenuItem, BasaltAccountProps } from './account-types.js';
|
|
4
|
+
import type { SidebarSearchActions, SidebarSearchConfig } from './sidebar-search.js';
|
|
5
|
+
import type { MobileNavConfig, SidebarBlock, SidebarSection } from '../nav/types.js';
|
|
5
6
|
export { AppSidebar, type AppSidebarProps } from './app-sidebar.js';
|
|
6
7
|
export { NavCountBadge } from './nav-count-badge.js';
|
|
7
|
-
export { SidebarSearch, type SidebarSearchConfig } from './sidebar-search.js';
|
|
8
|
+
export { SidebarSearch, type SidebarSearchConfig, type SidebarSearchActions, } from './sidebar-search.js';
|
|
8
9
|
export { SidebarAccount } from './app-sidebar-account.js';
|
|
9
10
|
export type { AccountBadgeTone, BasaltIdentity, BasaltRole, BasaltPlan, AccountMenuItem, BasaltAccountState, BasaltAccountActions, BasaltAccountProps, } from './account-types.js';
|
|
10
11
|
export { MobileNav, type MobileNavProps } from './app-mobile-nav.js';
|
|
11
12
|
export { projectMobileNav, type ProjectMobileNavOptions, MOBILE_MAX_TABS_DEFAULT, MOBILE_MENU_MAX_DEFAULT, MOBILE_MORE_KEY, } from './mobile-nav-model.js';
|
|
12
13
|
export { AppBreadcrumbs } from './app-breadcrumbs.js';
|
|
13
|
-
export {
|
|
14
|
+
export { PageBar, type PageBarProps } from './page-bar.js';
|
|
14
15
|
/**
|
|
15
16
|
* The shared nav vocabulary lives in `src/nav/types.ts` so the headless router bridge can `import
|
|
16
17
|
* type` it without reaching into the Mantine layer. Re-exported here so `SidebarItem` /
|
|
17
18
|
* `SidebarSection` keep resolving straight from `basalt-ui`, exactly as before.
|
|
18
19
|
*/
|
|
19
|
-
export type { NavAnchor, NavAnchorProps, NavMobilePlacement, NavSectionMobile, SidebarItem, SidebarSection, MobileNavConfig, MobileNavGroup, MobileNavModel, MobileNavSlot, MobileNavSurface, } from '../nav/types.js';
|
|
20
|
+
export type { NavAnchor, NavAnchorProps, NavMobilePlacement, NavSectionMobile, SidebarItem, SidebarSection, SidebarBlock, SidebarBlockItem, SidebarBlockTone, SidebarListBlock, SidebarProgressBlock, SidebarCustomBlock, MobileNavConfig, MobileNavGroup, MobileNavModel, MobileNavSlot, MobileNavSurface, } from '../nav/types.js';
|
|
20
21
|
/** Brand identity shown in the sidebar header (logo + name). */
|
|
21
22
|
export type BrandConfig = {
|
|
22
23
|
/** Display name (e.g. "Argo"). */
|
|
@@ -36,8 +37,13 @@ export type SettingsMenuItem = {
|
|
|
36
37
|
onClick?: (e: MouseEvent) => void;
|
|
37
38
|
};
|
|
38
39
|
export type BasaltShellProps = {
|
|
39
|
-
/**
|
|
40
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Brand identity for the sidebar header. Supplying `menu` turns the brand row into a `Name ▾`
|
|
42
|
+
* workspace switcher — the rows are `AccountMenuItem`s, the shape the account menu already uses.
|
|
43
|
+
*/
|
|
44
|
+
brand: BrandConfig & {
|
|
45
|
+
menu?: AccountMenuItem[];
|
|
46
|
+
};
|
|
41
47
|
/** Grouped nav sections — the ONE definition, rendered as the sidebar and projected to the bar. */
|
|
42
48
|
sections: SidebarSection[];
|
|
43
49
|
/**
|
|
@@ -45,28 +51,56 @@ export type BasaltShellProps = {
|
|
|
45
51
|
* configured still produces a working bar (see `projectMobileNav`'s zero-config fallback).
|
|
46
52
|
*/
|
|
47
53
|
mobileNav?: MobileNavConfig;
|
|
48
|
-
/** Persistent, shell-owned top-bar slot (timer, refresh, notifications). */
|
|
49
|
-
globalActions?: ReactNode;
|
|
50
54
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* `
|
|
55
|
-
* `
|
|
55
|
+
* Persistent, shell-owned header actions (timer, notifications, a global `SyncButton`) — DECLARED
|
|
56
|
+
* DATA, not a `ReactNode` slot, so basalt owns the mobile projection: the first two ride the bar,
|
|
57
|
+
* the rest fold into the header's single kebab (`mobile: 'bar' | 'more' | 'hidden'`, see
|
|
58
|
+
* `GlobalAction`). That kebab is the SAME one `PageBar`'s ROW 1 opens — a route whose bar has
|
|
59
|
+
* row-1 actions (or `filtersEnd`) lends it, any other route gets it from the shell. An
|
|
60
|
+
* `ActionGroup` a consumer mounts in some other home never inherits these rows.
|
|
61
|
+
*/
|
|
62
|
+
globalActions?: GlobalAction[];
|
|
63
|
+
/**
|
|
64
|
+
* Sidebar blocks — DECLARED DATA (law C13, `docs/CONTROLS-SPEC.md` §2.3), which replaced both
|
|
65
|
+
* `sidebarNavExtra` and `mobileNav.moreExtra`. `placement: 'nav'` (the default for `list` and
|
|
66
|
+
* `custom`) appends after the nav sections inside the scroll region; `'bottom'` pins above the
|
|
67
|
+
* settings footer.
|
|
68
|
+
*
|
|
69
|
+
* Because they are data, basalt owns the projections the two `ReactNode` slots could not express:
|
|
70
|
+
* a `list` with a `count` becomes a dot on its icon in the collapsed rail, a `progress` block
|
|
71
|
+
* becomes a ring on the settings row, and a block with `mobile: 'more'` becomes one More-sheet
|
|
72
|
+
* row opening a nested sheet of its items. A `kind: 'custom'` block is desktop-only, exactly as
|
|
73
|
+
* `sidebarNavExtra` was.
|
|
74
|
+
*/
|
|
75
|
+
sidebarBlocks?: SidebarBlock[];
|
|
76
|
+
/**
|
|
77
|
+
* Entries appended to the sidebar settings footer — flat link rows at three or fewer, one gear
|
|
78
|
+
* menu at four or more (`AppSidebarProps.settingsMenuItems` documents the threshold).
|
|
56
79
|
*/
|
|
57
|
-
sidebarNavExtra?: ReactNode;
|
|
58
|
-
/** Entries appended to the sidebar settings menu. */
|
|
59
80
|
settingsMenuItems?: SettingsMenuItem[];
|
|
60
81
|
/**
|
|
61
|
-
*
|
|
82
|
+
* Forces the footer form instead of taking the count rule above: `'flat'` always renders link
|
|
83
|
+
* rows, `'menu'` always renders the gear dropdown. `'auto'` (the default) is today's ≤3 → flat
|
|
84
|
+
* behaviour. Reach for it when the rows are CONTROLS rather than destinations — three of those
|
|
85
|
+
* (a theme radio group, a devtools switch) read as a widget pile in the footer even though the
|
|
86
|
+
* count says flat. Full rationale on `AppSidebarProps.settingsMenu`.
|
|
87
|
+
*
|
|
88
|
+
* @default 'auto'
|
|
89
|
+
*/
|
|
90
|
+
settingsMenu?: 'auto' | 'flat' | 'menu';
|
|
91
|
+
/**
|
|
92
|
+
* Optional account row rendered below the settings menu in the sidebar footer (see
|
|
62
93
|
* `SidebarAccount` / `BasaltAccountProps`). Omitting it reproduces today's footer unchanged.
|
|
63
94
|
*/
|
|
64
95
|
account?: BasaltAccountProps;
|
|
65
96
|
/**
|
|
66
97
|
* Optional search field below the brand in the sidebar (fixed, above the nav scroll). Supply
|
|
67
|
-
* `onOpen`, e.g. `() => openSpotlight()` from basalt-ui/commands.
|
|
98
|
+
* `onOpen`, e.g. `() => openSpotlight()` from basalt-ui/commands. `actions` adds one or two
|
|
99
|
+
* icon-only buttons to the right of that row (a tuple by type — see `SidebarSearchActions`).
|
|
68
100
|
*/
|
|
69
|
-
search?: SidebarSearchConfig
|
|
101
|
+
search?: SidebarSearchConfig & {
|
|
102
|
+
actions?: SidebarSearchActions;
|
|
103
|
+
};
|
|
70
104
|
/**
|
|
71
105
|
* localStorage key for the persisted sidebar-collapsed flag. Ignored when `collapsed` is set.
|
|
72
106
|
*
|
|
@@ -92,5 +126,5 @@ export type BasaltShellProps = {
|
|
|
92
126
|
/** Page content. */
|
|
93
127
|
children?: ReactNode;
|
|
94
128
|
};
|
|
95
|
-
export declare function BasaltShell({ brand, sections, mobileNav, globalActions,
|
|
129
|
+
export declare function BasaltShell({ brand, sections, mobileNav, globalActions, sidebarBlocks, settingsMenuItems, settingsMenu, storageKey, collapsed: collapsedProp, onCollapsedChange, account, search, children, }: BasaltShellProps): import("react").JSX.Element;
|
|
96
130
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shell/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shell/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAOlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACjF,OAAO,KAAK,EACV,eAAe,EAEf,YAAY,EAEZ,cAAc,EACf,MAAM,cAAc,CAAA;AAMrB,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjE,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAA;AAEvD;;;;GAIG;AACH,YAAY,EACV,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAA;AAErB,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG;IACxB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,6DAA6D;AAC7D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,KAAK,EAAE,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,CAAA;IACjD,mGAAmG;IACnG,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACtC;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IACvC;;;OAGG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B;;;;OAIG;IACH,MAAM,CAAC,EAAE,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAA;IACjE;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IAChD,oBAAoB;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB,CAAA;AAgGD,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,SAAS,EACT,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,UAAuC,EACvC,SAAS,EAAE,aAAa,EACxB,iBAAiB,EACjB,OAAO,EACP,MAAM,EACN,QAAQ,GACT,EAAE,gBAAgB,+BAiGlB"}
|
package/dist/shell/index.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AppShell } from "@mantine/core";
|
|
3
|
-
import { useMemo } from "react";
|
|
2
|
+
import { AppShell, Box } from "@mantine/core";
|
|
3
|
+
import { Fragment, useMemo } from "react";
|
|
4
4
|
import { AppSidebar } from "./app-sidebar.js";
|
|
5
5
|
import { MobileNav, accountRowCount } from "./app-mobile-nav.js";
|
|
6
|
-
import { projectMobileNav } from "./mobile-nav-model.js";
|
|
6
|
+
import { blockRowCount, projectMobileNav } from "./mobile-nav-model.js";
|
|
7
7
|
import { AppBreadcrumbs } from "./app-breadcrumbs.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { PageBarOutlet, PageBarProvider, usePageKebabClaimed } from "./page-bar.js";
|
|
9
|
+
import { OverflowMenu, globalActionAsBarAction, globalActionMobile } from "../controls/actions.js";
|
|
10
|
+
import { CtlSlot, useBasaltSpacing } from "../theme/index.js";
|
|
10
11
|
import { createPersistedState } from "../state.js";
|
|
11
12
|
import headerClasses from "./app-header.module.css";
|
|
12
13
|
import mobileNavClasses from "./app-mobile-nav.module.css";
|
|
13
14
|
import { AppSidebar as AppSidebar2 } from "./app-sidebar.js";
|
|
14
15
|
import { NavCountBadge } from "./nav-count-badge.js";
|
|
15
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
SidebarSearch
|
|
18
|
+
} from "./sidebar-search.js";
|
|
16
19
|
import { SidebarAccount } from "./app-sidebar-account.js";
|
|
17
20
|
import { MobileNav as MobileNav2 } from "./app-mobile-nav.js";
|
|
18
21
|
import {
|
|
@@ -22,7 +25,7 @@ import {
|
|
|
22
25
|
MOBILE_MORE_KEY
|
|
23
26
|
} from "./mobile-nav-model.js";
|
|
24
27
|
import { AppBreadcrumbs as AppBreadcrumbs2 } from "./app-breadcrumbs.js";
|
|
25
|
-
import {
|
|
28
|
+
import { PageBar } from "./page-bar.js";
|
|
26
29
|
function findActiveCrumb(sections) {
|
|
27
30
|
for (const section of sections) {
|
|
28
31
|
const found = findActiveWithParent(section.items);
|
|
@@ -74,8 +77,9 @@ function BasaltShell({
|
|
|
74
77
|
sections,
|
|
75
78
|
mobileNav,
|
|
76
79
|
globalActions,
|
|
77
|
-
|
|
80
|
+
sidebarBlocks,
|
|
78
81
|
settingsMenuItems,
|
|
82
|
+
settingsMenu,
|
|
79
83
|
storageKey = "basalt-sidebar-collapsed",
|
|
80
84
|
collapsed: collapsedProp,
|
|
81
85
|
onCollapsedChange,
|
|
@@ -93,18 +97,19 @@ function BasaltShell({
|
|
|
93
97
|
onCollapsedChange?.(next);
|
|
94
98
|
};
|
|
95
99
|
const activeCrumb = findActiveCrumb(sections);
|
|
96
|
-
const extraMoreRows = accountRowCount(account) + (settingsMenuItems?.length ?? 0) + (
|
|
100
|
+
const extraMoreRows = accountRowCount(account) + (settingsMenuItems?.length ?? 0) + blockRowCount(sidebarBlocks);
|
|
97
101
|
const model = useMemo(
|
|
98
102
|
() => projectMobileNav(sections, { config: mobileNav, extraMoreRows }),
|
|
99
103
|
[sections, mobileNav, extraMoreRows]
|
|
100
104
|
);
|
|
101
|
-
return /* @__PURE__ */ jsx(
|
|
105
|
+
return /* @__PURE__ */ jsx(PageBarProvider, { globalActions: globalActions ?? [], children: /* @__PURE__ */ jsxs(
|
|
102
106
|
AppShell,
|
|
103
107
|
{
|
|
104
108
|
h: "100dvh",
|
|
105
109
|
layout: "alt",
|
|
106
110
|
header: {
|
|
107
|
-
height
|
|
111
|
+
// ONE height at every width (law C14): nothing reserves a second mobile row any more.
|
|
112
|
+
height: step.appShellHeaderHeight
|
|
108
113
|
},
|
|
109
114
|
navbar: {
|
|
110
115
|
width: {
|
|
@@ -120,8 +125,8 @@ function BasaltShell({
|
|
|
120
125
|
children: [
|
|
121
126
|
/* @__PURE__ */ jsx(AppShell.Header, { px: "md", withBorder: false, children: /* @__PURE__ */ jsxs("div", { className: headerClasses.bar, children: [
|
|
122
127
|
/* @__PURE__ */ jsx("div", { className: headerClasses.lead, children: /* @__PURE__ */ jsx(AppBreadcrumbs, { ...activeCrumb }) }),
|
|
123
|
-
/* @__PURE__ */ jsx(
|
|
124
|
-
|
|
128
|
+
/* @__PURE__ */ jsx(PageBarOutlet, { className: headerClasses.pageBar }),
|
|
129
|
+
/* @__PURE__ */ jsx(HeaderGlobalActions, { actions: globalActions ?? [] })
|
|
125
130
|
] }) }),
|
|
126
131
|
/* @__PURE__ */ jsx(AppShell.Navbar, { p: 0, withBorder: false, children: /* @__PURE__ */ jsx(
|
|
127
132
|
AppSidebar,
|
|
@@ -130,8 +135,9 @@ function BasaltShell({
|
|
|
130
135
|
sections,
|
|
131
136
|
collapsed,
|
|
132
137
|
onToggleCollapse: toggleCollapse,
|
|
133
|
-
|
|
138
|
+
...sidebarBlocks !== void 0 && { blocks: sidebarBlocks },
|
|
134
139
|
...settingsMenuItems !== void 0 && { settingsMenuItems },
|
|
140
|
+
...settingsMenu !== void 0 && { settingsMenu },
|
|
135
141
|
...account !== void 0 && { account },
|
|
136
142
|
...search !== void 0 && { search }
|
|
137
143
|
}
|
|
@@ -143,13 +149,31 @@ function BasaltShell({
|
|
|
143
149
|
model,
|
|
144
150
|
config: mobileNav,
|
|
145
151
|
...account !== void 0 && { account },
|
|
146
|
-
...settingsMenuItems !== void 0 && { settingsMenuItems }
|
|
152
|
+
...settingsMenuItems !== void 0 && { settingsMenuItems },
|
|
153
|
+
...sidebarBlocks !== void 0 && { blocks: sidebarBlocks }
|
|
147
154
|
}
|
|
148
155
|
) })
|
|
149
156
|
]
|
|
150
157
|
}
|
|
151
158
|
) });
|
|
152
159
|
}
|
|
160
|
+
function HeaderGlobalActions({ actions }) {
|
|
161
|
+
const kebabClaimed = usePageKebabClaimed();
|
|
162
|
+
if (actions.length === 0) return null;
|
|
163
|
+
const more = actions.filter((action, index) => globalActionMobile(action, index) === "more").map(globalActionAsBarAction);
|
|
164
|
+
return (
|
|
165
|
+
// `CtlSlot` here for the same reason a home wraps its own slot (law C5): `globalActions` are
|
|
166
|
+
// consumer NODES, so basalt cannot pass them a size — it can only provide the tier they resolve
|
|
167
|
+
// against. Without it a `<NotificationBell/>`'s internal `ActionIcon` fell back to Mantine's
|
|
168
|
+
// `md` (28px) beside a 30px page group.
|
|
169
|
+
/* @__PURE__ */ jsx(CtlSlot, { children: /* @__PURE__ */ jsxs("div", { className: headerClasses.global, children: [
|
|
170
|
+
actions.map(
|
|
171
|
+
(action, index) => globalActionMobile(action, index) === "bar" ? /* @__PURE__ */ jsx(Fragment, { children: action.node }, action.key) : /* @__PURE__ */ jsx(Box, { visibleFrom: "sm", children: action.node }, action.key)
|
|
172
|
+
),
|
|
173
|
+
!kebabClaimed && more.length > 0 && /* @__PURE__ */ jsx(Box, { hiddenFrom: "sm", children: /* @__PURE__ */ jsx(OverflowMenu, { actions: more, trigger: "kebab", label: "More actions" }) })
|
|
174
|
+
] }) })
|
|
175
|
+
);
|
|
176
|
+
}
|
|
153
177
|
export {
|
|
154
178
|
AppBreadcrumbs2 as AppBreadcrumbs,
|
|
155
179
|
AppSidebar2 as AppSidebar,
|
|
@@ -159,9 +183,7 @@ export {
|
|
|
159
183
|
MOBILE_MORE_KEY,
|
|
160
184
|
MobileNav2 as MobileNav,
|
|
161
185
|
NavCountBadge,
|
|
162
|
-
|
|
163
|
-
PageActionsOutlet2 as PageActionsOutlet,
|
|
164
|
-
PageHeaderProvider2 as PageHeaderProvider,
|
|
186
|
+
PageBar,
|
|
165
187
|
SidebarAccount,
|
|
166
188
|
SidebarSearch,
|
|
167
189
|
projectMobileNav2 as projectMobileNav
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* ever rendering below the fold (6 x 44px + 8px padding = 272px against 415px of headroom on the
|
|
14
14
|
* smallest supported viewport), so past that the surface becomes a bottom sheet.
|
|
15
15
|
*/
|
|
16
|
-
import type { MobileNavConfig, MobileNavModel, SidebarSection } from '../nav/types.js';
|
|
16
|
+
import type { MobileNavConfig, MobileNavModel, SidebarBlock, SidebarSection } from '../nav/types.js';
|
|
17
17
|
/** Hard cap on bar slots, INCLUDING More. Five 72px slots is the widest a 360px viewport holds. */
|
|
18
18
|
export declare const MOBILE_MAX_TABS_DEFAULT = 5;
|
|
19
19
|
/**
|
|
@@ -27,12 +27,23 @@ export declare const MOBILE_MORE_KEY = "__more";
|
|
|
27
27
|
export type ProjectMobileNavOptions = {
|
|
28
28
|
config?: MobileNavConfig | undefined;
|
|
29
29
|
/**
|
|
30
|
-
* Extra rows the More surface will hold — account + settings +
|
|
30
|
+
* Extra rows the More surface will hold — account + settings + sidebar blocks. Drives both
|
|
31
31
|
* `needsMore` and the menu-vs-sheet threshold. The model cannot see those rows (they are
|
|
32
32
|
* Mantine-rendered chrome, not `SidebarItem`s), so the shell counts them and passes the total.
|
|
33
33
|
*/
|
|
34
34
|
extraMoreRows?: number;
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* How many More-surface rows `blocks` contribute — the `accountRowCount` sibling for sidebar
|
|
38
|
+
* blocks, and for the same reason: `BasaltShell` needs the number BEFORE the projection runs (it
|
|
39
|
+
* feeds `extraMoreRows`, which picks `menu` vs `sheet` against `menuMax`) while the renderer is
|
|
40
|
+
* what decides how many rows a block actually becomes.
|
|
41
|
+
*
|
|
42
|
+
* ONE row per block, never one per item: a list block projects to a single `Awaiting action · 3`
|
|
43
|
+
* row that opens a nested sheet of its items. Counting the items instead would push a 12-item
|
|
44
|
+
* block's More surface to a sheet on the strength of rows that surface never paints.
|
|
45
|
+
*/
|
|
46
|
+
export declare function blockRowCount(blocks: readonly SidebarBlock[] | undefined): number;
|
|
36
47
|
/**
|
|
37
48
|
* Projects `sections` onto the bar. Implements §2.3's thirteen rules in order, and is the ONLY
|
|
38
49
|
* place slot selection happens — `MobileNav` receives a finished model and paints it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobile-nav-model.d.ts","sourceRoot":"","sources":["../../src/shell/mobile-nav-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,
|
|
1
|
+
{"version":3,"file":"mobile-nav-model.d.ts","sourceRoot":"","sources":["../../src/shell/mobile-nav-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EAGd,YAAY,EAEZ,cAAc,EACf,MAAM,cAAc,CAAA;AAGrB,mGAAmG;AACnG,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,iGAAiG;AACjG,eAAO,MAAM,eAAe,WAAW,CAAA;AAEvC,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACpC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,GAAG,MAAM,CAQjF;AAgSD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,cAAc,EAAE,EAC1B,IAAI,CAAC,EAAE,uBAAuB,GAC7B,cAAc,CA2EhB"}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { sidebarBlockMobile } from "./sidebar-block-model.js";
|
|
1
2
|
const MOBILE_MAX_TABS_DEFAULT = 5;
|
|
2
3
|
const MOBILE_MENU_MAX_DEFAULT = 6;
|
|
3
4
|
const MOBILE_MORE_KEY = "__more";
|
|
5
|
+
function blockRowCount(blocks) {
|
|
6
|
+
if (blocks === void 0) return 0;
|
|
7
|
+
return blocks.filter((block) => {
|
|
8
|
+
if (sidebarBlockMobile(block) !== "more") return false;
|
|
9
|
+
return block.kind !== "list" || block.items.length > 0;
|
|
10
|
+
}).length;
|
|
11
|
+
}
|
|
4
12
|
const DEV = process.env["NODE_ENV"] !== "production";
|
|
5
13
|
function placementOf(item, sectionHidden) {
|
|
6
14
|
if (sectionHidden) return "hidden";
|
|
@@ -17,6 +25,9 @@ function hasActiveDestination(item) {
|
|
|
17
25
|
if (item.active) return true;
|
|
18
26
|
return item.children?.some(hasActiveDestination) ?? false;
|
|
19
27
|
}
|
|
28
|
+
function isActiveDestination(item) {
|
|
29
|
+
return item.active === true;
|
|
30
|
+
}
|
|
20
31
|
function countRows(items) {
|
|
21
32
|
return items.reduce((total, item) => total + 1 + countRows(item.children ?? []), 0);
|
|
22
33
|
}
|
|
@@ -51,13 +62,15 @@ function itemCandidate(item) {
|
|
|
51
62
|
return {
|
|
52
63
|
key: item.key,
|
|
53
64
|
covered: /* @__PURE__ */ new Set([item.key]),
|
|
65
|
+
// `isActiveDestination`, not the rollup: this slot COVERS one key, so it reads one key
|
|
66
|
+
// (`hasActiveDestination`'s doc has the whole accounting).
|
|
54
67
|
toSlot: () => ({
|
|
55
68
|
kind: "link",
|
|
56
69
|
key: item.key,
|
|
57
70
|
label: item.label,
|
|
58
71
|
short: item.short ?? item.label,
|
|
59
72
|
icon: item.icon,
|
|
60
|
-
active:
|
|
73
|
+
active: isActiveDestination(item),
|
|
61
74
|
item
|
|
62
75
|
})
|
|
63
76
|
};
|
|
@@ -240,5 +253,6 @@ export {
|
|
|
240
253
|
MOBILE_MAX_TABS_DEFAULT,
|
|
241
254
|
MOBILE_MENU_MAX_DEFAULT,
|
|
242
255
|
MOBILE_MORE_KEY,
|
|
256
|
+
blockRowCount,
|
|
243
257
|
projectMobileNav
|
|
244
258
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sidebar nav count badge (docs/DESIGN-SPEC.md §5): mono
|
|
2
|
+
* Sidebar nav count badge (docs/DESIGN-SPEC.md §5): mono micro (11px), ink-8% bg, radius 5, height 16,
|
|
3
3
|
* padding 0 5px, muted text; `marginLeft: auto` pins it to the row end on any render path.
|
|
4
4
|
* `styles` (inline) rather than a token color prop, since none of Mantine's variant/color
|
|
5
5
|
* combinations land on the ink-tint idiom. Returns `null` for a zero/empty count so the badge slot
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ActionGroupProps, BarAction, GlobalAction } from '../controls/actions.js';
|
|
3
|
+
import type { SyncButtonProps } from '../controls/sync-button.js';
|
|
4
|
+
/** The custom property row 2's measured height is published on. */
|
|
5
|
+
export declare const PAGE_BAR_HEIGHT_VAR = "--basalt-page-bar-h";
|
|
6
|
+
/**
|
|
7
|
+
* Internal — mounted by `BasaltShell`. Owns the portal target, and the single-kebab claim that
|
|
8
|
+
* lets the shell fall back to its OWN kebab on a route that renders no `PageBar`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function PageBarProvider({ globalActions, children, }: {
|
|
11
|
+
globalActions: readonly GlobalAction[];
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}): ReactNode;
|
|
14
|
+
/** Internal — the app-shell header node the active page's row 1 portals into. */
|
|
15
|
+
export declare function PageBarOutlet({ className }: {
|
|
16
|
+
className?: string;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
/** Internal — `true` while a page's `ActionGroup` owns the header's one mobile kebab. */
|
|
19
|
+
export declare function usePageKebabClaimed(): boolean;
|
|
20
|
+
export type PageBarProps = {
|
|
21
|
+
/**
|
|
22
|
+
* Read only when there is no `BasaltShell` outlet (a shell-less app such as linewatch). Inside a
|
|
23
|
+
* shell the breadcrumb names the page and this is ignored.
|
|
24
|
+
*/
|
|
25
|
+
title?: string;
|
|
26
|
+
icon?: ReactNode;
|
|
27
|
+
actions?: ActionGroupProps;
|
|
28
|
+
/** `scope` is fixed to `'page'` — a global sync belongs in the shell's `globalActions` (law C12). */
|
|
29
|
+
sync?: Omit<SyncButtonProps, 'scope'>;
|
|
30
|
+
/** `FilterSet` descendants only (law C1). */
|
|
31
|
+
filters?: ReactNode;
|
|
32
|
+
/** Right-aligned row-2 actions ("Manage metrics"). */
|
|
33
|
+
filtersEnd?: BarAction[];
|
|
34
|
+
/** One `ViewTabs`. */
|
|
35
|
+
tabs?: ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Added to the bar's ROOT — the shell-less `<div data-basalt-page-bar="standalone">`, or row 2's
|
|
38
|
+
* sticky wrapper (`data-basalt-page-bar="shell"`) inside a `BasaltShell`. The seam for the two
|
|
39
|
+
* things only the consumer's own layout knows: bleeding the sticky bar across its container's
|
|
40
|
+
* gutters (`margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter)`) and drawing
|
|
41
|
+
* a hairline under it (`border-bottom: 1px solid var(--vx-surface-hairline)`).
|
|
42
|
+
*
|
|
43
|
+
* Scope that CSS through this class, not through a global `[data-basalt-page-bar]` selector: the
|
|
44
|
+
* data attributes are stable enough to READ (a shell-less consumer can style
|
|
45
|
+
* `[data-basalt-page-bar="standalone"]` in a pinch, and this doc is the promise that the value
|
|
46
|
+
* stays), but a global rule reaches every page in the app including the ones that want neither.
|
|
47
|
+
*/
|
|
48
|
+
className?: string;
|
|
49
|
+
};
|
|
50
|
+
export declare function PageBar({ title, icon, actions, sync, filters, filtersEnd, tabs, className, }: PageBarProps): ReactNode;
|
|
51
|
+
//# sourceMappingURL=page-bar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-bar.d.ts","sourceRoot":"","sources":["../../src/shell/page-bar.tsx"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,OAAO,CAAA;AAKjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAG9D,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,wBAAwB,CAAA;AA0BxD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,aAAa,EACb,QAAQ,GACT,EAAE;IACD,aAAa,EAAE,SAAS,YAAY,EAAE,CAAA;IACtC,QAAQ,EAAE,SAAS,CAAA;CACpB,GAAG,SAAS,CA2BZ;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAGlE;AAED,yFAAyF;AACzF,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B,qGAAqG;IACrG,IAAI,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAA;IACrC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,sDAAsD;IACtD,UAAU,CAAC,EAAE,SAAS,EAAE,CAAA;IACxB,sBAAsB;IACtB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AA2DD,wBAAgB,OAAO,CAAC,EACtB,KAAK,EACL,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,OAAO,EACP,UAAU,EACV,IAAI,EACJ,SAAS,GACV,EAAE,YAAY,GAAG,SAAS,CAmG1B"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
useCallback,
|
|
5
|
+
useContext,
|
|
6
|
+
useEffect,
|
|
7
|
+
useLayoutEffect,
|
|
8
|
+
useRef,
|
|
9
|
+
useState
|
|
10
|
+
} from "react";
|
|
11
|
+
import { createPortal } from "react-dom";
|
|
12
|
+
import { CtlSlot } from "../theme/index.js";
|
|
13
|
+
import { BarActionRow, BarExtrasProvider, globalActionAsBarAction } from "../controls/actions.js";
|
|
14
|
+
import { SyncButton } from "../controls/sync-button.js";
|
|
15
|
+
import classes from "./page-bar.module.css";
|
|
16
|
+
const PAGE_BAR_HEIGHT_VAR = "--basalt-page-bar-h";
|
|
17
|
+
const NO_SLOTS = {
|
|
18
|
+
target: null,
|
|
19
|
+
setTarget: () => {
|
|
20
|
+
},
|
|
21
|
+
inShell: false,
|
|
22
|
+
mobileMoreActions: [],
|
|
23
|
+
kebabClaims: 0,
|
|
24
|
+
claimKebab: () => () => {
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const PageBarContext = createContext(NO_SLOTS);
|
|
28
|
+
function PageBarProvider({
|
|
29
|
+
globalActions,
|
|
30
|
+
children
|
|
31
|
+
}) {
|
|
32
|
+
const [target, setTarget] = useState(null);
|
|
33
|
+
const [kebabClaims, setKebabClaims] = useState(0);
|
|
34
|
+
const claimKebab = useCallback(() => {
|
|
35
|
+
setKebabClaims((n) => n + 1);
|
|
36
|
+
return () => setKebabClaims((n) => n - 1);
|
|
37
|
+
}, []);
|
|
38
|
+
const mobileMoreActions = globalActions.filter((action, index) => (action.mobile ?? (index < 2 ? "bar" : "more")) === "more").map(globalActionAsBarAction);
|
|
39
|
+
const value = {
|
|
40
|
+
target,
|
|
41
|
+
setTarget,
|
|
42
|
+
inShell: true,
|
|
43
|
+
mobileMoreActions,
|
|
44
|
+
kebabClaims,
|
|
45
|
+
claimKebab
|
|
46
|
+
};
|
|
47
|
+
return /* @__PURE__ */ jsx(PageBarContext.Provider, { value, children: /* @__PURE__ */ jsx(BarExtrasProvider, { value: { mobileMoreActions, claimKebab }, children }) });
|
|
48
|
+
}
|
|
49
|
+
function PageBarOutlet({ className }) {
|
|
50
|
+
const { setTarget } = useContext(PageBarContext);
|
|
51
|
+
return /* @__PURE__ */ jsx("div", { ref: setTarget, className });
|
|
52
|
+
}
|
|
53
|
+
function usePageKebabClaimed() {
|
|
54
|
+
return useContext(PageBarContext).kebabClaims > 0;
|
|
55
|
+
}
|
|
56
|
+
const useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
57
|
+
function useMeasuredHeightVar(active) {
|
|
58
|
+
const ref = useRef(null);
|
|
59
|
+
useIsomorphicLayoutEffect(() => {
|
|
60
|
+
const node = ref.current;
|
|
61
|
+
if (!active || node === null) return;
|
|
62
|
+
const publish = () => {
|
|
63
|
+
const { height } = node.getBoundingClientRect();
|
|
64
|
+
if (height > 0) {
|
|
65
|
+
document.documentElement.style.setProperty(PAGE_BAR_HEIGHT_VAR, `${height}px`);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
publish();
|
|
69
|
+
if (typeof ResizeObserver === "undefined") {
|
|
70
|
+
return () => document.documentElement.style.removeProperty(PAGE_BAR_HEIGHT_VAR);
|
|
71
|
+
}
|
|
72
|
+
const observer = new ResizeObserver(publish);
|
|
73
|
+
observer.observe(node);
|
|
74
|
+
return () => {
|
|
75
|
+
observer.disconnect();
|
|
76
|
+
document.documentElement.style.removeProperty(PAGE_BAR_HEIGHT_VAR);
|
|
77
|
+
};
|
|
78
|
+
}, [active]);
|
|
79
|
+
return ref;
|
|
80
|
+
}
|
|
81
|
+
function rootClass(own, extra) {
|
|
82
|
+
return [own, extra].filter(Boolean).join(" ");
|
|
83
|
+
}
|
|
84
|
+
function PageBar({
|
|
85
|
+
title,
|
|
86
|
+
icon,
|
|
87
|
+
actions,
|
|
88
|
+
sync,
|
|
89
|
+
filters,
|
|
90
|
+
filtersEnd,
|
|
91
|
+
tabs,
|
|
92
|
+
className
|
|
93
|
+
}) {
|
|
94
|
+
const { target, inShell } = useContext(PageBarContext);
|
|
95
|
+
const filtersEndActions = filtersEnd ?? [];
|
|
96
|
+
const hasRow2 = tabs !== void 0 || filters !== void 0 || filtersEndActions.length > 0;
|
|
97
|
+
const hasLead = !inShell && (title !== void 0 || icon !== void 0);
|
|
98
|
+
const hasRow1 = actions !== void 0 || sync !== void 0 || hasLead || filtersEndActions.length > 0;
|
|
99
|
+
const measureRef = useMeasuredHeightVar(hasRow2 || !inShell && hasRow1);
|
|
100
|
+
const row1 = hasRow1 ? /* @__PURE__ */ jsxs("div", { className: classes.row1, children: [
|
|
101
|
+
hasLead && /* @__PURE__ */ jsxs("div", { className: classes.lead, children: [
|
|
102
|
+
icon !== void 0 && /* @__PURE__ */ jsx("span", { className: classes.icon, "aria-hidden": true, children: icon }),
|
|
103
|
+
title !== void 0 && /* @__PURE__ */ jsx("h1", { className: classes.title, children: title })
|
|
104
|
+
] }),
|
|
105
|
+
/* @__PURE__ */ jsx("div", { className: classes.row1End, children: (actions !== void 0 || filtersEndActions.length > 0 || sync !== void 0) && /* @__PURE__ */ jsx(CtlSlot, { children: /* @__PURE__ */ jsx(
|
|
106
|
+
BarActionRow,
|
|
107
|
+
{
|
|
108
|
+
...actions,
|
|
109
|
+
host: "page",
|
|
110
|
+
mobileOnly: filtersEndActions,
|
|
111
|
+
...sync !== void 0 && { syncNode: /* @__PURE__ */ jsx(SyncButton, { ...sync, scope: "page" }) }
|
|
112
|
+
}
|
|
113
|
+
) }) })
|
|
114
|
+
] }) : null;
|
|
115
|
+
const row2 = hasRow2 ? /* @__PURE__ */ jsxs("div", { className: classes.row2, children: [
|
|
116
|
+
tabs !== void 0 && /* @__PURE__ */ jsx(CtlSlot, { children: tabs }),
|
|
117
|
+
filters !== void 0 && /* @__PURE__ */ jsx("div", { className: classes.filters, children: /* @__PURE__ */ jsx(CtlSlot, { children: filters }) }),
|
|
118
|
+
filtersEndActions.length > 0 && /* @__PURE__ */ jsx("div", { className: classes.filtersEnd, children: /* @__PURE__ */ jsx(CtlSlot, { children: /* @__PURE__ */ jsx(BarActionRow, { secondary: filtersEndActions, host: "slot", viewport: "desktop" }) }) })
|
|
119
|
+
] }) : null;
|
|
120
|
+
if (!inShell) {
|
|
121
|
+
if (row1 === null && row2 === null) return null;
|
|
122
|
+
return /* @__PURE__ */ jsxs(
|
|
123
|
+
"div",
|
|
124
|
+
{
|
|
125
|
+
ref: measureRef,
|
|
126
|
+
className: rootClass(classes.bar, className),
|
|
127
|
+
"data-basalt-page-bar": "standalone",
|
|
128
|
+
children: [
|
|
129
|
+
row1,
|
|
130
|
+
row2
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
136
|
+
row1 !== null && target !== null && createPortal(row1, target),
|
|
137
|
+
row2 !== null && /* @__PURE__ */ jsx(
|
|
138
|
+
"div",
|
|
139
|
+
{
|
|
140
|
+
ref: measureRef,
|
|
141
|
+
className: rootClass(classes.row2Sticky, className),
|
|
142
|
+
"data-basalt-page-bar": "shell",
|
|
143
|
+
children: row2
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
] });
|
|
147
|
+
}
|
|
148
|
+
export {
|
|
149
|
+
PAGE_BAR_HEIGHT_VAR,
|
|
150
|
+
PageBar,
|
|
151
|
+
PageBarOutlet,
|
|
152
|
+
PageBarProvider,
|
|
153
|
+
usePageKebabClaimed
|
|
154
|
+
};
|