basalt-ui 2.0.2 → 2.0.3
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/CHANGELOG.md +9 -0
- package/MIGRATING.md +35 -28
- package/configs/check.yml +5 -5
- package/dist/cli/doctor-upgrade.d.ts +1 -1
- package/dist/cli/doctor-upgrade.d.ts.map +1 -1
- package/dist/cli/doctor-upgrade.js +36 -1
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +17 -2
- package/dist/provider/index.d.ts +8 -1
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +3 -2
- package/dist/provider/spotlight-actions.d.ts +3 -2
- package/dist/provider/spotlight-actions.d.ts.map +1 -1
- package/dist/provider/spotlight-actions.js +5 -3
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +9 -2
- package/dist/shell/app-sidebar.module.css +6 -0
- package/dist/shell/app-sidebar.module.css.d.ts +1 -0
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/cli/doctor-upgrade.ts +49 -2
- package/src/cli/index.ts +31 -4
- package/src/provider/index.tsx +10 -2
- package/src/provider/spotlight-actions.tsx +8 -3
- package/src/shell/app-sidebar.module.css +6 -0
- package/src/shell/app-sidebar.module.css.d.ts +1 -0
- package/src/shell/app-sidebar.tsx +16 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [2.0.3](https://github.com/jkrumm/basalt-ui/compare/v2.0.2...v2.0.3) (2026-10-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* follow the router import in app-wiring and let CI run make check ([47b6152](https://github.com/jkrumm/basalt-ui/commit/47b61526ab3ae959c1d9e4595916782defb0454f))
|
|
7
|
+
* label the provider's nav commands and drop duplicate nav entries ([08ec6ee](https://github.com/jkrumm/basalt-ui/commit/08ec6eef320f1ae8e072584c48a903f672222364))
|
|
8
|
+
* show nav badges in the collapsed rail ([5e09ea0](https://github.com/jkrumm/basalt-ui/commit/5e09ea07f05822f853c118a19c2cf72fe593501a))
|
|
9
|
+
|
|
1
10
|
## [2.0.2](https://github.com/jkrumm/basalt-ui/compare/v2.0.1...v2.0.2) (2026-10-14)
|
|
2
11
|
|
|
3
12
|
|
package/MIGRATING.md
CHANGED
|
@@ -66,18 +66,18 @@ There is one row per SURFACE, not per export, and a surface earns a row once any
|
|
|
66
66
|
shipped lefthook preset both changed in 1.30.0 with no row that owned them — which is how a
|
|
67
67
|
consumer read this index, found nothing, and diffed a KPI row that had silently gone 4-up → 2-up.
|
|
68
68
|
|
|
69
|
-
| Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | 1.34.0 | 1.34.1 | 1.35.0 | 1.36.0 | 1.36.1 | 1.37.0 | 1.37.1 | 1.38.0 | 1.38.1 | 1.39.0 | 1.40.0 | 1.40.1 | 1.40.2 | 1.40.3 | 1.41.0 | 2.0.0 | 2.0.1 | 2.0.2 | Unreleased |
|
|
70
|
-
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------- | ------ | ------ | -------------------------------------------------------------------------------------------- | ------ | ------ | ------ | ------ | ------ | ----------------------------------------------- | ------ | ------ | ------ | ------ | ------------------------------------------------------------ | ---------- | --- | --- | --- | --- |
|
|
71
|
-
| **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | `CONTAINER_KEYS` (§ 1.34.0) | — | — | — | — | — | — | — | | `appShellInset` 20 → 16 (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — |
|
|
72
|
-
| **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
73
|
-
| **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | `useBreakpoint` removed (§ 1.34.0) | — | — | `useCoarsePointer()` (§ `useCoarsePointer()`) | — | — | — | — | | content gutter 16, block 8 from `sm` (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — |
|
|
74
|
-
| **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — | — | — | `FormSection`/`FormRow`/`FormGroup`/`FormActions` move here (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
75
|
-
| **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — | — | — | the layout + `useForm`/`schemaResolver` deprecated, removed 1.37.0 (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
76
|
-
| **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
77
|
-
| **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
78
|
-
| **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
79
|
-
| **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | the managed block moves `CLAUDE.md` → `AGENTS.md` (§ 1.41.0) | — | — | — | — |
|
|
80
|
-
| **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — | — | — | `unknown-vx-token` → `error`; the token factories throw (§ Guards) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
69
|
+
| Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | 1.34.0 | 1.34.1 | 1.35.0 | 1.36.0 | 1.36.1 | 1.37.0 | 1.37.1 | 1.38.0 | 1.38.1 | 1.39.0 | 1.40.0 | 1.40.1 | 1.40.2 | 1.40.3 | 1.41.0 | 2.0.0 | 2.0.1 | 2.0.2 | 2.0.3 | Unreleased |
|
|
70
|
+
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------- | ------ | ------ | -------------------------------------------------------------------------------------------- | ------ | ------ | ------ | ------ | ------ | ----------------------------------------------- | ------ | ------ | ------ | ------ | ------------------------------------------------------------ | ---------- | --- | --- | --- | --- | --- |
|
|
71
|
+
| **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | `CONTAINER_KEYS` (§ 1.34.0) | — | — | — | — | — | — | — | | `appShellInset` 20 → 16 (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — | — |
|
|
72
|
+
| **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
73
|
+
| **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | `useBreakpoint` removed (§ 1.34.0) | — | — | `useCoarsePointer()` (§ `useCoarsePointer()`) | — | — | — | — | | content gutter 16, block 8 from `sm` (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — | — |
|
|
74
|
+
| **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — | — | — | `FormSection`/`FormRow`/`FormGroup`/`FormActions` move here (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
75
|
+
| **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — | — | — | the layout + `useForm`/`schemaResolver` deprecated, removed 1.37.0 (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
76
|
+
| **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
77
|
+
| **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
78
|
+
| **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
79
|
+
| **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | the managed block moves `CLAUDE.md` → `AGENTS.md` (§ 1.41.0) | — | — | — | — | — |
|
|
80
|
+
| **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — | — | — | `unknown-vx-token` → `error`; the token factories throw (§ Guards) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
@@ -992,16 +992,34 @@ optional, subpath-required peers.
|
|
|
992
992
|
_Nothing yet. Author the next section under this heading as `## Unreleased — <title>`; the
|
|
993
993
|
release renames it and opens a new one here._
|
|
994
994
|
|
|
995
|
+
## 2.0.3 — argo shell and CI friction
|
|
996
|
+
|
|
997
|
+
- `doctor`'s `app-wiring` follows the entry's relative imports (three deep): `createBasaltRouter`
|
|
998
|
+
may be called in `src/lib/router.ts` (or any module `main.tsx` imports), not only in `main.tsx`.
|
|
999
|
+
- The seeded `.github/workflows/check.yml` runs `make check` when the repo's Makefile has a
|
|
1000
|
+
`check:` target, after `doctor` and `sync --check` (which always run, so drift is never
|
|
1001
|
+
skippable); otherwise it keeps the built-in lint, theme and format steps. `init` decides once, on
|
|
1002
|
+
seeding. An already-seeded workflow is yours and unchanged: replace its lint/theme/format steps
|
|
1003
|
+
with `- run: make check` to adopt it.
|
|
1004
|
+
- The collapsed `BasaltShell` rail shows a dot on the icon of any nav item with a count or badge,
|
|
1005
|
+
and the link's accessible name carries the count (e.g. "Calendar, 3"). Expanded rendering is
|
|
1006
|
+
unchanged.
|
|
1007
|
+
- `BasaltProvider` takes `navCommandLabel?: (item) => string` to label the Spotlight `nav.<id>`
|
|
1008
|
+
entries it generates from the nav (e.g. "Go to …"); default unchanged. A `defineCommands` entry
|
|
1009
|
+
with id `nav.<id>` now replaces the generated one instead of showing twice.
|
|
1010
|
+
|
|
995
1011
|
## 2.0.2
|
|
996
1012
|
|
|
997
|
-
|
|
1013
|
+
- `doctor` and `sync` are monorepo-aware. The manifest, `.claude/` and the AGENTS block stay at the
|
|
1014
|
+
install root; the app-scoped half (`tsconfig-base`, `app-wiring`, the `src/main.tsx`,
|
|
1015
|
+
`src/lib/nav.tsx` and `src/routes/__root.tsx` seeds) targets the app package: `basalt.app`
|
|
1016
|
+
(relative path, e.g. `"apps/dashboard"`) in the root package.json, else the one workspace package
|
|
1017
|
+
that depends on basalt-ui and has `src/main.tsx` or `index.html`, else the cwd. Two candidates
|
|
1018
|
+
fail with a message naming `basalt.app`. `doctor` run inside the app package finds the root
|
|
1019
|
+
manifest, and warns about a router seed an earlier `sync` left at the root — delete it.
|
|
998
1020
|
|
|
999
1021
|
## 2.0.1
|
|
1000
1022
|
|
|
1001
|
-
_Nothing to migrate in this release._
|
|
1002
|
-
|
|
1003
|
-
## Next patch — doctor reads the peers and the config
|
|
1004
|
-
|
|
1005
1023
|
- `doctor` gains `exact-peers`: for each exact-pinned peer of the installed basalt-ui (the three
|
|
1006
1024
|
`@fontsource-variable/*`, `motion`, `remend`, …) it compares your installed version and prints a
|
|
1007
1025
|
one-line `bun add <pkg>@<version>` fix on a mismatch. `bun add` accepts the mismatch silently.
|
|
@@ -1012,17 +1030,6 @@ _Nothing to migrate in this release._
|
|
|
1012
1030
|
- Corrected the § 2.0 "Upgrading from 1.x" step 2: delete only the core, notifications and
|
|
1013
1031
|
spotlight layer imports; extension packages (`@mantine/dates`, `@mantine/schedule`) stay, after
|
|
1014
1032
|
`basalt-ui/styles.css`.
|
|
1015
|
-
- `doctor` and `sync` are monorepo-aware. The manifest, `.claude/` and the AGENTS block stay at the
|
|
1016
|
-
install root; the app-scoped half (`tsconfig-base`, `app-wiring`, the `src/main.tsx`,
|
|
1017
|
-
`src/lib/nav.tsx` and `src/routes/__root.tsx` seeds) targets the app package: `basalt.app`
|
|
1018
|
-
(relative path, e.g. `"apps/dashboard"`) in the root package.json, else the one workspace package
|
|
1019
|
-
that depends on basalt-ui and has `src/main.tsx` or `index.html`, else the cwd. Two candidates
|
|
1020
|
-
fail with a message naming `basalt.app`. `doctor` run inside the app package finds the root
|
|
1021
|
-
manifest, and warns about a router seed an earlier `sync` left at the root — delete it.
|
|
1022
|
-
|
|
1023
|
-
## 2.0.0
|
|
1024
|
-
|
|
1025
|
-
_Nothing to migrate in this release._
|
|
1026
1033
|
|
|
1027
1034
|
## 1.41.0 — the managed block moves to AGENTS.md
|
|
1028
1035
|
|
package/configs/check.yml
CHANGED
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
# from the working directory (bun's isolated linker puts it beside the package that depends
|
|
14
14
|
# on it, not at the root) bunx silently downloads a DIFFERENT copy from npm and the gate
|
|
15
15
|
# runs a version nobody pinned.
|
|
16
|
+
# The gate is the consumer's when it has one: with a Makefile `check:` target the workflow runs
|
|
17
|
+
# `make check` (after `doctor` and `sync --check`, which always run first so drift can never be
|
|
18
|
+
# skipped by a custom gate); without one it runs the built-in lint + theme guard + format steps.
|
|
19
|
+
# `init` decides once, when it seeds this file. Add gates to your `make check`, not to this file.
|
|
16
20
|
name: check
|
|
17
21
|
on:
|
|
18
22
|
pull_request:
|
|
@@ -28,11 +32,7 @@ jobs:
|
|
|
28
32
|
with:
|
|
29
33
|
bun-version: latest
|
|
30
34
|
- run: bun install --frozen-lockfile
|
|
31
|
-
|
|
32
|
-
- run: '{{BASALT_BIN}} doctor'
|
|
33
|
-
- run: '{{BASALT_BIN}} check-theme'
|
|
34
|
-
- run: '{{BASALT_BIN}} sync --check'
|
|
35
|
-
- run: bunx oxfmt {{ROOTS_GLOBS}} '!**/dist/**' --check
|
|
35
|
+
# {{GATE_STEPS}}
|
|
36
36
|
# Enable once your app defines these package.json scripts:
|
|
37
37
|
# - run: bun run typecheck
|
|
38
38
|
# - run: bun run test
|
|
@@ -22,7 +22,7 @@ export declare function droppedSubpathsCheck(cwd: string, cfg: BasaltConfig, ins
|
|
|
22
22
|
export declare function seedTsconfigExtends(cwd: string): string | null;
|
|
23
23
|
/**
|
|
24
24
|
* `app-wiring`: the entry module `index.html` loads (default src/main.tsx) mounts `BasaltProvider`
|
|
25
|
-
* on a `createBasaltRouter` router, and the router tree is generated: the vite config calls a
|
|
25
|
+
* on a `createBasaltRouter` router (called in the entry or a module it imports), and the router tree is generated: the vite config calls a
|
|
26
26
|
* binding imported from `@tanstack/router-plugin` in `plugins`, or a `routeTree.gen.*` already sits
|
|
27
27
|
* beside the entry (or in src/). `basaltViteConfig` does not register that plugin, so naming it
|
|
28
28
|
* proves nothing.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-upgrade.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-upgrade.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAgB9D,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,MACc,CAAA;AA+CvD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAqBpD;AA+CD,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAyBhF;AA4CD,mGAAmG;AACnG,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,aAAa,GACrB,KAAK,CA8BP;AAUD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC9D;
|
|
1
|
+
{"version":3,"file":"doctor-upgrade.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-upgrade.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAgB9D,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,MACc,CAAA;AA+CvD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAqBpD;AA+CD,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAyBhF;AA4CD,mGAAmG;AACnG,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,aAAa,GACrB,KAAK,CA8BP;AAUD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC9D;AAgGD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAkCjD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAezD;AAaD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAwB1E"}
|
|
@@ -234,6 +234,39 @@ function registersRouterPlugin(src) {
|
|
|
234
234
|
);
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
|
+
const RELATIVE_IMPORT = /(?:\b(?:import|export)\b[^'";]*?\bfrom|\bimport)\s*['"](\.{1,2}\/[^'"]+)['"]/g;
|
|
238
|
+
function resolveRelative(from, spec) {
|
|
239
|
+
const base = resolve(dirname(from), spec.replace(/\.[jt]sx?$/, ""));
|
|
240
|
+
return [
|
|
241
|
+
resolve(dirname(from), spec),
|
|
242
|
+
`${base}.ts`,
|
|
243
|
+
`${base}.tsx`,
|
|
244
|
+
`${base}/index.ts`,
|
|
245
|
+
`${base}/index.tsx`
|
|
246
|
+
].find((f) => /\.[jt]sx?$/.test(f) && existsSync(f)) ?? null;
|
|
247
|
+
}
|
|
248
|
+
function routerCreatedInImports(cwd, entry) {
|
|
249
|
+
const seen = /* @__PURE__ */ new Set([resolve(cwd, entry)]);
|
|
250
|
+
let frontier = [...seen];
|
|
251
|
+
for (let depth = 0; depth < 3 && frontier.length > 0; depth++) {
|
|
252
|
+
const next = [];
|
|
253
|
+
for (const file of frontier) {
|
|
254
|
+
for (const m of (readIfExists(file) ?? "").matchAll(RELATIVE_IMPORT)) {
|
|
255
|
+
const dep = resolveRelative(file, m[1] ?? "");
|
|
256
|
+
if (dep === null || seen.has(dep)) continue;
|
|
257
|
+
seen.add(dep);
|
|
258
|
+
const { code, inLiteral } = tokenize(readIfExists(dep) ?? "");
|
|
259
|
+
const called = [...code.matchAll(/\bcreateBasaltRouter\b/g)].some(
|
|
260
|
+
(c) => !inLiteral(c.index)
|
|
261
|
+
);
|
|
262
|
+
if (called) return true;
|
|
263
|
+
next.push(dep);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
frontier = next;
|
|
267
|
+
}
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
237
270
|
function appWiringCheck(cwd) {
|
|
238
271
|
return guarded("app-wiring", () => {
|
|
239
272
|
const entry = (htmlEntry(readIfExists(resolve(cwd, "index.html")) ?? "") ?? "src/main.tsx").replace(/^\//, "");
|
|
@@ -243,7 +276,9 @@ function appWiringCheck(cwd) {
|
|
|
243
276
|
}
|
|
244
277
|
const { code, inLiteral } = tokenize(text);
|
|
245
278
|
const used = (name) => [...code.matchAll(new RegExp(`\\b${name}\\b`, "g"))].some((m) => !inLiteral(m.index));
|
|
246
|
-
const missing = ["BasaltProvider", "createBasaltRouter"].filter(
|
|
279
|
+
const missing = ["BasaltProvider", "createBasaltRouter"].filter(
|
|
280
|
+
(name) => !used(name) && !(name === "createBasaltRouter" && routerCreatedInImports(cwd, entry))
|
|
281
|
+
);
|
|
247
282
|
if (missing.length > 0) {
|
|
248
283
|
return {
|
|
249
284
|
fail: `app-wiring: ${entry} does not use ${missing.join(" or ")}. Fix: make it match ${SEED_HINT} (\`init\` seeds it only when the file is absent).`
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -152,6 +152,8 @@ type TemplateVars = {
|
|
|
152
152
|
* `bunx basalt-ui` only as the pre-install fallback.
|
|
153
153
|
*/
|
|
154
154
|
BASALT_BIN: string;
|
|
155
|
+
/** The CI gate steps after install: `make check` when the repo owns one, else the built-in set. */
|
|
156
|
+
GATE_STEPS: string;
|
|
155
157
|
};
|
|
156
158
|
export declare const MANIFEST_PATH = ".basalt/manifest.json";
|
|
157
159
|
/** The host file the managed block is spliced into (and its manifest key). */
|
|
@@ -170,6 +172,12 @@ export declare function readFrameworkVersion(pkgRoot: string): string;
|
|
|
170
172
|
* cached package, so it lets a consumer pin one version and be gated by another).
|
|
171
173
|
*/
|
|
172
174
|
export declare function basaltBinCommand(install: BasaltInstall, cwd: string): string;
|
|
175
|
+
/**
|
|
176
|
+
* The consumer owns the CI gate when its Makefile has a `check:` target: `doctor` and `sync --check`
|
|
177
|
+
* stay as steps of their own (drift is never skippable), then `make check` replaces the built-in
|
|
178
|
+
* lint/theme/format steps. Without one, the built-in steps run. Rendered at `{{GATE_STEPS}}`.
|
|
179
|
+
*/
|
|
180
|
+
export declare function ciGateSteps(cwd: string): string;
|
|
173
181
|
/** True when both paths resolve to one file (a symlinked pair). A missing path is simply "no". */
|
|
174
182
|
export declare function sameFile(a: string, b: string): boolean;
|
|
175
183
|
/** True when the host text carries a managed block (begin marker present). */
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -268,6 +268,18 @@ function basaltBinCommand(install, cwd) {
|
|
|
268
268
|
const binDir = resolve(install.dir, "..", ".bin");
|
|
269
269
|
return `${relativePosix(cwd, binDir).replace(/^\.\//, "")}/basalt-ui`;
|
|
270
270
|
}
|
|
271
|
+
function ciGateSteps(cwd) {
|
|
272
|
+
const owned = /^check\s*:/m.test(readIfExists(resolve(cwd, "Makefile")) ?? "");
|
|
273
|
+
const drift = ["- run: '{{BASALT_BIN}} doctor'", "- run: '{{BASALT_BIN}} sync --check'"];
|
|
274
|
+
const steps = owned ? [...drift, "- run: make check"] : [
|
|
275
|
+
"- run: bunx oxlint .",
|
|
276
|
+
drift[0],
|
|
277
|
+
"- run: '{{BASALT_BIN}} check-theme'",
|
|
278
|
+
drift[1],
|
|
279
|
+
"- run: bunx oxfmt {{ROOTS_GLOBS}} '!**/dist/**' --check"
|
|
280
|
+
];
|
|
281
|
+
return steps.join("\n ");
|
|
282
|
+
}
|
|
271
283
|
function buildTemplateVars(pkgRoot, cwd, cfg) {
|
|
272
284
|
const install = findBasaltInstall(cwd);
|
|
273
285
|
return {
|
|
@@ -278,14 +290,16 @@ function buildTemplateVars(pkgRoot, cwd, cfg) {
|
|
|
278
290
|
ROOTS_GLOBS: resolveRoots(cfg).map(toRootGlob).join(" "),
|
|
279
291
|
OXLINT_PRESET_PATH: shippedAssetPath(install, cwd, OXLINT_FILES.preset),
|
|
280
292
|
LEFTHOOK_PRESET_PATH: shippedAssetPath(install, cwd, "configs/lefthook.yml"),
|
|
281
|
-
BASALT_BIN: basaltBinCommand(install, cwd)
|
|
293
|
+
BASALT_BIN: basaltBinCommand(install, cwd),
|
|
294
|
+
GATE_STEPS: ciGateSteps(cwd)
|
|
282
295
|
};
|
|
283
296
|
}
|
|
284
297
|
function fillTemplate(tpl, vars) {
|
|
285
|
-
|
|
298
|
+
const fill = (text) => text.replace(/\{\{(\w+)\}\}/g, (m, key) => {
|
|
286
299
|
const v = vars[key];
|
|
287
300
|
return v ?? m;
|
|
288
301
|
});
|
|
302
|
+
return fill(tpl.replace("# {{GATE_STEPS}}", vars.GATE_STEPS));
|
|
289
303
|
}
|
|
290
304
|
function findBlockRegion(host) {
|
|
291
305
|
const start = host.indexOf(BLOCK_BEGIN_PREFIX);
|
|
@@ -1000,6 +1014,7 @@ export {
|
|
|
1000
1014
|
basaltBinCommand,
|
|
1001
1015
|
basaltPresetEntry,
|
|
1002
1016
|
checkTheme,
|
|
1017
|
+
ciGateSteps,
|
|
1003
1018
|
classify,
|
|
1004
1019
|
conflictingProfileFlags,
|
|
1005
1020
|
declaredProfile,
|
package/dist/provider/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { BuildPaletteOpts } from '../tokens/core.js';
|
|
|
5
5
|
import type { SizeClass } from '../shell/use-size-class.js';
|
|
6
6
|
import type { Telemetry } from '../telemetry.js';
|
|
7
7
|
import type { BasaltRouter } from './create-router.js';
|
|
8
|
+
import type { FlatNavItem } from '../router-tanstack/nav.js';
|
|
8
9
|
export type BasaltProviderProps = {
|
|
9
10
|
/** From `createBasaltRouter`; the provider mounts it and reads its `queryClient`. */
|
|
10
11
|
router: BasaltRouter;
|
|
@@ -41,6 +42,12 @@ export type BasaltProviderProps = {
|
|
|
41
42
|
* can answer. Default `'compact'`. SSR only; an SSR desktop app SHOULD pass it.
|
|
42
43
|
*/
|
|
43
44
|
sizeClassHint?: SizeClass;
|
|
45
|
+
/**
|
|
46
|
+
* Label for the `nav.<id>` Spotlight entries generated from `defineNav`, e.g.
|
|
47
|
+
* `(item) => `Go to ${item.label}``. Default: the destination's own label. A `defineCommands`
|
|
48
|
+
* entry with id `nav.<id>` replaces the generated one outright.
|
|
49
|
+
*/
|
|
50
|
+
navCommandLabel?: (item: FlatNavItem) => string;
|
|
44
51
|
} & Omit<MantineProviderProps, 'children' | 'theme' | 'defaultColorScheme' | 'cssVariablesResolver'>;
|
|
45
52
|
type RootBoundaryProps = {
|
|
46
53
|
children: ReactNode;
|
|
@@ -76,6 +83,6 @@ export declare function composeInjectedCss(base: string, fontsCss: string, radiu
|
|
|
76
83
|
* closes the gap between hydration and the next client paint.
|
|
77
84
|
*/
|
|
78
85
|
export declare function useHostAttribute(): void;
|
|
79
|
-
export declare function BasaltProvider({ router, theme, telemetry, fallback, injectPalette, paletteOptions, defaultColorScheme, nonce, sizeClassHint, ...rest }: BasaltProviderProps): import("react").JSX.Element;
|
|
86
|
+
export declare function BasaltProvider({ router, theme, telemetry, fallback, injectPalette, paletteOptions, defaultColorScheme, nonce, sizeClassHint, navCommandLabel, ...rest }: BasaltProviderProps): import("react").JSX.Element;
|
|
80
87
|
export {};
|
|
81
88
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/provider/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AASzD,OAAO,EAAE,SAAS,EAAqE,MAAM,OAAO,CAAA;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAStD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/provider/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AASzD,OAAO,EAAE,SAAS,EAAqE,MAAM,OAAO,CAAA;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAStD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,iBAAiB,CAAA;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAGzD,MAAM,MAAM,mBAAmB,GAAG;IAChC,qFAAqF;IACrF,MAAM,EAAE,YAAY,CAAA;IACpB,qFAAqF;IACrF,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IACrC;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAAC,CAAA;IACtD;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAA;IACjC,8CAA8C;IAC9C,kBAAkB,CAAC,EAAE,oBAAoB,CAAC,oBAAoB,CAAC,CAAA;IAC/D;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,CAAA;CAChD,GAAG,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,OAAO,GAAG,oBAAoB,GAAG,sBAAsB,CAAC,CAAA;AAIpG,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,SAAS,CAAA;IACnB,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAA;CAC1C,CAAA;AAED,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAwB1D,mGAAmG;AACnG,qBAAa,YAAa,SAAQ,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC;gBAC/D,KAAK,EAAE,iBAAiB;IAKpC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa;IAIrD,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;IAczD,MAAM,IAAI,SAAS;CAO7B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAYD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAmBvC;AAqMD,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,aAAoB,EACpB,cAAc,EACd,kBAA2B,EAC3B,KAAK,EACL,aAAyB,EACzB,eAAe,EACf,GAAG,IAAI,EACR,EAAE,mBAAmB,+BA6ErB"}
|
package/dist/provider/index.js
CHANGED
|
@@ -242,6 +242,7 @@ function BasaltProvider({
|
|
|
242
242
|
defaultColorScheme = "dark",
|
|
243
243
|
nonce,
|
|
244
244
|
sizeClassHint = "compact",
|
|
245
|
+
navCommandLabel,
|
|
245
246
|
...rest
|
|
246
247
|
}) {
|
|
247
248
|
useDuplicateProviderGuard();
|
|
@@ -259,8 +260,8 @@ function BasaltProvider({
|
|
|
259
260
|
const [devTool, setDevTool] = useState(null);
|
|
260
261
|
const [actions, setActions] = useState([]);
|
|
261
262
|
const refreshActions = useCallback(
|
|
262
|
-
() => setActions(buildSpotlightActions(router, setDevTool)),
|
|
263
|
-
[router]
|
|
263
|
+
() => setActions(buildSpotlightActions(router, setDevTool, navCommandLabel)),
|
|
264
|
+
[router, navCommandLabel]
|
|
264
265
|
);
|
|
265
266
|
useEffect(refreshActions, [refreshActions]);
|
|
266
267
|
const resolvedTheme = useLabTheme(theme);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The provider's Spotlight list: the `defineCommands` registry, then the `defineNav` destinations
|
|
3
|
-
* (via `flattenNav`), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
|
|
3
|
+
* (via `flattenNav`, skipping any id a registered `nav.<id>` command already owns), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
|
|
4
4
|
* opens, so a command's `when()` is current. Not for use during render (`detectMac` reads `navigator`).
|
|
5
5
|
*/
|
|
6
6
|
import type { SpotlightActionData } from '@mantine/spotlight';
|
|
7
7
|
import type { AnyRouter } from '@tanstack/react-router';
|
|
8
|
+
import type { FlatNavItem } from '../router-tanstack/nav.js';
|
|
8
9
|
import type { BasaltDevDockTool } from '../dev-dock.js';
|
|
9
|
-
export declare function buildSpotlightActions(router: AnyRouter, openDevTool: (tool: BasaltDevDockTool) => void): SpotlightActionData[];
|
|
10
|
+
export declare function buildSpotlightActions(router: AnyRouter, openDevTool: (tool: BasaltDevDockTool) => void, navCommandLabel?: (item: FlatNavItem) => string): SpotlightActionData[];
|
|
10
11
|
//# sourceMappingURL=spotlight-actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spotlight-actions.d.ts","sourceRoot":"","sources":["../../src/provider/spotlight-actions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AASpD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"spotlight-actions.d.ts","sourceRoot":"","sources":["../../src/provider/spotlight-actions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AASpD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,EAC9C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,GAC9C,mBAAmB,EAAE,CAiDvB"}
|
|
@@ -7,9 +7,10 @@ const DEV_TOOLS = [
|
|
|
7
7
|
{ tool: "query", label: "Query devtools" },
|
|
8
8
|
{ tool: "theme", label: "Theme lab" }
|
|
9
9
|
];
|
|
10
|
-
function buildSpotlightActions(router, openDevTool) {
|
|
10
|
+
function buildSpotlightActions(router, openDevTool, navCommandLabel) {
|
|
11
11
|
const actions = [];
|
|
12
|
-
|
|
12
|
+
const commands = getActiveCommands();
|
|
13
|
+
for (const [id, cmd] of Object.entries(commands)) {
|
|
13
14
|
if (cmd.when !== void 0 && !cmd.when()) continue;
|
|
14
15
|
actions.push({
|
|
15
16
|
id,
|
|
@@ -27,9 +28,10 @@ function buildSpotlightActions(router, openDevTool) {
|
|
|
27
28
|
if (nav !== void 0) {
|
|
28
29
|
for (const item of flattenNav(nav)) {
|
|
29
30
|
if (item.disabled === true) continue;
|
|
31
|
+
if (`nav.${item.id}` in commands) continue;
|
|
30
32
|
actions.push({
|
|
31
33
|
id: `nav.${item.id}`,
|
|
32
|
-
label: item.label,
|
|
34
|
+
label: navCommandLabel?.(item) ?? item.label,
|
|
33
35
|
group: item.groupLabel,
|
|
34
36
|
leftSection: item.icon,
|
|
35
37
|
// `link` is the destination's own `linkOptions`, so a store-backed `search` thunk restores
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-sidebar.d.ts","sourceRoot":"","sources":["../../src/shell/app-sidebar.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAe,cAAc,EAAE,MAAM,aAAa,CAAA;AAI5E,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAgBjF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C;;;;OAIG;IACH,KAAK,EAAE,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,CAAA;IACjD,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,SAAS,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAC5B;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACtC;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IACvC;;;;OAIG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B;;;;OAIG;IACH,MAAM,CAAC,EAAE,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAA;IACjE;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;CACxB,CAAA;
|
|
1
|
+
{"version":3,"file":"app-sidebar.d.ts","sourceRoot":"","sources":["../../src/shell/app-sidebar.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAe,cAAc,EAAE,MAAM,aAAa,CAAA;AAI5E,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAgBjF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C;;;;OAIG;IACH,KAAK,EAAE,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,CAAA;IACjD,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,SAAS,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAC5B;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACtC;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IACvC;;;;OAIG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B;;;;OAIG;IACH,MAAM,CAAC,EAAE,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAA;IACjE;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;CACxB,CAAA;AAiUD,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BA2KhD"}
|
|
@@ -88,14 +88,21 @@ function NavLinkBody({
|
|
|
88
88
|
collapsed = false
|
|
89
89
|
}) {
|
|
90
90
|
const Anchor = item.Anchor;
|
|
91
|
+
const icon = iconOrInitial(item.icon, item.label);
|
|
92
|
+
const railDot = collapsed && (item.badge !== void 0 && item.badge !== null || Boolean(item.count));
|
|
91
93
|
const shared = {
|
|
92
94
|
classNames: { root: classes.link },
|
|
93
95
|
label: item.label,
|
|
94
|
-
leftSection:
|
|
96
|
+
leftSection: railDot ? /* @__PURE__ */ jsxs("span", { className: classes.navIconDotHost, children: [
|
|
97
|
+
icon,
|
|
98
|
+
/* @__PURE__ */ jsx("span", { className: classes.blockDot, "data-basalt-rail-dot": true, "aria-hidden": true })
|
|
99
|
+
] }) : icon,
|
|
95
100
|
// Only the collapsed rail hides the label (CSS), leaving the icon alone — name the link there.
|
|
96
101
|
// Expanded, the visible text IS the name and carries the count badge; an `aria-label` would
|
|
97
102
|
// override both and drop the count ("Inbox 5" → "Inbox").
|
|
98
|
-
...collapsed && {
|
|
103
|
+
...collapsed && {
|
|
104
|
+
"aria-label": item.count ? `${item.label}, ${item.count}` : item.label
|
|
105
|
+
},
|
|
99
106
|
rightSection: item.badge ?? (item.count ? /* @__PURE__ */ jsx(NavCountBadge, { count: item.count }) : void 0),
|
|
100
107
|
active,
|
|
101
108
|
// Basalt is the one that stamps `aria-current`, not the theme and not a router `<Link>`'s own
|
|
@@ -472,6 +472,12 @@
|
|
|
472
472
|
box-shadow: 0 0 0 2px var(--mantine-color-body);
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
+
/* Host for a nav row's rail dot: the dot anchors on the icon itself, not the 48px row. */
|
|
476
|
+
.navIconDotHost {
|
|
477
|
+
position: relative;
|
|
478
|
+
display: inline-flex;
|
|
479
|
+
}
|
|
480
|
+
|
|
475
481
|
.blockItems {
|
|
476
482
|
display: flex;
|
|
477
483
|
flex-direction: column;
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# basalt-ui v2.0.
|
|
1
|
+
# basalt-ui v2.0.3
|
|
2
2
|
# Opinionated framework for Mantine-based React apps — theme, app shell, TanStack Charts, toolchain presets
|
|
3
3
|
#
|
|
4
4
|
# Entry points: use the exact import specifier below; do not guess.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# A subpath's `Install:` line is its required peers; `OptionalPeers:` are import()-only, install on use.
|
|
14
14
|
|
|
15
15
|
Package: basalt-ui
|
|
16
|
-
Version: 2.0.
|
|
16
|
+
Version: 2.0.3
|
|
17
17
|
|
|
18
18
|
## basalt-ui
|
|
19
19
|
Import: import { ... } from 'basalt-ui'
|
package/package.json
CHANGED
|
@@ -352,9 +352,53 @@ function registersRouterPlugin(src: string): boolean {
|
|
|
352
352
|
})
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
+
const RELATIVE_IMPORT =
|
|
356
|
+
/(?:\b(?:import|export)\b[^'";]*?\bfrom|\bimport)\s*['"](\.{1,2}\/[^'"]+)['"]/g
|
|
357
|
+
|
|
358
|
+
/** The source file a relative specifier names: as written, `.ts`/`.tsx` appended, or a directory index. */
|
|
359
|
+
function resolveRelative(from: string, spec: string): string | null {
|
|
360
|
+
const base = resolve(dirname(from), spec.replace(/\.[jt]sx?$/, ''))
|
|
361
|
+
return (
|
|
362
|
+
[
|
|
363
|
+
resolve(dirname(from), spec),
|
|
364
|
+
`${base}.ts`,
|
|
365
|
+
`${base}.tsx`,
|
|
366
|
+
`${base}/index.ts`,
|
|
367
|
+
`${base}/index.tsx`,
|
|
368
|
+
].find((f) => /\.[jt]sx?$/.test(f) && existsSync(f)) ?? null
|
|
369
|
+
)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Whether a module the entry imports (relative imports, three deep) calls `createBasaltRouter` —
|
|
374
|
+
* the router often lives in a singleton module other code also imports.
|
|
375
|
+
*/
|
|
376
|
+
function routerCreatedInImports(cwd: string, entry: string): boolean {
|
|
377
|
+
const seen = new Set([resolve(cwd, entry)])
|
|
378
|
+
let frontier = [...seen]
|
|
379
|
+
for (let depth = 0; depth < 3 && frontier.length > 0; depth++) {
|
|
380
|
+
const next: string[] = []
|
|
381
|
+
for (const file of frontier) {
|
|
382
|
+
for (const m of (readIfExists(file) ?? '').matchAll(RELATIVE_IMPORT)) {
|
|
383
|
+
const dep = resolveRelative(file, m[1] ?? '')
|
|
384
|
+
if (dep === null || seen.has(dep)) continue
|
|
385
|
+
seen.add(dep)
|
|
386
|
+
const { code, inLiteral } = tokenize(readIfExists(dep) ?? '')
|
|
387
|
+
const called = [...code.matchAll(/\bcreateBasaltRouter\b/g)].some(
|
|
388
|
+
(c) => !inLiteral(c.index),
|
|
389
|
+
)
|
|
390
|
+
if (called) return true
|
|
391
|
+
next.push(dep)
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
frontier = next
|
|
395
|
+
}
|
|
396
|
+
return false
|
|
397
|
+
}
|
|
398
|
+
|
|
355
399
|
/**
|
|
356
400
|
* `app-wiring`: the entry module `index.html` loads (default src/main.tsx) mounts `BasaltProvider`
|
|
357
|
-
* on a `createBasaltRouter` router, and the router tree is generated: the vite config calls a
|
|
401
|
+
* on a `createBasaltRouter` router (called in the entry or a module it imports), and the router tree is generated: the vite config calls a
|
|
358
402
|
* binding imported from `@tanstack/router-plugin` in `plugins`, or a `routeTree.gen.*` already sits
|
|
359
403
|
* beside the entry (or in src/). `basaltViteConfig` does not register that plugin, so naming it
|
|
360
404
|
* proves nothing.
|
|
@@ -371,7 +415,10 @@ export function appWiringCheck(cwd: string): Check {
|
|
|
371
415
|
const { code, inLiteral } = tokenize(text)
|
|
372
416
|
const used = (name: string): boolean =>
|
|
373
417
|
[...code.matchAll(new RegExp(`\\b${name}\\b`, 'g'))].some((m) => !inLiteral(m.index))
|
|
374
|
-
const missing = ['BasaltProvider', 'createBasaltRouter'].filter(
|
|
418
|
+
const missing = ['BasaltProvider', 'createBasaltRouter'].filter(
|
|
419
|
+
(name) =>
|
|
420
|
+
!used(name) && !(name === 'createBasaltRouter' && routerCreatedInImports(cwd, entry)),
|
|
421
|
+
)
|
|
375
422
|
if (missing.length > 0) {
|
|
376
423
|
return {
|
|
377
424
|
fail:
|
package/src/cli/index.ts
CHANGED
|
@@ -474,6 +474,8 @@ type TemplateVars = {
|
|
|
474
474
|
* `bunx basalt-ui` only as the pre-install fallback.
|
|
475
475
|
*/
|
|
476
476
|
BASALT_BIN: string
|
|
477
|
+
/** The CI gate steps after install: `make check` when the repo owns one, else the built-in set. */
|
|
478
|
+
GATE_STEPS: string
|
|
477
479
|
}
|
|
478
480
|
|
|
479
481
|
// The block markers the AGENTS.md template emits. The begin marker carries the framework version
|
|
@@ -536,6 +538,26 @@ export function basaltBinCommand(install: BasaltInstall, cwd: string): string {
|
|
|
536
538
|
return `${relativePosix(cwd, binDir).replace(/^\.\//, '')}/basalt-ui`
|
|
537
539
|
}
|
|
538
540
|
|
|
541
|
+
/**
|
|
542
|
+
* The consumer owns the CI gate when its Makefile has a `check:` target: `doctor` and `sync --check`
|
|
543
|
+
* stay as steps of their own (drift is never skippable), then `make check` replaces the built-in
|
|
544
|
+
* lint/theme/format steps. Without one, the built-in steps run. Rendered at `{{GATE_STEPS}}`.
|
|
545
|
+
*/
|
|
546
|
+
export function ciGateSteps(cwd: string): string {
|
|
547
|
+
const owned = /^check\s*:/m.test(readIfExists(resolve(cwd, 'Makefile')) ?? '')
|
|
548
|
+
const drift = ["- run: '{{BASALT_BIN}} doctor'", "- run: '{{BASALT_BIN}} sync --check'"]
|
|
549
|
+
const steps = owned
|
|
550
|
+
? [...drift, '- run: make check']
|
|
551
|
+
: [
|
|
552
|
+
'- run: bunx oxlint .',
|
|
553
|
+
drift[0],
|
|
554
|
+
"- run: '{{BASALT_BIN}} check-theme'",
|
|
555
|
+
drift[1],
|
|
556
|
+
"- run: bunx oxfmt {{ROOTS_GLOBS}} '!**/dist/**' --check",
|
|
557
|
+
]
|
|
558
|
+
return steps.join('\n ')
|
|
559
|
+
}
|
|
560
|
+
|
|
539
561
|
/** Build the template-variable map from the framework root + consumer cwd/config. */
|
|
540
562
|
function buildTemplateVars(pkgRoot: string, cwd: string, cfg: BasaltConfig): TemplateVars {
|
|
541
563
|
const install = findBasaltInstall(cwd)
|
|
@@ -548,15 +570,20 @@ function buildTemplateVars(pkgRoot: string, cwd: string, cfg: BasaltConfig): Tem
|
|
|
548
570
|
OXLINT_PRESET_PATH: shippedAssetPath(install, cwd, OXLINT_FILES.preset),
|
|
549
571
|
LEFTHOOK_PRESET_PATH: shippedAssetPath(install, cwd, 'configs/lefthook.yml'),
|
|
550
572
|
BASALT_BIN: basaltBinCommand(install, cwd),
|
|
573
|
+
GATE_STEPS: ciGateSteps(cwd),
|
|
551
574
|
}
|
|
552
575
|
}
|
|
553
576
|
|
|
554
577
|
/** Substitute every `{{KEY}}` placeholder from the variable map; unknown keys are left verbatim. */
|
|
555
578
|
function fillTemplate(tpl: string, vars: TemplateVars): string {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
579
|
+
const fill = (text: string): string =>
|
|
580
|
+
text.replace(/\{\{(\w+)\}\}/g, (m, key: string) => {
|
|
581
|
+
const v = (vars as Record<string, string>)[key]
|
|
582
|
+
return v ?? m
|
|
583
|
+
})
|
|
584
|
+
// The marker is a YAML comment so the template stays valid YAML; GATE_STEPS itself carries
|
|
585
|
+
// placeholders, so it expands before the generic pass.
|
|
586
|
+
return fill(tpl.replace('# {{GATE_STEPS}}', vars.GATE_STEPS))
|
|
560
587
|
}
|
|
561
588
|
|
|
562
589
|
/**
|
package/src/provider/index.tsx
CHANGED
|
@@ -41,6 +41,7 @@ import type { Telemetry } from '../telemetry'
|
|
|
41
41
|
import type { BasaltDevDockTool } from '../dev-dock'
|
|
42
42
|
import type { BasaltRouter, BasaltRouterContext } from './create-router'
|
|
43
43
|
import { useRegistryHotkeys } from './hotkeys'
|
|
44
|
+
import type { FlatNavItem } from '../router-tanstack/nav'
|
|
44
45
|
import { buildSpotlightActions } from './spotlight-actions'
|
|
45
46
|
|
|
46
47
|
export type BasaltProviderProps = {
|
|
@@ -79,6 +80,12 @@ export type BasaltProviderProps = {
|
|
|
79
80
|
* can answer. Default `'compact'`. SSR only; an SSR desktop app SHOULD pass it.
|
|
80
81
|
*/
|
|
81
82
|
sizeClassHint?: SizeClass
|
|
83
|
+
/**
|
|
84
|
+
* Label for the `nav.<id>` Spotlight entries generated from `defineNav`, e.g.
|
|
85
|
+
* `(item) => `Go to ${item.label}``. Default: the destination's own label. A `defineCommands`
|
|
86
|
+
* entry with id `nav.<id>` replaces the generated one outright.
|
|
87
|
+
*/
|
|
88
|
+
navCommandLabel?: (item: FlatNavItem) => string
|
|
82
89
|
} & Omit<MantineProviderProps, 'children' | 'theme' | 'defaultColorScheme' | 'cssVariablesResolver'>
|
|
83
90
|
|
|
84
91
|
// ── Root error boundary ───────────────────────────────────────────────────────────────────────────
|
|
@@ -408,6 +415,7 @@ export function BasaltProvider({
|
|
|
408
415
|
defaultColorScheme = 'dark',
|
|
409
416
|
nonce,
|
|
410
417
|
sizeClassHint = 'compact',
|
|
418
|
+
navCommandLabel,
|
|
411
419
|
...rest
|
|
412
420
|
}: BasaltProviderProps) {
|
|
413
421
|
useDuplicateProviderGuard()
|
|
@@ -432,8 +440,8 @@ export function BasaltProvider({
|
|
|
432
440
|
// appears, not frozen at mount — and `detectMac` (inside the builder) never runs during render.
|
|
433
441
|
const [actions, setActions] = useState<SpotlightActionData[]>([])
|
|
434
442
|
const refreshActions = useCallback(
|
|
435
|
-
() => setActions(buildSpotlightActions(router, setDevTool)),
|
|
436
|
-
[router],
|
|
443
|
+
() => setActions(buildSpotlightActions(router, setDevTool, navCommandLabel)),
|
|
444
|
+
[router, navCommandLabel],
|
|
437
445
|
)
|
|
438
446
|
useEffect(refreshActions, [refreshActions])
|
|
439
447
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The provider's Spotlight list: the `defineCommands` registry, then the `defineNav` destinations
|
|
3
|
-
* (via `flattenNav`), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
|
|
3
|
+
* (via `flattenNav`, skipping any id a registered `nav.<id>` command already owns), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
|
|
4
4
|
* opens, so a command's `when()` is current. Not for use during render (`detectMac` reads `navigator`).
|
|
5
5
|
*/
|
|
6
6
|
import type { SpotlightActionData } from '@mantine/spotlight'
|
|
@@ -8,6 +8,7 @@ import type { AnyRouter } from '@tanstack/react-router'
|
|
|
8
8
|
import { getActiveCommands } from '../commands/define-commands'
|
|
9
9
|
import { detectMac, formatShortcutDisplay } from '../commands/shortcut-format'
|
|
10
10
|
import { flattenNav, getActiveNav } from '../router-tanstack/nav'
|
|
11
|
+
import type { FlatNavItem } from '../router-tanstack/nav'
|
|
11
12
|
import type { BasaltDevDockTool } from '../dev-dock'
|
|
12
13
|
import { runCommandSafely } from './hotkeys'
|
|
13
14
|
|
|
@@ -20,10 +21,12 @@ const DEV_TOOLS: ReadonlyArray<{ tool: BasaltDevDockTool; label: string }> = [
|
|
|
20
21
|
export function buildSpotlightActions(
|
|
21
22
|
router: AnyRouter,
|
|
22
23
|
openDevTool: (tool: BasaltDevDockTool) => void,
|
|
24
|
+
navCommandLabel?: (item: FlatNavItem) => string,
|
|
23
25
|
): SpotlightActionData[] {
|
|
24
26
|
const actions: SpotlightActionData[] = []
|
|
27
|
+
const commands = getActiveCommands()
|
|
25
28
|
|
|
26
|
-
for (const [id, cmd] of Object.entries(
|
|
29
|
+
for (const [id, cmd] of Object.entries(commands)) {
|
|
27
30
|
if (cmd.when !== undefined && !cmd.when()) continue
|
|
28
31
|
actions.push({
|
|
29
32
|
id,
|
|
@@ -42,9 +45,11 @@ export function buildSpotlightActions(
|
|
|
42
45
|
if (nav !== undefined) {
|
|
43
46
|
for (const item of flattenNav(nav)) {
|
|
44
47
|
if (item.disabled === true) continue
|
|
48
|
+
// A registered `nav.<id>` command owns that destination: the consumer wins, no duplicate.
|
|
49
|
+
if (`nav.${item.id}` in commands) continue
|
|
45
50
|
actions.push({
|
|
46
51
|
id: `nav.${item.id}`,
|
|
47
|
-
label: item.label,
|
|
52
|
+
label: navCommandLabel?.(item) ?? item.label,
|
|
48
53
|
group: item.groupLabel,
|
|
49
54
|
leftSection: item.icon,
|
|
50
55
|
// `link` is the destination's own `linkOptions`, so a store-backed `search` thunk restores
|
|
@@ -472,6 +472,12 @@
|
|
|
472
472
|
box-shadow: 0 0 0 2px var(--mantine-color-body);
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
+
/* Host for a nav row's rail dot: the dot anchors on the icon itself, not the 48px row. */
|
|
476
|
+
.navIconDotHost {
|
|
477
|
+
position: relative;
|
|
478
|
+
display: inline-flex;
|
|
479
|
+
}
|
|
480
|
+
|
|
475
481
|
.blockItems {
|
|
476
482
|
display: flex;
|
|
477
483
|
flex-direction: column;
|
|
@@ -207,14 +207,28 @@ function NavLinkBody({
|
|
|
207
207
|
collapsed?: boolean
|
|
208
208
|
}) {
|
|
209
209
|
const Anchor = item.Anchor
|
|
210
|
+
const icon = iconOrInitial(item.icon, item.label)
|
|
211
|
+
// The rail hides the right section (where the badge lives), so a badged row keeps a dot on its
|
|
212
|
+
// icon instead — the count rides the accessible name since the number itself has no room.
|
|
213
|
+
const railDot =
|
|
214
|
+
collapsed && ((item.badge !== undefined && item.badge !== null) || Boolean(item.count))
|
|
210
215
|
const shared = {
|
|
211
216
|
classNames: { root: classes.link },
|
|
212
217
|
label: item.label,
|
|
213
|
-
leftSection:
|
|
218
|
+
leftSection: railDot ? (
|
|
219
|
+
<span className={classes.navIconDotHost}>
|
|
220
|
+
{icon}
|
|
221
|
+
<span className={classes.blockDot} data-basalt-rail-dot aria-hidden />
|
|
222
|
+
</span>
|
|
223
|
+
) : (
|
|
224
|
+
icon
|
|
225
|
+
),
|
|
214
226
|
// Only the collapsed rail hides the label (CSS), leaving the icon alone — name the link there.
|
|
215
227
|
// Expanded, the visible text IS the name and carries the count badge; an `aria-label` would
|
|
216
228
|
// override both and drop the count ("Inbox 5" → "Inbox").
|
|
217
|
-
...(collapsed && {
|
|
229
|
+
...(collapsed && {
|
|
230
|
+
'aria-label': item.count ? `${item.label}, ${item.count}` : item.label,
|
|
231
|
+
}),
|
|
218
232
|
rightSection: item.badge ?? (item.count ? <NavCountBadge count={item.count} /> : undefined),
|
|
219
233
|
active,
|
|
220
234
|
// Basalt is the one that stamps `aria-current`, not the theme and not a router `<Link>`'s own
|