basalt-ui 1.22.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.
Files changed (79) hide show
  1. package/AGENTS.md +9 -1
  2. package/CHANGELOG.md +19 -0
  3. package/MIGRATING.md +125 -12
  4. package/README.md +45 -11
  5. package/agent/rules/basalt-app.md +26 -2
  6. package/agent/rules/basalt-charts.md +40 -5
  7. package/agent/rules/basalt-tokens.md +17 -1
  8. package/agent/skills/basalt-charts/SKILL.md +23 -8
  9. package/agent/templates/DESIGN.md.tpl +3 -1
  10. package/configs/oxlint-plugin.js +49 -8
  11. package/configs/oxlint-plugin.test.ts +88 -31
  12. package/dist/charts/hooks/useBandPlot.d.ts +138 -0
  13. package/dist/charts/hooks/useBandPlot.d.ts.map +1 -0
  14. package/dist/charts/hooks/useBandPlot.js +127 -0
  15. package/dist/charts/index.d.ts +4 -0
  16. package/dist/charts/index.d.ts.map +1 -1
  17. package/dist/charts/index.js +14 -0
  18. package/dist/charts/kinds/BandStrip.d.ts +113 -0
  19. package/dist/charts/kinds/BandStrip.d.ts.map +1 -0
  20. package/dist/charts/kinds/BandStrip.js +218 -0
  21. package/dist/charts/kinds/BandStrip.test.d.ts +2 -0
  22. package/dist/charts/kinds/BandStrip.test.d.ts.map +1 -0
  23. package/dist/charts/kinds/Bars.d.ts +5 -1
  24. package/dist/charts/kinds/Bars.d.ts.map +1 -1
  25. package/dist/charts/kinds/Bars.js +2 -0
  26. package/dist/charts/kinds/MirroredBars.d.ts +93 -0
  27. package/dist/charts/kinds/MirroredBars.d.ts.map +1 -0
  28. package/dist/charts/kinds/MirroredBars.js +315 -0
  29. package/dist/charts/kinds/MirroredBars.test.d.ts +2 -0
  30. package/dist/charts/kinds/MirroredBars.test.d.ts.map +1 -0
  31. package/dist/charts/kinds/MultiLine.d.ts +5 -1
  32. package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
  33. package/dist/charts/kinds/MultiLine.js +2 -0
  34. package/dist/charts/kinds/StackedArea.d.ts +5 -1
  35. package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
  36. package/dist/charts/kinds/StackedArea.js +2 -0
  37. package/dist/charts/kinds/ZonedLine.d.ts +5 -1
  38. package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
  39. package/dist/charts/kinds/ZonedLine.js +2 -0
  40. package/dist/charts/primitives/CartesianChart.d.ts +18 -2
  41. package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
  42. package/dist/charts/primitives/CartesianChart.js +5 -2
  43. package/dist/charts/primitives/HatchPattern.d.ts +31 -0
  44. package/dist/charts/primitives/HatchPattern.d.ts.map +1 -0
  45. package/dist/charts/primitives/HatchPattern.js +31 -0
  46. package/dist/cli/index.d.ts +2 -0
  47. package/dist/cli/index.d.ts.map +1 -1
  48. package/dist/cli/index.js +47 -8
  49. package/dist/cli/shipped-versions.test.d.ts +2 -0
  50. package/dist/cli/shipped-versions.test.d.ts.map +1 -0
  51. package/dist/guard/index.d.ts.map +1 -1
  52. package/dist/guard/index.js +32 -11
  53. package/dist/vite.d.ts +42 -3
  54. package/dist/vite.d.ts.map +1 -1
  55. package/dist/vite.js +67 -30
  56. package/llms.txt +2 -2
  57. package/package.json +1 -1
  58. package/src/charts/hooks/useBandPlot.ts +302 -0
  59. package/src/charts/index.ts +14 -0
  60. package/src/charts/kinds/BandStrip.test.tsx +200 -0
  61. package/src/charts/kinds/BandStrip.tsx +364 -0
  62. package/src/charts/kinds/Bars.tsx +7 -1
  63. package/src/charts/kinds/DualPanel.test.tsx +10 -4
  64. package/src/charts/kinds/MirroredBars.test.tsx +193 -0
  65. package/src/charts/kinds/MirroredBars.tsx +455 -0
  66. package/src/charts/kinds/MultiLine.tsx +7 -1
  67. package/src/charts/kinds/StackedArea.tsx +7 -1
  68. package/src/charts/kinds/ZonedLine.tsx +7 -1
  69. package/src/charts/primitives/CartesianChart.test.tsx +86 -4
  70. package/src/charts/primitives/CartesianChart.tsx +28 -3
  71. package/src/charts/primitives/HatchPattern.tsx +55 -0
  72. package/src/cli/index.ts +125 -18
  73. package/src/cli/shipped-versions.test.ts +83 -0
  74. package/src/cli/toolchain-wiring.test.ts +171 -4
  75. package/src/cli/waiver-audit.test.ts +7 -3
  76. package/src/guard/check-source.test.ts +138 -42
  77. package/src/guard/index.ts +83 -17
  78. package/src/vite.test.ts +79 -0
  79. package/src/vite.ts +141 -39
