basalt-ui 1.23.0 → 1.23.1
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 +22 -13
- package/CHANGELOG.md +9 -0
- package/MIGRATING.md +86 -4
- package/README.md +35 -16
- package/agent/rules/basalt-app.md +8 -2
- package/agent/rules/basalt-charts.md +38 -2
- package/agent/rules/basalt-content.md +3 -3
- package/agent/rules/basalt-mantine.md +4 -4
- package/agent/rules/basalt-tokens.md +18 -5
- package/agent/skills/basalt-app/SKILL.md +25 -12
- package/agent/skills/basalt-charts/SKILL.md +4 -2
- package/agent/templates/CLAUDE-block.md.tpl +3 -2
- package/dist/charts/kinds/BandStrip.d.ts +20 -6
- package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
- package/dist/charts/kinds/BandStrip.js +59 -6
- package/dist/charts/kinds/MirroredBars.d.ts +4 -2
- package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
- package/dist/charts/kinds/MirroredBars.js +13 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +182 -24
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +29 -3
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/charts/kinds/BandStrip.test.tsx +87 -5
- package/src/charts/kinds/BandStrip.tsx +105 -12
- package/src/charts/kinds/MirroredBars.test.tsx +39 -0
- package/src/charts/kinds/MirroredBars.tsx +38 -2
- package/src/cli/help.test.ts +74 -1
- package/src/cli/index.ts +312 -35
- package/src/cli/tokens-css.test.ts +62 -0
- package/src/guard/check-source.test.ts +73 -0
- package/src/guard/index.ts +67 -7
|
@@ -7,16 +7,29 @@ import type { ChartLegendConfig, SeriesStyle } from '../series.js';
|
|
|
7
7
|
* numeric value to plot — `formatValue` reads the datum directly.
|
|
8
8
|
*/
|
|
9
9
|
export type BandStripSeries<T> = SeriesStyle & {
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The derived tooltip row's value for a band in this state.
|
|
12
|
+
*
|
|
13
|
+
* Return `null` for a datum in this state whose reading is ABSENT — the row renders
|
|
14
|
+
* {@link NO_READING} instead, which is the escape `ChartSeries.getValue` has and this shape did
|
|
15
|
+
* not: with no value accessor, an absent reading had to come back as `''` and render as a label
|
|
16
|
+
* with an empty value, indistinguishable from a state whose name is the whole reading.
|
|
17
|
+
*
|
|
18
|
+
* Omit the function entirely for a state whose NAME *is* the whole reading ("Not measured").
|
|
19
|
+
*/
|
|
20
|
+
formatValue?: (d: T) => string | null;
|
|
13
21
|
};
|
|
14
22
|
/** One drawn band — which state it is in, and the three ways a state can be qualified. */
|
|
15
23
|
export type BandSpan = {
|
|
16
24
|
/**
|
|
17
25
|
* Series key naming this band's state: the tie to its legend entry, its fill, and its derived
|
|
18
|
-
* tooltip row.
|
|
19
|
-
*
|
|
26
|
+
* tooltip row.
|
|
27
|
+
*
|
|
28
|
+
* A key not present in `series` is a bug TypeScript cannot catch (this is a `string`), and it
|
|
29
|
+
* used to draw NOTHING — which on a strip whose vocabulary is measured/not-measured is
|
|
30
|
+
* indistinguishable from a real coverage gap, so a typo silently asserted "not measured". It now
|
|
31
|
+
* throws in development and draws an explicit unknown band in production; see
|
|
32
|
+
* {@link unknownStateError} for why the two differ.
|
|
20
33
|
*/
|
|
21
34
|
state: string;
|
|
22
35
|
/**
|
|
@@ -79,7 +92,8 @@ export type BandStripProps<T> = {
|
|
|
79
92
|
legend?: ChartLegendConfig | false;
|
|
80
93
|
/** Colour of the absence hatch. Names a `series` entry, so absence is legended like any other
|
|
81
94
|
* state — a hatched band is the one mark a reader cannot decode from an axis. Default
|
|
82
|
-
* `VX.neutral`, unnamed.
|
|
95
|
+
* `VX.neutral`, unnamed. A key naming no `series` entry throws (a PROP, so a typo can only be a
|
|
96
|
+
* wiring error) rather than falling back to the unnamed default. */
|
|
83
97
|
absentState?: string;
|
|
84
98
|
/** Per-side overrides of the measured margins — applied last. */
|
|
85
99
|
margin?: Partial<ChartMargin>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BandStrip.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/BandStrip.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAYvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,WAAW,GAAG;IAC7C;
|
|
1
|
+
{"version":3,"file":"BandStrip.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/BandStrip.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAYvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,WAAW,GAAG;IAC7C;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,CAAA;CACtC,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,QAAQ,GAAG;IACrB;;;;;;;;;OASG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACP,iFAAiF;QACjF,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,uEAAuE;QACvE,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;CACF,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAA;IACf;yFACqF;IACrF,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;sCACkC;IAClC,MAAM,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IACrC,oCAAoC;IACpC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,QAAQ,CAAA;IAC3B;kEAC8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,mDAAmD;IACnD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,CAAA;IAC/E,4EAA4E;IAC5E,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IAClB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,OAAO,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IACtC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC;;;wEAGoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7B;iDAC6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAkDD;;;;;;;;;;;;;GAaG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BAgBlD;AAwPD;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
|
|
@@ -16,6 +16,25 @@ import { HatchPattern, hatchFill, hatchSizeFor } from "../primitives/HatchPatter
|
|
|
16
16
|
import { HoverOverlay } from "../primitives/HoverOverlay.js";
|
|
17
17
|
import { fmtAxisDate } from "../utils/format.js";
|
|
18
18
|
const DEFAULT_MARKER_INSET = 6;
|
|
19
|
+
const NO_READING = "\u2014";
|
|
20
|
+
const UNKNOWN_MARK = {
|
|
21
|
+
fill: alpha(VX.neutral, 0.2),
|
|
22
|
+
stroke: VX.neutral,
|
|
23
|
+
strokeWidth: 1,
|
|
24
|
+
strokeDasharray: "3 2"
|
|
25
|
+
};
|
|
26
|
+
function isDev() {
|
|
27
|
+
return process.env["NODE_ENV"] !== "production";
|
|
28
|
+
}
|
|
29
|
+
function unknownStateError(what, key, known) {
|
|
30
|
+
return new Error(
|
|
31
|
+
`BandStrip: ${what} "${key}" names no \`series\` entry (known: ${[...known].join(", ")}) \u2014 so it has no legend entry, no colour and no tooltip row. Add the state to \`series\`, or map the datum onto one that is there.`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
function formatBandValue(style, datum) {
|
|
35
|
+
if (style.formatValue === void 0) return "";
|
|
36
|
+
return style.formatValue(datum) ?? NO_READING;
|
|
37
|
+
}
|
|
19
38
|
function BandStripInner(props) {
|
|
20
39
|
const { series, chartId, height, fill, legend, ariaLabel, isPending } = props;
|
|
21
40
|
return /* @__PURE__ */ jsx(
|
|
@@ -66,19 +85,44 @@ function BandStripPlot(props) {
|
|
|
66
85
|
const { bands, margin, plotWidth, scale, cursor, point, crosshairX, step, bandWidth } = band;
|
|
67
86
|
const stripHeight = Math.max(plot.height - margin.top - margin.bottom, 1);
|
|
68
87
|
const hatchId = `${chartId}-band-absent`;
|
|
88
|
+
if (absentState !== void 0 && !styleByKey.has(absentState)) {
|
|
89
|
+
throw unknownStateError("absentState", absentState, styleByKey.keys());
|
|
90
|
+
}
|
|
69
91
|
const absentColor = (absentState === void 0 ? void 0 : styleByKey.get(absentState)?.color) ?? VX.neutral;
|
|
70
92
|
const rects = useMemo(() => {
|
|
71
93
|
const out = [];
|
|
72
94
|
bands.forEach((d, i) => {
|
|
73
95
|
const span = getBand(d);
|
|
74
96
|
const style = styleByKey.get(span.state);
|
|
75
|
-
|
|
97
|
+
const x = i * step;
|
|
98
|
+
if (style === void 0) {
|
|
99
|
+
if (isDev()) throw unknownStateError("BandSpan.state", span.state, styleByKey.keys());
|
|
100
|
+
out.push(
|
|
101
|
+
/* @__PURE__ */ jsx(
|
|
102
|
+
"rect",
|
|
103
|
+
{
|
|
104
|
+
...UNKNOWN_MARK,
|
|
105
|
+
x,
|
|
106
|
+
y: 0,
|
|
107
|
+
width: bandWidth,
|
|
108
|
+
height: stripHeight,
|
|
109
|
+
rx: 1,
|
|
110
|
+
pointerEvents: "none"
|
|
111
|
+
},
|
|
112
|
+
getX(d)
|
|
113
|
+
)
|
|
114
|
+
);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (hidden.has(span.state)) return;
|
|
76
118
|
const absent = clampFraction(span.absentFraction);
|
|
77
119
|
const measuredWidth = bandWidth * (1 - absent);
|
|
78
120
|
const hatchWidth = bandWidth - measuredWidth;
|
|
79
|
-
const x = i * step;
|
|
80
121
|
const markerKey = span.marker?.state ?? span.state;
|
|
81
122
|
const markerColor = styleByKey.get(markerKey)?.color;
|
|
123
|
+
if (span.marker !== void 0 && markerColor === void 0 && isDev()) {
|
|
124
|
+
throw unknownStateError("BandSpan.marker.state", markerKey, styleByKey.keys());
|
|
125
|
+
}
|
|
82
126
|
const inset = span.marker?.inset ?? DEFAULT_MARKER_INSET;
|
|
83
127
|
out.push(
|
|
84
128
|
/* @__PURE__ */ jsxs("g", { children: [
|
|
@@ -106,15 +150,15 @@ function BandStripPlot(props) {
|
|
|
106
150
|
pointerEvents: "none"
|
|
107
151
|
}
|
|
108
152
|
),
|
|
109
|
-
span.marker !== void 0 &&
|
|
153
|
+
span.marker !== void 0 && measuredWidth > 0 && /* @__PURE__ */ jsx(
|
|
110
154
|
"rect",
|
|
111
155
|
{
|
|
156
|
+
...markerColor === void 0 ? UNKNOWN_MARK : { fill: markerColor },
|
|
112
157
|
x,
|
|
113
158
|
y: inset,
|
|
114
159
|
width: measuredWidth,
|
|
115
160
|
height: Math.max(stripHeight - 2 * inset, 2),
|
|
116
161
|
rx: 1,
|
|
117
|
-
fill: markerColor,
|
|
118
162
|
pointerEvents: "none"
|
|
119
163
|
}
|
|
120
164
|
)
|
|
@@ -203,11 +247,20 @@ function clampFraction(value) {
|
|
|
203
247
|
}
|
|
204
248
|
function deriveBandRow(span, styleByKey, hidden, datum) {
|
|
205
249
|
const style = styleByKey.get(span.state);
|
|
206
|
-
if (style === void 0
|
|
250
|
+
if (style === void 0) {
|
|
251
|
+
return {
|
|
252
|
+
color: VX.neutral,
|
|
253
|
+
label: "Unknown state",
|
|
254
|
+
value: span.state,
|
|
255
|
+
shape: "bar",
|
|
256
|
+
dashed: true
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
if (style.tooltip === false || hidden.has(span.state)) return null;
|
|
207
260
|
return {
|
|
208
261
|
color: style.color,
|
|
209
262
|
label: style.label,
|
|
210
|
-
value: style
|
|
263
|
+
value: formatBandValue(style, datum),
|
|
211
264
|
shape: style.mark === "line" ? "line" : "bar",
|
|
212
265
|
dashed: style.dash === "dashed"
|
|
213
266
|
};
|
|
@@ -4,7 +4,8 @@ import type { BandFold, BandTooltipConfig } from '../hooks/useBandPlot.js';
|
|
|
4
4
|
import type { ChartLegendConfig, ChartSeries } from '../series.js';
|
|
5
5
|
/** One of the two panes. Each resolves its own domain — that is the whole point of the kind. */
|
|
6
6
|
export type MirroredBarPane = {
|
|
7
|
-
/** Key of the `series` entry this pane draws: its colour, its legend entry, its tooltip row.
|
|
7
|
+
/** Key of the `series` entry this pane draws: its colour, its legend entry, its tooltip row.
|
|
8
|
+
* A key naming no entry throws — see {@link assertPaneKey}. */
|
|
8
9
|
key: string;
|
|
9
10
|
/**
|
|
10
11
|
* The pane's upper bound. `'auto'` (default) is its own visible maximum; a number pins it.
|
|
@@ -63,7 +64,8 @@ export type MirroredBarsProps<T> = {
|
|
|
63
64
|
cursorResolution?: CursorResolution;
|
|
64
65
|
tooltip?: BandTooltipConfig<T> | false;
|
|
65
66
|
legend?: ChartLegendConfig | false;
|
|
66
|
-
/** Series key whose colour the absence hatch is drawn in. Default `VX.neutral`.
|
|
67
|
+
/** Series key whose colour the absence hatch is drawn in. Default `VX.neutral`. A key naming no
|
|
68
|
+
* `series` entry throws rather than falling back to the unnamed default. */
|
|
67
69
|
absentState?: string;
|
|
68
70
|
margin?: Partial<ChartMargin>;
|
|
69
71
|
ariaLabel?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MirroredBars.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MirroredBars.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAcvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D,gGAAgG;AAChG,MAAM,MAAM,eAAe,GAAG;IAC5B
|
|
1
|
+
{"version":3,"file":"MirroredBars.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MirroredBars.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAcvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D,gGAAgG;AAChG,MAAM,MAAM,eAAe,GAAG;IAC5B;mEAC+D;IAC/D,GAAG,EAAE,MAAM,CAAA;IACX;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB;sBACkB;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;oFACgF;IAChF,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;IACjC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,sFAAsF;IACtF,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;;;;;OAKG;IACH,MAAM,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACjC,yCAAyC;IACzC,EAAE,EAAE,eAAe,CAAA;IACnB,yCAAyC;IACzC,IAAI,EAAE,eAAe,CAAA;IACrB;8FAC0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACpC;kCAC8B;IAC9B,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IAChC,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,CAAA;IAC/E,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IAClB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,OAAO,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IACtC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC;gFAC4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AA8BD;;;;;;;;;;;;;GAaG;AACH,iBAAS,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,+BAgBxD;AA4UD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAA8B,OAAO,iBAAiB,CAAA"}
|
|
@@ -20,6 +20,12 @@ import { deriveTooltipRows } from "../series.js";
|
|
|
20
20
|
import { fmtAxisDate } from "../utils/format.js";
|
|
21
21
|
const DEFAULT_UP_FRACTION = 0.35;
|
|
22
22
|
const DEFAULT_PANE_TICKS = 3;
|
|
23
|
+
function assertPaneKey(side, key, resolved, series) {
|
|
24
|
+
if (resolved !== void 0) return;
|
|
25
|
+
throw new Error(
|
|
26
|
+
`MirroredBars: ${side}.key "${key}" names no \`series\` entry (known: ${series.map((s) => s.key).join(", ")}) \u2014 the pane would silently vanish, which reads as a measured zero. Add the series, or point the pane at one that exists.`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
23
29
|
function MirroredBarsInner(props) {
|
|
24
30
|
const { series, chartId, height, fill, legend, ariaLabel, isPending } = props;
|
|
25
31
|
return /* @__PURE__ */ jsx(
|
|
@@ -61,6 +67,8 @@ function MirroredBarsPlot(props) {
|
|
|
61
67
|
const seriesByKey = useMemo(() => new Map(series.map((s) => [s.key, s])), [series]);
|
|
62
68
|
const upSeries = seriesByKey.get(up.key);
|
|
63
69
|
const downSeries = seriesByKey.get(down.key);
|
|
70
|
+
assertPaneKey("up", up.key, upSeries, series);
|
|
71
|
+
assertPaneKey("down", down.key, downSeries, series);
|
|
64
72
|
const upVisible = upSeries !== void 0 && !hidden.has(up.key);
|
|
65
73
|
const downVisible = downSeries !== void 0 && !hidden.has(down.key);
|
|
66
74
|
const upMax = usePaneMax(data, upSeries, up, upVisible);
|
|
@@ -112,6 +120,11 @@ function MirroredBarsPlot(props) {
|
|
|
112
120
|
[upMax, upHeight]
|
|
113
121
|
);
|
|
114
122
|
const hatchId = `${chartId}-mirrored-absent`;
|
|
123
|
+
if (absentState !== void 0 && !seriesByKey.has(absentState)) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`MirroredBars: absentState "${absentState}" names no \`series\` entry (known: ${series.map((s) => s.key).join(", ")}) \u2014 the hatch would fall back to an unnamed neutral, and a hatched bar is the one mark a reader cannot decode from either axis.`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
115
128
|
const absentColor = (absentState === void 0 ? void 0 : seriesByKey.get(absentState)?.color) ?? VX.neutral;
|
|
116
129
|
const drawnUp = upVisible ? upSeries : void 0;
|
|
117
130
|
const drawnDown = downVisible ? downSeries : void 0;
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -617,9 +617,13 @@ function readFrameworkVersion(pkgRoot) {
|
|
|
617
617
|
return "0.0.0";
|
|
618
618
|
}
|
|
619
619
|
}
|
|
620
|
+
function basaltBinCommand(install, cwd) {
|
|
621
|
+
if (install.dir === null) return "bunx basalt-ui";
|
|
622
|
+
const binDir = resolve(install.dir, "..", ".bin");
|
|
623
|
+
return `${relativePosix(cwd, binDir).replace(/^\.\//, "")}/basalt-ui`;
|
|
624
|
+
}
|
|
620
625
|
function buildTemplateVars(pkgRoot, cwd, cfg) {
|
|
621
626
|
const install = findBasaltInstall(cwd);
|
|
622
|
-
const binDir = install.dir === null ? null : resolve(install.dir, "..", ".bin");
|
|
623
627
|
return {
|
|
624
628
|
APP_NAME: readPackageName(cwd),
|
|
625
629
|
BASALT_VERSION: readFrameworkVersion(pkgRoot),
|
|
@@ -628,7 +632,7 @@ function buildTemplateVars(pkgRoot, cwd, cfg) {
|
|
|
628
632
|
ROOTS_GLOBS: resolveRoots(cfg).map(toRootGlob).join(" "),
|
|
629
633
|
OXLINT_PRESET_PATH: shippedAssetPath(install, cwd, "configs/oxlint.json"),
|
|
630
634
|
LEFTHOOK_PRESET_PATH: shippedAssetPath(install, cwd, "configs/lefthook.yml"),
|
|
631
|
-
BASALT_BIN:
|
|
635
|
+
BASALT_BIN: basaltBinCommand(install, cwd)
|
|
632
636
|
};
|
|
633
637
|
}
|
|
634
638
|
function fillTemplate(tpl, vars) {
|
|
@@ -1268,7 +1272,7 @@ Theme guard hook: add to .claude/settings.json \u2192 hooks.PreToolUse to catch
|
|
|
1268
1272
|
"PreToolUse": [
|
|
1269
1273
|
{
|
|
1270
1274
|
"matcher": "Write|Edit|MultiEdit",
|
|
1271
|
-
"hooks": [{ "type": "command", "command": "
|
|
1275
|
+
"hooks": [{ "type": "command", "command": "${ctx.vars.BASALT_BIN} guard-hook" }]
|
|
1272
1276
|
}
|
|
1273
1277
|
]
|
|
1274
1278
|
}`
|
|
@@ -1299,6 +1303,9 @@ function readOxlintPresetPlugins(pkgRoot) {
|
|
|
1299
1303
|
return [];
|
|
1300
1304
|
}
|
|
1301
1305
|
}
|
|
1306
|
+
function parentInstallAdvice(cwd, parent, verb) {
|
|
1307
|
+
return `This repo's install is at ${relativePosix(cwd, parent)} (${parent}) \u2014 run ${verb} there, or set BASALT_CWD to it.`;
|
|
1308
|
+
}
|
|
1302
1309
|
function findManifestAbove(dir) {
|
|
1303
1310
|
let current = resolve(dir, "..");
|
|
1304
1311
|
for (; ; ) {
|
|
@@ -1337,7 +1344,7 @@ function sync(opts = {}, invocationCwd = process.cwd()) {
|
|
|
1337
1344
|
const elsewhere = findManifestAbove(cwd);
|
|
1338
1345
|
const wouldWrite = managedFiles(resolvePeerFlags(cwd, {}), resolvePlacement(cwd)).length;
|
|
1339
1346
|
console.error(
|
|
1340
|
-
`\u2716 basalt-ui sync: no ${MANIFEST_PATH} at ${cwd} \u2014 refusing to scaffold. \`sync\` refreshes an EXISTING basalt install; creating one is \`basalt-ui init\`'s decision, and continuing here would write ${wouldWrite} managed file(s) into this directory.` + (elsewhere === null ? " No manifest exists at any ancestor either \u2014 run `basalt-ui init` here if this package really is meant to be a consumer." : `
|
|
1347
|
+
`\u2716 basalt-ui sync: no ${MANIFEST_PATH} at ${cwd} \u2014 refusing to scaffold. \`sync\` refreshes an EXISTING basalt install; creating one is \`basalt-ui init\`'s decision, and continuing here would write ${wouldWrite} managed file(s) into this directory.` + (elsewhere === null ? " No manifest exists at any ancestor either \u2014 run `basalt-ui init` here if this package really is meant to be a consumer." : ` ${parentInstallAdvice(cwd, elsewhere, "sync")}`)
|
|
1341
1348
|
);
|
|
1342
1349
|
return 1;
|
|
1343
1350
|
}
|
|
@@ -1706,6 +1713,7 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
1706
1713
|
}
|
|
1707
1714
|
const manifestAbs = resolve(cwd, MANIFEST_PATH);
|
|
1708
1715
|
const manifestExists = existsSync(manifestAbs);
|
|
1716
|
+
const parentInstall = manifestExists ? null : findManifestAbove(cwd);
|
|
1709
1717
|
const profile = inferredProfile(cwd, cfg, flags);
|
|
1710
1718
|
if (profile === "tokens-only") {
|
|
1711
1719
|
lines.push(
|
|
@@ -1721,6 +1729,10 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
1721
1729
|
pass(`${MANIFEST_PATH}: n/a \u2014 a tokens-only consumer has no scaffold to reconcile`);
|
|
1722
1730
|
} else if (manifestExists) {
|
|
1723
1731
|
pass(`${MANIFEST_PATH} exists`);
|
|
1732
|
+
} else if (parentInstall !== null) {
|
|
1733
|
+
fail(
|
|
1734
|
+
`${MANIFEST_PATH} missing here, but this is not an unscaffolded consumer. ${parentInstallAdvice(cwd, parentInstall, "doctor")} \`basalt-ui init\` is NOT the fix: it would scaffold a SECOND consumer beside the real one.`
|
|
1735
|
+
);
|
|
1724
1736
|
} else {
|
|
1725
1737
|
fail(`${MANIFEST_PATH} missing \u2014 run \`basalt-ui init\` to scaffold the consumer repo`);
|
|
1726
1738
|
}
|
|
@@ -1816,7 +1828,7 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
1816
1828
|
const oxlintrcRaw = readIfExists(resolve(cwd, ".oxlintrc.json"));
|
|
1817
1829
|
if (oxlintrcRaw === null) {
|
|
1818
1830
|
fail(
|
|
1819
|
-
".oxlintrc.json missing \u2014 the shipped oxlint preset (the basalt/* design rules) is not active. Run `basalt-ui init` to seed it."
|
|
1831
|
+
".oxlintrc.json missing \u2014 the shipped oxlint preset (the basalt/* design rules) is not active. " + (parentInstall === null ? "Run `basalt-ui init` to seed it." : `${parentInstallAdvice(cwd, parentInstall, "doctor")} The preset is seeded once, at the install \u2014 not per package.`)
|
|
1820
1832
|
);
|
|
1821
1833
|
} else {
|
|
1822
1834
|
const parsed = parseJsonc(oxlintrcRaw);
|
|
@@ -1864,30 +1876,43 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
1864
1876
|
);
|
|
1865
1877
|
} else if (lefthookGate.kind === "absent") {
|
|
1866
1878
|
warn(
|
|
1867
|
-
`${lefthookGate.file}: \`lefthook dump\` resolves the merged config and NO pre-commit command runs check-theme \u2014 the theme guard is not gating commits. Either add "extends: [${lefthookCorrect}]", or add your own command running
|
|
1879
|
+
`${lefthookGate.file}: \`lefthook dump\` resolves the merged config and NO pre-commit command runs check-theme \u2014 the theme guard is not gating commits. Either add "extends: [${lefthookCorrect}]", or add your own command running \`${basaltBinCommand(install, cwd)} check-theme\` (with \`root:\` if it must run in a subdirectory).`
|
|
1868
1880
|
);
|
|
1869
1881
|
} else {
|
|
1870
1882
|
warn(
|
|
1871
|
-
`${lefthookGate.file} names no basalt gate and \`lefthook dump\` could not be run here, so this check cannot tell a missing gate from one wired through an \`include:\` or a remote config it never read \u2014 treat it as advisory. If the guard really is unwired, add "extends: [${lefthookCorrect}]" or your own command running
|
|
1883
|
+
`${lefthookGate.file} names no basalt gate and \`lefthook dump\` could not be run here, so this check cannot tell a missing gate from one wired through an \`include:\` or a remote config it never read \u2014 treat it as advisory. If the guard really is unwired, add "extends: [${lefthookCorrect}]" or your own command running \`${basaltBinCommand(install, cwd)} check-theme\`.`
|
|
1872
1884
|
);
|
|
1873
1885
|
}
|
|
1874
1886
|
const publicDir = resolve(cwd, "public");
|
|
1875
1887
|
if (profile === "framework" && existsSync(publicDir)) {
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
"
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
"web-app-manifest-512x512.png"
|
|
1883
|
-
];
|
|
1884
|
-
const missingIcons = iconFiles.filter((f) => !existsSync(resolve(publicDir, f)));
|
|
1885
|
-
if (missingIcons.length > 0) {
|
|
1886
|
-
warn(
|
|
1887
|
-
`public/ is missing basaltAppPlugin icon file(s): ${missingIcons.join(", ")} \u2014 generate them (e.g. via realfavicongenerator.net) and place them at the public/ root.`
|
|
1888
|
+
const icons = readAppIconsOption(cwd);
|
|
1889
|
+
if (icons.kind === "none") {
|
|
1890
|
+
pass("basaltAppPlugin is configured with no icons \u2014 nothing to check");
|
|
1891
|
+
} else if (icons.kind === "explicit") {
|
|
1892
|
+
const missing = icons.sources.filter(
|
|
1893
|
+
(src) => !existsSync(resolve(publicDir, src.replace(/^\//, "")))
|
|
1888
1894
|
);
|
|
1895
|
+
if (missing.length > 0) {
|
|
1896
|
+
warn(
|
|
1897
|
+
`basaltAppPlugin declares icon(s) that are not in public/: ${missing.join(", ")} \u2014 the manifest and the head links will point at a 404. Place them, or drop them from the \`icons\` array.`
|
|
1898
|
+
);
|
|
1899
|
+
} else {
|
|
1900
|
+
pass(
|
|
1901
|
+
`public/ has all ${icons.sources.length} icon file(s) basaltAppPlugin's \`icons\` option names`
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1889
1904
|
} else {
|
|
1890
|
-
|
|
1905
|
+
const dir = icons.kind === "default" ? icons.dir : null;
|
|
1906
|
+
const iconRoot = dir === null ? publicDir : resolve(publicDir, dir.replace(/^\//, ""));
|
|
1907
|
+
const shown = dir === null ? "public/" : `public/${dir.replace(/^\//, "")}`;
|
|
1908
|
+
const missingIcons = DEFAULT_APP_ICON_FILES.filter((f) => !existsSync(resolve(iconRoot, f)));
|
|
1909
|
+
if (missingIcons.length > 0) {
|
|
1910
|
+
warn(
|
|
1911
|
+
`${shown} is missing basaltAppPlugin icon file(s): ${missingIcons.join(", ")} \u2014 generate them (e.g. via realfavicongenerator.net) and place them at the ${shown} root, or name the icons this app really has via the plugin's \`icons\` array.`
|
|
1912
|
+
);
|
|
1913
|
+
} else {
|
|
1914
|
+
pass(`${shown} has all of basaltAppPlugin's default icon files`);
|
|
1915
|
+
}
|
|
1891
1916
|
}
|
|
1892
1917
|
}
|
|
1893
1918
|
const workspaceWalk = collectWorkspacePackages(cwd);
|
|
@@ -2008,6 +2033,68 @@ basalt-ui v${pkgVersion} \u2014 published surface
|
|
|
2008
2033
|
console.log("");
|
|
2009
2034
|
return 0;
|
|
2010
2035
|
}
|
|
2036
|
+
const DEFAULT_APP_ICON_FILES = [
|
|
2037
|
+
"favicon.ico",
|
|
2038
|
+
"favicon.svg",
|
|
2039
|
+
"favicon-96x96.png",
|
|
2040
|
+
"apple-touch-icon.png",
|
|
2041
|
+
"web-app-manifest-192x192.png",
|
|
2042
|
+
"web-app-manifest-512x512.png"
|
|
2043
|
+
];
|
|
2044
|
+
const VITE_CONFIG_FILES = [
|
|
2045
|
+
"vite.config.ts",
|
|
2046
|
+
"vite.config.mts",
|
|
2047
|
+
"vite.config.cts",
|
|
2048
|
+
"vite.config.js",
|
|
2049
|
+
"vite.config.mjs",
|
|
2050
|
+
"vite.config.cjs"
|
|
2051
|
+
];
|
|
2052
|
+
function balancedSpan(text, open) {
|
|
2053
|
+
const pairs = { "(": ")", "{": "}", "[": "]" };
|
|
2054
|
+
const closer = pairs[text[open]];
|
|
2055
|
+
if (closer === void 0) return null;
|
|
2056
|
+
let depth = 0;
|
|
2057
|
+
for (let i = open; i < text.length; i++) {
|
|
2058
|
+
const ch = text[i];
|
|
2059
|
+
if (ch === text[open]) depth++;
|
|
2060
|
+
else if (ch === closer) {
|
|
2061
|
+
depth--;
|
|
2062
|
+
if (depth === 0) return text.slice(open, i + 1);
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
return null;
|
|
2066
|
+
}
|
|
2067
|
+
function readAppIconsOption(cwd) {
|
|
2068
|
+
const configPath = VITE_CONFIG_FILES.map((f) => resolve(cwd, f)).find((f) => existsSync(f));
|
|
2069
|
+
if (configPath === void 0) return { kind: "unknown" };
|
|
2070
|
+
const text = readIfExists(configPath);
|
|
2071
|
+
if (text === null) return { kind: "unknown" };
|
|
2072
|
+
const call = text.indexOf("basaltAppPlugin(");
|
|
2073
|
+
if (call === -1) return { kind: "unknown" };
|
|
2074
|
+
const args = balancedSpan(text, call + "basaltAppPlugin".length);
|
|
2075
|
+
if (args === null) return { kind: "unknown" };
|
|
2076
|
+
const key = args.search(/\bicons\s*:/);
|
|
2077
|
+
if (key === -1) return { kind: "default", dir: null };
|
|
2078
|
+
const valueStart = args.indexOf(":", key) + 1;
|
|
2079
|
+
const rest = args.slice(valueStart).trimStart();
|
|
2080
|
+
if (rest.startsWith("false")) return { kind: "none" };
|
|
2081
|
+
const offset = args.length - rest.length;
|
|
2082
|
+
if (rest.startsWith("[")) {
|
|
2083
|
+
const list = balancedSpan(args, offset);
|
|
2084
|
+
if (list === null) return { kind: "unknown" };
|
|
2085
|
+
const sources = [...list.matchAll(/\bsrc\s*:\s*['"`]([^'"`]+)['"`]/g)].map(
|
|
2086
|
+
(m) => m[1]
|
|
2087
|
+
);
|
|
2088
|
+
return sources.length === 0 ? { kind: "none" } : { kind: "explicit", sources };
|
|
2089
|
+
}
|
|
2090
|
+
if (rest.startsWith("{")) {
|
|
2091
|
+
const obj = balancedSpan(args, offset);
|
|
2092
|
+
if (obj === null) return { kind: "unknown" };
|
|
2093
|
+
const dir = /\bdir\s*:\s*['"`]([^'"`]+)['"`]/.exec(obj);
|
|
2094
|
+
return { kind: "default", dir: dir === null ? null : dir[1] };
|
|
2095
|
+
}
|
|
2096
|
+
return { kind: "unknown" };
|
|
2097
|
+
}
|
|
2011
2098
|
function flagValue(flags, name) {
|
|
2012
2099
|
const i = flags.indexOf(name);
|
|
2013
2100
|
if (i === -1) return void 0;
|
|
@@ -2021,6 +2108,12 @@ function generatedHeader(version, command, flags) {
|
|
|
2021
2108
|
/* basalt-ui ${version} \u2014 \`basalt-ui ${invocation}\` */
|
|
2022
2109
|
`;
|
|
2023
2110
|
}
|
|
2111
|
+
function withoutProvenanceLine(css) {
|
|
2112
|
+
const lines = css.split("\n");
|
|
2113
|
+
if (lines.length < 2) return css;
|
|
2114
|
+
lines[1] = "";
|
|
2115
|
+
return lines.join("\n");
|
|
2116
|
+
}
|
|
2024
2117
|
function normalizeColorFunctions(css) {
|
|
2025
2118
|
return css.replace(/\b(rgba?|hsla?)\(([^()]*)\)/g, (_match, fn, args) => {
|
|
2026
2119
|
const parts = args.split(",").map((part) => normalizeCssNumber(part.trim()));
|
|
@@ -2055,12 +2148,15 @@ function emitGeneratedCss(content, flags, cwd, command) {
|
|
|
2055
2148
|
);
|
|
2056
2149
|
return 1;
|
|
2057
2150
|
}
|
|
2058
|
-
if (onDisk === content) {
|
|
2059
|
-
|
|
2151
|
+
if (withoutProvenanceLine(onDisk) === withoutProvenanceLine(content)) {
|
|
2152
|
+
const staleProvenance = onDisk.split("\n")[1] !== content.split("\n")[1];
|
|
2153
|
+
console.log(
|
|
2154
|
+
`\u2713 ${command} --check: ${shown} is up to date.` + (staleProvenance ? " (Its provenance line still names an older basalt-ui; that line is deliberately not gated \u2014 re-run without --check whenever you want it refreshed.)" : "")
|
|
2155
|
+
);
|
|
2060
2156
|
return 0;
|
|
2061
2157
|
}
|
|
2062
2158
|
console.error(
|
|
2063
|
-
`\u2716 ${command} --check: ${shown} differs from what \`basalt-ui ${command}\` emits today (on disk ${onDisk.split("\n").length} lines, emitted ${content.split("\n").length}) \u2014 re-run the same command without --check and commit the result.`
|
|
2159
|
+
`\u2716 ${command} --check: ${shown} differs from what \`basalt-ui ${command}\` emits today (on disk ${onDisk.split("\n").length} lines, emitted ${content.split("\n").length}) \u2014 re-run the same command without --check and commit the result. The \`@generated\` header's provenance line is excluded from this comparison, so a version bump alone never trips it.`
|
|
2064
2160
|
);
|
|
2065
2161
|
return 1;
|
|
2066
2162
|
}
|
|
@@ -2241,13 +2337,71 @@ async function guardHook(cwd = process.cwd()) {
|
|
|
2241
2337
|
}
|
|
2242
2338
|
return 0;
|
|
2243
2339
|
}
|
|
2244
|
-
const
|
|
2340
|
+
const COMMAND_FLAGS = {
|
|
2341
|
+
init: ["--with-router", "--with-query", "--merge-lint"],
|
|
2342
|
+
sync: ["--force", "--check", "--tokens-only", "--framework"],
|
|
2343
|
+
"check-theme": ["--audit-allows", "--tokens-only", "--framework"],
|
|
2344
|
+
"check-coverage": [],
|
|
2345
|
+
info: ["--json"],
|
|
2346
|
+
doctor: ["--tokens-only", "--framework"],
|
|
2347
|
+
"guard-hook": [],
|
|
2348
|
+
"tokens:css": [
|
|
2349
|
+
"--out",
|
|
2350
|
+
"--check",
|
|
2351
|
+
"--selector-attribute",
|
|
2352
|
+
"--selector-class",
|
|
2353
|
+
"--light-class",
|
|
2354
|
+
"--dark-value",
|
|
2355
|
+
"--light-value",
|
|
2356
|
+
"--default-scheme",
|
|
2357
|
+
"--media-fallback",
|
|
2358
|
+
"--only",
|
|
2359
|
+
"--no-legacy-aliases"
|
|
2360
|
+
],
|
|
2361
|
+
"fonts:css": ["--out", "--check"]
|
|
2362
|
+
};
|
|
2363
|
+
const VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
2364
|
+
"--out",
|
|
2365
|
+
"--selector-attribute",
|
|
2366
|
+
"--selector-class",
|
|
2367
|
+
"--light-class",
|
|
2368
|
+
"--dark-value",
|
|
2369
|
+
"--light-value",
|
|
2370
|
+
"--default-scheme",
|
|
2371
|
+
"--only"
|
|
2372
|
+
]);
|
|
2373
|
+
function unknownFlag(cmd, flags) {
|
|
2374
|
+
const allowed = COMMAND_FLAGS[cmd];
|
|
2375
|
+
if (allowed === void 0) return null;
|
|
2376
|
+
for (let i = 0; i < flags.length; i++) {
|
|
2377
|
+
const flag = flags[i];
|
|
2378
|
+
if (!flag.startsWith("-")) continue;
|
|
2379
|
+
if (!allowed.includes(flag)) return flag;
|
|
2380
|
+
if (VALUE_FLAGS.has(flag)) i++;
|
|
2381
|
+
}
|
|
2382
|
+
return null;
|
|
2383
|
+
}
|
|
2384
|
+
const USAGE = "Usage: basalt-ui <--version | init [--with-router] [--with-query] [--merge-lint] |\n sync [--force] [--check] [--tokens-only|--framework] |\n check-theme [--audit-allows] | check-coverage | info [--json] |\n doctor [--tokens-only|--framework] | guard-hook | tokens:css | fonts:css | help>\n\ncheck-theme [--tokens-only|--framework] [--audit-allows]\n --audit-allows reports instead of scanning: every `theme-allow` annotation and every\n `basalt.exemptRules` entry, with what each one still suppresses \u2014 proved by re-running the\n guard with that one waiver neutralized, not by reading its text. Exits 1 on a waiver that\n suppresses nothing (dead), which is what makes it usable as a CI gate.\n\ntokens:css [--out <path>] [--check] [--selector-attribute <attr> | --selector-class <class>]\n [--light-class <class>] [--dark-value <v>] [--light-value <v>]\n [--default-scheme <dark|light|none>] [--media-fallback] [--only <core|all>]\n [--no-legacy-aliases]\n Emit the --vx-* stylesheet (stdout unless --out). Defaults reproduce basalt-ui/tokens.css.\n --selector-class emits `:root.dark` instead of an attribute selector (the Tailwind convention).\n --check writes nothing and exits 1 when --out differs from what would be emitted (a CI gate).\n --no-legacy-aliases drops the deprecated camelCase spellings (--vx-accentFill and friends),\n which are emitted by default as aliases of the canonical kebab-case names.\n\nfonts:css [--out <path>] [--check]\n Emit the shipped --basalt-font-* stacks as plain CSS \u2014 the typeface half of the token layer,\n otherwise reachable only by importing styles.css.\n\ndoctor [--tokens-only|--framework]\n Auto-detects a tokens-only consumer (no manifest + no @mantine/core) and checks only what\n applies. A check that cannot RUN is reported as SKIPPED and exits non-zero.\n\nsync [--force] [--check] [--tokens-only|--framework]\n Refreshes an EXISTING install; it never creates one (that is init). A tokens-only consumer\n has no scaffold to reconcile, so sync reports n/a and exits 0 there \u2014 as doctor does.\n\ncheck-theme / doctor / sync all resolve their project the same way: they honour BASALT_CWD, and\nrelocate to the single package below the cwd carrying a basalt config when invoked from a repo\nroot that has none \u2014 several carrying one is ambiguous and exits 1 in ALL THREE.\n--tokens-only and --framework are alternatives; passing both is an error.\n\nEvery subcommand accepts --help / -h to print this message and exit without running.\n--version / -v prints the resolved package version and exits 0 \u2014 the one command that proves\nWHICH basalt-ui ran, which a `bunx` cache can otherwise make a lie. An unknown command or an\nunrecognized flag exits 1 and names what it did not understand; neither is ever ignored.";
|
|
2245
2385
|
function run(argv, cwd = process.cwd()) {
|
|
2246
2386
|
const [cmd, ...flags] = argv;
|
|
2247
2387
|
if (cmd === "help" || cmd === "--help" || cmd === "-h" || flags.includes("--help") || flags.includes("-h")) {
|
|
2248
2388
|
console.log(USAGE);
|
|
2249
2389
|
return 0;
|
|
2250
2390
|
}
|
|
2391
|
+
if (cmd === "--version" || cmd === "-v" || cmd === "version") {
|
|
2392
|
+
console.log(readFrameworkVersion(packageRoot()));
|
|
2393
|
+
return 0;
|
|
2394
|
+
}
|
|
2395
|
+
if (cmd !== void 0) {
|
|
2396
|
+
const bad = unknownFlag(cmd, flags);
|
|
2397
|
+
if (bad !== null) {
|
|
2398
|
+
console.error(
|
|
2399
|
+
`basalt-ui ${cmd}: unrecognized flag '${bad}'. Accepted: ${(COMMAND_FLAGS[cmd] ?? []).join(" ") || "(none)"} --help
|
|
2400
|
+
`
|
|
2401
|
+
);
|
|
2402
|
+
return 1;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2251
2405
|
switch (cmd) {
|
|
2252
2406
|
case "init":
|
|
2253
2407
|
return init(cwd, {
|
|
@@ -2275,6 +2429,10 @@ function run(argv, cwd = process.cwd()) {
|
|
|
2275
2429
|
case "fonts:css":
|
|
2276
2430
|
return fontsCss(flags, cwd);
|
|
2277
2431
|
default:
|
|
2432
|
+
console.error(
|
|
2433
|
+
cmd === void 0 ? "basalt-ui: no command given.\n" : `basalt-ui: unknown command '${cmd}'.
|
|
2434
|
+
`
|
|
2435
|
+
);
|
|
2278
2436
|
console.error(USAGE);
|
|
2279
2437
|
return 1;
|
|
2280
2438
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guard/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE7E,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guard/index.ts"],"names":[],"mappings":"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"}
|