basalt-ui 1.20.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +11 -5
- package/CHANGELOG.md +33 -0
- package/MIGRATING.md +231 -50
- package/README.md +57 -10
- package/agent/rules/basalt-app.md +49 -2
- package/agent/rules/basalt-charts.md +15 -12
- package/agent/rules/basalt-content.md +4 -0
- package/agent/rules/basalt-router.md +57 -5
- package/agent/rules/basalt-state.md +21 -3
- package/agent/rules/basalt-tokens.md +78 -16
- package/agent/skills/basalt-app/SKILL.md +5 -1
- package/agent/skills/basalt-charts/SKILL.md +5 -3
- package/agent/templates/CLAUDE-block.md.tpl +11 -5
- package/configs/lefthook.yml +48 -15
- package/configs/oxlint-plugin.js +218 -69
- package/configs/oxlint-plugin.test.ts +331 -9
- package/dist/charts/kinds/Bars.d.ts +1 -1
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Donut.d.ts +1 -1
- package/dist/charts/kinds/Donut.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.d.ts +1 -1
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/Heatmap.d.ts +1 -1
- package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
- package/dist/charts/kinds/MultiLine.d.ts +1 -1
- package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
- package/dist/charts/kinds/StackedArea.d.ts +1 -1
- package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
- package/dist/charts/kinds/ZonedLine.d.ts +1 -1
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/cli/index.d.ts +55 -15
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +521 -71
- package/dist/cli/waiver-audit.test.d.ts +2 -0
- package/dist/cli/waiver-audit.test.d.ts.map +1 -0
- package/dist/guard/index.d.ts +114 -2
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +216 -33
- package/dist/router-tanstack/multi-search-param-store.d.ts +13 -0
- package/dist/router-tanstack/multi-search-param-store.d.ts.map +1 -1
- package/dist/router-tanstack/multi-search-param-store.js +4 -1
- package/dist/router-tanstack/search-param-store.d.ts +29 -5
- package/dist/router-tanstack/search-param-store.d.ts.map +1 -1
- package/dist/router-tanstack/search-param-store.js +31 -3
- package/dist/router-tanstack/search-param-store.test.d.ts +2 -0
- package/dist/router-tanstack/search-param-store.test.d.ts.map +1 -0
- package/dist/shell/index.d.ts +12 -5
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +24 -6
- package/dist/tokens/index.d.ts +3 -1
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +5 -1
- package/dist/tokens/palette.d.ts +2 -2
- package/dist/tokens/palette.js +2 -2
- package/dist/tokens/text-scale.test.d.ts +2 -0
- package/dist/tokens/text-scale.test.d.ts.map +1 -0
- package/dist/tokens.css +4 -2
- package/dist/vite.d.ts +28 -3
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +75 -26
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/charts/kinds/Bars.tsx +1 -1
- package/src/charts/kinds/Donut.tsx +1 -1
- package/src/charts/kinds/DualPanel.tsx +2 -2
- package/src/charts/kinds/Heatmap.tsx +1 -1
- package/src/charts/kinds/MultiLine.tsx +1 -1
- package/src/charts/kinds/StackedArea.tsx +1 -1
- package/src/charts/kinds/ZonedLine.tsx +1 -1
- package/src/cli/check-theme.test.ts +35 -0
- package/src/cli/help.test.ts +5 -1
- package/src/cli/index.ts +978 -133
- package/src/cli/init-sync.test.ts +2 -0
- package/src/cli/template-ledger.test.ts +1 -1
- package/src/cli/toolchain-wiring.test.ts +352 -1
- package/src/cli/waiver-audit.test.ts +211 -0
- package/src/guard/check-source.test.ts +638 -1
- package/src/guard/index.ts +556 -63
- package/src/router-tanstack/multi-search-param-store.ts +16 -1
- package/src/router-tanstack/search-param-store.test.ts +135 -0
- package/src/router-tanstack/search-param-store.ts +90 -8
- package/src/shell/app-mobile-nav.tsx +1 -1
- package/src/shell/index.test.tsx +52 -0
- package/src/shell/index.tsx +64 -13
- package/src/tokens/index.ts +24 -1
- package/src/tokens/palette.ts +2 -2
- package/src/tokens/text-scale.test.ts +51 -0
- package/src/vite.test.ts +158 -6
- package/src/vite.ts +176 -34
|
@@ -1,25 +1,53 @@
|
|
|
1
1
|
import { createPersistedState, readPersistedValue } from "../state.js";
|
|
2
|
+
function warnLinkPinsFallback(input) {
|
|
3
|
+
const { key, param, urlValue, storedValue } = input;
|
|
4
|
+
console.warn(
|
|
5
|
+
`[basalt-ui] createSearchParamStore('${key}'): the URL pinned \`${param}=${urlValue}\` (the fallback) while '${storedValue}' was persisted, and nothing has read this store back. A nav link is almost certainly declaring \`search: { ${param}: '${urlValue}' }\` at module scope, which overrides the stored value on every click \u2014 pass the store's own reader instead: \`search: <store>.linkSearch\`. (dev only)`
|
|
6
|
+
);
|
|
7
|
+
}
|
|
2
8
|
function createSearchParamStore(opts) {
|
|
3
9
|
const version = opts.version ?? 1;
|
|
4
|
-
|
|
10
|
+
let readerWired = false;
|
|
11
|
+
let warned = false;
|
|
12
|
+
const read = () => {
|
|
5
13
|
const raw = readPersistedValue(opts.key, version);
|
|
6
14
|
if (typeof raw !== "string") return null;
|
|
7
15
|
if (opts.values.includes(raw)) return raw;
|
|
8
16
|
return null;
|
|
9
17
|
};
|
|
18
|
+
const readStored = () => {
|
|
19
|
+
readerWired = true;
|
|
20
|
+
return read();
|
|
21
|
+
};
|
|
22
|
+
const linkSearch = () => {
|
|
23
|
+
readerWired = true;
|
|
24
|
+
return { [opts.param]: read() ?? opts.fallback };
|
|
25
|
+
};
|
|
10
26
|
const validateSearch = (search) => {
|
|
11
27
|
const raw = search[opts.param];
|
|
12
28
|
if (typeof raw === "string" && opts.values.includes(raw)) {
|
|
29
|
+
if (!warned && !readerWired && raw === opts.fallback && process.env["NODE_ENV"] !== "production") {
|
|
30
|
+
const stored = read();
|
|
31
|
+
if (stored !== null && stored !== raw) {
|
|
32
|
+
warned = true;
|
|
33
|
+
warnLinkPinsFallback({
|
|
34
|
+
key: opts.key,
|
|
35
|
+
param: opts.param,
|
|
36
|
+
urlValue: raw,
|
|
37
|
+
storedValue: stored
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
13
41
|
return { [opts.param]: raw };
|
|
14
42
|
}
|
|
15
|
-
return { [opts.param]:
|
|
43
|
+
return { [opts.param]: read() ?? opts.fallback };
|
|
16
44
|
};
|
|
17
45
|
const useStore = createPersistedState({
|
|
18
46
|
key: opts.key,
|
|
19
47
|
version,
|
|
20
48
|
initial: opts.fallback
|
|
21
49
|
});
|
|
22
|
-
return { validateSearch, useStore, readStored };
|
|
50
|
+
return { validateSearch, useStore, readStored, linkSearch };
|
|
23
51
|
}
|
|
24
52
|
export {
|
|
25
53
|
createSearchParamStore
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-param-store.test.d.ts","sourceRoot":"","sources":["../../src/router-tanstack/search-param-store.test.ts"],"names":[],"mappings":""}
|
package/dist/shell/index.d.ts
CHANGED
|
@@ -67,13 +67,20 @@ export type BasaltShellProps = {
|
|
|
67
67
|
* `onOpen`, e.g. `() => openSpotlight()` from basalt-ui/commands.
|
|
68
68
|
*/
|
|
69
69
|
search?: SidebarSearchConfig;
|
|
70
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* localStorage key for the persisted sidebar-collapsed flag. Ignored when `collapsed` is set.
|
|
72
|
+
*
|
|
73
|
+
* Persisted through basalt's own `createPersistedState`, so the real storage key is
|
|
74
|
+
* `basalt:<storageKey>` and the value is the versioned `{ v, value }` envelope. A consumer
|
|
75
|
+
* mirroring this state reads it with `readPersistedValue(storageKey, 1)` from `basalt-ui/state`
|
|
76
|
+
* — never with a bare `localStorage.getItem`, which is what the pre-1.20.1 shell forced.
|
|
77
|
+
*/
|
|
71
78
|
storageKey?: string;
|
|
72
79
|
/**
|
|
73
|
-
* Controlled desktop-collapse value. When provided, the shell no longer owns the
|
|
74
|
-
*
|
|
75
|
-
* `
|
|
76
|
-
* reproduces today's internal, persisted collapse behavior unchanged.
|
|
80
|
+
* Controlled desktop-collapse value. When provided, the shell no longer owns the persisted
|
|
81
|
+
* collapse state — the consumer does (e.g. to drive it from its own `Cmd+B` hotkey), and should
|
|
82
|
+
* own it through `createPersistedState` too. Pair with `onCollapsedChange` to receive toggle
|
|
83
|
+
* events; omitting both reproduces today's internal, persisted collapse behavior unchanged.
|
|
77
84
|
*/
|
|
78
85
|
collapsed?: boolean;
|
|
79
86
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shell/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shell/index.tsx"],"names":[],"mappings":"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"}
|
package/dist/shell/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { AppShell } from "@mantine/core";
|
|
3
|
-
import { useLocalStorage } from "@mantine/hooks";
|
|
4
3
|
import { useMemo } from "react";
|
|
5
4
|
import { AppSidebar } from "./app-sidebar.js";
|
|
6
5
|
import { MobileNav, accountRowCount } from "./app-mobile-nav.js";
|
|
@@ -8,6 +7,7 @@ import { projectMobileNav } from "./mobile-nav-model.js";
|
|
|
8
7
|
import { AppBreadcrumbs } from "./app-breadcrumbs.js";
|
|
9
8
|
import { PageActionsOutlet, PageHeaderProvider } from "./page-header.js";
|
|
10
9
|
import { useBasaltSpacing } from "../theme/index.js";
|
|
10
|
+
import { createPersistedState } from "../state.js";
|
|
11
11
|
import headerClasses from "./app-header.module.css";
|
|
12
12
|
import mobileNavClasses from "./app-mobile-nav.module.css";
|
|
13
13
|
import { AppSidebar as AppSidebar2 } from "./app-sidebar.js";
|
|
@@ -47,6 +47,28 @@ function findActiveWithParent(items, parentLabel, parentAnchor, parentHref) {
|
|
|
47
47
|
}
|
|
48
48
|
return void 0;
|
|
49
49
|
}
|
|
50
|
+
const COLLAPSE_VERSION = 1;
|
|
51
|
+
const collapseStores = /* @__PURE__ */ new Map();
|
|
52
|
+
function migrateLegacyCollapse(key) {
|
|
53
|
+
try {
|
|
54
|
+
if (window.localStorage.getItem(`basalt:${key}`) !== null) return;
|
|
55
|
+
const legacy = window.localStorage.getItem(key);
|
|
56
|
+
if (legacy !== "true" && legacy !== "false") return;
|
|
57
|
+
window.localStorage.setItem(
|
|
58
|
+
`basalt:${key}`,
|
|
59
|
+
JSON.stringify({ v: COLLAPSE_VERSION, value: legacy === "true" })
|
|
60
|
+
);
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function collapseStore(key) {
|
|
65
|
+
const cached = collapseStores.get(key);
|
|
66
|
+
if (cached) return cached;
|
|
67
|
+
if (typeof window !== "undefined") migrateLegacyCollapse(key);
|
|
68
|
+
const store = createPersistedState({ key, version: COLLAPSE_VERSION, initial: false });
|
|
69
|
+
collapseStores.set(key, store);
|
|
70
|
+
return store;
|
|
71
|
+
}
|
|
50
72
|
function BasaltShell({
|
|
51
73
|
brand,
|
|
52
74
|
sections,
|
|
@@ -62,11 +84,7 @@ function BasaltShell({
|
|
|
62
84
|
children
|
|
63
85
|
}) {
|
|
64
86
|
const { step } = useBasaltSpacing();
|
|
65
|
-
const [storedCollapsed, setStoredCollapsed] =
|
|
66
|
-
key: storageKey,
|
|
67
|
-
defaultValue: false,
|
|
68
|
-
getInitialValueInEffect: false
|
|
69
|
-
});
|
|
87
|
+
const [storedCollapsed, setStoredCollapsed] = collapseStore(storageKey)();
|
|
70
88
|
const isCollapseControlled = collapsedProp !== void 0;
|
|
71
89
|
const collapsed = isCollapseControlled ? collapsedProp : storedCollapsed;
|
|
72
90
|
const toggleCollapse = () => {
|
package/dist/tokens/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export declare const VX: {
|
|
|
40
40
|
readonly legendGap: number;
|
|
41
41
|
readonly legendFontSize: 13.5;
|
|
42
42
|
readonly text: {
|
|
43
|
+
readonly nano: 10;
|
|
43
44
|
readonly micro: 11;
|
|
44
45
|
readonly xs: 12.5;
|
|
45
46
|
readonly sm: 13.5;
|
|
@@ -49,6 +50,7 @@ export declare const VX: {
|
|
|
49
50
|
readonly h2: 21;
|
|
50
51
|
readonly kpi: 24;
|
|
51
52
|
readonly h1: 26;
|
|
53
|
+
readonly display: 30;
|
|
52
54
|
};
|
|
53
55
|
readonly radiusCard: "var(--vx-radius-card)";
|
|
54
56
|
readonly radiusCtrl: "var(--vx-radius-ctrl)";
|
|
@@ -240,7 +242,7 @@ export type BuildPaletteOpts = {
|
|
|
240
242
|
* `'core'` keeps the 9 generic anchors — the stack rhythm, the two control heights, the row
|
|
241
243
|
* insets — and drops the 99 named for a specific basalt component
|
|
242
244
|
* (`--vx-space-agent-transcript-inset`, `--vx-space-toc-sub-indent`, …), taking the emitted set
|
|
243
|
-
* from
|
|
245
|
+
* from 204 variables to 105. Nothing outside basalt's own React components reads those, so a
|
|
244
246
|
* framework-free consumer is carrying them for nothing.
|
|
245
247
|
*
|
|
246
248
|
* This is a SPACING filter only: color, radius, shadow, type and status variables are identical
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAMvE,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,WAAW,CAAA;AAOjC,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnF,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAM5D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAO7C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,wFAAwF;AACxF,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,GAAG,MAAM,KAAG,MACoB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tokens/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tokens/index.js
CHANGED
|
@@ -14,6 +14,8 @@ import { deriveRadius } from "./palette.js";
|
|
|
14
14
|
import { deriveSpacing } from "./palette.js";
|
|
15
15
|
const alpha = (token, a) => `color-mix(in srgb, ${token} ${Math.round(a * 100)}%, transparent)`;
|
|
16
16
|
const TEXT = {
|
|
17
|
+
nano: 10,
|
|
18
|
+
// engraved/graphic label INSIDE a drawn object (a plate face, a dial, a chip) — never UI copy or prose
|
|
17
19
|
micro: 11,
|
|
18
20
|
// mono uppercase micro-label (table th, Menu.Label, sidebar/section headers, axis ticks)
|
|
19
21
|
xs: 12.5,
|
|
@@ -30,8 +32,10 @@ const TEXT = {
|
|
|
30
32
|
// article-density Prose h2 (docs/CONTENT-SPEC.md §5)
|
|
31
33
|
kpi: 24,
|
|
32
34
|
// the StatCard hero numeral (density pass: 31 → 24, tighter/less shouty)
|
|
33
|
-
h1: 26
|
|
35
|
+
h1: 26,
|
|
34
36
|
// article-density Prose h1 (docs/CONTENT-SPEC.md §5)
|
|
37
|
+
display: 30
|
|
38
|
+
// a numeral read at arm's length (a keypad readout, a timer, a kiosk figure) — not a heading
|
|
35
39
|
};
|
|
36
40
|
const VX = {
|
|
37
41
|
// Non-color sizing constants
|
package/dist/tokens/palette.d.ts
CHANGED
|
@@ -112,11 +112,11 @@ export declare const SHADOW: {
|
|
|
112
112
|
* ever needs more, raise the DROP. Do not reintroduce an edge; both shapes have been tried.
|
|
113
113
|
*/
|
|
114
114
|
readonly raised: {
|
|
115
|
-
readonly light: "0 1px 2px rgba(28, 25, 23, 0.
|
|
115
|
+
readonly light: "0 1px 2px rgba(28, 25, 23, 0.1)";
|
|
116
116
|
readonly dark: "0 1px 2px rgba(0, 0, 0, 0.35), inset 0 0 0 1px color-mix(in srgb, #ffffff 8%, transparent)";
|
|
117
117
|
};
|
|
118
118
|
readonly overlay: {
|
|
119
|
-
readonly light: "0 8px 24px rgba(28, 25, 23, 0.
|
|
119
|
+
readonly light: "0 8px 24px rgba(28, 25, 23, 0.1)";
|
|
120
120
|
readonly dark: "0 8px 24px rgba(0, 0, 0, 0.5)";
|
|
121
121
|
};
|
|
122
122
|
};
|
package/dist/tokens/palette.js
CHANGED
|
@@ -72,7 +72,7 @@ const SHADOW = {
|
|
|
72
72
|
* ever needs more, raise the DROP. Do not reintroduce an edge; both shapes have been tried.
|
|
73
73
|
*/
|
|
74
74
|
raised: {
|
|
75
|
-
light: "0 1px 2px rgba(28, 25, 23, 0.
|
|
75
|
+
light: "0 1px 2px rgba(28, 25, 23, 0.1)",
|
|
76
76
|
dark: "0 1px 2px rgba(0, 0, 0, 0.35), inset 0 0 0 1px color-mix(in srgb, #ffffff 8%, transparent)"
|
|
77
77
|
},
|
|
78
78
|
// Floating-layer elevation (menus, popovers, tooltips, modals, drawers) — a REAL drop shadow, a
|
|
@@ -80,7 +80,7 @@ const SHADOW = {
|
|
|
80
80
|
// Unlike `card`, no embedded ring: floating surfaces carry a real 1px `--vx-surface-border` so
|
|
81
81
|
// Mantine's rotated-square arrow inherits a proper edge.
|
|
82
82
|
overlay: {
|
|
83
|
-
light: "0 8px 24px rgba(28, 25, 23, 0.
|
|
83
|
+
light: "0 8px 24px rgba(28, 25, 23, 0.1)",
|
|
84
84
|
dark: "0 8px 24px rgba(0, 0, 0, 0.5)"
|
|
85
85
|
}
|
|
86
86
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-scale.test.d.ts","sourceRoot":"","sources":["../../src/tokens/text-scale.test.ts"],"names":[],"mappings":""}
|
package/dist/tokens.css
CHANGED
|
@@ -138,6 +138,7 @@
|
|
|
138
138
|
--vx-fill-hover-lime: color-mix(in srgb, var(--vx-fill-lime) 88%, #000);
|
|
139
139
|
--vx-fill-hover-yellow: color-mix(in srgb, var(--vx-fill-yellow) 88%, #000);
|
|
140
140
|
--vx-fill-hover-orange: color-mix(in srgb, var(--vx-fill-orange) 88%, #000);
|
|
141
|
+
--vx-text-nano: 10px;
|
|
141
142
|
--vx-text-micro: 11px;
|
|
142
143
|
--vx-text-xs: 12.5px;
|
|
143
144
|
--vx-text-sm: 13.5px;
|
|
@@ -147,6 +148,7 @@
|
|
|
147
148
|
--vx-text-h2: 21px;
|
|
148
149
|
--vx-text-kpi: 24px;
|
|
149
150
|
--vx-text-h1: 26px;
|
|
151
|
+
--vx-text-display: 30px;
|
|
150
152
|
--vx-area-top: 22%;
|
|
151
153
|
--vx-area-bottom: 1%;
|
|
152
154
|
--vx-good: color-mix(in srgb, var(--vx-good-solid) 18%, transparent);
|
|
@@ -274,8 +276,8 @@ html[data-mantine-color-scheme='light'] {
|
|
|
274
276
|
--vx-divider: color-mix(in srgb, #e5e5e5 65%, transparent);
|
|
275
277
|
--vx-shadow-card: 0 1px 2px rgba(28, 25, 23, 0.05), 0 0 0 1px var(--vx-surface-hairline);
|
|
276
278
|
--vx-shadow-ctrl: 0 1px 2px rgba(28, 25, 23, 0.12);
|
|
277
|
-
--vx-shadow-raised: 0 1px 2px rgba(28, 25, 23, 0.
|
|
278
|
-
--vx-shadow-overlay: 0 8px 24px rgba(28, 25, 23, 0.
|
|
279
|
+
--vx-shadow-raised: 0 1px 2px rgba(28, 25, 23, 0.1);
|
|
280
|
+
--vx-shadow-overlay: 0 8px 24px rgba(28, 25, 23, 0.1);
|
|
279
281
|
--vx-surface-bg: #f2f2f5;
|
|
280
282
|
--vx-surface-panel: #fafafd;
|
|
281
283
|
--vx-surface-panel-hover: #ffffff;
|
package/dist/vite.d.ts
CHANGED
|
@@ -49,7 +49,21 @@ export type BasaltAppOptions = {
|
|
|
49
49
|
light: string;
|
|
50
50
|
dark: string;
|
|
51
51
|
};
|
|
52
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Which scheme the anti-FOUC `<style>` paints before the app boots. Default `'dark'` —
|
|
54
|
+
* `BasaltProvider`'s own default. `'light'` paints the light surface, `'auto'` declares
|
|
55
|
+
* `color-scheme: light dark` and picks the background off `prefers-color-scheme`, and `false`
|
|
56
|
+
* paints the background but declares no `color-scheme` at all (leave native controls to Mantine).
|
|
57
|
+
*
|
|
58
|
+
* Set this to whatever the app passes as `defaultColorScheme` — a mismatch is a visible flash of
|
|
59
|
+
* the wrong surface, not a correctness bug: the boot rule stops applying the moment Mantine
|
|
60
|
+
* writes `data-mantine-color-scheme` on `<html>` (see `BOOT_SCOPE`).
|
|
61
|
+
*/
|
|
62
|
+
colorScheme?: 'dark' | 'light' | 'auto' | false;
|
|
63
|
+
/**
|
|
64
|
+
* Manifest `background_color` + anti-FOUC paint color. Default: the theme color matching
|
|
65
|
+
* `colorScheme` (the dark one for `'dark'` / `'auto'` / `false`, the light one for `'light'`).
|
|
66
|
+
*/
|
|
53
67
|
backgroundColor?: string;
|
|
54
68
|
/** Manifest `display` mode. Default: `'standalone'`. */
|
|
55
69
|
display?: 'standalone' | 'minimal-ui' | 'fullscreen' | 'browser';
|
|
@@ -66,7 +80,10 @@ export type BasaltAppOptions = {
|
|
|
66
80
|
scope?: string;
|
|
67
81
|
/** Manifest `id`. Default: the resolved `startUrl` (default- or explicitly-derived, per above). */
|
|
68
82
|
id?: string;
|
|
69
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* Icon links + manifest icon paths. `false` skips BOTH — the head `<link>` icons and the
|
|
85
|
+
* manifest's `icons` array — so a manifest is never emitted pointing at files that 404.
|
|
86
|
+
*/
|
|
70
87
|
icons?: false | {
|
|
71
88
|
dir?: string;
|
|
72
89
|
};
|
|
@@ -104,13 +121,21 @@ export type BasaltAppOptions = {
|
|
|
104
121
|
* manifest `theme_color` both need a FLAT color, so the flattening step is the contract this
|
|
105
122
|
* plugin owes its output regardless of which shape the palette hands it.
|
|
106
123
|
*
|
|
124
|
+
* Two behaviours worth knowing before adopting it, both of which the plugin owns because the
|
|
125
|
+
* consumer cannot reach them:
|
|
126
|
+
* • It HOISTS the shell's `<meta charset>` ahead of everything it injects, so the encoding
|
|
127
|
+
* declaration stays inside the spec's first 1024 bytes (see `hoistCharset`).
|
|
128
|
+
* • The anti-FOUC `<style>` expires the moment Mantine resolves the real scheme, and `colorScheme`
|
|
129
|
+
* selects which surface it paints until then (see `BOOT_SCOPE` / `buildBootStyle`).
|
|
130
|
+
*
|
|
107
131
|
* @example
|
|
108
132
|
* // vite.config.ts
|
|
109
133
|
* import { basaltAppPlugin, basaltViteConfig } from 'basalt-ui/vite'
|
|
110
134
|
*
|
|
111
135
|
* export default {
|
|
112
136
|
* ...basaltViteConfig({ port: 5173 }),
|
|
113
|
-
*
|
|
137
|
+
* // colorScheme mirrors <BasaltProvider defaultColorScheme> — omit it for the dark default.
|
|
138
|
+
* plugins: [react(), ...basaltAppPlugin({ name: 'Argo', colorScheme: 'auto' })],
|
|
114
139
|
* }
|
|
115
140
|
*/
|
|
116
141
|
export declare function basaltAppPlugin(options: BasaltAppOptions): PluginOption[];
|
package/dist/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAA6B,YAAY,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAI/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B,CAAA;AA6CD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,UAAU,CAgFpE;AAgBD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACrD,
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAA6B,YAAY,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAI/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B,CAAA;AA6CD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,UAAU,CAgFpE;AAgBD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACrD;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAA;IAC/C;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,wDAAwD;IACxD,OAAO,CAAC,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,CAAA;IAChE;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mGAAmG;IACnG,EAAE,CAAC,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChC,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC3B,oFAAoF;IACpF,GAAG,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,SAAS,GAAG,qBAAqB,CAAA;KAAE,CAAA;IACvF,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClD,CAAA;AA4gBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,YAAY,EAAE,CAMzE"}
|
package/dist/vite.js
CHANGED
|
@@ -140,6 +140,29 @@ const VIEWPORT_TAG = {
|
|
|
140
140
|
tag: "meta",
|
|
141
141
|
attrs: { name: "viewport", content: "width=device-width, initial-scale=1.0, viewport-fit=cover" }
|
|
142
142
|
};
|
|
143
|
+
const BOOT_SCOPE = "html:not([data-mantine-color-scheme])";
|
|
144
|
+
const BOOT_COLOR_SCHEME = { dark: "dark", light: "light", auto: "light dark" };
|
|
145
|
+
function buildBootStyle(input) {
|
|
146
|
+
const { colorScheme, themeColor, backgroundColor, explicitBackground } = input;
|
|
147
|
+
if (colorScheme === false) return `${BOOT_SCOPE}{background-color:${backgroundColor}}`;
|
|
148
|
+
const scheme = BOOT_COLOR_SCHEME[colorScheme];
|
|
149
|
+
if (colorScheme !== "auto" || explicitBackground) {
|
|
150
|
+
return `${BOOT_SCOPE}{background-color:${backgroundColor};color-scheme:${scheme}}`;
|
|
151
|
+
}
|
|
152
|
+
return `${BOOT_SCOPE}{background-color:${themeColor.light};color-scheme:${scheme}}@media(prefers-color-scheme:dark){${BOOT_SCOPE}{background-color:${themeColor.dark}}}`;
|
|
153
|
+
}
|
|
154
|
+
const CHARSET_META_RE = /[ \t]*<meta\s+charset\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>=]+))\s*\/?>[ \t]*\r?\n?/i;
|
|
155
|
+
const HTTP_EQUIV_CHARSET_RE = /<meta\s[^>]*http-equiv\s*=\s*["']?content-type["']?[^>]*>/i;
|
|
156
|
+
const DEFAULT_CHARSET = "UTF-8";
|
|
157
|
+
function hoistCharset(html) {
|
|
158
|
+
if (HTTP_EQUIV_CHARSET_RE.test(html)) return { html, tag: void 0 };
|
|
159
|
+
const match = CHARSET_META_RE.exec(html);
|
|
160
|
+
const charset = match?.[1] ?? match?.[2] ?? match?.[3] ?? DEFAULT_CHARSET;
|
|
161
|
+
return {
|
|
162
|
+
html: match ? html.replace(CHARSET_META_RE, "") : html,
|
|
163
|
+
tag: { tag: "meta", attrs: { charset } }
|
|
164
|
+
};
|
|
165
|
+
}
|
|
143
166
|
function buildSeoTags(input) {
|
|
144
167
|
const { name, description, seo } = input;
|
|
145
168
|
const tags = [];
|
|
@@ -183,7 +206,7 @@ function buildStaticTags(input) {
|
|
|
183
206
|
options,
|
|
184
207
|
shortName,
|
|
185
208
|
themeColor,
|
|
186
|
-
|
|
209
|
+
bootStyle,
|
|
187
210
|
iconsEnabled,
|
|
188
211
|
iconsDir,
|
|
189
212
|
darkreader,
|
|
@@ -210,10 +233,7 @@ function buildStaticTags(input) {
|
|
|
210
233
|
}
|
|
211
234
|
}
|
|
212
235
|
);
|
|
213
|
-
tags.push({
|
|
214
|
-
tag: "style",
|
|
215
|
-
children: `html{background-color:${backgroundColor};color-scheme:dark}`
|
|
216
|
-
});
|
|
236
|
+
tags.push({ tag: "style", children: bootStyle });
|
|
217
237
|
if (iconsEnabled) {
|
|
218
238
|
tags.push(
|
|
219
239
|
{
|
|
@@ -274,8 +294,9 @@ function buildManifestJson(input) {
|
|
|
274
294
|
scope,
|
|
275
295
|
id,
|
|
276
296
|
display,
|
|
277
|
-
|
|
297
|
+
schemeColor,
|
|
278
298
|
backgroundColor,
|
|
299
|
+
iconsEnabled,
|
|
279
300
|
iconsDir,
|
|
280
301
|
base
|
|
281
302
|
} = input;
|
|
@@ -287,21 +308,29 @@ function buildManifestJson(input) {
|
|
|
287
308
|
start_url: startUrl,
|
|
288
309
|
scope,
|
|
289
310
|
display,
|
|
290
|
-
|
|
311
|
+
// A manifest carries ONE theme color, so it follows the boot scheme rather than the dual
|
|
312
|
+
// `<meta name="theme-color">` pair. Unchanged for the default (`'dark'`) and for `'auto'`.
|
|
313
|
+
theme_color: schemeColor,
|
|
291
314
|
background_color: backgroundColor,
|
|
292
|
-
icons:
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
315
|
+
// `icons: false` reaches HERE too, not just the head links. The array was unconditional, so
|
|
316
|
+
// `{ manifest: true, icons: false }` shipped a manifest pointing at two PNGs the app never
|
|
317
|
+
// ships — an installable app with broken icons, and the reason rb went hybrid (plugin for the
|
|
318
|
+
// head, a hand-written manifest for the rest). A manifest with NO icons member is valid.
|
|
319
|
+
...iconsEnabled ? {
|
|
320
|
+
icons: [
|
|
321
|
+
{
|
|
322
|
+
src: withBase(base, withIconPath(iconsDir, ICON_FILES.manifest192)),
|
|
323
|
+
sizes: "192x192",
|
|
324
|
+
type: "image/png"
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
src: withBase(base, withIconPath(iconsDir, ICON_FILES.manifest512)),
|
|
328
|
+
sizes: "512x512",
|
|
329
|
+
type: "image/png",
|
|
330
|
+
purpose: "any maskable"
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
} : {}
|
|
305
334
|
};
|
|
306
335
|
return JSON.stringify(manifest, null, 2);
|
|
307
336
|
}
|
|
@@ -313,7 +342,15 @@ function createMainPlugin(options) {
|
|
|
313
342
|
const iconsDir = options.icons === false ? void 0 : options.icons?.dir;
|
|
314
343
|
const manifestEnabled = options.manifest !== false;
|
|
315
344
|
const themeColor = resolveThemeColors(options.themeColor);
|
|
316
|
-
const
|
|
345
|
+
const colorScheme = options.colorScheme ?? "dark";
|
|
346
|
+
const schemeColor = colorScheme === "light" ? themeColor.light : themeColor.dark;
|
|
347
|
+
const backgroundColor = options.backgroundColor ?? schemeColor;
|
|
348
|
+
const bootStyle = buildBootStyle({
|
|
349
|
+
colorScheme,
|
|
350
|
+
themeColor,
|
|
351
|
+
backgroundColor,
|
|
352
|
+
explicitBackground: options.backgroundColor !== void 0
|
|
353
|
+
});
|
|
317
354
|
let manifestJson = "";
|
|
318
355
|
let manifestHref = "/site.webmanifest";
|
|
319
356
|
let staticTags = [];
|
|
@@ -332,8 +369,9 @@ function createMainPlugin(options) {
|
|
|
332
369
|
scope,
|
|
333
370
|
id,
|
|
334
371
|
display,
|
|
335
|
-
|
|
372
|
+
schemeColor,
|
|
336
373
|
backgroundColor,
|
|
374
|
+
iconsEnabled,
|
|
337
375
|
iconsDir,
|
|
338
376
|
base
|
|
339
377
|
});
|
|
@@ -341,7 +379,7 @@ function createMainPlugin(options) {
|
|
|
341
379
|
options,
|
|
342
380
|
shortName,
|
|
343
381
|
themeColor,
|
|
344
|
-
|
|
382
|
+
bootStyle,
|
|
345
383
|
iconsEnabled,
|
|
346
384
|
iconsDir,
|
|
347
385
|
darkreader,
|
|
@@ -350,9 +388,20 @@ function createMainPlugin(options) {
|
|
|
350
388
|
manifestHref
|
|
351
389
|
});
|
|
352
390
|
},
|
|
353
|
-
transformIndexHtml
|
|
354
|
-
|
|
355
|
-
|
|
391
|
+
transformIndexHtml: {
|
|
392
|
+
// `pre` so this plugin's tags are the FIRST head-prepend contributions Vite collects — that
|
|
393
|
+
// ordering is what puts the hoisted <meta charset> at the very top of <head> rather than
|
|
394
|
+
// behind another plugin's tags. Vite injects all collected tags after every hook has run.
|
|
395
|
+
order: "pre",
|
|
396
|
+
handler(html) {
|
|
397
|
+
const hoisted = hoistCharset(html);
|
|
398
|
+
const tags = [
|
|
399
|
+
...hoisted.tag ? [hoisted.tag] : [],
|
|
400
|
+
...hasViewportMeta(html) ? [] : [VIEWPORT_TAG],
|
|
401
|
+
...staticTags
|
|
402
|
+
];
|
|
403
|
+
return { html: hoisted.html, tags };
|
|
404
|
+
}
|
|
356
405
|
},
|
|
357
406
|
generateBundle() {
|
|
358
407
|
if (!manifestEnabled) return;
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# basalt-ui v1.
|
|
1
|
+
# basalt-ui v1.22.0
|
|
2
2
|
# Opinionated framework for Mantine-based React apps — theme, app shell, visx charts, toolchain presets
|
|
3
3
|
#
|
|
4
4
|
# basalt-ui is an opinionated framework for Mantine-based React apps.
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
# ./tokens.css subpath. Guide: docs/FRAMEWORK-FREE.md in the repo.
|
|
20
20
|
|
|
21
21
|
Package: basalt-ui
|
|
22
|
-
Version: 1.
|
|
22
|
+
Version: 1.22.0
|
|
23
23
|
|
|
24
24
|
## basalt-ui
|
|
25
25
|
Import: import { ... } from 'basalt-ui'
|
package/package.json
CHANGED
|
@@ -125,7 +125,7 @@ export type BarsProps<T> = {
|
|
|
125
125
|
/** Legend config forwarded to `CartesianChart`; `false` disables the legend (sparkline escape).
|
|
126
126
|
* Default `{ placement: 'bottom' }`. */
|
|
127
127
|
legend?: ChartLegendConfig | false
|
|
128
|
-
/** Accessible text alternative, forwarded as `aria-label` (+ `role="
|
|
128
|
+
/** Accessible text alternative, forwarded as `aria-label` (+ `role="group"`). */
|
|
129
129
|
ariaLabel?: string
|
|
130
130
|
/** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
131
131
|
isPending?: boolean
|
|
@@ -50,7 +50,7 @@ export type DonutProps<K extends string = SeriesKey> = {
|
|
|
50
50
|
centerContent?: ReactNode
|
|
51
51
|
innerRatio?: number
|
|
52
52
|
padAngle?: number
|
|
53
|
-
/** Accessible text alternative, forwarded to `ChartFrame` as `aria-label` (+ `role="
|
|
53
|
+
/** Accessible text alternative, forwarded to `ChartFrame` as `aria-label` (+ `role="group"`). */
|
|
54
54
|
ariaLabel?: string
|
|
55
55
|
/** Forwarded to `ChartFrame` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
56
56
|
isPending?: boolean
|
|
@@ -94,7 +94,7 @@ export type DualPanelProps<T> = {
|
|
|
94
94
|
/** Legend config forwarded to `ChartFrame`; `false` disables the legend (sparkline escape).
|
|
95
95
|
* Default `{ placement: 'bottom' }`. */
|
|
96
96
|
legend?: ChartLegendConfig | false
|
|
97
|
-
/** Accessible text alternative, forwarded to `ChartFrame` as `aria-label` (+ `role="
|
|
97
|
+
/** Accessible text alternative, forwarded to `ChartFrame` as `aria-label` (+ `role="group"`). */
|
|
98
98
|
ariaLabel?: string
|
|
99
99
|
/** Forwarded to `ChartFrame` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
100
100
|
isPending?: boolean
|
|
@@ -521,7 +521,7 @@ function DualPanelPlot<T>(props: DualPanelPlotProps<T>) {
|
|
|
521
521
|
</>
|
|
522
522
|
)}
|
|
523
523
|
|
|
524
|
-
{/* theme-allow basalt/hand-rolled-plot: TWO panes over one x scale is not a single
|
|
524
|
+
{/* theme-allow-file basalt/hand-rolled-plot: TWO panes over one x scale is not a single
|
|
525
525
|
cartesian plot, so `CartesianChart` (one plot rect, one or two y axes) cannot express
|
|
526
526
|
it. This file therefore assembles the plot itself — but from the SAME parts every
|
|
527
527
|
other chart gets: `ChartFrame`, `autoMargin` + `probeAxisLabels`, `useChartCursor`,
|
|
@@ -53,7 +53,7 @@ export type HeatmapProps<T> = {
|
|
|
53
53
|
renderTooltip?: (cell: HeatmapCell) => ReactNode
|
|
54
54
|
/** Optional gradient legend strip below the grid (faint → solid color). */
|
|
55
55
|
legend?: { min: string; max: string }
|
|
56
|
-
/** Accessible text alternative, forwarded to `ChartFrame` as `aria-label` (+ `role="
|
|
56
|
+
/** Accessible text alternative, forwarded to `ChartFrame` as `aria-label` (+ `role="group"`). */
|
|
57
57
|
ariaLabel?: string
|
|
58
58
|
/** Forwarded to `ChartFrame` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
59
59
|
isPending?: boolean
|
|
@@ -52,7 +52,7 @@ export type MultiLineProps<T> = {
|
|
|
52
52
|
/** Legend config forwarded to `CartesianChart`; `false` disables the legend (sparkline escape).
|
|
53
53
|
* Default `{ placement: 'bottom' }`. */
|
|
54
54
|
legend?: ChartLegendConfig | false
|
|
55
|
-
/** Accessible text alternative, forwarded to `CartesianChart` as `aria-label` (+ `role="
|
|
55
|
+
/** Accessible text alternative, forwarded to `CartesianChart` as `aria-label` (+ `role="group"`). */
|
|
56
56
|
ariaLabel?: string
|
|
57
57
|
/** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
58
58
|
isPending?: boolean
|
|
@@ -33,7 +33,7 @@ export type StackedAreaProps<T> = {
|
|
|
33
33
|
/** Legend config forwarded to `CartesianChart`; `false` disables the legend (sparkline escape).
|
|
34
34
|
* Default `{ placement: 'bottom' }`. */
|
|
35
35
|
legend?: ChartLegendConfig | false
|
|
36
|
-
/** Accessible text alternative, forwarded as `aria-label` (+ `role="
|
|
36
|
+
/** Accessible text alternative, forwarded as `aria-label` (+ `role="group"`). */
|
|
37
37
|
ariaLabel?: string
|
|
38
38
|
/** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
39
39
|
isPending?: boolean
|
|
@@ -73,7 +73,7 @@ export type ZonedLineProps<T> = {
|
|
|
73
73
|
/** Legend config forwarded to `CartesianChart`; `false` disables the legend (sparkline escape).
|
|
74
74
|
* Default `{ placement: 'bottom' }`. */
|
|
75
75
|
legend?: ChartLegendConfig | false
|
|
76
|
-
/** Accessible text alternative, forwarded to `CartesianChart` as `aria-label` (+ `role="
|
|
76
|
+
/** Accessible text alternative, forwarded to `CartesianChart` as `aria-label` (+ `role="group"`). */
|
|
77
77
|
ariaLabel?: string
|
|
78
78
|
/** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
79
79
|
isPending?: boolean
|