basalt-ui 1.21.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +11 -1
- package/CHANGELOG.md +33 -0
- package/MIGRATING.md +205 -9
- package/README.md +63 -16
- package/agent/rules/basalt-app.md +39 -9
- package/agent/rules/basalt-charts.md +41 -6
- package/agent/rules/basalt-router.md +1 -1
- package/agent/rules/basalt-state.md +4 -4
- package/agent/rules/basalt-tokens.md +25 -4
- package/agent/skills/basalt-app/SKILL.md +4 -3
- package/agent/skills/basalt-charts/SKILL.md +23 -8
- package/agent/templates/DESIGN.md.tpl +3 -1
- package/configs/oxlint-plugin.js +86 -9
- package/configs/oxlint-plugin.test.ts +173 -0
- package/dist/charts/hooks/useBandPlot.d.ts +138 -0
- package/dist/charts/hooks/useBandPlot.d.ts.map +1 -0
- package/dist/charts/hooks/useBandPlot.js +127 -0
- package/dist/charts/index.d.ts +4 -0
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +14 -0
- package/dist/charts/kinds/BandStrip.d.ts +113 -0
- package/dist/charts/kinds/BandStrip.d.ts.map +1 -0
- package/dist/charts/kinds/BandStrip.js +218 -0
- package/dist/charts/kinds/BandStrip.test.d.ts +2 -0
- package/dist/charts/kinds/BandStrip.test.d.ts.map +1 -0
- package/dist/charts/kinds/Bars.d.ts +5 -1
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.js +2 -0
- package/dist/charts/kinds/MirroredBars.d.ts +93 -0
- package/dist/charts/kinds/MirroredBars.d.ts.map +1 -0
- package/dist/charts/kinds/MirroredBars.js +315 -0
- package/dist/charts/kinds/MirroredBars.test.d.ts +2 -0
- package/dist/charts/kinds/MirroredBars.test.d.ts.map +1 -0
- package/dist/charts/kinds/MultiLine.d.ts +5 -1
- package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
- package/dist/charts/kinds/MultiLine.js +2 -0
- package/dist/charts/kinds/StackedArea.d.ts +5 -1
- package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
- package/dist/charts/kinds/StackedArea.js +2 -0
- package/dist/charts/kinds/ZonedLine.d.ts +5 -1
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/charts/kinds/ZonedLine.js +2 -0
- package/dist/charts/primitives/CartesianChart.d.ts +18 -2
- package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
- package/dist/charts/primitives/CartesianChart.js +5 -2
- package/dist/charts/primitives/HatchPattern.d.ts +31 -0
- package/dist/charts/primitives/HatchPattern.d.ts.map +1 -0
- package/dist/charts/primitives/HatchPattern.js +31 -0
- package/dist/cli/index.d.ts +9 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +275 -48
- package/dist/cli/shipped-versions.test.d.ts +2 -0
- package/dist/cli/shipped-versions.test.d.ts.map +1 -0
- package/dist/guard/index.d.ts +67 -0
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +70 -11
- package/dist/vite.d.ts +44 -2
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +71 -26
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/charts/hooks/useBandPlot.ts +302 -0
- package/src/charts/index.ts +14 -0
- package/src/charts/kinds/BandStrip.test.tsx +200 -0
- package/src/charts/kinds/BandStrip.tsx +364 -0
- package/src/charts/kinds/Bars.tsx +7 -1
- package/src/charts/kinds/DualPanel.test.tsx +10 -4
- package/src/charts/kinds/MirroredBars.test.tsx +193 -0
- package/src/charts/kinds/MirroredBars.tsx +455 -0
- package/src/charts/kinds/MultiLine.tsx +7 -1
- package/src/charts/kinds/StackedArea.tsx +7 -1
- package/src/charts/kinds/ZonedLine.tsx +7 -1
- package/src/charts/primitives/CartesianChart.test.tsx +86 -4
- package/src/charts/primitives/CartesianChart.tsx +28 -3
- package/src/charts/primitives/HatchPattern.tsx +55 -0
- package/src/cli/check-theme.test.ts +35 -0
- package/src/cli/help.test.ts +5 -1
- package/src/cli/index.ts +552 -79
- package/src/cli/shipped-versions.test.ts +83 -0
- package/src/cli/toolchain-wiring.test.ts +362 -6
- package/src/cli/waiver-audit.test.ts +88 -4
- package/src/guard/check-source.test.ts +293 -0
- package/src/guard/index.ts +209 -20
- package/src/vite.test.ts +112 -0
- package/src/vite.ts +147 -31
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The choreography shared by every BANDED x plot — one slot per datum, drawn as a rect, with no
|
|
3
|
+
* point in between.
|
|
4
|
+
*
|
|
5
|
+
* `CartesianChart` cannot host these: its x scale is `scalePoint` (positions, no width) and it
|
|
6
|
+
* renders `AxisLeftNumeric` unconditionally. `BandStrip` has no numeric y axis at all and
|
|
7
|
+
* `MirroredBars` has two, in two independent scales. Both are therefore
|
|
8
|
+
* `basalt/hand-rolled-plot` shapes — and this module is what stops the second one from being a
|
|
9
|
+
* copy of the first, per `DualPanel`'s own instruction to "promote the shared choreography rather
|
|
10
|
+
* than copying this file".
|
|
11
|
+
*
|
|
12
|
+
* What lives here: width-driven folding, the measured gutters, the band scale and its
|
|
13
|
+
* half-bandwidth cursor correction, the shared cursor itself, and the source/follower tooltip
|
|
14
|
+
* anchor arithmetic. What does NOT: any mark. See `docs/CHARTS-SPEC.md` § "The contract".
|
|
15
|
+
*/
|
|
16
|
+
import { scaleBand } from '@visx/scale';
|
|
17
|
+
import type { ReactNode, RefObject } from 'react';
|
|
18
|
+
import type { ChartMargin } from '../../tokens/index.js';
|
|
19
|
+
import type { CursorResolution } from '../cursor/resolve.js';
|
|
20
|
+
import type { ChartCursor, CursorAnchor } from './useChartCursor.js';
|
|
21
|
+
type BandScale = ReturnType<typeof scaleBand<string>>;
|
|
22
|
+
/**
|
|
23
|
+
* Collapse adjacent data into one drawn band at widths where one-band-per-datum sub-pixels.
|
|
24
|
+
*
|
|
25
|
+
* 288 buckets over a 234px plot is a 0.81px pitch: every band draws at a flat 1px and a single
|
|
26
|
+
* catastrophic slot can be overdrawn by its neighbour. Folding is the only honest answer — the
|
|
27
|
+
* alternative is a chart that silently loses its worst column.
|
|
28
|
+
*/
|
|
29
|
+
export type BandFold<T> = {
|
|
30
|
+
/**
|
|
31
|
+
* Floor on the px pitch of a drawn band. Default 3 — not 2, because a band also has to be wide
|
|
32
|
+
* enough for a partial-absence split (`absentFraction`) to render as two visibly distinct
|
|
33
|
+
* pieces, and at 2px the fill and the hatch antialias into one smudge.
|
|
34
|
+
*/
|
|
35
|
+
minBandPx?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Collapse a group of adjacent source data into the one datum drawn in its place.
|
|
38
|
+
*
|
|
39
|
+
* The merge is the CONSUMER's, deliberately: whether a folded slot's value is a max, a sum, or
|
|
40
|
+
* a rate recomputed from summed parts is a question about the measurement, not about the
|
|
41
|
+
* chart — and averaging a fully-down bucket into its clean neighbours describes a bucket that
|
|
42
|
+
* never happened. The kind owns only the arithmetic of how many groups there are.
|
|
43
|
+
*
|
|
44
|
+
* Identity (`getX`) MUST come from `group[0]`, or the axis stops being monotone and the cursor
|
|
45
|
+
* key stops naming a real slot start.
|
|
46
|
+
*/
|
|
47
|
+
merge: (group: T[]) => T;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* The grouping half of {@link BandFold}, exported so a consumer can test their `merge` against the
|
|
51
|
+
* arithmetic that will actually run rather than re-implementing it in the test file — the merge is
|
|
52
|
+
* where the honesty rules live (max vs mean vs a rate recomputed from summed parts), and a test
|
|
53
|
+
* that groups differently from the kind is testing the wrong function.
|
|
54
|
+
*/
|
|
55
|
+
export declare function foldBands<T>(data: readonly T[], cap: number, merge: (group: T[]) => T): T[];
|
|
56
|
+
/** Tooltip seams shared by `BandStrip` and `MirroredBars` — the `CartesianTooltipConfig` subset
|
|
57
|
+
* that means anything on a banded plot (there is no per-point `follow` distinction to make that
|
|
58
|
+
* `CartesianChart` doesn't already document identically). */
|
|
59
|
+
export type BandTooltipConfig<T> = {
|
|
60
|
+
/** Default true — the tooltip tracks the pointer. `false` anchors it to the crosshair at the
|
|
61
|
+
* plot's top edge, so a column of charts sharing one cursor lines every tooltip up on one x. */
|
|
62
|
+
follow?: boolean;
|
|
63
|
+
/** Right-aligned badge in the tooltip header. */
|
|
64
|
+
label?: (d: T) => {
|
|
65
|
+
text: string;
|
|
66
|
+
color: string;
|
|
67
|
+
} | null;
|
|
68
|
+
/** Overrides the header's date text — same seam, same reason, as
|
|
69
|
+
* `CartesianTooltipConfig.formatHeader`. */
|
|
70
|
+
formatHeader?: (key: string, d: T) => string;
|
|
71
|
+
/** Rows rendered BEFORE the derived rows. `hidden` is the same legend-toggle set the marks
|
|
72
|
+
* draw from, so a hand-authored row cannot desync from it. */
|
|
73
|
+
prependRows?: (d: T, ctx: BandTooltipRowContext) => ReactNode;
|
|
74
|
+
/** Rows appended after the derived rows. Same `ctx` as {@link prependRows}. */
|
|
75
|
+
extraRows?: (d: T, ctx: BandTooltipRowContext) => ReactNode;
|
|
76
|
+
/**
|
|
77
|
+
* Render this chart's tooltip when it is a cursor FOLLOWER, not only when it is the SOURCE.
|
|
78
|
+
* Default false. A follower has no pointer under it, so it always anchors to the crosshair
|
|
79
|
+
* regardless of `follow`; only the SOURCE is `aria-live`. Costs one `getBoundingClientRect`
|
|
80
|
+
* per hovered frame per opted-in chart — see `CartesianTooltipConfig.onFollow`.
|
|
81
|
+
*/
|
|
82
|
+
onFollow?: boolean;
|
|
83
|
+
};
|
|
84
|
+
export type BandTooltipRowContext = {
|
|
85
|
+
hidden: ReadonlySet<string>;
|
|
86
|
+
};
|
|
87
|
+
export type UseBandPlotInput<T> = {
|
|
88
|
+
data: readonly T[];
|
|
89
|
+
chartId: string;
|
|
90
|
+
getX: (d: T) => string;
|
|
91
|
+
formatX: (key: string) => string;
|
|
92
|
+
/** The plot rect's width, as handed down by `ChartFrame`. */
|
|
93
|
+
width: number;
|
|
94
|
+
fold?: BandFold<T>;
|
|
95
|
+
cursorResolution?: CursorResolution;
|
|
96
|
+
/**
|
|
97
|
+
* Which of the (possibly folded) keys get a tick. Default `smartTicks`. The seam exists because
|
|
98
|
+
* `smartTicks` appends the final value unconditionally, which on a dense time axis puts the last
|
|
99
|
+
* two labels on top of each other — a chart whose x labels are richer than `DD.MM` needs its own
|
|
100
|
+
* rule.
|
|
101
|
+
*/
|
|
102
|
+
xTickValues?: (keys: readonly string[], plotWidth: number) => readonly string[];
|
|
103
|
+
/** Left-axis tick labels, already formatted. Empty for a plot with no left axis. */
|
|
104
|
+
leftLabels?: readonly string[];
|
|
105
|
+
/** Per-side margin overrides — applied last, so the escape hatch always wins. */
|
|
106
|
+
margin?: Partial<ChartMargin>;
|
|
107
|
+
tooltip?: BandTooltipConfig<T> | false;
|
|
108
|
+
};
|
|
109
|
+
export type BandPlot<T> = {
|
|
110
|
+
/** The data actually drawn — `data` when it fits, the folded slots when it does not. */
|
|
111
|
+
bands: T[];
|
|
112
|
+
keys: string[];
|
|
113
|
+
margin: ChartMargin;
|
|
114
|
+
plotWidth: number;
|
|
115
|
+
scale: BandScale;
|
|
116
|
+
cursor: ChartCursor<T>;
|
|
117
|
+
point: T | null;
|
|
118
|
+
/** Plot-local x of the crosshair, or null when no point resolves. */
|
|
119
|
+
crosshairX: number | null;
|
|
120
|
+
/** Pitch between adjacent band origins. */
|
|
121
|
+
step: number;
|
|
122
|
+
/** Drawn width of one band — the pitch minus a 1px separator, floored at 1. */
|
|
123
|
+
bandWidth: number;
|
|
124
|
+
tickValues: string[];
|
|
125
|
+
svgRef: RefObject<SVGSVGElement | null>;
|
|
126
|
+
tooltipAnchor: CursorAnchor | null;
|
|
127
|
+
showTooltip: boolean;
|
|
128
|
+
/** Only the cursor SOURCE announces — N followers on one page would fire N live-region updates
|
|
129
|
+
* per pointer move. */
|
|
130
|
+
ariaLive: boolean;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Wire a banded plot into the framework's measured margins, band scale, shared cursor and tooltip
|
|
134
|
+
* positioning. Returns everything except the marks.
|
|
135
|
+
*/
|
|
136
|
+
export declare function useBandPlot<T>(input: UseBandPlotInput<T>): BandPlot<T>;
|
|
137
|
+
export {};
|
|
138
|
+
//# sourceMappingURL=useBandPlot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBandPlot.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useBandPlot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { scaleBand } from "@visx/scale";
|
|
2
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
3
|
+
import { VX } from "../../tokens/index.js";
|
|
4
|
+
import { autoMargin } from "../layout/auto-margin.js";
|
|
5
|
+
import { maxTextWidth } from "../utils/measure-text.js";
|
|
6
|
+
import { smartTicks } from "../utils/ticks.js";
|
|
7
|
+
import { useChartCursor } from "./useChartCursor.js";
|
|
8
|
+
const DEFAULT_MIN_BAND_PX = 3;
|
|
9
|
+
const TERMINAL_GUTTER_MAX_FRACTION = { left: 0.14, right: 0.12 };
|
|
10
|
+
function foldBands(data, cap, merge) {
|
|
11
|
+
if (cap <= 0) return [];
|
|
12
|
+
if (data.length <= cap) return [...data];
|
|
13
|
+
const groupSize = Math.ceil(data.length / cap);
|
|
14
|
+
const out = [];
|
|
15
|
+
for (let i = 0; i < data.length; i += groupSize) out.push(merge(data.slice(i, i + groupSize)));
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
function useBandPlot(input) {
|
|
19
|
+
const {
|
|
20
|
+
data,
|
|
21
|
+
chartId,
|
|
22
|
+
getX,
|
|
23
|
+
formatX,
|
|
24
|
+
width,
|
|
25
|
+
fold,
|
|
26
|
+
cursorResolution,
|
|
27
|
+
xTickValues,
|
|
28
|
+
leftLabels,
|
|
29
|
+
margin: marginOverride,
|
|
30
|
+
tooltip
|
|
31
|
+
} = input;
|
|
32
|
+
const hasLeftAxis = leftLabels !== void 0 && leftLabels.length > 0;
|
|
33
|
+
const xLabelsAll = useMemo(() => data.map((d) => formatX(getX(d))), [data, getX, formatX]);
|
|
34
|
+
const margin = useMemo(() => {
|
|
35
|
+
const measured = autoMargin({
|
|
36
|
+
...leftLabels !== void 0 && { left: leftLabels },
|
|
37
|
+
bottom: xLabelsAll,
|
|
38
|
+
...marginOverride !== void 0 && { override: marginOverride }
|
|
39
|
+
});
|
|
40
|
+
if (marginOverride?.left !== void 0 && marginOverride.right !== void 0) return measured;
|
|
41
|
+
const halfXLabel = Math.ceil(maxTextWidth(xLabelsAll, VX.axisFont) / 2);
|
|
42
|
+
const left = hasLeftAxis ? measured.left : Math.max(measured.left, halfXLabel);
|
|
43
|
+
return {
|
|
44
|
+
...measured,
|
|
45
|
+
...marginOverride?.left === void 0 && {
|
|
46
|
+
left: hasLeftAxis ? left : capTerminalGutter(left, width, TERMINAL_GUTTER_MAX_FRACTION.left, VX.margin.left)
|
|
47
|
+
},
|
|
48
|
+
...marginOverride?.right === void 0 && {
|
|
49
|
+
right: capTerminalGutter(
|
|
50
|
+
measured.right,
|
|
51
|
+
width,
|
|
52
|
+
TERMINAL_GUTTER_MAX_FRACTION.right,
|
|
53
|
+
VX.margin.right
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}, [leftLabels, xLabelsAll, marginOverride, hasLeftAxis, width]);
|
|
58
|
+
const plotWidth = Math.max(width - margin.left - margin.right, 0);
|
|
59
|
+
const minBandPx = fold?.minBandPx ?? DEFAULT_MIN_BAND_PX;
|
|
60
|
+
const merge = fold?.merge;
|
|
61
|
+
const bands = useMemo(
|
|
62
|
+
() => merge === void 0 ? [...data] : foldBands(data, Math.floor(plotWidth / minBandPx), merge),
|
|
63
|
+
[data, plotWidth, minBandPx, merge]
|
|
64
|
+
);
|
|
65
|
+
const keys = useMemo(() => bands.map(getX), [bands, getX]);
|
|
66
|
+
const scale = useMemo(
|
|
67
|
+
() => scaleBand({ domain: keys, range: [0, plotWidth] }),
|
|
68
|
+
[keys, plotWidth]
|
|
69
|
+
);
|
|
70
|
+
const bandCenter = useCallback(
|
|
71
|
+
(key) => {
|
|
72
|
+
const v = scale(key);
|
|
73
|
+
return v === void 0 ? void 0 : v + scale.bandwidth() / 2;
|
|
74
|
+
},
|
|
75
|
+
[scale]
|
|
76
|
+
);
|
|
77
|
+
const cursor = useChartCursor({
|
|
78
|
+
data: bands,
|
|
79
|
+
chartId,
|
|
80
|
+
getKey: getX,
|
|
81
|
+
xScale: bandCenter,
|
|
82
|
+
marginLeft: margin.left,
|
|
83
|
+
...cursorResolution !== void 0 && { resolution: cursorResolution }
|
|
84
|
+
});
|
|
85
|
+
const tickValues = useMemo(
|
|
86
|
+
() => [
|
|
87
|
+
...xTickValues === void 0 ? smartTicks(keys, plotWidth) : xTickValues(keys, plotWidth)
|
|
88
|
+
],
|
|
89
|
+
[keys, plotWidth, xTickValues]
|
|
90
|
+
);
|
|
91
|
+
const svgRef = useRef(null);
|
|
92
|
+
const point = cursor.point;
|
|
93
|
+
const crosshairX = point === null ? null : bandCenter(getX(point)) ?? null;
|
|
94
|
+
const cfg = tooltip === false ? void 0 : tooltip;
|
|
95
|
+
const isFollowerRender = !cursor.isSource && cfg?.onFollow === true;
|
|
96
|
+
const showTooltip = tooltip !== false && point !== null && (cursor.isSource || isFollowerRender);
|
|
97
|
+
const useAnchored = cfg?.follow === false || isFollowerRender;
|
|
98
|
+
const anchorX = useAnchored ? crosshairX : null;
|
|
99
|
+
const svgRect = anchorX === null ? void 0 : svgRef.current?.getBoundingClientRect();
|
|
100
|
+
const tooltipAnchor = svgRect === void 0 || anchorX === null ? cursor.anchor : { x: svgRect.left + margin.left + anchorX, y: svgRect.top + margin.top };
|
|
101
|
+
const step = bands.length > 0 ? plotWidth / bands.length : 0;
|
|
102
|
+
const bandWidth = Math.max(step - 1, 1);
|
|
103
|
+
return {
|
|
104
|
+
bands,
|
|
105
|
+
keys,
|
|
106
|
+
margin,
|
|
107
|
+
plotWidth,
|
|
108
|
+
scale,
|
|
109
|
+
cursor,
|
|
110
|
+
point,
|
|
111
|
+
crosshairX,
|
|
112
|
+
step,
|
|
113
|
+
bandWidth,
|
|
114
|
+
tickValues,
|
|
115
|
+
svgRef,
|
|
116
|
+
tooltipAnchor,
|
|
117
|
+
showTooltip,
|
|
118
|
+
ariaLive: cursor.isSource
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function capTerminalGutter(gutter, width, fraction, floor) {
|
|
122
|
+
return Math.min(gutter, Math.max(floor, Math.round(width * fraction)));
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
foldBands,
|
|
126
|
+
useBandPlot
|
|
127
|
+
};
|
package/dist/charts/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { CartesianChart, resolveAxisDomain, type CartesianChartProps, type Carte
|
|
|
20
20
|
export { ChartFrame, type ChartFrameProps, type ChartFrameLegend, type PlotRect, resolveLegend, } from './primitives/ChartFrame.js';
|
|
21
21
|
export { ChartCenter, type ChartCenterProps, ChartPending, type ChartPendingProps, } from './primitives/ChartPending.js';
|
|
22
22
|
export { Crosshair, SeriesDot } from './primitives/Crosshair.js';
|
|
23
|
+
export { HatchPattern, hatchFill, hatchSizeFor } from './primitives/HatchPattern.js';
|
|
23
24
|
export { ChartCard } from './primitives/ChartCard.js';
|
|
24
25
|
export { ChartLegend, type LegendEntry } from './primitives/ChartLegend.js';
|
|
25
26
|
export { ChartTooltipFloat, TooltipHeader, TooltipRow, TooltipBody, } from './primitives/ChartTooltip.js';
|
|
@@ -29,6 +30,7 @@ export { ZoneRects, type ZoneSpec } from './primitives/ZoneRects.js';
|
|
|
29
30
|
export { XZoneRects, type XZoneSpec } from './primitives/XZoneRects.js';
|
|
30
31
|
export { AreaGradient, areaFillUrl } from './primitives/AreaGradient.js';
|
|
31
32
|
export { useChartCursor, type ChartCursor, type CursorAnchor } from './hooks/useChartCursor.js';
|
|
33
|
+
export { foldBands, type BandFold, type BandTooltipConfig, type BandTooltipRowContext, } from './hooks/useBandPlot.js';
|
|
32
34
|
export type { CursorResolution } from './cursor/resolve.js';
|
|
33
35
|
export { useChartSize, type UseChartSizeResult, type ChartSize } from './hooks/useChartSize.js';
|
|
34
36
|
export { fmtAxisDate, fmtTooltipDate } from './utils/format.js';
|
|
@@ -42,6 +44,8 @@ export { Donut, type DonutProps, type DonutDatum } from './kinds/Donut.js';
|
|
|
42
44
|
export { MultiLine, type MultiLineProps } from './kinds/MultiLine.js';
|
|
43
45
|
export { DualPanel, type DualPanelProps } from './kinds/DualPanel.js';
|
|
44
46
|
export { Heatmap, type HeatmapProps } from './kinds/Heatmap.js';
|
|
47
|
+
export { BandStrip, type BandStripProps, type BandStripSeries, type BandSpan, } from './kinds/BandStrip.js';
|
|
48
|
+
export { MirroredBars, type MirroredBarsProps, type MirroredBarPane } from './kinds/MirroredBars.js';
|
|
45
49
|
export { LineSparkline, BarSparkline } from './sparklines/index.js';
|
|
46
50
|
export { Group } from '@visx/group';
|
|
47
51
|
export { GridRows, GridColumns } from '@visx/grid';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EACL,EAAE,EACF,KAAK,EACL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,WAAW,GACjB,MAAM,WAAW,CAAA;AAGlB,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAG5C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC7F,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,UAAU,CAAA;AAGjB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,aAAa,GACd,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,YAAY,EACZ,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,WAAW,GACZ,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAGrE,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC5F,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAG5F,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACxF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGhE,OAAO,EACL,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACL,IAAI,EACJ,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,WAAW,GACjB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAEvE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"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"}
|
package/dist/charts/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
ChartPending
|
|
31
31
|
} from "./primitives/ChartPending.js";
|
|
32
32
|
import { Crosshair, SeriesDot } from "./primitives/Crosshair.js";
|
|
33
|
+
import { HatchPattern, hatchFill, hatchSizeFor } from "./primitives/HatchPattern.js";
|
|
33
34
|
import { ChartCard } from "./primitives/ChartCard.js";
|
|
34
35
|
import { ChartLegend } from "./primitives/ChartLegend.js";
|
|
35
36
|
import {
|
|
@@ -44,6 +45,9 @@ import { ZoneRects } from "./primitives/ZoneRects.js";
|
|
|
44
45
|
import { XZoneRects } from "./primitives/XZoneRects.js";
|
|
45
46
|
import { AreaGradient, areaFillUrl } from "./primitives/AreaGradient.js";
|
|
46
47
|
import { useChartCursor } from "./hooks/useChartCursor.js";
|
|
48
|
+
import {
|
|
49
|
+
foldBands
|
|
50
|
+
} from "./hooks/useBandPlot.js";
|
|
47
51
|
import { useChartSize } from "./hooks/useChartSize.js";
|
|
48
52
|
import { fmtAxisDate, fmtTooltipDate } from "./utils/format.js";
|
|
49
53
|
import { smartTicks, smartTicksEvery } from "./utils/ticks.js";
|
|
@@ -60,6 +64,10 @@ import { Donut } from "./kinds/Donut.js";
|
|
|
60
64
|
import { MultiLine } from "./kinds/MultiLine.js";
|
|
61
65
|
import { DualPanel } from "./kinds/DualPanel.js";
|
|
62
66
|
import { Heatmap } from "./kinds/Heatmap.js";
|
|
67
|
+
import {
|
|
68
|
+
BandStrip
|
|
69
|
+
} from "./kinds/BandStrip.js";
|
|
70
|
+
import { MirroredBars } from "./kinds/MirroredBars.js";
|
|
63
71
|
import { LineSparkline, BarSparkline } from "./sparklines/index.js";
|
|
64
72
|
import { Group } from "@visx/group";
|
|
65
73
|
import { GridRows, GridColumns } from "@visx/grid";
|
|
@@ -80,6 +88,7 @@ export {
|
|
|
80
88
|
AxisBottomDate,
|
|
81
89
|
AxisLeftNumeric,
|
|
82
90
|
AxisRightNumeric,
|
|
91
|
+
BandStrip,
|
|
83
92
|
Bar,
|
|
84
93
|
BarGroup,
|
|
85
94
|
BarSparkline,
|
|
@@ -99,11 +108,13 @@ export {
|
|
|
99
108
|
GridColumns,
|
|
100
109
|
GridRows,
|
|
101
110
|
Group,
|
|
111
|
+
HatchPattern,
|
|
102
112
|
Heatmap,
|
|
103
113
|
HoverOverlay,
|
|
104
114
|
Line,
|
|
105
115
|
LinePath,
|
|
106
116
|
LineSparkline,
|
|
117
|
+
MirroredBars,
|
|
107
118
|
MultiLine,
|
|
108
119
|
Pie,
|
|
109
120
|
SeriesDot,
|
|
@@ -133,8 +144,11 @@ export {
|
|
|
133
144
|
deriveTooltipRows,
|
|
134
145
|
fmtAxisDate,
|
|
135
146
|
fmtTooltipDate,
|
|
147
|
+
foldBands,
|
|
136
148
|
globalCursorStore,
|
|
137
149
|
groupTokens,
|
|
150
|
+
hatchFill,
|
|
151
|
+
hatchSizeFor,
|
|
138
152
|
maxTextWidth,
|
|
139
153
|
measureText,
|
|
140
154
|
probeAxisLabels,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { ChartMargin } from '../../tokens/index.js';
|
|
2
|
+
import type { CursorResolution } from '../cursor/resolve.js';
|
|
3
|
+
import type { BandFold, BandTooltipConfig } from '../hooks/useBandPlot.js';
|
|
4
|
+
import type { ChartLegendConfig, SeriesStyle } from '../series.js';
|
|
5
|
+
/**
|
|
6
|
+
* A state a strip can draw. Extends `SeriesStyle` rather than `ChartSeries` because a band has no
|
|
7
|
+
* numeric value to plot — `formatValue` reads the datum directly.
|
|
8
|
+
*/
|
|
9
|
+
export type BandStripSeries<T> = SeriesStyle & {
|
|
10
|
+
/** The derived tooltip row's value for a band in this state. Omit for a state whose NAME is the
|
|
11
|
+
* whole reading ("Not measured"), which then renders as a label with an empty value. */
|
|
12
|
+
formatValue?: (d: T) => string;
|
|
13
|
+
};
|
|
14
|
+
/** One drawn band — which state it is in, and the three ways a state can be qualified. */
|
|
15
|
+
export type BandSpan = {
|
|
16
|
+
/**
|
|
17
|
+
* Series key naming this band's state: the tie to its legend entry, its fill, and its derived
|
|
18
|
+
* tooltip row. A key not present in `series` draws nothing — the loud failure is deliberate,
|
|
19
|
+
* since the alternative is a mark no legend entry accounts for.
|
|
20
|
+
*/
|
|
21
|
+
state: string;
|
|
22
|
+
/**
|
|
23
|
+
* Overrides the fill derived from the state's series entry — the seam for an intensity ramp
|
|
24
|
+
* WITHIN one state (5% loss vs 0.5% loss are the same state at different strengths). Build it
|
|
25
|
+
* with `alpha(VX.*, …)`, never a raw hex.
|
|
26
|
+
*/
|
|
27
|
+
fill?: string;
|
|
28
|
+
/**
|
|
29
|
+
* 0..1 of this band's width that no source sample covers, drawn hatched from the band's right.
|
|
30
|
+
*
|
|
31
|
+
* This is what a fold owes the reader. A 1-of-3-measured slot whose merge reports the one
|
|
32
|
+
* measured member's reading paints, without this, as a fully-measured band — a reading asserted
|
|
33
|
+
* over two slots that reported nothing either way.
|
|
34
|
+
*/
|
|
35
|
+
absentFraction?: number;
|
|
36
|
+
/**
|
|
37
|
+
* A shorter, inset bar drawn over the band — for a fact that must NOT be readable off the fill
|
|
38
|
+
* ramp (a renegotiation, a restart, a config change). Its colour comes from a `series` entry, so
|
|
39
|
+
* it cannot be drawn in a hue the legend does not name.
|
|
40
|
+
*/
|
|
41
|
+
marker?: {
|
|
42
|
+
/** Series key naming the marker's colour. Defaults to the band's own `state`. */
|
|
43
|
+
state?: string;
|
|
44
|
+
/** Vertical inset from the band's top and bottom, in px. Default 6. */
|
|
45
|
+
inset?: number;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export type BandStripProps<T> = {
|
|
49
|
+
data: readonly T[];
|
|
50
|
+
/** Stable id — identifies this chart as the cursor's source. */
|
|
51
|
+
chartId: string;
|
|
52
|
+
/** Extracts the x-domain key. On a band strip this is a SLOT START, so `cursorResolution`
|
|
53
|
+
* defaults to `'leading'` (see below) rather than `CartesianChart`'s `'nearest'`. */
|
|
54
|
+
getX: (d: T) => string;
|
|
55
|
+
/** The states this strip can draw — the single source of truth for legend entries, band fills,
|
|
56
|
+
* and the derived tooltip row. */
|
|
57
|
+
series: readonly BandStripSeries<T>[];
|
|
58
|
+
/** Which state each datum is in. */
|
|
59
|
+
getBand: (d: T) => BandSpan;
|
|
60
|
+
/** Fixed height in px, forwarded to `ChartFrame`. The band row gets whatever the measured
|
|
61
|
+
* margins and the measured legend band leave. Default 240. */
|
|
62
|
+
height?: number;
|
|
63
|
+
/** Fill the parent flex/grid cell's measured height instead of a fixed one. */
|
|
64
|
+
fill?: boolean;
|
|
65
|
+
/** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
|
|
66
|
+
formatX?: (key: string) => string;
|
|
67
|
+
/** Which keys get a tick. Default `smartTicks`. */
|
|
68
|
+
xTickValues?: (keys: readonly string[], plotWidth: number) => readonly string[];
|
|
69
|
+
/** Collapse adjacent data at widths where one band per datum sub-pixels. */
|
|
70
|
+
fold?: BandFold<T>;
|
|
71
|
+
/**
|
|
72
|
+
* How a sibling's broadcast cursor key resolves against this strip's slots. Default
|
|
73
|
+
* `'leading'` — strict containment, "the slot that swallowed this key" — because a band IS a
|
|
74
|
+
* span keyed by its leading edge, and it stays correct at every fold width. `'nearest'` puts
|
|
75
|
+
* the crosshair one slot right for every source key in the back half of a slot.
|
|
76
|
+
*/
|
|
77
|
+
cursorResolution?: CursorResolution;
|
|
78
|
+
tooltip?: BandTooltipConfig<T> | false;
|
|
79
|
+
legend?: ChartLegendConfig | false;
|
|
80
|
+
/** Colour of the absence hatch. Names a `series` entry, so absence is legended like any other
|
|
81
|
+
* state — a hatched band is the one mark a reader cannot decode from an axis. Default
|
|
82
|
+
* `VX.neutral`, unnamed. */
|
|
83
|
+
absentState?: string;
|
|
84
|
+
/** Per-side overrides of the measured margins — applied last. */
|
|
85
|
+
margin?: Partial<ChartMargin>;
|
|
86
|
+
/** Accessible text alternative, forwarded to `ChartFrame` (+ `role="group"`) and to the
|
|
87
|
+
* focusable hover overlay's slider label. */
|
|
88
|
+
ariaLabel?: string;
|
|
89
|
+
/** Forwarded to `ChartFrame` — see `ChartPending`'s JSDoc. */
|
|
90
|
+
isPending?: boolean;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* A 1-D categorical band strip: one rect per slot over a shared x axis, no y dimension at all.
|
|
94
|
+
*
|
|
95
|
+
* `CartesianChart` cannot host this. It renders `AxisLeftNumeric` unconditionally, so composing it
|
|
96
|
+
* would draw a numeric axis over a chart that measures nothing vertically — and its `scalePoint` x
|
|
97
|
+
* scale has positions but no widths, which is the whole content of a strip. This is the
|
|
98
|
+
* non-single-plot escape `docs/CHARTS-SPEC.md` § "The contract" describes, assembled from the same
|
|
99
|
+
* parts every other chart gets (`ChartFrame`, `autoMargin`, `useChartCursor`, `ChartTooltipFloat`)
|
|
100
|
+
* via `useBandPlot`, never re-implemented.
|
|
101
|
+
*
|
|
102
|
+
* The three qualifications on {@link BandSpan} — `fill`, `absentFraction`, `marker` — are the ones
|
|
103
|
+
* a state strip cannot do without: an intensity ramp inside a state, the share of a folded slot
|
|
104
|
+
* nothing measured, and a fact that must not be read off the ramp.
|
|
105
|
+
*/
|
|
106
|
+
declare function BandStripInner<T>(props: BandStripProps<T>): import("react").JSX.Element;
|
|
107
|
+
/**
|
|
108
|
+
* Hand-memoized: React Compiler does not process the shipped dist, so the hot kind is wrapped in
|
|
109
|
+
* `React.memo` to retain the auto-memoization it had as source (parity with `DualPanel`).
|
|
110
|
+
*/
|
|
111
|
+
export declare const BandStrip: typeof BandStripInner;
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=BandStrip.d.ts.map
|
|
@@ -0,0 +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;4FACwF;IACxF,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;CAC/B,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,QAAQ,GAAG;IACrB;;;;OAIG;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;;gCAE4B;IAC5B,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;AAID;;;;;;;;;;;;;GAaG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BAgBlD;AAuND;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
|