basalt-ui 1.15.0 → 1.17.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 (91) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/agent/rules/basalt-charts.md +74 -13
  3. package/agent/templates/CLAUDE-block.md.tpl +9 -6
  4. package/dist/charts/cursor/resolve.d.ts +29 -5
  5. package/dist/charts/cursor/resolve.d.ts.map +1 -1
  6. package/dist/charts/cursor/resolve.js +25 -4
  7. package/dist/charts/hooks/useChartCursor.d.ts +8 -1
  8. package/dist/charts/hooks/useChartCursor.d.ts.map +1 -1
  9. package/dist/charts/hooks/useChartCursor.js +6 -2
  10. package/dist/charts/index.d.ts +2 -1
  11. package/dist/charts/index.d.ts.map +1 -1
  12. package/dist/charts/kinds/Bars.d.ts +30 -8
  13. package/dist/charts/kinds/Bars.d.ts.map +1 -1
  14. package/dist/charts/kinds/Bars.js +10 -3
  15. package/dist/charts/kinds/Bars.test.d.ts +2 -0
  16. package/dist/charts/kinds/Bars.test.d.ts.map +1 -0
  17. package/dist/charts/kinds/DualPanel.d.ts +30 -0
  18. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  19. package/dist/charts/kinds/DualPanel.js +82 -12
  20. package/dist/charts/kinds/DualPanel.test.d.ts +2 -0
  21. package/dist/charts/kinds/DualPanel.test.d.ts.map +1 -0
  22. package/dist/charts/kinds/MultiLine.d.ts +9 -0
  23. package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
  24. package/dist/charts/kinds/MultiLine.js +45 -33
  25. package/dist/charts/kinds/MultiLine.test.d.ts +2 -0
  26. package/dist/charts/kinds/MultiLine.test.d.ts.map +1 -0
  27. package/dist/charts/kinds/StackedArea.d.ts +9 -0
  28. package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
  29. package/dist/charts/kinds/StackedArea.js +16 -1
  30. package/dist/charts/kinds/StackedArea.test.d.ts +2 -0
  31. package/dist/charts/kinds/StackedArea.test.d.ts.map +1 -0
  32. package/dist/charts/kinds/ZonedLine.d.ts +9 -0
  33. package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
  34. package/dist/charts/kinds/ZonedLine.js +5 -0
  35. package/dist/charts/kinds/ZonedLine.test.d.ts +2 -0
  36. package/dist/charts/kinds/ZonedLine.test.d.ts.map +1 -0
  37. package/dist/charts/primitives/CartesianChart.d.ts +45 -6
  38. package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
  39. package/dist/charts/primitives/CartesianChart.js +29 -12
  40. package/dist/charts/primitives/CartesianChart.test.d.ts.map +1 -1
  41. package/dist/charts/primitives/ChartFrame.d.ts +8 -1
  42. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  43. package/dist/charts/primitives/ChartFrame.js +1 -1
  44. package/dist/charts/primitives/ChartLegend.d.ts +3 -0
  45. package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
  46. package/dist/charts/primitives/ChartLegend.js +4 -0
  47. package/dist/charts/primitives/ChartTooltip.d.ts +6 -1
  48. package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
  49. package/dist/charts/primitives/ChartTooltip.js +3 -2
  50. package/dist/charts/primitives/ChartTooltip.test.d.ts +2 -0
  51. package/dist/charts/primitives/ChartTooltip.test.d.ts.map +1 -0
  52. package/dist/charts/primitives/XZoneRects.d.ts +22 -8
  53. package/dist/charts/primitives/XZoneRects.d.ts.map +1 -1
  54. package/dist/charts/primitives/XZoneRects.js +39 -2
  55. package/dist/charts/series.d.ts +16 -3
  56. package/dist/charts/series.d.ts.map +1 -1
  57. package/dist/charts/series.js +2 -1
  58. package/dist/charts/utils/domain.d.ts +15 -0
  59. package/dist/charts/utils/domain.d.ts.map +1 -1
  60. package/dist/charts/utils/domain.js +6 -1
  61. package/llms.txt +2 -2
  62. package/package.json +1 -1
  63. package/src/charts/cursor/resolve.test.ts +62 -0
  64. package/src/charts/cursor/resolve.ts +71 -7
  65. package/src/charts/hooks/useChartCursor.ts +12 -1
  66. package/src/charts/index.ts +2 -0
  67. package/src/charts/kinds/Bars.test.tsx +183 -0
  68. package/src/charts/kinds/Bars.tsx +41 -12
  69. package/src/charts/kinds/DualPanel.test.tsx +441 -0
  70. package/src/charts/kinds/DualPanel.tsx +127 -11
  71. package/src/charts/kinds/MultiLine.test.tsx +218 -0
  72. package/src/charts/kinds/MultiLine.tsx +64 -36
  73. package/src/charts/kinds/StackedArea.test.tsx +114 -0
  74. package/src/charts/kinds/StackedArea.tsx +25 -1
  75. package/src/charts/kinds/ZonedLine.test.tsx +147 -0
  76. package/src/charts/kinds/ZonedLine.tsx +14 -0
  77. package/src/charts/primitives/CartesianChart.test.tsx +269 -0
  78. package/src/charts/primitives/CartesianChart.tsx +79 -19
  79. package/src/charts/primitives/ChartFrame.test.tsx +42 -0
  80. package/src/charts/primitives/ChartFrame.tsx +9 -2
  81. package/src/charts/primitives/ChartLegend.test.tsx +30 -0
  82. package/src/charts/primitives/ChartLegend.tsx +7 -0
  83. package/src/charts/primitives/ChartTooltip.test.tsx +23 -0
  84. package/src/charts/primitives/ChartTooltip.tsx +7 -1
  85. package/src/charts/primitives/XZoneRects.test.tsx +60 -0
  86. package/src/charts/primitives/XZoneRects.tsx +75 -10
  87. package/src/charts/series.test.ts +51 -0
  88. package/src/charts/series.ts +18 -6
  89. package/src/charts/utils/domain.test.ts +31 -1
  90. package/src/charts/utils/domain.ts +19 -0
  91. package/src/charts/primitives/CartesianChart.test.ts +0 -99
