basalt-ui 2.1.0 → 2.2.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/CHANGELOG.md +17 -0
- package/MIGRATING.md +25 -12
- package/configs/oxlint.json +1 -0
- package/dist/charts/Heatmap.d.ts +3 -1
- package/dist/charts/Heatmap.d.ts.map +1 -1
- package/dist/charts/Heatmap.js +8 -2
- package/dist/charts/Sparkline.d.ts +4 -0
- package/dist/charts/Sparkline.d.ts.map +1 -1
- package/dist/charts/Sparkline.js +18 -12
- package/dist/charts/compile.d.ts +6 -0
- package/dist/charts/compile.d.ts.map +1 -1
- package/dist/charts/compile.js +5 -0
- package/dist/charts/state.d.ts +3 -0
- package/dist/charts/state.d.ts.map +1 -1
- package/dist/charts/state.js +14 -3
- package/dist/charts/types.d.ts +2 -1
- package/dist/charts/types.d.ts.map +1 -1
- package/dist/cli/doctor.js +2 -2
- 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/stat-card.d.ts +16 -1
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +14 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/charts/Heatmap.tsx +11 -3
- package/src/charts/Sparkline.tsx +9 -1
- package/src/charts/compile.ts +10 -0
- package/src/charts/state.tsx +15 -3
- package/src/charts/types.ts +2 -1
- package/src/cli/doctor.ts +2 -2
- package/src/dashboard/index.ts +6 -1
- package/src/dashboard/stat-card.tsx +34 -3
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# [2.2.0](https://github.com/jkrumm/basalt-ui/compare/v2.1.0...v2.2.0) (2026-10-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* read subpath peers from the app package in a monorepo ([ca1263d](https://github.com/jkrumm/basalt-ui/commit/ca1263d04ceb41e966c0e93ef3243db4f1359bd1))
|
|
7
|
+
* scan the app package for dropped subpaths in a monorepo ([a4a076c](https://github.com/jkrumm/basalt-ui/commit/a4a076ceee33d70a4180c1f45eb1cbd8a43087aa))
|
|
8
|
+
* stride Heatmap x labels to the container class tick count ([00c93b2](https://github.com/jkrumm/basalt-ui/commit/00c93b2aa34d99e1afd67f979e1e39a9f79f3630))
|
|
9
|
+
* stub getBoundingClientRect on Element.prototype in the sparkline state test ([3ceeb9f](https://github.com/jkrumm/basalt-ui/commit/3ceeb9f5041978d85fbb1e696bc142bef8872402))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* export StatCardSparklineSize and allow render props in the preset ([29fcc01](https://github.com/jkrumm/basalt-ui/commit/29fcc01b6a9565aad34001a7ac2e281022cb8b1f))
|
|
15
|
+
* give Sparkline a state and derive it from StatCard query ([4fb9b39](https://github.com/jkrumm/basalt-ui/commit/4fb9b394105f28cec4ca7753d755cb99b6154514))
|
|
16
|
+
* re-export StatCardSparklineSize from the root ([2c9629d](https://github.com/jkrumm/basalt-ui/commit/2c9629d2cfe042b2ba18947f8ffdf56915ddedc8))
|
|
17
|
+
|
|
1
18
|
# [2.1.0](https://github.com/jkrumm/basalt-ui/compare/v2.0.5...v2.1.0) (2026-10-14)
|
|
2
19
|
|
|
3
20
|
|
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 | 2.0.3 | 2.0.4 | 2.0.5 | 2.1.0 | 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 | 2.0.4 | 2.0.5 | 2.1.0 | 2.2.0 | 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,6 +992,19 @@ 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.2.0 — `doctor` in a monorepo, sparkline state, heatmap ticks
|
|
996
|
+
|
|
997
|
+
- `Sparkline` takes the same `state` as the other chart kinds (pending fills its box, error and
|
|
998
|
+
empty show a dash with the label as its name). `StatCard` derives it from `query` and passes it to
|
|
999
|
+
the `sparkline` render prop as `size.state`, so `<Sparkline {...size} />` is the whole call site.
|
|
1000
|
+
- `StatCardSparklineSize` is exported from `basalt-ui`. The shipped oxlint preset sets
|
|
1001
|
+
`react/no-unstable-nested-components` `allowAsProps: true`, so the documented `sparkline` render
|
|
1002
|
+
prop no longer warns.
|
|
1003
|
+
- `Heatmap` strides its x labels to the container class's tick count (6 at `wide`), where it drew
|
|
1004
|
+
every column.
|
|
1005
|
+
- `doctor`'s `subpath-peers` check scans the app package's source and resolves each peer from the app directory (`basalt.app`, or the single workspace package that depends on basalt-ui), so a monorepo with the peers declared in `apps/<app>` no longer reports every peer missing. No action needed.
|
|
1006
|
+
- `doctor`'s `dropped-subpaths` check likewise scans the app package's source rather than the install root, so a monorepo app's dropped `basalt-ui/<subpath>` imports are found. No action needed.
|
|
1007
|
+
|
|
995
1008
|
## 2.1.0 — the rail reaches folded groups, `toAgentError`
|
|
996
1009
|
|
|
997
1010
|
- `basalt-ui/agent` exports `toAgentError(error: unknown): AgentError`, the classifier
|
package/configs/oxlint.json
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"react/incompatible-library": "error",
|
|
29
29
|
"react/preserve-manual-memoization": "error",
|
|
30
30
|
"react/refs": "error",
|
|
31
|
+
"react/no-unstable-nested-components": ["warn", { "allowAsProps": true }],
|
|
31
32
|
"react/only-export-components": ["warn", { "allowExportNames": ["Route"] }],
|
|
32
33
|
"react/set-state-in-effect": "error",
|
|
33
34
|
"no-constant-binary-expression": "error"
|
package/dist/charts/Heatmap.d.ts
CHANGED
|
@@ -33,7 +33,9 @@ export type HeatmapProps<T> = BasaltProps & {
|
|
|
33
33
|
};
|
|
34
34
|
/** A fixed height, or one per container class. Default: by row count (160–420px). */
|
|
35
35
|
height?: number | ResponsiveChartHeight;
|
|
36
|
-
/** Fill the parent's height instead
|
|
36
|
+
/** Fill the parent's height instead. Overrides `height`. CSS-owned like every other kind's box
|
|
37
|
+
* (`ChartBox`, no measuring, SSR-stable), so the parent needs a definite CSS height — a grid or
|
|
38
|
+
* flex stretch, `h-full`, an explicit height — which no kind can read off an auto-height parent. */
|
|
37
39
|
matchHeight?: boolean;
|
|
38
40
|
state?: ChartState;
|
|
39
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Heatmap.d.ts","sourceRoot":"","sources":["../../src/charts/Heatmap.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"Heatmap.d.ts","sourceRoot":"","sources":["../../src/charts/Heatmap.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAUlD,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAEjF,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,WAAW,GAAG;IAC1C,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,qCAAqC;IACrC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,wCAAwC;IACxC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,4EAA4E;IAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,CAAA;IACjC,0DAA0D;IAC1D,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IACnC,kEAAkE;IAClE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACnC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACnC,4DAA4D;IAC5D,MAAM,CAAC,EAAE,KAAK,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACnC,oGAAoG;IACpG,OAAO,CAAC,EAAE,KAAK,GAAG;QAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,SAAS,eAAe,EAAE,CAAA;KAAE,CAAA;IACjE,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,GAAG,qBAAqB,CAAA;IACvC;;wGAEoG;IACpG,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB,CAAA;AAuBD,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CA4M/D"}
|
package/dist/charts/Heatmap.js
CHANGED
|
@@ -9,6 +9,7 @@ import { scaleQuantize } from "d3-scale";
|
|
|
9
9
|
import { useId, useMemo } from "react";
|
|
10
10
|
import { alpha, VX } from "../tokens/index.js";
|
|
11
11
|
import { resolveContainerClass } from "../tokens/size-classes.js";
|
|
12
|
+
import { strideTicks } from "./compile.js";
|
|
12
13
|
import { ChartEngine, idPrefixOf } from "./host.js";
|
|
13
14
|
import { useCoarsePointer } from "../common/use-media-query.js";
|
|
14
15
|
import { HEIGHT_MAX, HEIGHT_MIN } from "./box.js";
|
|
@@ -87,8 +88,9 @@ function Heatmap(props) {
|
|
|
87
88
|
return {
|
|
88
89
|
chart: ({ width }) => {
|
|
89
90
|
const ticks = { line: false, size: 0 };
|
|
91
|
+
const cls = resolveContainerClass(width);
|
|
90
92
|
const tickLabels = {
|
|
91
|
-
fontSize:
|
|
93
|
+
fontSize: cls === "wide" ? VX.text.micro : VX.text.nano,
|
|
92
94
|
opacity: 1,
|
|
93
95
|
thin: true
|
|
94
96
|
};
|
|
@@ -128,7 +130,11 @@ function Heatmap(props) {
|
|
|
128
130
|
scale: scaleBand().domain(cols).paddingInner(0).paddingOuter(0),
|
|
129
131
|
axis: {
|
|
130
132
|
line: AXIS_LINE,
|
|
131
|
-
ticks: {
|
|
133
|
+
ticks: {
|
|
134
|
+
values: strideTicks(cols, cls),
|
|
135
|
+
format: (v) => formatCol(String(v)),
|
|
136
|
+
...ticks
|
|
137
|
+
},
|
|
132
138
|
tickLabels
|
|
133
139
|
}
|
|
134
140
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
2
|
import type { BasaltProps } from '../common/props.js';
|
|
3
|
+
import type { ChartState } from './types.js';
|
|
3
4
|
export type SparklineProps = BasaltProps & {
|
|
4
5
|
/** The accessible name. Required: a chart without one is an unlabeled image. */
|
|
5
6
|
ariaLabel: string;
|
|
@@ -16,6 +17,9 @@ export type SparklineProps = BasaltProps & {
|
|
|
16
17
|
emphasizeLast?: boolean;
|
|
17
18
|
/** Default `VX.accent`. */
|
|
18
19
|
emphasisColor?: string;
|
|
20
|
+
/** Pending / error / empty, the same contract as every other kind. The placeholder fills the
|
|
21
|
+
* sparkline's own `width` × `height`, so a loading tile does not shift when the trend lands. */
|
|
22
|
+
state?: ChartState;
|
|
19
23
|
};
|
|
20
24
|
/** `useId` output (`«r1»`, `:r1:`) is not a safe SVG id fragment. */
|
|
21
25
|
export declare function Sparkline(props: SparklineProps): ReactElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sparkline.d.ts","sourceRoot":"","sources":["../../src/charts/Sparkline.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAQlD,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IACzC,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IACrB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,2BAA2B;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"Sparkline.d.ts","sourceRoot":"","sources":["../../src/charts/Sparkline.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAQlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IACzC,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IACrB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,2BAA2B;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;oGACgG;IAChG,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB,CAAA;AAiGD,qEAAqE;AAErE,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,CAyC7D"}
|
package/dist/charts/Sparkline.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { dot } from "@tanstack/charts/dot";
|
|
3
3
|
import { decorative } from "@tanstack/charts/mark/decorative";
|
|
4
4
|
import { lineY } from "@tanstack/charts/line";
|
|
@@ -9,6 +9,7 @@ import { VX } from "../tokens/index.js";
|
|
|
9
9
|
import { chartCurve } from "./curves.js";
|
|
10
10
|
import { barMark } from "./marks.js";
|
|
11
11
|
import { ChartEngine, idPrefixOf } from "./host.js";
|
|
12
|
+
import { ChartPlaceholder, resolveChartState } from "./state.js";
|
|
12
13
|
import { CHART_THEME } from "./theme.js";
|
|
13
14
|
const LINE_WIDTH = 1.6;
|
|
14
15
|
const DOT_R = 2.5;
|
|
@@ -95,6 +96,7 @@ function Sparkline(props) {
|
|
|
95
96
|
color = VX.faint,
|
|
96
97
|
emphasizeLast = false,
|
|
97
98
|
emphasisColor = VX.accent,
|
|
99
|
+
state,
|
|
98
100
|
className,
|
|
99
101
|
style
|
|
100
102
|
} = props;
|
|
@@ -105,22 +107,26 @@ function Sparkline(props) {
|
|
|
105
107
|
if (range === null) return null;
|
|
106
108
|
return compileSparkline(rows, range, mark, color, emphasizeLast ? emphasisColor : null);
|
|
107
109
|
}, [data, mark, color, emphasizeLast, emphasisColor]);
|
|
108
|
-
|
|
110
|
+
const resolved = resolveChartState(state);
|
|
111
|
+
return /* @__PURE__ */ jsxs(
|
|
109
112
|
"div",
|
|
110
113
|
{
|
|
111
114
|
"data-basalt-sparkline": "",
|
|
112
115
|
...className !== void 0 && { className },
|
|
113
116
|
style: { width: width ?? "100%", height, minWidth: 0, ...style },
|
|
114
|
-
children:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
children: [
|
|
118
|
+
resolved !== null && /* @__PURE__ */ jsx(ChartPlaceholder, { state, height, compact: true }),
|
|
119
|
+
resolved === null && definition !== null && /* @__PURE__ */ jsx(
|
|
120
|
+
ChartEngine,
|
|
121
|
+
{
|
|
122
|
+
definition,
|
|
123
|
+
ariaLabel,
|
|
124
|
+
height,
|
|
125
|
+
idPrefix: idPrefixOf(id, "spark"),
|
|
126
|
+
coarse: false
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
]
|
|
124
130
|
}
|
|
125
131
|
);
|
|
126
132
|
}
|
package/dist/charts/compile.d.ts
CHANGED
|
@@ -48,6 +48,12 @@ export declare function yGuide<T>(opts: {
|
|
|
48
48
|
side: 'left' | 'right';
|
|
49
49
|
grid: boolean;
|
|
50
50
|
}): Omit<ChartPositionScaleOptions<number>, 'scale'>;
|
|
51
|
+
/**
|
|
52
|
+
* Every n-th value, n the smallest stride that leaves at most the class's x tick count (the same
|
|
53
|
+
* ladder a continuous x axis counts to). A band axis labels every value it is given and only drops
|
|
54
|
+
* the ones that collide, so a short-label grid (18 hour columns) would otherwise draw all of them.
|
|
55
|
+
*/
|
|
56
|
+
export declare function strideTicks<V>(values: readonly V[], cls: ContainerClass): V[];
|
|
51
57
|
export declare function xGuide<X extends ChartX>(opts: {
|
|
52
58
|
model: XScaleModel<X>;
|
|
53
59
|
xTicks: number | readonly X[] | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/charts/compile.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/charts/compile.ts"],"names":[],"mappings":"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"}
|
package/dist/charts/compile.js
CHANGED
|
@@ -86,6 +86,10 @@ function xTickPolicy(model, xTicks) {
|
|
|
86
86
|
};
|
|
87
87
|
return { count: xTicks };
|
|
88
88
|
}
|
|
89
|
+
function strideTicks(values, cls) {
|
|
90
|
+
const stride = Math.max(1, Math.ceil(values.length / LADDER[cls].xTicks));
|
|
91
|
+
return values.filter((_, i) => i % stride === 0);
|
|
92
|
+
}
|
|
89
93
|
function xGuide(opts) {
|
|
90
94
|
const { model, xTicks, format, cls } = opts;
|
|
91
95
|
const ladder = LADDER[cls];
|
|
@@ -378,6 +382,7 @@ export {
|
|
|
378
382
|
dateTicks,
|
|
379
383
|
defaultFormatX,
|
|
380
384
|
defaultNumberFormat,
|
|
385
|
+
strideTicks,
|
|
381
386
|
utcAxisDate,
|
|
382
387
|
utcHeaderDate,
|
|
383
388
|
visibleSeries,
|
package/dist/charts/state.d.ts
CHANGED
|
@@ -13,5 +13,8 @@ export declare function ChartPlaceholder(props: {
|
|
|
13
13
|
state: ChartState | undefined;
|
|
14
14
|
height?: ChartBoxHeight;
|
|
15
15
|
action?: ReactNode;
|
|
16
|
+
/** For a box too small to hold a sentence (a sparkline): error and empty show a `—` and carry the
|
|
17
|
+
* label as the accessible name and the hover title. */
|
|
18
|
+
compact?: boolean;
|
|
16
19
|
}): ReactElement | null;
|
|
17
20
|
//# sourceMappingURL=state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/charts/state.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAInE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,IAAI,CAAA;AAErE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,kBAAkB,CAMnF;AAsBD;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IAC7B,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/charts/state.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAInE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,IAAI,CAAA;AAErE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,kBAAkB,CAMnF;AAsBD;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IAC7B,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB;2DACuD;IACvD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,YAAY,GAAG,IAAI,CAyCtB"}
|
package/dist/charts/state.js
CHANGED
|
@@ -35,16 +35,27 @@ function ChartPlaceholder(props) {
|
|
|
35
35
|
/* @__PURE__ */ jsx("output", { "aria-label": "Loading chart", "aria-busy": "true", className: stateClass, style })
|
|
36
36
|
);
|
|
37
37
|
const label = kind === "error" ? toErrorMessage(props.state?.error, "The chart failed to load.") : emptyLabel(props.state);
|
|
38
|
-
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38
|
+
const body = props.compact ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2014" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39
39
|
/* @__PURE__ */ jsx("span", { children: label }),
|
|
40
40
|
props.action
|
|
41
41
|
] });
|
|
42
|
+
const name = props.compact ? { "aria-label": label, title: label } : {};
|
|
42
43
|
if (kind === "error")
|
|
43
44
|
return fit(
|
|
44
|
-
/* @__PURE__ */ jsx(
|
|
45
|
+
/* @__PURE__ */ jsx(
|
|
46
|
+
"div",
|
|
47
|
+
{
|
|
48
|
+
role: "alert",
|
|
49
|
+
"data-basalt-chart-state": kind,
|
|
50
|
+
className: stateClass,
|
|
51
|
+
style,
|
|
52
|
+
...name,
|
|
53
|
+
children: body
|
|
54
|
+
}
|
|
55
|
+
)
|
|
45
56
|
);
|
|
46
57
|
return fit(
|
|
47
|
-
/* @__PURE__ */ jsx("output", { "data-basalt-chart-state": kind, className: stateClass, style, children: body })
|
|
58
|
+
/* @__PURE__ */ jsx("output", { "data-basalt-chart-state": kind, className: stateClass, style, ...name, children: body })
|
|
48
59
|
);
|
|
49
60
|
}
|
|
50
61
|
export {
|
package/dist/charts/types.d.ts
CHANGED
|
@@ -158,7 +158,8 @@ export type ChartState = {
|
|
|
158
158
|
pending?: boolean;
|
|
159
159
|
/** Truthy = the query failed; an `Error`'s message is the label. */
|
|
160
160
|
error?: unknown;
|
|
161
|
-
/** `true`, or the empty label itself.
|
|
161
|
+
/** `true`, or the empty label itself. The label is the one way to say WHY (`'No runs match the
|
|
162
|
+
* filter'` vs `'No runs yet'`): § 9 fixes the state shape, so there is no reason field. */
|
|
162
163
|
empty?: boolean | string;
|
|
163
164
|
};
|
|
164
165
|
/** A row of `plot.rows(key)`: one per datum, `y: null` kept as a gap. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/charts/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/charts/types.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/doctor.js
CHANGED
|
@@ -266,7 +266,7 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
266
266
|
],
|
|
267
267
|
[
|
|
268
268
|
"dropped-subpaths: no import of a basalt-ui subpath the install lacks",
|
|
269
|
-
droppedSubpathsCheck(
|
|
269
|
+
droppedSubpathsCheck(appDir, cfg, install)
|
|
270
270
|
],
|
|
271
271
|
[
|
|
272
272
|
"app-wiring: the entry mounts BasaltProvider and the router tree is generated",
|
|
@@ -275,7 +275,7 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
275
275
|
["exact-peers: installed exact-pinned peers match basalt-ui", exactPeersCheck(cwd, install)],
|
|
276
276
|
[
|
|
277
277
|
"subpath-peers: every imported basalt-ui subpath has its required peers installed",
|
|
278
|
-
subpathPeersCheck(
|
|
278
|
+
subpathPeersCheck(appDir, cfg, install)
|
|
279
279
|
],
|
|
280
280
|
[
|
|
281
281
|
"config-keys: the basalt config block sets only keys basalt-ui reads",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { WidgetHeader } from './widget-header.js';
|
|
2
2
|
export { DeltaBadge } from './delta-badge.js';
|
|
3
3
|
export { Section } from './section.js';
|
|
4
|
-
export { StatCard, type StatCardBreakdownRow, type StatCardTone } from './stat-card.js';
|
|
4
|
+
export { StatCard, type StatCardBreakdownRow, type StatCardSparklineSize, type StatCardTone, } from './stat-card.js';
|
|
5
5
|
export { StatGroup } from './stat-group.js';
|
|
6
6
|
export { EmptyState } from './empty-state.js';
|
|
7
7
|
export { SettingsSection, SettingsRow, DangerZone } from './settings-section.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EACL,QAAQ,EACR,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,GAClB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/dashboard/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { WidgetHeader } from "./widget-header.js";
|
|
2
2
|
import { DeltaBadge } from "./delta-badge.js";
|
|
3
3
|
import { Section } from "./section.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
StatCard
|
|
6
|
+
} from "./stat-card.js";
|
|
5
7
|
import { StatGroup } from "./stat-group.js";
|
|
6
8
|
import { EmptyState } from "./empty-state.js";
|
|
7
9
|
import { SettingsSection, SettingsRow, DangerZone } from "./settings-section.js";
|
|
@@ -39,6 +39,17 @@ export type StatCardBreakdownRow = {
|
|
|
39
39
|
export type StatCardSparklineSize = {
|
|
40
40
|
width: number;
|
|
41
41
|
height: number;
|
|
42
|
+
/**
|
|
43
|
+
* The card's `query` as a chart state — present only while the sparkline has nothing to draw
|
|
44
|
+
* (pending, or failed with no data), so `<Sparkline {...size} />` forwards it and the tile shows a
|
|
45
|
+
* sized placeholder instead of a hand-rolled `'—'`. Structurally a `ChartState`: this module
|
|
46
|
+
* stays chart-free. Absent without a `query`, and once data has arrived.
|
|
47
|
+
*/
|
|
48
|
+
state?: {
|
|
49
|
+
pending?: boolean;
|
|
50
|
+
error?: unknown;
|
|
51
|
+
empty?: boolean;
|
|
52
|
+
};
|
|
42
53
|
};
|
|
43
54
|
/**
|
|
44
55
|
* `StatCard` re-publishes three NAMED `WidgetHeader` slices (`WidgetHeaderTitleProps` /
|
|
@@ -97,8 +108,12 @@ export type StatCardProps = BasaltProps & SlotStylesProps<StatCardSlot> & Widget
|
|
|
97
108
|
* measured width is the card's own inner width including the bled inset; with `'right'` it is the
|
|
98
109
|
* fixed 72×26 slot (see {@link SPARKLINE_RIGHT_WIDTH} for why that one is not measured).
|
|
99
110
|
*
|
|
111
|
+
* A render prop is a sanctioned pattern here, so `react/no-unstable-nested-components` is
|
|
112
|
+
* configured with `allowAsProps` in the shipped preset. Spread the size (`{...size}`) to forward
|
|
113
|
+
* `state` along with the box.
|
|
114
|
+
*
|
|
100
115
|
* @example
|
|
101
|
-
* sparkline={(
|
|
116
|
+
* sparkline={(size) => <Sparkline ariaLabel="Active users" data={history} {...size} />}
|
|
102
117
|
*/
|
|
103
118
|
sparkline?: ReactNode | ((size: StatCardSparklineSize) => ReactNode);
|
|
104
119
|
/** Where `sparkline` sits. `'bleed'` (default) is today's full-width row bled to the card edges;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../src/dashboard/stat-card.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../src/dashboard/stat-card.tsx"],"names":[],"mappings":"AAiGA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,iBAAiB,CAAA;AAIxB,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAInD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAA;AAE/B;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAA;AAEnE;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAC7B,CAAA;AAcD;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAChE,CAAA;AA6DD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GACrC,eAAe,CAAC,YAAY,CAAC,GAC7B,sBAAsB,GACtB,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,GACtC,sBAAsB,GAAG;IACvB;iEAC6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;IAC3C;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;IAC/B;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,qBAAqB,KAAK,SAAS,CAAC,CAAA;IACpE;4GACwG;IACxG,kBAAkB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IACtC;mGAC+F;IAC/F,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;+EAG2E;IAC3E,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB,CAAA;AAEH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,SAAS,EACT,KAAK,EACL,KAAK,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,kBAA4B,EAC5B,OAAO,EACP,IAAI,EACJ,SAAS,EACT,KAAK,EACL,UAAU,GACX,EAAE,aAAa,+BA0Kf"}
|
|
@@ -6,6 +6,7 @@ import { CtlSlot } from "../theme/index.js";
|
|
|
6
6
|
import { VX } from "../tokens/index.js";
|
|
7
7
|
import { cx } from "../common/props.js";
|
|
8
8
|
import { QueryState } from "./query-state.js";
|
|
9
|
+
import { assertQueryStateLike } from "../common/query-state-like.js";
|
|
9
10
|
import classes from "./stat-card.module.css";
|
|
10
11
|
const SPARKLINE_RIGHT_WIDTH = 72;
|
|
11
12
|
const SPARKLINE_RIGHT_HEIGHT = 26;
|
|
@@ -33,6 +34,13 @@ function useSlotWidth(active) {
|
|
|
33
34
|
width
|
|
34
35
|
};
|
|
35
36
|
}
|
|
37
|
+
function sparklineState(query) {
|
|
38
|
+
if (query === void 0) return void 0;
|
|
39
|
+
assertQueryStateLike("StatCard", query);
|
|
40
|
+
if (query.data !== void 0) return void 0;
|
|
41
|
+
if (query.isError) return { error: query.error ?? true };
|
|
42
|
+
return query.fetchStatus === "idle" ? void 0 : { pending: true };
|
|
43
|
+
}
|
|
36
44
|
const TONE_RAIL_WIDTH = 3;
|
|
37
45
|
const TONE_LABEL = {
|
|
38
46
|
good: "Within the good threshold",
|
|
@@ -64,7 +72,12 @@ function StatCard({
|
|
|
64
72
|
const isRender = typeof sparkline === "function";
|
|
65
73
|
const bleeds = sparklinePlacement === "bleed";
|
|
66
74
|
const { ref: slotRef, width: slotWidth } = useSlotWidth(isRender);
|
|
67
|
-
const
|
|
75
|
+
const state = sparklineState(query);
|
|
76
|
+
const measured = {
|
|
77
|
+
width: slotWidth,
|
|
78
|
+
height: SPARKLINE_RIGHT_HEIGHT,
|
|
79
|
+
...state !== void 0 && { state }
|
|
80
|
+
};
|
|
68
81
|
const breakdownRows = breakdown === void 0 || breakdown.length === 0 ? null : /* @__PURE__ */ jsx("dl", { className: classes.breakdown, children: breakdown.map((row) => /* @__PURE__ */ jsxs(
|
|
69
82
|
"div",
|
|
70
83
|
{
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export { scrollParentOf, useCoarsePointer } from './common/index.js';
|
|
|
13
13
|
export { createBasaltTheme } from './theme/index.js';
|
|
14
14
|
export { ThemeToggle } from './theme/theme-toggle.js';
|
|
15
15
|
export { BasaltShell, PageBar, PageAside, useSizeClass, PageTitle, type ShellBaseProps, type SidebarBlock, type SettingsMenuItem, } from './shell/index.js';
|
|
16
|
-
export { WidgetHeader, DeltaBadge, Section, StatCard, type StatCardBreakdownRow, type StatCardTone, StatGroup, EmptyState, SettingsSection, SettingsRow, DangerZone, } from './dashboard/index.js';
|
|
16
|
+
export { WidgetHeader, DeltaBadge, Section, StatCard, type StatCardBreakdownRow, type StatCardSparklineSize, type StatCardTone, StatGroup, EmptyState, SettingsSection, SettingsRow, DangerZone, } from './dashboard/index.js';
|
|
17
17
|
export { unwrap } from './query-client.js';
|
|
18
18
|
export type { BasaltRegister, SeriesKey } from './register.js';
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,UAAU,EACV,YAAY,EACZ,KAAK,SAAS,GACf,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EACL,WAAW,EACX,OAAO,EACP,SAAS,EACT,YAAY,EACZ,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACtB,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,OAAO,EACP,QAAQ,EACR,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAMvC,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,UAAU,EACV,YAAY,EACZ,KAAK,SAAS,GACf,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EACL,WAAW,EACX,OAAO,EACP,SAAS,EACT,YAAY,EACZ,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACtB,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,OAAO,EACP,QAAQ,EACR,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAMvC,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA"}
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# basalt-ui v2.
|
|
1
|
+
# basalt-ui v2.2.0
|
|
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.
|
|
16
|
+
Version: 2.2.0
|
|
17
17
|
|
|
18
18
|
## basalt-ui
|
|
19
19
|
Import: import { ... } from 'basalt-ui'
|
package/package.json
CHANGED
package/src/charts/Heatmap.tsx
CHANGED
|
@@ -18,6 +18,7 @@ import type { CSSProperties, ReactElement } from 'react'
|
|
|
18
18
|
import type { BasaltProps } from '../common/props'
|
|
19
19
|
import { alpha, VX } from '../tokens'
|
|
20
20
|
import { resolveContainerClass } from '../tokens/size-classes'
|
|
21
|
+
import { strideTicks } from './compile'
|
|
21
22
|
import type { CartesianDefinition } from './compile'
|
|
22
23
|
import { ChartEngine, idPrefixOf } from './host'
|
|
23
24
|
import { useCoarsePointer } from '../common/use-media-query'
|
|
@@ -54,7 +55,9 @@ export type HeatmapProps<T> = BasaltProps & {
|
|
|
54
55
|
tooltip?: false | { rows?: (d: T) => readonly ChartTooltipRow[] }
|
|
55
56
|
/** A fixed height, or one per container class. Default: by row count (160–420px). */
|
|
56
57
|
height?: number | ResponsiveChartHeight
|
|
57
|
-
/** Fill the parent's height instead
|
|
58
|
+
/** Fill the parent's height instead. Overrides `height`. CSS-owned like every other kind's box
|
|
59
|
+
* (`ChartBox`, no measuring, SSR-stable), so the parent needs a definite CSS height — a grid or
|
|
60
|
+
* flex stretch, `h-full`, an explicit height — which no kind can read off an auto-height parent. */
|
|
58
61
|
matchHeight?: boolean
|
|
59
62
|
state?: ChartState
|
|
60
63
|
}
|
|
@@ -149,8 +152,9 @@ export function Heatmap<T>(props: HeatmapProps<T>): ReactElement {
|
|
|
149
152
|
return {
|
|
150
153
|
chart: ({ width }: ChartBuildContext): StoredChartSpec => {
|
|
151
154
|
const ticks = { line: false as const, size: 0 }
|
|
155
|
+
const cls = resolveContainerClass(width)
|
|
152
156
|
const tickLabels = {
|
|
153
|
-
fontSize:
|
|
157
|
+
fontSize: cls === 'wide' ? VX.text.micro : VX.text.nano,
|
|
154
158
|
opacity: 1,
|
|
155
159
|
thin: true,
|
|
156
160
|
}
|
|
@@ -190,7 +194,11 @@ export function Heatmap<T>(props: HeatmapProps<T>): ReactElement {
|
|
|
190
194
|
scale: scaleBand<string>().domain(cols).paddingInner(0).paddingOuter(0),
|
|
191
195
|
axis: {
|
|
192
196
|
line: AXIS_LINE,
|
|
193
|
-
ticks: {
|
|
197
|
+
ticks: {
|
|
198
|
+
values: strideTicks(cols, cls),
|
|
199
|
+
format: (v) => formatCol(String(v)),
|
|
200
|
+
...ticks,
|
|
201
|
+
},
|
|
194
202
|
tickLabels,
|
|
195
203
|
},
|
|
196
204
|
},
|
package/src/charts/Sparkline.tsx
CHANGED
|
@@ -18,7 +18,9 @@ import type { CartesianDefinition } from './compile'
|
|
|
18
18
|
import { chartCurve } from './curves'
|
|
19
19
|
import { barMark } from './marks'
|
|
20
20
|
import { ChartEngine, idPrefixOf } from './host'
|
|
21
|
+
import { ChartPlaceholder, resolveChartState } from './state'
|
|
21
22
|
import { CHART_THEME } from './theme'
|
|
23
|
+
import type { ChartState } from './types'
|
|
22
24
|
|
|
23
25
|
export type SparklineProps = BasaltProps & {
|
|
24
26
|
/** The accessible name. Required: a chart without one is an unlabeled image. */
|
|
@@ -36,6 +38,9 @@ export type SparklineProps = BasaltProps & {
|
|
|
36
38
|
emphasizeLast?: boolean
|
|
37
39
|
/** Default `VX.accent`. */
|
|
38
40
|
emphasisColor?: string
|
|
41
|
+
/** Pending / error / empty, the same contract as every other kind. The placeholder fills the
|
|
42
|
+
* sparkline's own `width` × `height`, so a loading tile does not shift when the trend lands. */
|
|
43
|
+
state?: ChartState
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
type Point = { i: number; v: number | null }
|
|
@@ -145,6 +150,7 @@ export function Sparkline(props: SparklineProps): ReactElement {
|
|
|
145
150
|
color = VX.faint,
|
|
146
151
|
emphasizeLast = false,
|
|
147
152
|
emphasisColor = VX.accent,
|
|
153
|
+
state,
|
|
148
154
|
className,
|
|
149
155
|
style,
|
|
150
156
|
} = props
|
|
@@ -156,13 +162,15 @@ export function Sparkline(props: SparklineProps): ReactElement {
|
|
|
156
162
|
if (range === null) return null
|
|
157
163
|
return compileSparkline(rows, range, mark, color, emphasizeLast ? emphasisColor : null)
|
|
158
164
|
}, [data, mark, color, emphasizeLast, emphasisColor])
|
|
165
|
+
const resolved = resolveChartState(state)
|
|
159
166
|
return (
|
|
160
167
|
<div
|
|
161
168
|
data-basalt-sparkline=""
|
|
162
169
|
{...(className !== undefined && { className })}
|
|
163
170
|
style={{ width: width ?? '100%', height, minWidth: 0, ...style }}
|
|
164
171
|
>
|
|
165
|
-
{
|
|
172
|
+
{resolved !== null && <ChartPlaceholder state={state} height={height} compact />}
|
|
173
|
+
{resolved === null && definition !== null && (
|
|
166
174
|
<ChartEngine
|
|
167
175
|
definition={definition}
|
|
168
176
|
ariaLabel={ariaLabel}
|
package/src/charts/compile.ts
CHANGED
|
@@ -196,6 +196,16 @@ function xTickPolicy<X extends ChartX>(
|
|
|
196
196
|
return { count: xTicks }
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Every n-th value, n the smallest stride that leaves at most the class's x tick count (the same
|
|
201
|
+
* ladder a continuous x axis counts to). A band axis labels every value it is given and only drops
|
|
202
|
+
* the ones that collide, so a short-label grid (18 hour columns) would otherwise draw all of them.
|
|
203
|
+
*/
|
|
204
|
+
export function strideTicks<V>(values: readonly V[], cls: ContainerClass): V[] {
|
|
205
|
+
const stride = Math.max(1, Math.ceil(values.length / LADDER[cls].xTicks))
|
|
206
|
+
return values.filter((_, i) => i % stride === 0)
|
|
207
|
+
}
|
|
208
|
+
|
|
199
209
|
export function xGuide<X extends ChartX>(opts: {
|
|
200
210
|
model: XScaleModel<X>
|
|
201
211
|
xTicks: number | readonly X[] | undefined
|
package/src/charts/state.tsx
CHANGED
|
@@ -45,6 +45,9 @@ export function ChartPlaceholder(props: {
|
|
|
45
45
|
state: ChartState | undefined
|
|
46
46
|
height?: ChartBoxHeight
|
|
47
47
|
action?: ReactNode
|
|
48
|
+
/** For a box too small to hold a sentence (a sparkline): error and empty show a `—` and carry the
|
|
49
|
+
* label as the accessible name and the hover title. */
|
|
50
|
+
compact?: boolean
|
|
48
51
|
}): ReactElement | null {
|
|
49
52
|
const kind = resolveChartState(props.state)
|
|
50
53
|
if (kind === null) return null
|
|
@@ -60,20 +63,29 @@ export function ChartPlaceholder(props: {
|
|
|
60
63
|
kind === 'error'
|
|
61
64
|
? toErrorMessage(props.state?.error, 'The chart failed to load.')
|
|
62
65
|
: emptyLabel(props.state)
|
|
63
|
-
const body = (
|
|
66
|
+
const body = props.compact ? (
|
|
67
|
+
<span aria-hidden="true">—</span>
|
|
68
|
+
) : (
|
|
64
69
|
<>
|
|
65
70
|
<span>{label}</span>
|
|
66
71
|
{props.action}
|
|
67
72
|
</>
|
|
68
73
|
)
|
|
74
|
+
const name = props.compact ? { 'aria-label': label, title: label } : {}
|
|
69
75
|
if (kind === 'error')
|
|
70
76
|
return fit(
|
|
71
|
-
<div
|
|
77
|
+
<div
|
|
78
|
+
role="alert"
|
|
79
|
+
data-basalt-chart-state={kind}
|
|
80
|
+
className={stateClass}
|
|
81
|
+
style={style}
|
|
82
|
+
{...name}
|
|
83
|
+
>
|
|
72
84
|
{body}
|
|
73
85
|
</div>,
|
|
74
86
|
)
|
|
75
87
|
return fit(
|
|
76
|
-
<output data-basalt-chart-state={kind} className={stateClass} style={style}>
|
|
88
|
+
<output data-basalt-chart-state={kind} className={stateClass} style={style} {...name}>
|
|
77
89
|
{body}
|
|
78
90
|
</output>,
|
|
79
91
|
)
|
package/src/charts/types.ts
CHANGED
|
@@ -169,7 +169,8 @@ export type ChartState = {
|
|
|
169
169
|
pending?: boolean
|
|
170
170
|
/** Truthy = the query failed; an `Error`'s message is the label. */
|
|
171
171
|
error?: unknown
|
|
172
|
-
/** `true`, or the empty label itself.
|
|
172
|
+
/** `true`, or the empty label itself. The label is the one way to say WHY (`'No runs match the
|
|
173
|
+
* filter'` vs `'No runs yet'`): § 9 fixes the state shape, so there is no reason field. */
|
|
173
174
|
empty?: boolean | string
|
|
174
175
|
}
|
|
175
176
|
|
package/src/cli/doctor.ts
CHANGED
|
@@ -395,7 +395,7 @@ export function doctor(invocationCwd: string = process.cwd(), flags: string[] =
|
|
|
395
395
|
],
|
|
396
396
|
[
|
|
397
397
|
'dropped-subpaths: no import of a basalt-ui subpath the install lacks',
|
|
398
|
-
droppedSubpathsCheck(
|
|
398
|
+
droppedSubpathsCheck(appDir, cfg, install),
|
|
399
399
|
],
|
|
400
400
|
[
|
|
401
401
|
'app-wiring: the entry mounts BasaltProvider and the router tree is generated',
|
|
@@ -404,7 +404,7 @@ export function doctor(invocationCwd: string = process.cwd(), flags: string[] =
|
|
|
404
404
|
['exact-peers: installed exact-pinned peers match basalt-ui', exactPeersCheck(cwd, install)],
|
|
405
405
|
[
|
|
406
406
|
'subpath-peers: every imported basalt-ui subpath has its required peers installed',
|
|
407
|
-
subpathPeersCheck(
|
|
407
|
+
subpathPeersCheck(appDir, cfg, install),
|
|
408
408
|
],
|
|
409
409
|
[
|
|
410
410
|
'config-keys: the basalt config block sets only keys basalt-ui reads',
|
package/src/dashboard/index.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export { WidgetHeader } from './widget-header'
|
|
2
2
|
export { DeltaBadge } from './delta-badge'
|
|
3
3
|
export { Section } from './section'
|
|
4
|
-
export {
|
|
4
|
+
export {
|
|
5
|
+
StatCard,
|
|
6
|
+
type StatCardBreakdownRow,
|
|
7
|
+
type StatCardSparklineSize,
|
|
8
|
+
type StatCardTone,
|
|
9
|
+
} from './stat-card'
|
|
5
10
|
export { StatGroup } from './stat-group'
|
|
6
11
|
export { EmptyState } from './empty-state'
|
|
7
12
|
export { SettingsSection, SettingsRow, DangerZone } from './settings-section'
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
* here. Pass your own sparkline at the call site (basalt ships no `Sparkline` kind in 2.0.0).
|
|
24
24
|
*
|
|
25
25
|
* `query` hands the card's pending/error/empty branch to `QueryState` at the `'section'` tier,
|
|
26
|
-
* rendered under the header rather than over it — the title row is chrome and must not flicker.
|
|
26
|
+
* rendered under the header rather than over it — the title row is chrome and must not flicker. The
|
|
27
|
+
* same query also reaches a render-prop `sparkline` as `size.state`, so `<Sparkline {...size} />`
|
|
28
|
+
* shows its sized pending / error placeholder with no hand-rolled `'—'`.
|
|
27
29
|
*
|
|
28
30
|
* `tone` marks the card as past a threshold with an accent rail down its leading edge. It exists
|
|
29
31
|
* because `value` is typed `string`: without it, a card whose number has crossed a threshold reads
|
|
@@ -106,6 +108,7 @@ import { cx } from '../common/props'
|
|
|
106
108
|
import type { BasaltProps, SlotStylesProps, Tone } from '../common/props'
|
|
107
109
|
import { QueryState } from './query-state'
|
|
108
110
|
import type { QueryStateLike } from './query-state'
|
|
111
|
+
import { assertQueryStateLike } from '../common/query-state-like'
|
|
109
112
|
import classes from './stat-card.module.css'
|
|
110
113
|
|
|
111
114
|
/**
|
|
@@ -160,6 +163,13 @@ const SPARKLINE_RIGHT_HEIGHT = 26
|
|
|
160
163
|
export type StatCardSparklineSize = {
|
|
161
164
|
width: number
|
|
162
165
|
height: number
|
|
166
|
+
/**
|
|
167
|
+
* The card's `query` as a chart state — present only while the sparkline has nothing to draw
|
|
168
|
+
* (pending, or failed with no data), so `<Sparkline {...size} />` forwards it and the tile shows a
|
|
169
|
+
* sized placeholder instead of a hand-rolled `'—'`. Structurally a `ChartState`: this module
|
|
170
|
+
* stays chart-free. Absent without a `query`, and once data has arrived.
|
|
171
|
+
*/
|
|
172
|
+
state?: { pending?: boolean; error?: unknown; empty?: boolean }
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
/**
|
|
@@ -199,6 +209,18 @@ function useSlotWidth(active: boolean): {
|
|
|
199
209
|
}
|
|
200
210
|
}
|
|
201
211
|
|
|
212
|
+
/** The `query` as a sparkline state, by the same precedence as {@link QueryState}: an error with no
|
|
213
|
+
* data is an error, no data and not idle is pending, anything else draws. */
|
|
214
|
+
function sparklineState(
|
|
215
|
+
query: QueryStateLike<unknown> | undefined,
|
|
216
|
+
): StatCardSparklineSize['state'] {
|
|
217
|
+
if (query === undefined) return undefined
|
|
218
|
+
assertQueryStateLike('StatCard', query)
|
|
219
|
+
if (query.data !== undefined) return undefined
|
|
220
|
+
if (query.isError) return { error: query.error ?? true }
|
|
221
|
+
return query.fetchStatus === 'idle' ? undefined : { pending: true }
|
|
222
|
+
}
|
|
223
|
+
|
|
202
224
|
/** The rail's width, in px. Wide enough to read as a deliberate mark at a glance, narrow enough
|
|
203
225
|
* that it cannot be mistaken for the card's own edge. */
|
|
204
226
|
const TONE_RAIL_WIDTH = 3
|
|
@@ -270,8 +292,12 @@ export type StatCardProps = BasaltProps &
|
|
|
270
292
|
* measured width is the card's own inner width including the bled inset; with `'right'` it is the
|
|
271
293
|
* fixed 72×26 slot (see {@link SPARKLINE_RIGHT_WIDTH} for why that one is not measured).
|
|
272
294
|
*
|
|
295
|
+
* A render prop is a sanctioned pattern here, so `react/no-unstable-nested-components` is
|
|
296
|
+
* configured with `allowAsProps` in the shipped preset. Spread the size (`{...size}`) to forward
|
|
297
|
+
* `state` along with the box.
|
|
298
|
+
*
|
|
273
299
|
* @example
|
|
274
|
-
* sparkline={(
|
|
300
|
+
* sparkline={(size) => <Sparkline ariaLabel="Active users" data={history} {...size} />}
|
|
275
301
|
*/
|
|
276
302
|
sparkline?: ReactNode | ((size: StatCardSparklineSize) => ReactNode)
|
|
277
303
|
/** Where `sparkline` sits. `'bleed'` (default) is today's full-width row bled to the card edges;
|
|
@@ -313,7 +339,12 @@ export function StatCard({
|
|
|
313
339
|
const bleeds = sparklinePlacement === 'bleed'
|
|
314
340
|
// Only a render prop needs a measurement; a plain node sizes itself.
|
|
315
341
|
const { ref: slotRef, width: slotWidth } = useSlotWidth(isRender)
|
|
316
|
-
const
|
|
342
|
+
const state = sparklineState(query)
|
|
343
|
+
const measured: StatCardSparklineSize = {
|
|
344
|
+
width: slotWidth,
|
|
345
|
+
height: SPARKLINE_RIGHT_HEIGHT,
|
|
346
|
+
...(state !== undefined && { state }),
|
|
347
|
+
}
|
|
317
348
|
|
|
318
349
|
// A `<dl>`, not a table and not a stack of divs: each row IS a term and its value, which is the
|
|
319
350
|
// one semantic that survives a reader meeting the card out of context.
|