@@ -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"}
@@ -0,0 +1,218 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Group } from "@visx/group";
3
+ import { memo, useMemo } from "react";
4
+ import { VX, alpha } from "../../tokens/index.js";
5
+ import { useBandPlot } from "../hooks/useBandPlot.js";
6
+ import { AxisBottomDate } from "../primitives/Axes.js";
7
+ import { ChartFrame, resolveLegend } from "../primitives/ChartFrame.js";
8
+ import {
9
+ ChartTooltipFloat,
10
+ TooltipBody,
11
+ TooltipHeader,
12
+ TooltipRow
13
+ } from "../primitives/ChartTooltip.js";
14
+ import { Crosshair } from "../primitives/Crosshair.js";
15
+ import { HatchPattern, hatchFill, hatchSizeFor } from "../primitives/HatchPattern.js";
16
+ import { HoverOverlay } from "../primitives/HoverOverlay.js";
17
+ import { fmtAxisDate } from "../utils/format.js";
18
+ const DEFAULT_MARKER_INSET = 6;
19
+ function BandStripInner(props) {
20
+ const { series, chartId, height, fill, legend, ariaLabel, isPending } = props;
21
+ return /* @__PURE__ */ jsx(
22
+ ChartFrame,
23
+ {
24
+ series,
25
+ chartId,
26
+ ...height !== void 0 && { height },
27
+ ...fill !== void 0 && { fill },
28
+ ...ariaLabel !== void 0 && { ariaLabel },
29
+ ...isPending !== void 0 && { isPending },
30
+ legend: resolveLegend(legend),
31
+ children: (plot) => /* @__PURE__ */ jsx(BandStripPlot, { ...props, plot })
32
+ }
33
+ );
34
+ }
35
+ function BandStripPlot(props) {
36
+ const {
37
+ data,
38
+ chartId,
39
+ getX,
40
+ series,
41
+ getBand,
42
+ formatX = fmtAxisDate,
43
+ xTickValues,
44
+ fold,
45
+ cursorResolution = "leading",
46
+ tooltip,
47
+ absentState,
48
+ margin: marginOverride,
49
+ ariaLabel,
50
+ plot
51
+ } = props;
52
+ const { hidden } = plot;
53
+ const styleByKey = useMemo(() => new Map(series.map((s) => [s.key, s])), [series]);
54
+ const band = useBandPlot({
55
+ data,
56
+ chartId,
57
+ getX,
58
+ formatX,
59
+ width: plot.width,
60
+ cursorResolution,
61
+ ...fold !== void 0 && { fold },
62
+ ...xTickValues !== void 0 && { xTickValues },
63
+ ...marginOverride !== void 0 && { margin: marginOverride },
64
+ ...tooltip !== void 0 && { tooltip }
65
+ });
66
+ const { bands, margin, plotWidth, scale, cursor, point, crosshairX, step, bandWidth } = band;
67
+ const stripHeight = Math.max(plot.height - margin.top - margin.bottom, 1);
68
+ const hatchId = `${chartId}-band-absent`;
69
+ const absentColor = (absentState === void 0 ? void 0 : styleByKey.get(absentState)?.color) ?? VX.neutral;
70
+ const rects = useMemo(() => {
71
+ const out = [];
72
+ bands.forEach((d, i) => {
73
+ const span = getBand(d);
74
+ const style = styleByKey.get(span.state);
75
+ if (style === void 0 || hidden.has(span.state)) return;
76
+ const absent = clampFraction(span.absentFraction);
77
+ const measuredWidth = bandWidth * (1 - absent);
78
+ const hatchWidth = bandWidth - measuredWidth;
79
+ const x = i * step;
80
+ const markerKey = span.marker?.state ?? span.state;
81
+ const markerColor = styleByKey.get(markerKey)?.color;
82
+ const inset = span.marker?.inset ?? DEFAULT_MARKER_INSET;
83
+ out.push(
84
+ /* @__PURE__ */ jsxs("g", { children: [
85
+ measuredWidth > 0 && /* @__PURE__ */ jsx(
86
+ "rect",
87
+ {
88
+ x,
89
+ y: 0,
90
+ width: measuredWidth,
91
+ height: stripHeight,
92
+ rx: 1,
93
+ fill: span.fill ?? alpha(style.color, style.fillOpacity ?? 1),
94
+ pointerEvents: "none"
95
+ }
96
+ ),
97
+ hatchWidth > 0 && /* @__PURE__ */ jsx(
98
+ "rect",
99
+ {
100
+ x: x + measuredWidth,
101
+ y: 0,
102
+ width: hatchWidth,
103
+ height: stripHeight,
104
+ rx: 1,
105
+ fill: hatchFill(hatchId),
106
+ pointerEvents: "none"
107
+ }
108
+ ),
109
+ span.marker !== void 0 && markerColor !== void 0 && measuredWidth > 0 && /* @__PURE__ */ jsx(
110
+ "rect",
111
+ {
112
+ x,
113
+ y: inset,
114
+ width: measuredWidth,
115
+ height: Math.max(stripHeight - 2 * inset, 2),
116
+ rx: 1,
117
+ fill: markerColor,
118
+ pointerEvents: "none"
119
+ }
120
+ )
121
+ ] }, getX(d))
122
+ );
123
+ });
124
+ return out;
125
+ }, [bands, getBand, getX, styleByKey, hidden, bandWidth, step, stripHeight, hatchId]);
126
+ if (plotWidth <= 0 || bands.length === 0) return null;
127
+ const cfg = tooltip === false ? void 0 : tooltip;
128
+ const badge = cfg?.label === void 0 || point === null ? null : cfg.label(point);
129
+ const row = point === null ? null : deriveBandRow(getBand(point), styleByKey, hidden, point);
130
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
131
+ /* @__PURE__ */ jsxs("svg", { ref: band.svgRef, width: plot.width, height: plot.height, children: [
132
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
133
+ HatchPattern,
134
+ {
135
+ id: hatchId,
136
+ color: absentColor,
137
+ opacity: 0.7,
138
+ size: hatchSizeFor(bandWidth)
139
+ }
140
+ ) }),
141
+ /* @__PURE__ */ jsxs(Group, { left: margin.left, top: margin.top, children: [
142
+ rects,
143
+ crosshairX !== null && /* @__PURE__ */ jsx(Crosshair, { x: crosshairX, top: 0, bottom: stripHeight }),
144
+ /* @__PURE__ */ jsx(
145
+ AxisBottomDate,
146
+ {
147
+ top: stripHeight,
148
+ scale,
149
+ tickValues: band.tickValues,
150
+ tickFormat: (v) => formatX(String(v))
151
+ }
152
+ ),
153
+ /* @__PURE__ */ jsx(
154
+ HoverOverlay,
155
+ {
156
+ width: plotWidth,
157
+ height: stripHeight,
158
+ onMove: cursor.onPointerMove,
159
+ onLeave: cursor.onPointerLeave,
160
+ onKeyDown: cursor.onKeyDown,
161
+ onBlur: cursor.onBlur,
162
+ valueMax: Math.max(bands.length - 1, 0),
163
+ ...point !== null && {
164
+ valueNow: bands.indexOf(point),
165
+ valueText: formatX(getX(point))
166
+ },
167
+ ...ariaLabel !== void 0 && { ariaLabel }
168
+ }
169
+ )
170
+ ] })
171
+ ] }),
172
+ band.showTooltip && point !== null && /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: band.tooltipAnchor, ariaLive: band.ariaLive, children: [
173
+ /* @__PURE__ */ jsx(
174
+ TooltipHeader,
175
+ {
176
+ date: getX(point),
177
+ ...cfg?.formatHeader !== void 0 && {
178
+ format: (key) => cfg.formatHeader?.(key, point) ?? key
179
+ },
180
+ ...badge !== null && { label: badge.text, labelColor: badge.color }
181
+ }
182
+ ),
183
+ /* @__PURE__ */ jsxs(TooltipBody, { children: [
184
+ cfg?.prependRows?.(point, { hidden }),
185
+ row !== null && /* @__PURE__ */ jsx(
186
+ TooltipRow,
187
+ {
188
+ color: row.color,
189
+ label: row.label,
190
+ value: row.value,
191
+ shape: row.shape,
192
+ dashed: row.dashed
193
+ }
194
+ ),
195
+ cfg?.extraRows?.(point, { hidden })
196
+ ] })
197
+ ] })
198
+ ] });
199
+ }
200
+ function clampFraction(value) {
201
+ if (value === void 0 || !Number.isFinite(value)) return 0;
202
+ return Math.min(Math.max(value, 0), 1);
203
+ }
204
+ function deriveBandRow(span, styleByKey, hidden, datum) {
205
+ const style = styleByKey.get(span.state);
206
+ if (style === void 0 || style.tooltip === false || hidden.has(span.state)) return null;
207
+ return {
208
+ color: style.color,
209
+ label: style.label,
210
+ value: style.formatValue?.(datum) ?? "",
211
+ shape: style.mark === "line" ? "line" : "bar",
212
+ dashed: style.dash === "dashed"
213
+ };
214
+ }
215
+ const BandStrip = memo(BandStripInner);
216
+ export {
217
+ BandStrip
218
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=BandStrip.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BandStrip.test.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/BandStrip.test.tsx"],"names":[],"mappings":""}
@@ -87,8 +87,12 @@ export type BarsProps<T> = {
87
87
  barLayout?: 'stacked' | 'grouped';
88
88
  /** Per-bar opacity override. Receives the data point + bar key. Default 0.85. */
89
89
  barOpacity?: (d: T, key: string) => number;
90
- /** X tick count override. Default: as many as fit. */
90
+ /** Exact number of x ticks. Default: as many as fit. Ignored when `xTickValues` is set. */
91
91
  xTicks?: number;
92
+ /** Which domain keys get a tick, from the full key list and the resolved plot width. Takes
93
+ * precedence over `xTicks` — see `CartesianChartProps.xTickValues` for why a count is not
94
+ * always enough. */
95
+ xTickValues?: (keys: readonly string[], xMax: number) => readonly string[];
92
96
  /** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
93
97
  formatX?: (key: string) => string;
94
98
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Bars.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/Bars.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Bars.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/Bars.tsx"],"names":[],"mappings":"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"}
@@ -24,6 +24,7 @@ function BarsInner(props) {
24
24
  barLayout = "stacked",
25
25
  barOpacity,
26
26
  xTicks,
27
+ xTickValues,
27
28
  formatX,
28
29
  cursorResolution,
29
30
  tooltip,
@@ -128,6 +129,7 @@ function BarsInner(props) {
128
129
  y: yConfig,
129
130
  ...y2 !== void 0 && { y2 },
130
131
  ...xTicks !== void 0 && { xTicks },
132
+ ...xTickValues !== void 0 && { xTickValues },
131
133
  ...formatX !== void 0 && { formatX },
132
134
  ...cursorResolution !== void 0 && { cursorResolution },
133
135
  ...zones !== void 0 && { zones },
@@ -0,0 +1,93 @@
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, ChartSeries } from '../series.js';
5
+ /** One of the two panes. Each resolves its own domain — that is the whole point of the kind. */
6
+ export type MirroredBarPane = {
7
+ /** Key of the `series` entry this pane draws: its colour, its legend entry, its tooltip row. */
8
+ key: string;
9
+ /**
10
+ * The pane's upper bound. `'auto'` (default) is its own visible maximum; a number pins it.
11
+ *
12
+ * A pane has no LOWER bound to configure — a mirrored bar's length is its magnitude measured
13
+ * from the shared baseline, so the pane's zero IS the baseline. That is also why the two panes
14
+ * never share a domain: an upload an order of magnitude below its download flattens to a line
15
+ * along the baseline on a shared scale, and it is the half that explains a stalled call.
16
+ */
17
+ max?: number | 'auto';
18
+ /** When `max` is `'auto'`: floors the upper bound, so a quiet window doesn't amplify noise to
19
+ * full height. */
20
+ autoMaxFloor?: number;
21
+ /** Tick count for this pane's own axis. Default 3. */
22
+ ticks?: number;
23
+ /** Tick + tooltip formatter for this pane. A pane's axis is in its OWN units — one shared
24
+ * formatter would be wrong for at least one of them whenever the two differ. */
25
+ format: (v: number) => string;
26
+ };
27
+ export type MirroredBarsProps<T> = {
28
+ data: readonly T[];
29
+ chartId: string;
30
+ /** Extracts the x-domain key — a slot start, hence the `'leading'` cursor default. */
31
+ getX: (d: T) => string;
32
+ /**
33
+ * The single source of truth for bar colours, legend entries and tooltip rows. `up.key` and
34
+ * `down.key` name two of these; any further entry is legend-only (give it `getValue: () => null`)
35
+ * — which is how ABSENCE gets named, and it has to be: a hatched bar is the one mark on this
36
+ * chart a reader cannot decode from either axis.
37
+ */
38
+ series: readonly ChartSeries<T>[];
39
+ /** The pane drawn ABOVE the baseline. */
40
+ up: MirroredBarPane;
41
+ /** The pane drawn BELOW the baseline. */
42
+ down: MirroredBarPane;
43
+ /** The up pane's share of the bar band. Default 0.35 — the mirrored pair is usually asymmetric,
44
+ * and splitting evenly spends most of the chart on empty space above the smaller half. */
45
+ upFraction?: number;
46
+ /**
47
+ * 0..1 of this bar's width no source sample covers, hatched across the FULL band height.
48
+ *
49
+ * Full height, both panes, deliberately: a hatch drawn on one pane only reads as "that half
50
+ * measured zero", which is the measured-and-idle state absence must stay distinguishable from.
51
+ */
52
+ getAbsentFraction?: (d: T) => number;
53
+ /** Per-datum bar opacity — a real but qualified measurement (a short bucket, a partial interval)
54
+ * drawn dimmer. Default 1. */
55
+ getBarOpacity?: (d: T) => number;
56
+ /** Fixed height in px, forwarded to `ChartFrame`. Default 240. */
57
+ height?: number;
58
+ fill?: boolean;
59
+ formatX?: (key: string) => string;
60
+ xTickValues?: (keys: readonly string[], plotWidth: number) => readonly string[];
61
+ fold?: BandFold<T>;
62
+ /** Default `'leading'` — see `BandStripProps.cursorResolution`. */
63
+ cursorResolution?: CursorResolution;
64
+ tooltip?: BandTooltipConfig<T> | false;
65
+ legend?: ChartLegendConfig | false;
66
+ /** Series key whose colour the absence hatch is drawn in. Default `VX.neutral`. */
67
+ absentState?: string;
68
+ margin?: Partial<ChartMargin>;
69
+ ariaLabel?: string;
70
+ isPending?: boolean;
71
+ };
72
+ /**
73
+ * Two bar panes over ONE x scale and one cursor, mirrored around a shared baseline, each in its
74
+ * own independent domain.
75
+ *
76
+ * **Why not `DualPanel`.** `DualPanel`'s two panes are a LINE pane and a signed-histogram pane: it
77
+ * requires `series` to be line series it draws with `LinePath`, and its bottom pane takes a single
78
+ * signed `getBar` over one symmetric `[-maxAbs, maxAbs]` scale. Neither half fits. Two independent
79
+ * magnitudes mirrored around a baseline are not one signed quantity — a 220 kB/s down and a 20 kB/s
80
+ * up are two readings, not `+220` and `−20` of one — and forcing them onto one scale is exactly the
81
+ * flattening this shape exists to avoid. Bending `DualPanel` to cover it would mean a
82
+ * `topMark: 'line' | 'bars'` switch, a second value accessor, and a per-pane domain law that
83
+ * contradicts its symmetric one: a fork of its internals wearing one name. It composes the same
84
+ * `useBandPlot` choreography instead, which is where the sharing actually belongs.
85
+ */
86
+ declare function MirroredBarsInner<T>(props: MirroredBarsProps<T>): import("react").JSX.Element;
87
+ /**
88
+ * Hand-memoized: React Compiler does not process the shipped dist, so the hot kind is wrapped in
89
+ * `React.memo` to retain the auto-memoization it had as source (parity with `DualPanel`).
90
+ */
91
+ export declare const MirroredBars: typeof MirroredBarsInner;
92
+ export {};
93
+ //# sourceMappingURL=MirroredBars.d.ts.map
@@ -0,0 +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,gGAAgG;IAChG,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,mFAAmF;IACnF,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;AAKD;;;;;;;;;;;;;GAaG;AACH,iBAAS,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,+BAgBxD;AAmUD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAA8B,OAAO,iBAAiB,CAAA"}