@@ -55,6 +55,9 @@ function DualPanelPlot(props) {
55
55
  data,
56
56
  chartId,
57
57
  getX,
58
+ formatX = fmtAxisDate,
59
+ cursorResolution,
60
+ ariaLabel,
58
61
  series,
59
62
  topYDomain = "auto",
60
63
  fillBetween,
@@ -67,7 +70,11 @@ function DualPanelPlot(props) {
67
70
  topFraction = 0.62,
68
71
  formatTop,
69
72
  formatBottom,
73
+ formatBar,
74
+ bottomYDomain = "auto",
75
+ bottomMaxAbsFloor,
70
76
  tooltipLabel,
77
+ formatHeader,
71
78
  plot
72
79
  } = props;
73
80
  const { hidden } = plot;
@@ -97,7 +104,9 @@ function DualPanelPlot(props) {
97
104
  () => probeAxisLabels({ domain: topDomain, ticks: 4, format: formatTop, nice: useNiceTop }).labels,
98
105
  [topDomain, useNiceTop, formatTop]
99
106
  );
107
+ const useNiceBottom = bottomYDomain === "auto";
100
108
  const maxAbs = useMemo(() => {
109
+ if (bottomYDomain !== "auto") return 0;
101
110
  let m = 0;
102
111
  for (const d of data) {
103
112
  const v = getBar(d);
@@ -105,18 +114,23 @@ function DualPanelPlot(props) {
105
114
  const a = Math.abs(v);
106
115
  if (a > m) m = a;
107
116
  }
108
- return m === 0 ? 1 : m;
109
- }, [data, getBar]);
117
+ const floored = bottomMaxAbsFloor !== void 0 ? Math.max(m, bottomMaxAbsFloor) : m;
118
+ return floored === 0 ? 1 : floored;
119
+ }, [data, getBar, bottomYDomain, bottomMaxAbsFloor]);
120
+ const bottomDomain = useMemo(
121
+ () => bottomYDomain === "auto" ? [-maxAbs, maxAbs] : bottomYDomain,
122
+ [bottomYDomain, maxAbs]
123
+ );
110
124
  const bottomLabels = useMemo(
111
125
  () => probeAxisLabels({
112
- domain: [-maxAbs, maxAbs],
126
+ domain: bottomDomain,
113
127
  ticks: 3,
114
128
  format: formatBottom,
115
- nice: true
129
+ nice: useNiceBottom
116
130
  }).labels,
117
- [maxAbs, formatBottom]
131
+ [bottomDomain, formatBottom, useNiceBottom]
118
132
  );
