basalt-ui 1.20.0 → 1.21.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 +9 -5
- package/CHANGELOG.md +19 -0
- package/MIGRATING.md +147 -49
- package/README.md +42 -8
- package/agent/rules/basalt-app.md +41 -0
- 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 +73 -16
- package/agent/skills/basalt-app/SKILL.md +4 -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 +181 -68
- package/configs/oxlint-plugin.test.ts +215 -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 +48 -14
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +328 -66
- 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 +47 -2
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +176 -31
- 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 +24 -2
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +54 -13
- 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/index.ts +607 -128
- 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 +162 -0
- package/src/cli/waiver-audit.test.ts +131 -0
- package/src/guard/check-source.test.ts +441 -1
- package/src/guard/index.ts +430 -60
- 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 +125 -6
- package/src/vite.ts +148 -20
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';
|
|
@@ -104,13 +118,21 @@ export type BasaltAppOptions = {
|
|
|
104
118
|
* manifest `theme_color` both need a FLAT color, so the flattening step is the contract this
|
|
105
119
|
* plugin owes its output regardless of which shape the palette hands it.
|
|
106
120
|
*
|
|
121
|
+
* Two behaviours worth knowing before adopting it, both of which the plugin owns because the
|
|
122
|
+
* consumer cannot reach them:
|
|
123
|
+
* • It HOISTS the shell's `<meta charset>` ahead of everything it injects, so the encoding
|
|
124
|
+
* declaration stays inside the spec's first 1024 bytes (see `hoistCharset`).
|
|
125
|
+
* • The anti-FOUC `<style>` expires the moment Mantine resolves the real scheme, and `colorScheme`
|
|
126
|
+
* selects which surface it paints until then (see `BOOT_SCOPE` / `buildBootStyle`).
|
|
127
|
+
*
|
|
107
128
|
* @example
|
|
108
129
|
* // vite.config.ts
|
|
109
130
|
* import { basaltAppPlugin, basaltViteConfig } from 'basalt-ui/vite'
|
|
110
131
|
*
|
|
111
132
|
* export default {
|
|
112
133
|
* ...basaltViteConfig({ port: 5173 }),
|
|
113
|
-
*
|
|
134
|
+
* // colorScheme mirrors <BasaltProvider defaultColorScheme> — omit it for the dark default.
|
|
135
|
+
* plugins: [react(), ...basaltAppPlugin({ name: 'Argo', colorScheme: 'auto' })],
|
|
114
136
|
* }
|
|
115
137
|
*/
|
|
116
138
|
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,wFAAwF;IACxF,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;AAigBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,7 +294,7 @@ function buildManifestJson(input) {
|
|
|
274
294
|
scope,
|
|
275
295
|
id,
|
|
276
296
|
display,
|
|
277
|
-
|
|
297
|
+
schemeColor,
|
|
278
298
|
backgroundColor,
|
|
279
299
|
iconsDir,
|
|
280
300
|
base
|
|
@@ -287,7 +307,9 @@ function buildManifestJson(input) {
|
|
|
287
307
|
start_url: startUrl,
|
|
288
308
|
scope,
|
|
289
309
|
display,
|
|
290
|
-
|
|
310
|
+
// A manifest carries ONE theme color, so it follows the boot scheme rather than the dual
|
|
311
|
+
// `<meta name="theme-color">` pair. Unchanged for the default (`'dark'`) and for `'auto'`.
|
|
312
|
+
theme_color: schemeColor,
|
|
291
313
|
background_color: backgroundColor,
|
|
292
314
|
icons: [
|
|
293
315
|
{
|
|
@@ -313,7 +335,15 @@ function createMainPlugin(options) {
|
|
|
313
335
|
const iconsDir = options.icons === false ? void 0 : options.icons?.dir;
|
|
314
336
|
const manifestEnabled = options.manifest !== false;
|
|
315
337
|
const themeColor = resolveThemeColors(options.themeColor);
|
|
316
|
-
const
|
|
338
|
+
const colorScheme = options.colorScheme ?? "dark";
|
|
339
|
+
const schemeColor = colorScheme === "light" ? themeColor.light : themeColor.dark;
|
|
340
|
+
const backgroundColor = options.backgroundColor ?? schemeColor;
|
|
341
|
+
const bootStyle = buildBootStyle({
|
|
342
|
+
colorScheme,
|
|
343
|
+
themeColor,
|
|
344
|
+
backgroundColor,
|
|
345
|
+
explicitBackground: options.backgroundColor !== void 0
|
|
346
|
+
});
|
|
317
347
|
let manifestJson = "";
|
|
318
348
|
let manifestHref = "/site.webmanifest";
|
|
319
349
|
let staticTags = [];
|
|
@@ -332,7 +362,7 @@ function createMainPlugin(options) {
|
|
|
332
362
|
scope,
|
|
333
363
|
id,
|
|
334
364
|
display,
|
|
335
|
-
|
|
365
|
+
schemeColor,
|
|
336
366
|
backgroundColor,
|
|
337
367
|
iconsDir,
|
|
338
368
|
base
|
|
@@ -341,7 +371,7 @@ function createMainPlugin(options) {
|
|
|
341
371
|
options,
|
|
342
372
|
shortName,
|
|
343
373
|
themeColor,
|
|
344
|
-
|
|
374
|
+
bootStyle,
|
|
345
375
|
iconsEnabled,
|
|
346
376
|
iconsDir,
|
|
347
377
|
darkreader,
|
|
@@ -350,9 +380,20 @@ function createMainPlugin(options) {
|
|
|
350
380
|
manifestHref
|
|
351
381
|
});
|
|
352
382
|
},
|
|
353
|
-
transformIndexHtml
|
|
354
|
-
|
|
355
|
-
|
|
383
|
+
transformIndexHtml: {
|
|
384
|
+
// `pre` so this plugin's tags are the FIRST head-prepend contributions Vite collects — that
|
|
385
|
+
// ordering is what puts the hoisted <meta charset> at the very top of <head> rather than
|
|
386
|
+
// behind another plugin's tags. Vite injects all collected tags after every hook has run.
|
|
387
|
+
order: "pre",
|
|
388
|
+
handler(html) {
|
|
389
|
+
const hoisted = hoistCharset(html);
|
|
390
|
+
const tags = [
|
|
391
|
+
...hoisted.tag ? [hoisted.tag] : [],
|
|
392
|
+
...hasViewportMeta(html) ? [] : [VIEWPORT_TAG],
|
|
393
|
+
...staticTags
|
|
394
|
+
];
|
|
395
|
+
return { html: hoisted.html, tags };
|
|
396
|
+
}
|
|
356
397
|
},
|
|
357
398
|
generateBundle() {
|
|
358
399
|
if (!manifestEnabled) return;
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# basalt-ui v1.
|
|
1
|
+
# basalt-ui v1.21.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.21.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
|