basalt-ui 1.29.2 → 1.30.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/CHANGELOG.md +17 -0
- package/MIGRATING.md +901 -366
- package/README.md +23 -2
- package/agent/rules/basalt-controls.md +34 -34
- package/agent/skills/basalt-app/SKILL.md +4 -2
- package/agent/templates/query-client.ts.tpl +18 -4
- package/configs/lefthook.yml +51 -19
- package/configs/oxlint-plugin.js +210 -84
- package/configs/oxlint-plugin.test.ts +182 -5
- package/configs/oxlint.json +4 -4
- package/dist/charts/index.d.ts +1 -1
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/kinds/BandStrip.d.ts +5 -3
- package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.d.ts +4 -2
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Donut.d.ts +4 -2
- package/dist/charts/kinds/Donut.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.d.ts +4 -2
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/Heatmap.d.ts +5 -2
- package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
- package/dist/charts/kinds/MirroredBars.d.ts +4 -2
- package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
- package/dist/charts/kinds/MultiLine.d.ts +4 -2
- package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
- package/dist/charts/kinds/StackedArea.d.ts +4 -2
- package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
- package/dist/charts/kinds/ZonedLine.d.ts +4 -2
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/charts/primitives/CartesianChart.d.ts +4 -1
- package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.js +2 -2
- package/dist/charts/primitives/ChartFrame.d.ts +25 -4
- package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
- package/dist/charts/primitives/ChartFrame.js +23 -16
- package/dist/charts/primitives/chart-frame-layout.d.ts +115 -6
- package/dist/charts/primitives/chart-frame-layout.d.ts.map +1 -1
- package/dist/charts/primitives/chart-frame-layout.js +46 -6
- package/dist/cli/check-theme.d.ts.map +1 -1
- package/dist/cli/check-theme.js +6 -0
- package/dist/cli/doctor.d.ts +10 -4
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +28 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +2 -1
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +29 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +4 -15
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +8 -14
- package/dist/controls/actions.d.ts.map +1 -1
- package/dist/controls/actions.js +12 -2
- package/dist/dashboard/section.module.css +15 -7
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +7 -2
- package/dist/dashboard/stat-group.d.ts +8 -2
- package/dist/dashboard/stat-group.d.ts.map +1 -1
- package/dist/dashboard/stat-group.js +23 -15
- package/dist/dashboard/stat-group.module.css +85 -9
- package/dist/dashboard/stat-group.module.css.d.ts +1 -0
- package/dist/dashboard/widget-grid.d.ts.map +1 -1
- package/dist/dashboard/widget-grid.js +4 -5
- package/dist/dashboard/widget-grid.module.css +64 -21
- package/dist/dashboard/widget-grid.module.css.d.ts +1 -0
- package/dist/guard/index.d.ts +19 -2
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +27 -4
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/shell/app-brand.module.css +12 -3
- package/dist/shell/app-header.module.css +49 -9
- package/dist/shell/app-main.module.css +24 -4
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +98 -51
- package/dist/shell/app-mobile-nav.module.css +99 -11
- package/dist/shell/app-mobile-nav.module.css.d.ts +1 -0
- package/dist/shell/app-sidebar.module.css +55 -2
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +3 -3
- package/dist/shell/mobile-nav-model.d.ts +26 -7
- package/dist/shell/mobile-nav-model.d.ts.map +1 -1
- package/dist/shell/mobile-nav-model.js +12 -3
- package/dist/shell/page-aside.module.css +8 -6
- package/dist/shell/page-bar.d.ts +13 -0
- package/dist/shell/page-bar.d.ts.map +1 -1
- package/dist/shell/page-bar.js +13 -3
- package/dist/shell/page-bar.module.css +20 -12
- package/dist/shell/page-title.module.css +3 -1
- package/dist/theme/use-basalt-spacing.d.ts.map +1 -1
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +51 -7
- package/dist/tokens/palette.d.ts +98 -17
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +110 -18
- package/dist/tokens.css +17 -5
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/charts/index.ts +1 -0
- package/src/charts/kinds/BandStrip.tsx +5 -3
- package/src/charts/kinds/Bars.tsx +4 -2
- package/src/charts/kinds/Donut.tsx +4 -2
- package/src/charts/kinds/DualPanel.tsx +4 -2
- package/src/charts/kinds/Heatmap.tsx +5 -2
- package/src/charts/kinds/MirroredBars.tsx +4 -2
- package/src/charts/kinds/MultiLine.tsx +4 -2
- package/src/charts/kinds/StackedArea.tsx +4 -2
- package/src/charts/kinds/ZonedLine.tsx +4 -2
- package/src/charts/primitives/CartesianChart.tsx +4 -1
- package/src/charts/primitives/ChartCard.tsx +12 -7
- package/src/charts/primitives/ChartFrame.tsx +51 -37
- package/src/charts/primitives/chart-frame-layout.ts +172 -13
- package/src/cli/check-theme.ts +13 -0
- package/src/cli/doctor.ts +49 -8
- package/src/cli/help.ts +5 -3
- package/src/cli/index.ts +49 -0
- package/src/cli/init.ts +6 -27
- package/src/cli/sync.ts +11 -22
- package/src/controls/actions.tsx +51 -0
- package/src/dashboard/section.module.css +15 -7
- package/src/dashboard/stat-card.tsx +7 -2
- package/src/dashboard/stat-group.module.css +85 -9
- package/src/dashboard/stat-group.module.css.d.ts +1 -0
- package/src/dashboard/stat-group.tsx +40 -20
- package/src/dashboard/widget-grid.module.css +64 -21
- package/src/dashboard/widget-grid.module.css.d.ts +1 -0
- package/src/dashboard/widget-grid.tsx +30 -12
- package/src/guard/index.ts +79 -11
- package/src/index.ts +9 -0
- package/src/shell/app-brand.module.css +12 -3
- package/src/shell/app-header.module.css +49 -9
- package/src/shell/app-main.module.css +24 -4
- package/src/shell/app-mobile-nav.module.css +99 -11
- package/src/shell/app-mobile-nav.module.css.d.ts +1 -0
- package/src/shell/app-mobile-nav.tsx +225 -83
- package/src/shell/app-sidebar.module.css +55 -2
- package/src/shell/index.tsx +26 -6
- package/src/shell/mobile-nav-model.ts +37 -9
- package/src/shell/page-aside.module.css +8 -6
- package/src/shell/page-bar.module.css +20 -12
- package/src/shell/page-bar.tsx +39 -5
- package/src/shell/page-title.module.css +3 -1
- package/src/theme/use-basalt-spacing.ts +8 -6
- package/src/tokens/index.ts +90 -6
- package/src/tokens/palette.ts +111 -18
|
@@ -4,6 +4,7 @@ import type { BasaltProps } from '../../common/props.js';
|
|
|
4
4
|
import type { ChartMargin } from '../../tokens/index.js';
|
|
5
5
|
import type { CursorResolution } from '../cursor/resolve.js';
|
|
6
6
|
import type { ChartLegendConfig, ChartSeries } from '../series.js';
|
|
7
|
+
import type { ResponsiveChartHeight } from './ChartFrame.js';
|
|
7
8
|
import type { ChartState } from './ChartPending.js';
|
|
8
9
|
import type { XZoneSpec } from './XZoneRects.js';
|
|
9
10
|
import type { ZoneSpec } from './ZoneRects.js';
|
|
@@ -186,7 +187,9 @@ export type CartesianChartProps<T> = BasaltProps & {
|
|
|
186
187
|
dashed?: boolean;
|
|
187
188
|
axis?: 'left' | 'right';
|
|
188
189
|
}[];
|
|
189
|
-
|
|
190
|
+
/** Height in px, or one per size step (`{ base, sm?, md?, lg? }`). Default 240. Forwarded
|
|
191
|
+
* unchanged; `ChartFrameProps.height` owns the law — steps resolve off the MEASURED width. */
|
|
192
|
+
height?: number | ResponsiveChartHeight;
|
|
190
193
|
aspectRatio?: number;
|
|
191
194
|
fill?: boolean;
|
|
192
195
|
legend?: ChartLegendConfig | false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CartesianChart.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/CartesianChart.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAKzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"CartesianChart.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/CartesianChart.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartCard.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"ChartCard.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AA0ChD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEtD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GACtC,eAAe,CAAC,aAAa,CAAC,GAAG;IAC/B,mGAAmG;IACnG,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;8FAC0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;kEAC8D;IAC9D,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+FAA+F;IAC/F,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,8FAA8F;IAC9F,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;sDACkD;IAClD,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;oGACgG;IAChG,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB,CAAA;AAEH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,EACL,WAAW,EACX,aAAa,EACb,KAAK,EACL,OAAO,EACP,KAAK,EACL,iBAAuB,EACvB,WAAW,EACX,SAAS,EACT,UAAU,EACV,KAAK,EACL,QAAQ,GACT,EAAE,cAAc,+BAgEhB"}
|
|
@@ -17,10 +17,10 @@ const bodyClipStyle = {
|
|
|
17
17
|
borderBottomLeftRadius: VX.radiusCard,
|
|
18
18
|
borderBottomRightRadius: VX.radiusCard,
|
|
19
19
|
overflow: "hidden",
|
|
20
|
-
padding: "2px var(--
|
|
20
|
+
padding: "2px var(--vx-space-card-inset-x, 0.8125rem) var(--vx-space-card-inset-y, 0.6875rem)"
|
|
21
21
|
};
|
|
22
22
|
const headerWrapStyle = {
|
|
23
|
-
padding: "var(--
|
|
23
|
+
padding: "var(--vx-space-card-inset-y, 0.6875rem) var(--vx-space-card-inset-x, 0.8125rem) 4px"
|
|
24
24
|
};
|
|
25
25
|
function ChartCard({
|
|
26
26
|
title,
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { BasaltProps } from '../../common/props.js';
|
|
3
3
|
import type { ChartLegendConfig, LegendPlacement, SeriesStyle } from '../series.js';
|
|
4
|
+
import type { ResponsiveChartHeight } from './chart-frame-layout.js';
|
|
4
5
|
import type { ChartState } from './ChartPending.js';
|
|
5
6
|
/** Re-exported for `ChartFrame.test.tsx` and any other consumer that previously reached these
|
|
6
7
|
* through `ChartFrame` — the layout math itself lives in `./chart-frame-layout` (pure, DOM-free). */
|
|
7
|
-
export { legendEntryCap, resolvePlotRect, resolveChartTier } from './chart-frame-layout.js';
|
|
8
|
+
export { legendEntryCap, resolveLegendRollup, resolvePlotRect, resolveChartTier, } from './chart-frame-layout.js';
|
|
9
|
+
export type { ResponsiveChartHeight } from './chart-frame-layout.js';
|
|
8
10
|
/** Legend configuration for {@link ChartFrame}. Omit entirely (or pass `{}`) for the default
|
|
9
11
|
* bottom-placed legend; pass `false` only for the sparkline exemption. */
|
|
10
12
|
export type ChartFrameLegend = {
|
|
11
13
|
/** Default 'bottom'. */
|
|
12
14
|
placement?: LegendPlacement;
|
|
13
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Wrap cap → "+N more" rollup at high cardinality.
|
|
17
|
+
*
|
|
18
|
+
* An explicit value WINS OUTRIGHT — over the phone tier's two-row default (`chartTierMetrics`)
|
|
19
|
+
* AND over a `fill` frame's measured fit (`legendEntryCap`). 1.30.0 fixed only the first half:
|
|
20
|
+
* the fit still ran `Math.min(fitted, caller)` on top, so meteo's 7-entry meteogram legend in a
|
|
21
|
+
* 150px docked row rendered 2 entries at `maxRows` 3, 6 AND 99 — five series drawn in colours
|
|
22
|
+
* nothing named. Both losers are DEFAULTS (the tier's, and `VX.minPlotHeight`); this is the one
|
|
23
|
+
* number a caller stated, so under `fill` the PLOT yields the height instead
|
|
24
|
+
* ({@link resolvePlotRect}'s `legendWins`). State a number too large for the box and the plot
|
|
25
|
+
* gets what is left — visible, and yours.
|
|
26
|
+
*/
|
|
14
27
|
maxRows?: number;
|
|
15
28
|
/** Visually separate role: series | overlay | reference. */
|
|
16
29
|
groups?: boolean;
|
|
@@ -28,8 +41,16 @@ export type ChartFrameLegend = {
|
|
|
28
41
|
export type ChartFrameProps = BasaltProps & {
|
|
29
42
|
/** Series identity — drives the derived legend. Pass the SAME array the kind draws + tooltips from. */
|
|
30
43
|
series: readonly SeriesStyle[];
|
|
31
|
-
/**
|
|
32
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Height in pixels, or one per size step. Used when neither `aspectRatio` nor `fill` is set.
|
|
46
|
+
* Default 240.
|
|
47
|
+
*
|
|
48
|
+
* `{ base: 180, md: 260 }` is the declarative escape from a page of fixed-height charts: the
|
|
49
|
+
* steps are compared against the frame's own MEASURED width, not the viewport, so a chart squeezed
|
|
50
|
+
* by a `PageAside` gets the short height on a desktop too. A plain number is unchanged and stays
|
|
51
|
+
* supported ({@link resolveFrameHeight}).
|
|
52
|
+
*/
|
|
53
|
+
height?: number | ResponsiveChartHeight;
|
|
33
54
|
/** height = Math.round(containerWidth / aspectRatio). Ignored when `fill` is set. */
|
|
34
55
|
aspectRatio?: number;
|
|
35
56
|
/** Fill the parent flex/grid cell's measured height instead of a fixed/derived one. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartFrame.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartFrame.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAIrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"ChartFrame.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartFrame.tsx"],"names":[],"mappings":"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"}
|
|
@@ -4,15 +4,20 @@ import { VX } from "../../tokens/index.js";
|
|
|
4
4
|
import { useChartSize } from "../hooks/useChartSize.js";
|
|
5
5
|
import { deriveLegend } from "../series.js";
|
|
6
6
|
import {
|
|
7
|
-
chartTierMetrics,
|
|
8
|
-
legendEntryCap,
|
|
9
7
|
resolveChartTier,
|
|
8
|
+
resolveFrameHeight,
|
|
9
|
+
resolveLegendRollup,
|
|
10
10
|
resolvePlotRect
|
|
11
11
|
} from "./chart-frame-layout.js";
|
|
12
12
|
import { ChartTierProvider } from "./chart-tier.js";
|
|
13
13
|
import { ChartLegend } from "./ChartLegend.js";
|
|
14
14
|
import { ChartEmpty, ChartError, ChartPending, resolveChartState } from "./ChartPending.js";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
legendEntryCap,
|
|
17
|
+
resolveLegendRollup as resolveLegendRollup2,
|
|
18
|
+
resolvePlotRect as resolvePlotRect2,
|
|
19
|
+
resolveChartTier as resolveChartTier2
|
|
20
|
+
} from "./chart-frame-layout.js";
|
|
16
21
|
const DEFAULT_HEIGHT = 240;
|
|
17
22
|
const DEFAULT_MIN_WIDTH = 200;
|
|
18
23
|
const outerStyle = (fill, vertical) => ({
|
|
@@ -67,26 +72,27 @@ function ChartFrame({
|
|
|
67
72
|
const resolvedState = resolveChartState({ ...state !== void 0 && { state }, isPending });
|
|
68
73
|
const legendVisible = legend !== false && resolvedState === null;
|
|
69
74
|
const tier = resolveChartTier(containerW);
|
|
70
|
-
const resolvedHeight = fill ? containerH : aspectRatio !== void 0 ? Math.round(containerW / aspectRatio) : height ?? DEFAULT_HEIGHT;
|
|
75
|
+
const resolvedHeight = fill ? containerH : aspectRatio !== void 0 ? Math.round(containerW / aspectRatio) : resolveFrameHeight(height ?? DEFAULT_HEIGHT, containerW);
|
|
71
76
|
const sideLegendWidth = legendVisible && vertical ? legendW : 0;
|
|
72
77
|
const topBottomLegendHeight = legendVisible && !vertical ? legendH : 0;
|
|
78
|
+
const legendItems = legend === false ? [] : deriveLegend(series);
|
|
79
|
+
const togglable = legend !== false && (legend.toggle ?? legendItems.length > 1);
|
|
80
|
+
const { maxRows, legendWins } = resolveLegendRollup({
|
|
81
|
+
...legend !== false && legend.maxRows !== void 0 && { statedMaxRows: legend.maxRows },
|
|
82
|
+
tier,
|
|
83
|
+
fillBand: legendVisible && fill && !vertical,
|
|
84
|
+
items: legendItems,
|
|
85
|
+
containerW,
|
|
86
|
+
available: resolvedHeight - VX.minPlotHeight
|
|
87
|
+
});
|
|
73
88
|
const plot = resolvePlotRect({
|
|
74
89
|
containerW,
|
|
75
90
|
resolvedHeight,
|
|
76
91
|
minWidth,
|
|
77
92
|
sideLegendWidth,
|
|
78
|
-
topBottomLegendHeight
|
|
93
|
+
topBottomLegendHeight,
|
|
94
|
+
...legendWins && { legendWins }
|
|
79
95
|
});
|
|
80
|
-
const legendItems = legend === false ? [] : deriveLegend(series);
|
|
81
|
-
const togglable = legend !== false && (legend.toggle ?? legendItems.length > 1);
|
|
82
|
-
const tierMaxRows = chartTierMetrics(tier).legendMaxRows;
|
|
83
|
-
const callerMaxRows = legend === false ? void 0 : legend.maxRows === void 0 ? tierMaxRows : tierMaxRows === void 0 ? legend.maxRows : Math.min(legend.maxRows, tierMaxRows);
|
|
84
|
-
const maxRows = legend === false ? void 0 : fill && !vertical ? legendEntryCap({
|
|
85
|
-
items: legendItems,
|
|
86
|
-
containerW,
|
|
87
|
-
available: resolvedHeight - VX.minPlotHeight,
|
|
88
|
-
...callerMaxRows !== void 0 && { callerMaxRows }
|
|
89
|
-
}) : callerMaxRows;
|
|
90
96
|
const legendNode = legend === false || resolvedState !== null ? null : /* @__PURE__ */ jsx("div", { ref: legendRef, style: legendWrapperStyle(vertical), children: /* @__PURE__ */ jsx(
|
|
91
97
|
ChartLegend,
|
|
92
98
|
{
|
|
@@ -126,8 +132,9 @@ function ChartFrame({
|
|
|
126
132
|
}
|
|
127
133
|
export {
|
|
128
134
|
ChartFrame,
|
|
129
|
-
|
|
135
|
+
legendEntryCap,
|
|
130
136
|
resolveChartTier2 as resolveChartTier,
|
|
131
137
|
resolveLegend,
|
|
138
|
+
resolveLegendRollup2 as resolveLegendRollup,
|
|
132
139
|
resolvePlotRect2 as resolvePlotRect
|
|
133
140
|
};
|
|
@@ -24,6 +24,42 @@ export type ChartTier = 'phone' | 'desktop';
|
|
|
24
24
|
* later, and `resolvePlotRect` already treats an unmeasured width as the first-frame case.
|
|
25
25
|
*/
|
|
26
26
|
export declare function resolveChartTier(containerW: number): ChartTier;
|
|
27
|
+
/**
|
|
28
|
+
* A chart height stated per size step instead of as one number — the declarative escape from "every
|
|
29
|
+
* chart on this page is 260px tall on a 375px phone too".
|
|
30
|
+
*
|
|
31
|
+
* `base` is required and is the height a box narrower than every named step gets; each further key
|
|
32
|
+
* is the height from that step UP. Keys are Mantine's breakpoint names so a consumer writes the
|
|
33
|
+
* vocabulary they already write, and nothing more than `sm`/`md`/`lg` is offered: `xs`/`xl` would
|
|
34
|
+
* be two more rungs nobody has asked a chart to have.
|
|
35
|
+
*
|
|
36
|
+
* ```tsx
|
|
37
|
+
* <ChartFrame series={series} height={{ base: 180, md: 260 }}>{…}</ChartFrame>
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export type ResponsiveChartHeight = {
|
|
41
|
+
/** Below the narrowest STATED step — and NOT the first-frame value; see {@link resolveFrameHeight}. */
|
|
42
|
+
base: number;
|
|
43
|
+
/** From 768px of MEASURED container width up. */
|
|
44
|
+
sm?: number;
|
|
45
|
+
/** From 992px up. */
|
|
46
|
+
md?: number;
|
|
47
|
+
/** From 1200px up. */
|
|
48
|
+
lg?: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a `height` prop — a plain number, or a {@link ResponsiveChartHeight} — against the
|
|
52
|
+
* measured container width.
|
|
53
|
+
*
|
|
54
|
+
* A plain number passes through untouched: this is a WIDENING of the prop, not a replacement, and
|
|
55
|
+
* every existing `height={240}` must keep meaning exactly 240.
|
|
56
|
+
*
|
|
57
|
+
* An UNMEASURED box (`containerW <= 0` — SSR, or before the `ResizeObserver`'s first callback)
|
|
58
|
+
* resolves to the LARGEST stated step, matching {@link resolveChartTier}'s first-frame rule: the
|
|
59
|
+
* first paint must not be phone-shaped chrome that grows one frame later. Falling to `base` there
|
|
60
|
+
* would make every SSR'd chart short and then jump.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveFrameHeight(height: number | ResponsiveChartHeight, containerW: number): number;
|
|
27
63
|
/** Every size a chart's chrome resolves per tier. One object so a new tier-sensitive size is added
|
|
28
64
|
* in one place and read by name, rather than each primitive branching on the tier itself. */
|
|
29
65
|
export type ChartTierMetrics = {
|
|
@@ -39,13 +75,67 @@ export type ChartTierMetrics = {
|
|
|
39
75
|
/** Floating tooltip `minWidth`, px. */
|
|
40
76
|
tooltipMinWidth: number;
|
|
41
77
|
/** Default entry cap on the legend, or `undefined` for no default cap. An explicit
|
|
42
|
-
* `legend.maxRows`
|
|
78
|
+
* `legend.maxRows` replaces it outright ({@link resolveLegendMaxRows}). */
|
|
43
79
|
legendMaxRows: number | undefined;
|
|
44
80
|
/** Per-side margin FLOORS (`VX.margin` is a floor, never a ceiling — §1). */
|
|
45
81
|
margin: ChartMargin;
|
|
46
82
|
};
|
|
47
83
|
/** The resolved sizes for one tier. Frozen module constants — never a new object per render. */
|
|
48
84
|
export declare function chartTierMetrics(tier: ChartTier): ChartTierMetrics;
|
|
85
|
+
/**
|
|
86
|
+
* Which legend cap applies: the caller's, or the tier's own default.
|
|
87
|
+
*
|
|
88
|
+
* **An explicit `callerMaxRows` wins OUTRIGHT.** This used to be `Math.min(caller, tier)`, which
|
|
89
|
+
* made the documented per-chart opt-out ("opt back out with an explicit `legend.maxRows`") false in
|
|
90
|
+
* the one direction anybody needs it. The tier's `PHONE_LEGEND_MAX_ROWS` is a DEFAULT for charts
|
|
91
|
+
* that said nothing — a chart that names a number has already answered the question the default
|
|
92
|
+
* exists to answer, and it matters because the tier keys on the measured box: a 380px inspector
|
|
93
|
+
* panel on a 1440px desktop is "a phone", so a six-series legend rolled up to two rows + `+4 more`
|
|
94
|
+
* with no way to say no. `margin` and `xLabelRotate` always had that escape; the legend did not.
|
|
95
|
+
*
|
|
96
|
+
* The measured {@link legendEntryCap} a `fill` frame applies is NOT a second ceiling on top of
|
|
97
|
+
* this: it resolves an ABSENT cap only. 1.30.0 ran it over the caller's number as well
|
|
98
|
+
* (`Math.min(fitted, caller)`), which made "wins outright" false again in the one place it was
|
|
99
|
+
* needed — meteo measured a 7-entry legend pinned to 2 entries at `maxRows` 3, 6 AND 99, with 5
|
|
100
|
+
* series drawn in colours the legend refused to name. The fit is not physics either: it derives
|
|
101
|
+
* from `VX.minPlotHeight`, which is a framework DEFAULT about the plot. Two defaults do not
|
|
102
|
+
* outvote the one number a caller stated, so the PLOT yields the height instead
|
|
103
|
+
* ({@link resolvePlotRect}'s `legendWins`) — visibly, in the frame the caller sized.
|
|
104
|
+
*/
|
|
105
|
+
export declare function resolveLegendMaxRows(input: {
|
|
106
|
+
callerMaxRows?: number | undefined;
|
|
107
|
+
tier: ChartTier;
|
|
108
|
+
}): number | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* The whole legend-cap decision in one place: which cap `ChartLegend` gets, and whether the plot
|
|
111
|
+
* pays for it.
|
|
112
|
+
*
|
|
113
|
+
* It lives here rather than inline in `ChartFrame` because the COMPOSITION is what broke. 1.30.0
|
|
114
|
+
* had both halves right on their own — {@link resolveLegendMaxRows} honoured a stated cap,
|
|
115
|
+
* {@link legendEntryCap} measured a fit — and then ran the second over the first, which no test
|
|
116
|
+
* could see because neither pure function was wrong and the frame that combined them needs a
|
|
117
|
+
* `ResizeObserver` to test. Now the combination is a pure function too.
|
|
118
|
+
*
|
|
119
|
+
* Three cases, in order:
|
|
120
|
+
* 1. The caller STATED a number → it is the cap, and on a `fill` band the plot yields
|
|
121
|
+
* (`legendWins`). Nothing measured or defaulted trims it.
|
|
122
|
+
* 2. No `fill` band → the tier's default (or none), because the frame simply grows.
|
|
123
|
+
* 3. A `fill` band with nothing stated → the measured fit, bounded by the tier's default.
|
|
124
|
+
*/
|
|
125
|
+
export declare function resolveLegendRollup(input: {
|
|
126
|
+
/** The caller's own `legend.maxRows`. */
|
|
127
|
+
statedMaxRows?: number | undefined;
|
|
128
|
+
tier: ChartTier;
|
|
129
|
+
/** A visible top/bottom legend on a `fill` frame — the one shape whose box cannot grow. */
|
|
130
|
+
fillBand: boolean;
|
|
131
|
+
items: readonly LegendEntry[];
|
|
132
|
+
containerW: number;
|
|
133
|
+
/** Frame height the legend may consume — `resolvedHeight - VX.minPlotHeight`. */
|
|
134
|
+
available: number;
|
|
135
|
+
}): {
|
|
136
|
+
maxRows: number | undefined;
|
|
137
|
+
legendWins: boolean;
|
|
138
|
+
};
|
|
49
139
|
/**
|
|
50
140
|
* Resolve the plot rect from the measured box and the measured legend band. Pure and exported so
|
|
51
141
|
* the two floors below are testable without a `ResizeObserver`.
|
|
@@ -60,9 +150,11 @@ export declare function chartTierMetrics(tier: ChartTier): ChartTierMetrics;
|
|
|
60
150
|
* `height={240}` toward zero and the body stopped rendering entirely. The plot stops at
|
|
61
151
|
* `VX.minPlotHeight` and the frame's own box grows by the difference instead — it is a flex
|
|
62
152
|
* column with `height: auto`, so that growth is automatic. Under `fill` the box CANNOT grow, so
|
|
63
|
-
* the legend is capped instead ({@link legendEntryCap})
|
|
64
|
-
*
|
|
65
|
-
*
|
|
153
|
+
* the legend is capped instead ({@link legendEntryCap}) — UNLESS the caller stated
|
|
154
|
+
* `legend.maxRows`, which is `legendWins`: there the floor itself yields, because a floor is a
|
|
155
|
+
* default and the caller's number is not. An unmeasured box (`resolvedHeight <= 0`, i.e. a
|
|
156
|
+
* `fill` frame before its first measurement) stays at 0 and renders nothing, exactly as before —
|
|
157
|
+
* the floor must never invent a height for a box nobody has measured.
|
|
66
158
|
*/
|
|
67
159
|
export declare function resolvePlotRect(input: {
|
|
68
160
|
containerW: number;
|
|
@@ -70,6 +162,15 @@ export declare function resolvePlotRect(input: {
|
|
|
70
162
|
minWidth: number;
|
|
71
163
|
sideLegendWidth: number;
|
|
72
164
|
topBottomLegendHeight: number;
|
|
165
|
+
/**
|
|
166
|
+
* The caller stated `legend.maxRows` on a `fill` frame, so the legend takes the rows it asked
|
|
167
|
+
* for and the plot takes what is left — `VX.minPlotHeight` stops being a floor. Without this the
|
|
168
|
+
* honoured cap would push the frame's content PAST its own cell (the plot holds 120px, the legend
|
|
169
|
+
* band adds its own) and paint over whatever sits below it; with it, the cost of the caller's
|
|
170
|
+
* number lands where they can see it. Spend the whole box on legend rows and there is no plot
|
|
171
|
+
* left to draw — that is their arithmetic, made visible rather than silently rolled up.
|
|
172
|
+
*/
|
|
173
|
+
legendWins?: boolean;
|
|
73
174
|
}): {
|
|
74
175
|
width: number;
|
|
75
176
|
height: number;
|
|
@@ -83,13 +184,21 @@ export declare function resolvePlotRect(input: {
|
|
|
83
184
|
* MEASURING the labels, not from assuming one entry per row — otherwise a five-entry legend that
|
|
84
185
|
* fits on one line would roll up to `+2 more` in every 240px cell, moving rendering for charts
|
|
85
186
|
* that never had the bug. Returns `undefined` when the whole legend already fits.
|
|
187
|
+
*
|
|
188
|
+
* This resolves an ABSENT cap. A caller who stated `legend.maxRows` never reaches here at all —
|
|
189
|
+
* `ChartFrame` routes around it — because `Math.min`-ing a stated number against this one made the
|
|
190
|
+
* documented escape inert in exactly the narrow `fill` panel it exists for
|
|
191
|
+
* ({@link resolveLegendMaxRows}).
|
|
86
192
|
*/
|
|
87
193
|
export declare function legendEntryCap(input: {
|
|
88
194
|
items: readonly LegendEntry[];
|
|
89
195
|
containerW: number;
|
|
90
196
|
/** Frame height the legend may consume — `resolvedHeight - VX.minPlotHeight`. */
|
|
91
197
|
available: number;
|
|
92
|
-
/**
|
|
93
|
-
|
|
198
|
+
/**
|
|
199
|
+
* The cap that applies when nothing explicit was stated — today only the tier's own default
|
|
200
|
+
* ({@link chartTierMetrics}). Two defaults contending: the smaller wins.
|
|
201
|
+
*/
|
|
202
|
+
defaultMaxRows?: number;
|
|
94
203
|
}): number | undefined;
|
|
95
204
|
//# sourceMappingURL=chart-frame-layout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-frame-layout.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/chart-frame-layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAUhD;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;AAE3C;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAE9D;AAqBD;6FAC6F;AAC7F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,2FAA2F;IAC3F,IAAI,EAAE,SAAS,CAAA;IACf;uFACmF;IACnF,QAAQ,EAAE,MAAM,CAAA;IAChB,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAA;IACtB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAA;IACvB;
|
|
1
|
+
{"version":3,"file":"chart-frame-layout.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/chart-frame-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,17 @@ const LEGEND_SWATCH_W = 24;
|
|
|
6
6
|
function resolveChartTier(containerW) {
|
|
7
7
|
return containerW > 0 && containerW < VX.phoneChartWidth ? "phone" : "desktop";
|
|
8
8
|
}
|
|
9
|
+
const HEIGHT_STEP_WIDTH = { sm: 768, md: 992, lg: 1200 };
|
|
10
|
+
const HEIGHT_STEPS = ["lg", "md", "sm"];
|
|
11
|
+
function resolveFrameHeight(height, containerW) {
|
|
12
|
+
if (typeof height === "number") return height;
|
|
13
|
+
const widest = HEIGHT_STEPS.find((step2) => height[step2] !== void 0);
|
|
14
|
+
if (containerW <= 0) return widest === void 0 ? height.base : height[widest] ?? height.base;
|
|
15
|
+
const step = HEIGHT_STEPS.find(
|
|
16
|
+
(name) => containerW >= HEIGHT_STEP_WIDTH[name] && height[name] !== void 0
|
|
17
|
+
);
|
|
18
|
+
return step === void 0 ? height.base : height[step] ?? height.base;
|
|
19
|
+
}
|
|
9
20
|
const PHONE_MARGIN_SCALE = 0.75;
|
|
10
21
|
const PHONE_DOT_R = Math.max(VX.dotR - 1, 2);
|
|
11
22
|
const PHONE_LEGEND_MAX_ROWS = 2;
|
|
@@ -38,11 +49,37 @@ const PHONE_METRICS = {
|
|
|
38
49
|
function chartTierMetrics(tier) {
|
|
39
50
|
return tier === "phone" ? PHONE_METRICS : DESKTOP_METRICS;
|
|
40
51
|
}
|
|
52
|
+
function resolveLegendMaxRows(input) {
|
|
53
|
+
return input.callerMaxRows ?? chartTierMetrics(input.tier).legendMaxRows;
|
|
54
|
+
}
|
|
55
|
+
function resolveLegendRollup(input) {
|
|
56
|
+
const { statedMaxRows, tier, fillBand, items, containerW, available } = input;
|
|
57
|
+
if (statedMaxRows !== void 0) return { maxRows: statedMaxRows, legendWins: fillBand };
|
|
58
|
+
const tierMaxRows = resolveLegendMaxRows({ callerMaxRows: void 0, tier });
|
|
59
|
+
if (!fillBand) return { maxRows: tierMaxRows, legendWins: false };
|
|
60
|
+
return {
|
|
61
|
+
maxRows: legendEntryCap({
|
|
62
|
+
items,
|
|
63
|
+
containerW,
|
|
64
|
+
available,
|
|
65
|
+
...tierMaxRows !== void 0 && { defaultMaxRows: tierMaxRows }
|
|
66
|
+
}),
|
|
67
|
+
legendWins: false
|
|
68
|
+
};
|
|
69
|
+
}
|
|
41
70
|
function resolvePlotRect(input) {
|
|
42
|
-
const {
|
|
71
|
+
const {
|
|
72
|
+
containerW,
|
|
73
|
+
resolvedHeight,
|
|
74
|
+
minWidth,
|
|
75
|
+
sideLegendWidth,
|
|
76
|
+
topBottomLegendHeight,
|
|
77
|
+
legendWins = false
|
|
78
|
+
} = input;
|
|
79
|
+
const plotFloor = legendWins ? 0 : VX.minPlotHeight;
|
|
43
80
|
return {
|
|
44
81
|
width: containerW === 0 ? minWidth : Math.max(containerW - sideLegendWidth, 1),
|
|
45
|
-
height: resolvedHeight <= 0 ? 0 : Math.max(resolvedHeight - topBottomLegendHeight,
|
|
82
|
+
height: resolvedHeight <= 0 ? 0 : Math.max(resolvedHeight - topBottomLegendHeight, plotFloor)
|
|
46
83
|
};
|
|
47
84
|
}
|
|
48
85
|
const legendBandHeight = (rows) => LEGEND_PAD_Y + rows * LEGEND_LINE_H + Math.max(rows - 1, 0) * VX.legendGap;
|
|
@@ -69,21 +106,24 @@ function entriesWithinRows(items, width, rows) {
|
|
|
69
106
|
return fitted;
|
|
70
107
|
}
|
|
71
108
|
function legendEntryCap(input) {
|
|
72
|
-
const { items, containerW, available,
|
|
73
|
-
if (containerW <= 0 || items.length === 0) return
|
|
109
|
+
const { items, containerW, available, defaultMaxRows } = input;
|
|
110
|
+
if (containerW <= 0 || items.length === 0) return defaultMaxRows;
|
|
74
111
|
const rows = Math.max(
|
|
75
112
|
1,
|
|
76
113
|
Math.floor((available - LEGEND_PAD_Y + VX.legendGap) / (LEGEND_LINE_H + VX.legendGap))
|
|
77
114
|
);
|
|
78
115
|
if (legendBandHeight(rows) <= available && entriesWithinRows(items, containerW, rows) >= items.length) {
|
|
79
|
-
return
|
|
116
|
+
return defaultMaxRows;
|
|
80
117
|
}
|
|
81
118
|
const fitted = Math.max(1, entriesWithinRows(items, containerW, rows));
|
|
82
|
-
return
|
|
119
|
+
return defaultMaxRows === void 0 ? fitted : Math.min(fitted, defaultMaxRows);
|
|
83
120
|
}
|
|
84
121
|
export {
|
|
85
122
|
chartTierMetrics,
|
|
86
123
|
legendEntryCap,
|
|
87
124
|
resolveChartTier,
|
|
125
|
+
resolveFrameHeight,
|
|
126
|
+
resolveLegendMaxRows,
|
|
127
|
+
resolveLegendRollup,
|
|
88
128
|
resolvePlotRect
|
|
89
129
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-theme.d.ts","sourceRoot":"","sources":["../../src/cli/check-theme.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check-theme.d.ts","sourceRoot":"","sources":["../../src/cli/check-theme.ts"],"names":[],"mappings":"AA+BA;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,aAAa,GAAE,MAAsB,EACrC,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,MAAM,CAuKR"}
|
package/dist/cli/check-theme.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
conflictingProfileFlags,
|
|
13
13
|
declaredProfile,
|
|
14
14
|
DEFAULT_ROOTS,
|
|
15
|
+
hasBasaltKey,
|
|
15
16
|
readBasaltConfig,
|
|
16
17
|
resolveExemptRules,
|
|
17
18
|
resolveProjectDir,
|
|
@@ -69,6 +70,11 @@ function checkTheme(invocationCwd = process.cwd(), flags = []) {
|
|
|
69
70
|
findings.push(...checkSource(readFileSync(resolve(cwd, rel), "utf8"), rel, guardCfg));
|
|
70
71
|
}
|
|
71
72
|
if (scanned.length === 0) {
|
|
73
|
+
if (!hasBasaltKey(cwd)) {
|
|
74
|
+
console.error(
|
|
75
|
+
`\u2716 basalt-ui check-theme: ${cwd}/package.json has no "basalt" key \u2014 very likely not the package you meant to scan (BASALT_CWD, else the invocation cwd; nothing is inferred). At a repo root? Give the command \`root: <pkg>/\` (lefthook) or \`working-directory: <pkg>\` (Actions), or set BASALT_CWD=<pkg>. If this directory IS it, run \`basalt-ui init\`.`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
72
78
|
if (cfg.roots === void 0) {
|
|
73
79
|
console.error(
|
|
74
80
|
`\u2716 basalt-ui check-theme: 0 files scanned \u2014 no "basalt.roots" configured in package.json, and the built-in default roots (${DEFAULT_ROOTS.join(", ")}) matched zero files. Set "basalt": { "roots": [...] } in package.json to point at your source directories.`
|
package/dist/cli/doctor.d.ts
CHANGED
|
@@ -15,16 +15,22 @@ export type DoctorResult = {
|
|
|
15
15
|
* Check a consumer repo's basalt integration and print a pass/warn report.
|
|
16
16
|
*
|
|
17
17
|
* Narrowed to what a single-directory-scoped run can actually verify — no workspace-glob walking,
|
|
18
|
-
* no ascend/descend project discovery (see {@link resolveProjectDir}).
|
|
18
|
+
* no ascend/descend project discovery (see {@link resolveProjectDir}). Six checks, numbered in
|
|
19
19
|
* the order they run and print:
|
|
20
20
|
*
|
|
21
21
|
* Hard failures (exit non-zero):
|
|
22
22
|
* 1. `.basalt/manifest.json` exists (`basalt-ui init` was run).
|
|
23
|
-
* 2. `
|
|
23
|
+
* 2. `install-parity`: basalt-ui resolves, doctor prints WHERE and at what version, and that
|
|
24
|
+
* version agrees with the manifest's `basaltVersion`.
|
|
25
|
+
* 3. `guard-scan`: `check-theme` would scan more than zero files, sharing `scannableFiles` so the
|
|
26
|
+
* two cannot disagree. Both RESTORED in 1.30.0 after four minors gone with no MIGRATING row —
|
|
27
|
+
* README § `doctor` carries what their absence cost (a no-op CI gate, a green guard scanning
|
|
28
|
+
* nothing, and two basalt-WRITTEN docs describing output the CLI no longer produced).
|
|
29
|
+
* 4. `oxlint-preset` ("rules in sync"): the consumer's `.oxlintrc.json` extends the shipped
|
|
24
30
|
* preset AND that path resolves. `init` keeps an existing config, so the framework's whole
|
|
25
31
|
* lint half can be silently off — one repo carried six real violations invisibly across five
|
|
26
32
|
* minors this way.
|
|
27
|
-
*
|
|
33
|
+
* 6. `ai-major-parity`: within THIS package.json, `dependencies`/`devDependencies`/
|
|
28
34
|
* `peerDependencies` agree on the `ai` package's major. `basalt/ai-sdk-major` (the oxlint
|
|
29
35
|
* plugin rule) already catches this per linted FILE against its nearest package.json; this
|
|
30
36
|
* check exists for the shape a lint run cannot see — a package whose own manifest asks its
|
|
@@ -34,7 +40,7 @@ export type DoctorResult = {
|
|
|
34
40
|
* already agree warns that the exemption is stale.
|
|
35
41
|
*
|
|
36
42
|
* Warning (non-fatal):
|
|
37
|
-
*
|
|
43
|
+
* 5. `lefthook-preset` ("lefthook wired"): a pre-commit command runs `check-theme`, read from
|
|
38
44
|
* `lefthook dump --format json` (resolves `extends`/`include`/`root:` the way lefthook itself
|
|
39
45
|
* does — see {@link inspectLefthookGate}). No lefthook config at all is a pass (a consumer may
|
|
40
46
|
* gate elsewhere); a config that resolves but wires no guard command warns; a config lefthook
|
package/dist/cli/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AA6BA,MAAM,MAAM,YAAY,GAAG;IACzB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AA8DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,MAAM,CAAC,aAAa,GAAE,MAAsB,EAAE,KAAK,GAAE,MAAM,EAAO,GAAG,MAAM,CAsO1F"}
|
package/dist/cli/doctor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { resolve } from "node:path";
|
|
2
|
+
import { relative, resolve } from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
MANIFEST_PATH,
|
|
5
5
|
basaltBinCommand,
|
|
@@ -12,7 +12,10 @@ import {
|
|
|
12
12
|
parseJsonc,
|
|
13
13
|
readBasaltConfig,
|
|
14
14
|
readIfExists,
|
|
15
|
+
readManifest,
|
|
15
16
|
resolveProjectDir,
|
|
17
|
+
resolveRoots,
|
|
18
|
+
scannableFiles,
|
|
16
19
|
shippedAssetPath
|
|
17
20
|
} from "./index.js";
|
|
18
21
|
import { findManifestAbove, parentInstallAdvice } from "./sync.js";
|
|
@@ -93,6 +96,30 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
93
96
|
fail(`${MANIFEST_PATH} missing \u2014 run \`basalt-ui init\` to scaffold the consumer repo`);
|
|
94
97
|
}
|
|
95
98
|
const install = findBasaltInstall(cwd);
|
|
99
|
+
const manifestVersion = profile === "tokens-only" ? void 0 : readManifest(cwd).basaltVersion;
|
|
100
|
+
const at = install.dir === null ? "" : `${relative(cwd, install.dir)} (${install.version})`;
|
|
101
|
+
if (install.dir === null) {
|
|
102
|
+
fail(
|
|
103
|
+
"install-parity: basalt-ui does not resolve here, above, or in a sibling workspace package."
|
|
104
|
+
);
|
|
105
|
+
} else if (manifestVersion === void 0 || install.version === manifestVersion) {
|
|
106
|
+
const matches = manifestVersion === void 0 ? "" : " and matches the manifest's basaltVersion";
|
|
107
|
+
pass(`basalt-ui resolves at ${at}${matches}`);
|
|
108
|
+
} else {
|
|
109
|
+
fail(
|
|
110
|
+
`install-parity: basalt-ui resolves at ${at}, but ${MANIFEST_PATH} was last written by ${manifestVersion} \u2014 the managed layer is from a different release than the code. Run \`basalt-ui sync\` (or \`bun install\`, if the lockfile is what is stale).`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const scanned = profile === "tokens-only" ? null : scannableFiles(cwd, cfg).length;
|
|
114
|
+
if (scanned === null) {
|
|
115
|
+
pass("guard-scan: n/a \u2014 a tokens-only consumer runs the token lane, not the file walk");
|
|
116
|
+
} else if (scanned === 0) {
|
|
117
|
+
fail(
|
|
118
|
+
"guard-scan: `check-theme` would scan ZERO files here \u2014 either `basalt.roots` points at paths that do not exist, or this is not the package the config lives in (BASALT_CWD, else the cwd; nothing is inferred)."
|
|
119
|
+
);
|
|
120
|
+
} else {
|
|
121
|
+
pass(`guard-scan: check-theme covers ${scanned} file(s) under ${resolveRoots(cfg).join(", ")}`);
|
|
122
|
+
}
|
|
96
123
|
if (profile === "tokens-only") {
|
|
97
124
|
pass("oxlint-preset: n/a \u2014 the shipped preset is a Mantine/React preset");
|
|
98
125
|
} else {
|
package/dist/cli/help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,CAAC,CAkC1F,CAAA;AAED;yCACyC;AACzC,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAWhF;AAED,0GAA0G;AAC1G,eAAO,MAAM,KAAK,QAoC0E,CAAA"}
|
package/dist/cli/help.js
CHANGED
|
@@ -8,6 +8,7 @@ const COMMAND_OPTIONS = {
|
|
|
8
8
|
sync: {
|
|
9
9
|
force: { type: "boolean" },
|
|
10
10
|
check: { type: "boolean" },
|
|
11
|
+
verbose: { type: "boolean" },
|
|
11
12
|
"tokens-only": { type: "boolean" },
|
|
12
13
|
framework: { type: "boolean" }
|
|
13
14
|
},
|
|
@@ -45,7 +46,7 @@ function unknownFlag(cmd, flags) {
|
|
|
45
46
|
return match?.[1] ?? flags.find((f) => f.startsWith("-")) ?? flags[0] ?? null;
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
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] |\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 Checks THIS project only: the manifest exists, the oxlint preset is wired, the pre-commit\n hook runs check-theme (via `lefthook dump`), and the ai package major is consistent within\n this package.json. Profile is DECLARED, same as check-theme \u2014 never inferred.\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: BASALT_CWD, else the\ninvocation cwd \u2014 nothing inferred, nothing ascended or descended into.\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.";
|
|
49
|
+
const USAGE = "Usage: basalt-ui <--version | init [--with-router] [--with-query] [--merge-lint] |\n sync [--force] [--check] [--verbose] [--tokens-only|--framework] |\n check-theme [--audit-allows] |\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 Checks THIS project only: the manifest exists, the oxlint preset is wired, the pre-commit\n hook runs check-theme (via `lefthook dump`), and the ai package major is consistent within\n this package.json. Profile is DECLARED, same as check-theme \u2014 never inferred.\n\nsync [--force] [--check] [--verbose] [--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 --check prints the permanent placement skips as a COUNT; --verbose spells them out again.\n\ncheck-theme / doctor / sync all resolve their project the same way: BASALT_CWD, else the\ninvocation cwd \u2014 nothing inferred, nothing ascended or descended into.\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.";
|
|
49
50
|
export {
|
|
50
51
|
COMMAND_OPTIONS,
|
|
51
52
|
USAGE,
|