119
- const xLabelsAll = useMemo(() => data.map((d) => fmtAxisDate(getX(d))), [data, getX]);
133
+ const xLabelsAll = useMemo(() => data.map((d) => formatX(getX(d))), [data, getX, formatX]);
120
134
  const margin = useMemo(
121
135
  () => autoMargin({ left: [...topLabels, ...bottomLabels], bottom: xLabelsAll }),
122
136
  [topLabels, bottomLabels, xLabelsAll]
@@ -140,15 +154,20 @@ function DualPanelPlot(props) {
140
154
  [topDomain, useNiceTop, topH]
141
155
  );
142
156
  const bottomYScale = useMemo(
143
- () => scaleLinear({ domain: [-maxAbs, maxAbs], range: [bottomH, 0], nice: true }),
144
- [maxAbs, bottomH]
157
+ () => scaleLinear({
158
+ domain: bottomDomain,
159
+ range: [bottomH, 0],
160
+ ...useNiceBottom && { nice: true }
161
+ }),
162
+ [bottomDomain, bottomH, useNiceBottom]
145
163
  );
146
164
  const cursor = useChartCursor({
147
165
  data,
148
166
  chartId,
149
167
  getKey: getX,
150
168
  xScale,
151
- marginLeft: margin.left
169
+ marginLeft: margin.left,
170
+ ...cursorResolution !== void 0 && { resolution: cursorResolution }
152
171
  });
153
172
  const tickValues = useMemo(() => smartTicks(data.map(getX), xMax), [data, xMax, getX]);
154
173
  const barWidth = data.length > 0 ? Math.max(xMax / data.length * 0.6, 2) : 2;
@@ -209,6 +228,37 @@ function DualPanelPlot(props) {
209
228
  }
210
229
  return out;
211
230
  }, [data, visibleSeries]);
231
+ const markerNodes = useMemo(
232
+ () => visibleSeries.flatMap((s) => {
233
+ const getMarker = s.getMarker;
234
+ if (!getMarker) return [];
235
+ const pts = lineValid.get(s.key) ?? [];
236
+ const markers = [];
237
+ for (const p of pts) {
238
+ const m = getMarker(p.__d);
239
+ if (m === null) continue;
240
+ const cx = xScale(getX(p.__d)) ?? 0;
241
+ const cy = topYScale(p.__y);
242
+ const ring = m.ring ?? true;
243
+ markers.push(
244
+ /* @__PURE__ */ jsx(
245
+ "circle",
246
+ {
247
+ cx,
248
+ cy,
249
+ r: m.r ?? VX.dotR,
250
+ fill: m.color ?? s.color,
251
+ fillOpacity: m.fillOpacity ?? 1,
252
+ ...ring && { stroke: VX.dotStroke, strokeWidth: 2 }
253
+ },
254
+ `mk-${s.key}-${getX(p.__d)}`
255
+ )
256
+ );
257
+ }
258
+ return markers;
259
+ }),
260
+ [visibleSeries, lineValid, xScale, topYScale, getX]
261
+ );
212
262
  const point = cursor.point;
213
263
  const sx = point !== null ? xScale(getX(point)) ?? 0 : 0;
214
264
  const syncedBar = point !== null ? getBar(point) : null;
@@ -256,11 +306,13 @@ function DualPanelPlot(props) {
256
306
  stroke: s.color,
257
307
  strokeWidth: s.strokeWidth ?? VX.lineWidth,
258
308
  strokeDasharray: s.dash === "dashed" ? VX.dashArray : void 0,
309
+ strokeOpacity: s.strokeOpacity ?? 1,
259
310
  curve: curveMonotoneX
260
311
  },
261
312
  `top-line-${s.key}`
262
313
  );
263
314
  }),
315
+ markerNodes,
264
316
  point !== null && /* @__PURE__ */ jsx(Fragment, { children: visibleSeries.map((s) => {
265
317
  const v = s.getValue(point);
266
318
  if (v === null || v === void 0 || Number.isNaN(v)) return null;
@@ -275,7 +327,13 @@ function DualPanelPlot(props) {
275
327
  onMove: cursor.onPointerMove,
276
328
  onLeave: cursor.onPointerLeave,
277
329
  onKeyDown: cursor.onKeyDown,
278
- onBlur: cursor.onBlur
330
+ onBlur: cursor.onBlur,
331
+ valueMax: Math.max(data.length - 1, 0),
332
+ ...point !== null && {
333
+ valueNow: data.indexOf(point),
334
+ valueText: formatX(getX(point))
335
+ },
336
+ ...ariaLabel !== void 0 && { ariaLabel }
279
337
  }
280
338
  )
281
339
  ] }),
@@ -313,7 +371,15 @@ function DualPanelPlot(props) {
313
371
  }
314
372
  ),
315
373
  /* @__PURE__ */ jsx(AxisLeftNumeric, { scale: bottomYScale, numTicks: 3, tickFormat: formatBottom }),
316
- /* @__PURE__ */ jsx(AxisBottomDate, { top: bottomH, scale: xScale, tickValues }),
374
+ /* @__PURE__ */ jsx(
375
+ AxisBottomDate,
376
+ {
377
+ top: bottomH,
378
+ scale: xScale,
379
+ tickValues,
380
+ tickFormat: formatX
381
+ }
382
+ ),
317
383
  /* @__PURE__ */ jsx(
318
384
  HoverOverlay,
319
385
  {
@@ -331,6 +397,9 @@ function DualPanelPlot(props) {
331
397
  TooltipHeader,
332
398
  {
333
399
  date: getX(point),
400
+ ...formatHeader !== void 0 && {
401
+ format: (key) => formatHeader(key, point)
402
+ },
334
403
  ...(() => {
335
404
  const lbl = tooltipLabel?.(point) ?? null;
336
405
  return lbl !== null ? { label: lbl.text, labelColor: lbl.color } : {};
@@ -353,12 +422,13 @@ function DualPanelPlot(props) {
353
422
  barVisible && (() => {
354
423
  const v = getBar(point);
355
424
  if (v === null || v === void 0 || Number.isNaN(v)) return null;
425
+ const value = formatBar !== void 0 ? formatBar(v, point) : formatBottom(v);
356
426
  return /* @__PURE__ */ jsx(
357
427
  TooltipRow,
358
428
  {
359
429
  color: v >= 0 ? barColorPositive : barColorNegative,
360
430
  label: barLabel,
361
- value: formatBottom(v),
431
+ value,
362
432
  shape: "bar"
363
433
  }
364
434
  );
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DualPanel.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DualPanel.test.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/DualPanel.test.tsx"],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { CursorResolution } from '../cursor/resolve.js';
1
2
  import type { CartesianTooltipConfig, AxisConfig } from '../primitives/CartesianChart.js';
2
3
  import type { XZoneSpec } from '../primitives/XZoneRects.js';
3
4
  import type { ZoneSpec } from '../primitives/ZoneRects.js';
@@ -31,6 +32,14 @@ export type MultiLineProps<T> = {
31
32
  }[];
32
33
  /** Exact number of x ticks. Default: as many as fit. */
33
34
  xTicks?: number;
35
+ /** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
36
+ formatX?: (key: string) => string;
37
+ /**
38
+ * How a sibling chart's broadcast cursor key resolves against this chart's points. Default
39
+ * `'nearest'`. Pass `'leading'` when `getX` returns a bucket's leading edge (a weekly series
40
+ * keyed by its Monday) — see `CursorResolution`.
41
+ */
42
+ cursorResolution?: CursorResolution;
34
43
  /** Tooltip config — `label` for a right-aligned header badge, `extraRows` for rows appended
35
44
  * after the derived per-series rows. `false` disables the tooltip entirely. */
36
45
  tooltip?: CartesianTooltipConfig<T> | false;
@@ -1 +1 @@
1
- {"version":3,"file":"MultiLine.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MultiLine.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAEnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;mFAC+E;IAC/E,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;gEAC4D;IAC5D,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB;kEAC8D;IAC9D,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IAClB,iFAAiF;IACjF,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;IAClB;sBACkB;IAClB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAC/D,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;mFAC+E;IAC/E,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IAC3C,4DAA4D;IAC5D,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;IAC/B;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AA4BD;;;;;;;;;;;;GAYG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BAgDlD;AAoGD;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
1
+ {"version":3,"file":"MultiLine.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MultiLine.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAEnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;mFAC+E;IAC/E,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;gEAC4D;IAC5D,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB;kEAC8D;IAC9D,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IAClB,iFAAiF;IACjF,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;IAClB;sBACkB;IAClB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAC/D,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC;mFAC+E;IAC/E,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IAC3C,4DAA4D;IAC5D,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;IAC/B;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AA4BD;;;;;;;;;;;;GAYG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BAoDlD;AAmHD;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { curveMonotoneX } from "@visx/curve";
3
3
  import { LinePath } from "@visx/shape";
4
- import { memo, useMemo } from "react";
4
+ import { memo, useCallback, useMemo } from "react";
5
5
  import { CartesianChart } from "../primitives/CartesianChart.js";
6
6
  import { LINE_OVERLAY_STROKE_WIDTH } from "../series.js";
7
7
  import { VX } from "../../tokens/index.js";
@@ -36,6 +36,8 @@ function MultiLineInner(props) {
36
36
  xZones,
37
37
  refLines,
38
38
  xTicks,
39
+ formatX,
40
+ cursorResolution,
39
41
  tooltip,
40
42
  markerShape = "circle",
41
43
  height,
@@ -60,6 +62,8 @@ function MultiLineInner(props) {
60
62
  ...xZones !== void 0 && { xZones },
61
63
  ...refLines !== void 0 && { refLines },
62
64
  ...xTicks !== void 0 && { xTicks },
65
+ ...formatX !== void 0 && { formatX },
66
+ ...cursorResolution !== void 0 && { cursorResolution },
63
67
  ...tooltip !== void 0 && { tooltip },
64
68
  ...height !== void 0 && { height },
65
69
  ...legend !== void 0 && { legend },
@@ -80,29 +84,16 @@ function MultiLineMarks({
80
84
  for (const s of visible) m.set(s.key, seriesPoints(s, data));
81
85
  return m;
82
86
  }, [visible, data]);
83
- const dimOpacity = (s) => highlighted === null || s.key === highlighted || s.parent === highlighted ? 1 : 0.25;
84
- const scaleFor = (s) => s.axis === "right" && y2Scale !== null ? y2Scale : yScale;
85
- return /* @__PURE__ */ jsxs(Fragment, { children: [
86
- visible.map((s) => {
87
- const valid = pointsBySeries.get(s.key) ?? [];
88
- if (valid.length === 0) return null;
89
- const scale = scaleFor(s);
90
- return /* @__PURE__ */ jsx(
91
- LinePath,
92
- {
93
- data: valid,
94
- x: (p) => xScale(getX(p.__d)) ?? 0,
95
- y: (p) => scale(p.__y),
96
- stroke: s.color,
97
- strokeWidth: s.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH,
98
- strokeDasharray: s.dash === "dashed" ? VX.dashArray : void 0,
99
- strokeOpacity: dimOpacity(s),
100
- curve: curveMonotoneX
101
- },
102
- `line-${s.key}`
103
- );
104
- }),
105
- visible.flatMap((s) => {
87
+ const dimOpacity = useCallback(
88
+ (s) => highlighted === null || s.key === highlighted || s.parent === highlighted ? 1 : 0.25,
89
+ [highlighted]
90
+ );
91
+ const scaleFor = useCallback(
92
+ (s) => s.axis === "right" && y2Scale !== null ? y2Scale : yScale,
93
+ [y2Scale, yScale]
94
+ );
95
+ const markerNodes = useMemo(
96
+ () => visible.flatMap((s) => {
106
97
  const getMarker = s.getMarker;
107
98
  if (!getMarker) return [];
108
99
  const scale = scaleFor(s);
@@ -115,16 +106,16 @@ function MultiLineMarks({
115
106
  const cy = scale(p.__y);
116
107
  const color = m.color ?? s.color;
117
108
  const r = m.r ?? (markerShape === "star" ? STAR_R : VX.dotR);
109
+ const ring = m.ring ?? true;
110
+ const fillOpacity = (m.fillOpacity ?? 1) * op;
118
111
  markers.push(
119
112
  markerShape === "star" ? /* @__PURE__ */ jsx(
120
113
  "path",
121
114
  {
122
115
  d: starPath(cx, cy, r),
123
116
  fill: color,
124
- stroke: VX.dotStroke,
125
- strokeWidth: 1.5,
126
- fillOpacity: op,
127
- strokeOpacity: op
117
+ fillOpacity,
118
+ ...ring && { stroke: VX.dotStroke, strokeWidth: 1.5, strokeOpacity: op }
128
119
  },
129
120
  `mk-${s.key}-${getX(p.__d)}`
130
121
  ) : /* @__PURE__ */ jsx(
@@ -134,17 +125,38 @@ function MultiLineMarks({
134
125
  cy,
135
126
  r,
136
127
  fill: color,
137
- stroke: VX.dotStroke,
138
- strokeWidth: 2,
139
- fillOpacity: op,
140
- strokeOpacity: op
128
+ fillOpacity,
129
+ ...ring && { stroke: VX.dotStroke, strokeWidth: 2, strokeOpacity: op }
141
130
  },
142
131
  `mk-${s.key}-${getX(p.__d)}`
143
132
  )
144
133
  );
145
134
  }
146
135
  return markers;
147
- })
136
+ }),
137
+ [visible, pointsBySeries, xScale, getX, scaleFor, dimOpacity, markerShape]
138
+ );
139
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
140
+ visible.map((s) => {
141
+ const valid = pointsBySeries.get(s.key) ?? [];
142
+ if (valid.length === 0) return null;
143
+ const scale = scaleFor(s);
144
+ return /* @__PURE__ */ jsx(
145
+ LinePath,
146
+ {
147
+ data: valid,
148
+ x: (p) => xScale(getX(p.__d)) ?? 0,
149
+ y: (p) => scale(p.__y),
150
+ stroke: s.color,
151
+ strokeWidth: s.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH,
152
+ strokeDasharray: s.dash === "dashed" ? VX.dashArray : void 0,
153
+ strokeOpacity: dimOpacity(s) * (s.strokeOpacity ?? 1),
154
+ curve: curveMonotoneX
155
+ },
156
+ `line-${s.key}`
157
+ );
158
+ }),
159
+ markerNodes
148
160
  ] });
149
161
  }
150
162
  const MultiLine = memo(MultiLineInner);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MultiLine.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultiLine.test.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MultiLine.test.tsx"],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { CursorResolution } from '../cursor/resolve.js';
1
2
  import type { AxisConfig } from '../primitives/CartesianChart.js';
2
3
  import type { ChartLegendConfig, ChartSeries } from '../series.js';
3
4
  export type StackedAreaProps<T> = {
@@ -16,6 +17,14 @@ export type StackedAreaProps<T> = {
16
17
  y?: AxisConfig<T>;
17
18
  /** X tick count override. Default: as many as fit. */
18
19
  xTicks?: number;
20
+ /** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
21
+ formatX?: (key: string) => string;
22
+ /**
23
+ * How a sibling chart's broadcast cursor key resolves against this chart's points. Default
24
+ * `'nearest'`. Pass `'leading'` when `getX` returns a bucket's leading edge (a weekly series
25
+ * keyed by its Monday) — see `CursorResolution`.
26
+ */
27
+ cursorResolution?: CursorResolution;
19
28
  /** Legend config forwarded to `CartesianChart`; `false` disables the legend (sparkline escape).
20
29
  * Default `{ placement: 'bottom' }`. */
21
30
  legend?: ChartLegendConfig | false;
@@ -1 +1 @@
1
- {"version":3,"file":"StackedArea.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/StackedArea.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE/D,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;4FACwF;IACxF,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;;;qEAGiE;IACjE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,iBAAS,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,+BAgEtD;AA+CD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAA6B,OAAO,gBAAgB,CAAA"}
1
+ {"version":3,"file":"StackedArea.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/StackedArea.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE/D,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;4FACwF;IACxF,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;;;qEAGiE;IACjE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,iBAAS,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,+BA+EtD;AA+CD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAA6B,OAAO,gBAAgB,CAAA"}
@@ -4,7 +4,20 @@ import { AreaStack } from "@visx/shape";
4
4
  import { memo, useCallback, useMemo } from "react";
5
5
  import { CartesianChart } from "../primitives/CartesianChart.js";
6
6
  function StackedAreaInner(props) {
7
- const { data, chartId, getX, series, y, xTicks, height, legend, ariaLabel, isPending } = props;
7
+ const {
8
+ data,
9
+ chartId,
10
+ getX,
11
+ series,
12
+ y,
13
+ xTicks,
14
+ formatX,
15
+ cursorResolution,
16
+ height,
17
+ legend,
18
+ ariaLabel,
19
+ isPending
20
+ } = props;
8
21
  const yConfig = useMemo(() => {
9
22
  const base = y ?? {};
10
23
  if (base.domain !== void 0 && base.domain !== "auto") return base;
@@ -47,6 +60,8 @@ function StackedAreaInner(props) {
47
60
  y: yConfig,
48
61
  cursorValue: stackedCursorValue,
49
62
  ...xTicks !== void 0 && { xTicks },
63
+ ...formatX !== void 0 && { formatX },
64
+ ...cursorResolution !== void 0 && { cursorResolution },
50
65
  ...height !== void 0 && { height },
51
66
  ...legend !== void 0 && { legend },
52
67
  ...ariaLabel !== void 0 && { ariaLabel },
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=StackedArea.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackedArea.test.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/StackedArea.test.tsx"],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { CursorResolution } from '../cursor/resolve.js';
1
2
  import type { CartesianTooltipConfig, AxisConfig } from '../primitives/CartesianChart.js';
2
3
  import type { XZoneSpec } from '../primitives/XZoneRects.js';
3
4
  import type { ZoneSpec } from '../primitives/ZoneRects.js';
@@ -39,6 +40,14 @@ export type ZonedLineProps<T> = {
39
40
  refLines?: ZonedLineRefLine[];
40
41
  /** Exact number of x ticks. Default: as many as fit. */
41
42
  xTicks?: number;
43
+ /** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
44
+ formatX?: (key: string) => string;
45
+ /**
46
+ * How a sibling chart's broadcast cursor key resolves against this chart's points. Default
47
+ * `'nearest'`. Pass `'leading'` when `getX` returns a bucket's leading edge (a weekly series
48
+ * keyed by its Monday) — see `CursorResolution`.
49
+ */
50
+ cursorResolution?: CursorResolution;
42
51
  /** Tooltip config — `label` for a right-aligned header badge (e.g. zone name with zone color),
43
52
  * `extraRows` for rows appended after the derived row. `false` disables the tooltip entirely. */
44
53
  tooltip?: CartesianTooltipConfig<T> | false;
@@ -1 +1 @@
1
- {"version":3,"file":"ZonedLine.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/ZonedLine.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAEnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAA;AAEpC,mFAAmF;AACnF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,0EAA0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;;wEAEoE;IACpE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;gEAC4D;IAC5D,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;IACvB;sBACkB;IAClB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAA;IACjC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC7B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;qGACiG;IACjG,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAiBD;;;;;;;;;;;;GAYG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BA2DlD;AA8ED;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
1
+ {"version":3,"file":"ZonedLine.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/ZonedLine.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAEnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAA;AAEpC,mFAAmF;AACnF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,0EAA0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;;wEAEoE;IACpE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;gEAC4D;IAC5D,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;IACvB;sBACkB;IAClB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAA;IACjC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC7B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC;qGACiG;IACjG,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAiBD;;;;;;;;;;;;GAYG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BA+DlD;AA+ED;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
@@ -30,6 +30,8 @@ function ZonedLineInner(props) {
30
30
  thresholds,
31
31
  refLines,
32
32
  xTicks,
33
+ formatX,
34
+ cursorResolution,
33
35
  tooltip,
34
36
  areaFill,
35
37
  height,
@@ -56,6 +58,8 @@ function ZonedLineInner(props) {
56
58
  ...xZones !== void 0 && { xZones },
57
59
  ...refLines !== void 0 && { refLines },
58
60
  ...xTicks !== void 0 && { xTicks },
61
+ ...formatX !== void 0 && { formatX },
62
+ ...cursorResolution !== void 0 && { cursorResolution },
59
63
  ...tooltip !== void 0 && { tooltip },
60
64
  ...height !== void 0 && { height },
61
65
  ...legend !== void 0 && { legend },
@@ -127,6 +131,7 @@ function ZonedLineMarks({
127
131
  stroke: primary.color,
128
132
  strokeWidth: primary.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH,
129
133
  strokeDasharray: primary.dash === "dashed" ? VX.dashArray : void 0,
134
+ strokeOpacity: primary.strokeOpacity ?? 1,
130
135
  curve: curveMonotoneX
131
136
  }
132
137
  )
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ZonedLine.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ZonedLine.test.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/ZonedLine.test.tsx"],"names":[],"mappings":""}
@@ -1,6 +1,7 @@
1
1
  import { scaleLinear, scalePoint } from '@visx/scale';
2
2
  import type { ReactNode } from 'react';
3
3
  import type { ChartMargin } from '../../tokens/index.js';
4
+ import type { CursorResolution } from '../cursor/resolve.js';
4
5
  import type { ChartLegendConfig, ChartSeries } from '../series.js';
5
6
  import type { XZoneSpec } from './XZoneRects.js';
6
7
  import type { ZoneSpec } from './ZoneRects.js';
@@ -16,7 +17,11 @@ export type AxisConfig<T> = {
16
17
  * (summing `props.series` there would leave a permanent gap above the stack).
17
18
  */
18
19
  domain?: [number, number] | 'auto' | ((data: readonly T[], visible: readonly ChartSeries<T>[]) => [number, number]);
19
- /** When 'auto': the upper bound is at least this. */
20
+ /**
21
+ * When 'auto': the raw upper bound is at least this, and padding is applied AFTER — mirroring
22
+ * `autoMinCeil`, which clamps first and pads second. A floor that padded before the clamp used
23
+ * to land the axis top exactly on the floor value with zero headroom.
24
+ */
20
25
  autoMaxFloor?: number;
21
26
  /** When 'auto': the lower bound is at most this. Default 0 (forced zero baseline). `Infinity`
22
27
  * pads down from the raw data minimum instead. */
@@ -28,6 +33,22 @@ export type AxisConfig<T> = {
28
33
  format?: (v: number) => string;
29
34
  /** Horizontal grid rules. Default: on for the left axis, off for the right. */
30
35
  grid?: boolean;
36
+ /**
37
+ * Round the scale's domain outward to nice tick values (d3's `scale.nice()`). Threaded to BOTH
38
+ * `probeAxisLabels` (measurement) and the real `scaleLinear` (rendering) — they must agree, or
39
+ * the measured margin is computed from ticks the axis never paints.
40
+ *
41
+ * Default `false`, deliberately: flipping the default would move the domain of every
42
+ * already-migrated chart. Opt in per axis.
43
+ */
44
+ nice?: boolean;
45
+ };
46
+ /** Handed to `prependRows`/`extraRows` alongside the hovered datum — the same `visible`/`hidden`
47
+ * the plot itself draws from, so a hand-authored row can't structurally desync from legend
48
+ * toggling. */
49
+ export type CartesianTooltipRowContext<T> = {
50
+ visible: readonly ChartSeries<T>[];
51
+ hidden: ReadonlySet<string>;
31
52
  };
32
53
  export type CartesianTooltipConfig<T> = {
33
54
  /**
@@ -42,10 +63,20 @@ export type CartesianTooltipConfig<T> = {
42
63
  text: string;
43
64
  color: string;
44
65
  } | null;
45
- /** Rows rendered BEFORE the derived per-series rows (a total, a context line). */
46
- prependRows?: (d: T) => ReactNode;
47
- /** Rows appended after the derived per-series rows. */
48
- extraRows?: (d: T) => ReactNode;
66
+ /**
67
+ * Overrides the tooltip header's date text. Default: `TooltipHeader`'s own `fmtTooltipDate`
68
+ * behavior, unchanged. `fmtTooltipDate` regexes `YYYY-MM-DD` out of the domain key and builds a
69
+ * LOCAL `Date` from it — a UTC ISO key then names the wrong day next to `formatX`, the tooltip
70
+ * badge, and every sibling chart, which all resolve locally. Receives the raw `getX` key
71
+ * alongside the hovered datum, so a caller can format from either.
72
+ */
73
+ formatHeader?: (key: string, d: T) => string;
74
+ /** Rows rendered BEFORE the derived per-series rows (a total, a context line). The second
75
+ * argument carries the same `visible`/`hidden` the plot draws from, so a hand-authored row
76
+ * stays in sync with legend toggling instead of naming a series the plot no longer draws. */
77
+ prependRows?: (d: T, ctx: CartesianTooltipRowContext<T>) => ReactNode;
78
+ /** Rows appended after the derived per-series rows. Same `ctx` as {@link prependRows}. */
79
+ extraRows?: (d: T, ctx: CartesianTooltipRowContext<T>) => ReactNode;
49
80
  };
50
81
  /** Everything a mark renderer needs. Handed to `CartesianChart`'s child on every render. */
51
82
  export type PlotContext<T> = {
@@ -106,6 +137,14 @@ export type CartesianChartProps<T> = {
106
137
  * line the reader is actually looking at.
107
138
  */
108
139
  cursorValue?: (point: T, series: ChartSeries<T>, visible: readonly ChartSeries<T>[]) => number | null;
140
+ /**
141
+ * How a sibling chart's broadcast cursor key resolves against THIS chart's points. Default
142
+ * `'nearest'`, correct when `getX` returns an instant. Pass `'leading'` when it returns a
143
+ * bucket's leading edge (a weekly series keyed by its Monday): under `'nearest'` a hover landing
144
+ * in the back half of a bucket resolves to the FOLLOWING bucket, so the shared crosshair sits
145
+ * one column right of the data the reader is pointing at.
146
+ */
147
+ cursorResolution?: CursorResolution;
109
148
  ariaLabel?: string;
110
149
  isPending?: boolean;
111
150
  /** Draw ONLY the marks. Everything around them is the primitive's job. */
@@ -138,6 +177,6 @@ extraBounds?: readonly number[]): [number, number];
138
177
  * Margins are MEASURED from the labels that will actually be painted, so a wide tick label widens
139
178
  * its own gutter instead of clipping or needing a hand-tuned `margin` prop.
140
179
  */
141
- export declare function CartesianChart<T>({ data, chartId, getX, series, y, y2, xTicks, formatX, zones, xZones, refLines, height, aspectRatio, fill, legend, tooltip, margin: marginOverride, cursorValue, ariaLabel, isPending, children, }: CartesianChartProps<T>): ReactNode;
180
+ export declare function CartesianChart<T>({ data, chartId, getX, series, y, y2, xTicks, formatX, zones, xZones, refLines, height, aspectRatio, fill, legend, tooltip, margin: marginOverride, cursorValue, cursorResolution, ariaLabel, isPending, children, }: CartesianChartProps<T>): ReactNode;
142
181
  export {};
143
182
  //# sourceMappingURL=CartesianChart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CartesianChart.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/CartesianChart.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CartesianChart.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/CartesianChart.tsx"],"names":[],"mappings":"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"}