basalt-ui 1.16.0 → 1.18.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 (69) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/agent/rules/basalt-charts.md +58 -4
  3. package/agent/skills/basalt-design/SKILL.md +2 -2
  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 +1 -0
  11. package/dist/charts/index.d.ts.map +1 -1
  12. package/dist/charts/kinds/Bars.d.ts +9 -0
  13. package/dist/charts/kinds/Bars.d.ts.map +1 -1
  14. package/dist/charts/kinds/Bars.js +4 -0
  15. package/dist/charts/kinds/DualPanel.d.ts +24 -0
  16. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  17. package/dist/charts/kinds/DualPanel.js +39 -9
  18. package/dist/charts/kinds/MultiLine.d.ts +9 -0
  19. package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
  20. package/dist/charts/kinds/MultiLine.js +10 -8
  21. package/dist/charts/kinds/StackedArea.d.ts +9 -0
  22. package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
  23. package/dist/charts/kinds/StackedArea.js +16 -1
  24. package/dist/charts/kinds/StackedArea.test.d.ts +2 -0
  25. package/dist/charts/kinds/StackedArea.test.d.ts.map +1 -0
  26. package/dist/charts/kinds/ZonedLine.d.ts +9 -0
  27. package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
  28. package/dist/charts/kinds/ZonedLine.js +4 -0
  29. package/dist/charts/primitives/CartesianChart.d.ts +40 -2
  30. package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
  31. package/dist/charts/primitives/CartesianChart.js +16 -6
  32. package/dist/charts/primitives/ChartFrame.d.ts +8 -1
  33. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  34. package/dist/charts/primitives/ChartFrame.js +1 -1
  35. package/dist/charts/primitives/ChartTooltip.d.ts +12 -2
  36. package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
  37. package/dist/charts/primitives/ChartTooltip.js +5 -3
  38. package/dist/charts/primitives/ChartTooltip.test.d.ts +2 -0
  39. package/dist/charts/primitives/ChartTooltip.test.d.ts.map +1 -0
  40. package/dist/charts/series.d.ts +9 -1
  41. package/dist/charts/series.d.ts.map +1 -1
  42. package/dist/charts/utils/domain.d.ts +15 -0
  43. package/dist/charts/utils/domain.d.ts.map +1 -1
  44. package/dist/charts/utils/domain.js +6 -1
  45. package/llms.txt +2 -2
  46. package/package.json +1 -1
  47. package/src/charts/cursor/resolve.test.ts +62 -0
  48. package/src/charts/cursor/resolve.ts +71 -7
  49. package/src/charts/hooks/useChartCursor.ts +12 -1
  50. package/src/charts/index.ts +1 -0
  51. package/src/charts/kinds/Bars.test.tsx +85 -0
  52. package/src/charts/kinds/Bars.tsx +13 -0
  53. package/src/charts/kinds/DualPanel.test.tsx +391 -1
  54. package/src/charts/kinds/DualPanel.tsx +74 -8
  55. package/src/charts/kinds/MultiLine.test.tsx +181 -0
  56. package/src/charts/kinds/MultiLine.tsx +19 -8
  57. package/src/charts/kinds/StackedArea.test.tsx +114 -0
  58. package/src/charts/kinds/StackedArea.tsx +25 -1
  59. package/src/charts/kinds/ZonedLine.test.tsx +110 -0
  60. package/src/charts/kinds/ZonedLine.tsx +13 -0
  61. package/src/charts/primitives/CartesianChart.test.tsx +284 -3
  62. package/src/charts/primitives/CartesianChart.tsx +64 -12
  63. package/src/charts/primitives/ChartFrame.test.tsx +42 -0
  64. package/src/charts/primitives/ChartFrame.tsx +9 -2
  65. package/src/charts/primitives/ChartTooltip.test.tsx +44 -0
  66. package/src/charts/primitives/ChartTooltip.tsx +14 -2
  67. package/src/charts/series.ts +8 -2
  68. package/src/charts/utils/domain.test.ts +31 -1
  69. package/src/charts/utils/domain.ts +19 -0
@@ -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 },
@@ -102,16 +106,16 @@ function MultiLineMarks({
102
106
  const cy = scale(p.__y);
103
107
  const color = m.color ?? s.color;
104
108
  const r = m.r ?? (markerShape === "star" ? STAR_R : VX.dotR);
109
+ const ring = m.ring ?? true;
110
+ const fillOpacity = (m.fillOpacity ?? 1) * op;
105
111
  markers.push(
106
112
  markerShape === "star" ? /* @__PURE__ */ jsx(
107
113
  "path",
108
114
  {
109
115
  d: starPath(cx, cy, r),
110
116
  fill: color,
111
- stroke: VX.dotStroke,
112
- strokeWidth: 1.5,
113
- fillOpacity: op,
114
- strokeOpacity: op
117
+ fillOpacity,
118
+ ...ring && { stroke: VX.dotStroke, strokeWidth: 1.5, strokeOpacity: op }
115
119
  },
116
120
  `mk-${s.key}-${getX(p.__d)}`
117
121
  ) : /* @__PURE__ */ jsx(
@@ -121,10 +125,8 @@ function MultiLineMarks({
121
125
  cy,
122
126
  r,
123
127
  fill: color,
124
- stroke: VX.dotStroke,
125
- strokeWidth: 2,
126
- fillOpacity: op,
127
- strokeOpacity: op
128
+ fillOpacity,
129
+ ...ring && { stroke: VX.dotStroke, strokeWidth: 2, strokeOpacity: op }
128
130
  },
129
131
  `mk-${s.key}-${getX(p.__d)}`
130
132
  )
@@ -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;AA+ED;;;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 },
@@ -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. */
@@ -58,12 +63,37 @@ export type CartesianTooltipConfig<T> = {
58
63
  text: string;
59
64
  color: string;
60
65
  } | null;
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;
61
74
  /** Rows rendered BEFORE the derived per-series rows (a total, a context line). The second
62
75
  * argument carries the same `visible`/`hidden` the plot draws from, so a hand-authored row
63
76
  * stays in sync with legend toggling instead of naming a series the plot no longer draws. */
64
77
  prependRows?: (d: T, ctx: CartesianTooltipRowContext<T>) => ReactNode;
65
78
  /** Rows appended after the derived per-series rows. Same `ctx` as {@link prependRows}. */
66
79
  extraRows?: (d: T, ctx: CartesianTooltipRowContext<T>) => ReactNode;
80
+ /**
81
+ * Render this chart's tooltip when it is a cursor FOLLOWER (the crosshair came from a sibling
82
+ * chart sharing the cursor), not only when this chart is the SOURCE. Default false — today's
83
+ * behaviour, nothing moves. A follower has no pointer under it, so its tooltip is always ANCHORED
84
+ * to the crosshair — the same positioning `follow: false` gives the source — regardless of what
85
+ * `follow` is set to on this chart: there is no other valid position for a chart nobody is
86
+ * hovering. `follow` keeps governing the SOURCE's own tooltip exactly as before; the two options
87
+ * only interact for a follower, where `onFollow` always wins on positioning. Only the SOURCE's
88
+ * tooltip is `aria-live` — followers announce nothing, so a shared-cursor page doesn't fire N
89
+ * live-region updates per pointer move.
90
+ *
91
+ * Cost, since it scales with the page rather than the chart: anchoring reads one
92
+ * `getBoundingClientRect` per hovered frame (the same cost `follow: false` documents), so N
93
+ * opted-in followers pay N of them per frame. That is the reason this is opt-in per chart rather
94
+ * than a page-level switch — turn it on for the charts a reader actually correlates.
95
+ */
96
+ onFollow?: boolean;
67
97
  };
68
98
  /** Everything a mark renderer needs. Handed to `CartesianChart`'s child on every render. */
69
99
  export type PlotContext<T> = {
@@ -124,6 +154,14 @@ export type CartesianChartProps<T> = {
124
154
  * line the reader is actually looking at.
125
155
  */
126
156
  cursorValue?: (point: T, series: ChartSeries<T>, visible: readonly ChartSeries<T>[]) => number | null;
157
+ /**
158
+ * How a sibling chart's broadcast cursor key resolves against THIS chart's points. Default
159
+ * `'nearest'`, correct when `getX` returns an instant. Pass `'leading'` when it returns a
160
+ * bucket's leading edge (a weekly series keyed by its Monday): under `'nearest'` a hover landing
161
+ * in the back half of a bucket resolves to the FOLLOWING bucket, so the shared crosshair sits
162
+ * one column right of the data the reader is pointing at.
163
+ */
164
+ cursorResolution?: CursorResolution;
127
165
  ariaLabel?: string;
128
166
  isPending?: boolean;
129
167
  /** Draw ONLY the marks. Everything around them is the primitive's job. */
@@ -156,6 +194,6 @@ extraBounds?: readonly number[]): [number, number];
156
194
  * Margins are MEASURED from the labels that will actually be painted, so a wide tick label widens
157
195
  * its own gutter instead of clipping or needing a hand-tuned `margin` prop.
158
196
  */
159
- 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;
197
+ 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;
160
198
  export {};
161
199
  //# 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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"}
@@ -7,7 +7,7 @@ import { VX } from "../../tokens/index.js";
7
7
  import { useChartCursor } from "../hooks/useChartCursor.js";
8
8
  import { autoMargin, probeAxisLabels } from "../layout/auto-margin.js";
9
9
  import { deriveTooltipRows } from "../series.js";
10
- import { padAutoLower } from "../utils/domain.js";
10
+ import { padAutoLower, padAutoUpper } from "../utils/domain.js";
11
11
  import { fmtAxisDate } from "../utils/format.js";
12
12
  import { smartTicks, smartTicksEvery } from "../utils/ticks.js";
13
13
  import { AxisBottomDate, AxisLeftNumeric, AxisRightNumeric } from "./Axes.js";
@@ -41,8 +41,7 @@ function resolveAxisDomain(cfg, data, series, extraBounds = []) {
41
41
  if (min === Infinity) return [0, cfg?.autoMaxFloor ?? 1];
42
42
  const pad = cfg?.autoPad ?? DEFAULT_AUTO_PAD;
43
43
  const ceil = cfg?.autoMinCeil ?? 0;
44
- const paddedMax = max > 0 ? max * pad : max < 0 ? max / pad : 0;
45
- const upper = Math.max(paddedMax, cfg?.autoMaxFloor ?? -Infinity);
44
+ const upper = padAutoUpper(Math.max(max, cfg?.autoMaxFloor ?? -Infinity), pad);
46
45
  const lower = padAutoLower(Math.min(min, ceil), pad);
47
46
  if (lower === upper) return [Math.min(lower, 0), upper === 0 ? 1 : upper * pad];
48
47
  return [lower, upper];
@@ -66,6 +65,7 @@ function CartesianChart({
66
65
  tooltip,
67
66
  margin: marginOverride,
68
67
  cursorValue,
68
+ cursorResolution,
69
69
  ariaLabel,
70
70
  isPending,
71
71
  children
@@ -99,6 +99,7 @@ function CartesianChart({
99
99
  ...tooltip !== void 0 && { tooltip },
100
100
  ...marginOverride !== void 0 && { marginOverride },
101
101
  ...cursorValue !== void 0 && { cursorValue },
102
+ ...cursorResolution !== void 0 && { cursorResolution },
102
103
  ...ariaLabel !== void 0 && { ariaLabel },
103
104
  plot,
104
105
  highlighted,
@@ -123,6 +124,7 @@ function CartesianPlot({
123
124
  tooltip,
124
125
  marginOverride,
125
126
  cursorValue,
127
+ cursorResolution,
126
128
  ariaLabel,
127
129
  plot,
128
130
  highlighted,
@@ -209,7 +211,8 @@ function CartesianPlot({
209
211
  chartId,
210
212
  getKey: getX,
211
213
  xScale,
212
- marginLeft: margin.left
214
+ marginLeft: margin.left,
215
+ ...cursorResolution !== void 0 && { resolution: cursorResolution }
213
216
  });
214
217
  const svgRef = useRef(null);
215
218
  const tooltipEnabled = tooltip !== false;
@@ -217,6 +220,7 @@ function CartesianPlot({
217
220
  const point = cursor.point;
218
221
  const cursorX = point === null ? null : xScale(getX(point)) ?? null;
219
222
  const badge = tooltipCfg?.label === void 0 || point === null ? null : tooltipCfg.label(point);
223
+ const formatHeader = tooltipCfg?.formatHeader;
220
224
  const tooltipSeries = useMemo(
221
225
  () => visible.map(
222
226
  (s) => s.formatValue === void 0 ? { ...s, formatValue: s.axis === "right" ? rightFormat : leftFormat } : s
@@ -224,7 +228,10 @@ function CartesianPlot({
224
228
  [visible, leftFormat, rightFormat]
225
229
  );
226
230
  const rows = tooltipEnabled && point !== null ? deriveTooltipRows(tooltipSeries, point, leftFormat) : [];
227
- const anchorX = tooltipCfg?.follow === false && point !== null && cursorX !== null ? cursorX : null;
231
+ const isFollowerRender = !cursor.isSource && tooltipCfg?.onFollow === true;
232
+ const showTooltip = tooltipEnabled && point !== null && (cursor.isSource || isFollowerRender);
233
+ const useAnchoredPosition = tooltipCfg?.follow === false || isFollowerRender;
234
+ const anchorX = useAnchoredPosition && point !== null && cursorX !== null ? cursorX : null;
228
235
  const svgRect = anchorX === null ? void 0 : svgRef.current?.getBoundingClientRect();
229
236
  const tooltipAnchor = svgRect === void 0 || anchorX === null ? cursor.anchor : { x: svgRect.left + margin.left + anchorX, y: svgRect.top + margin.top };
230
237
  const ctx = {
@@ -326,11 +333,14 @@ function CartesianPlot({
326
333
  }
327
334
  )
328
335
  ] }) }),
329
- tooltipEnabled && cursor.isSource && point !== null && /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: tooltipAnchor, children: [
336
+ showTooltip && /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: tooltipAnchor, ariaLive: cursor.isSource, children: [
330
337
  /* @__PURE__ */ jsx(
331
338
  TooltipHeader,
332
339
  {
333
340
  date: getX(point),
341
+ ...formatHeader !== void 0 && {
342
+ format: (key) => formatHeader(key, point)
343
+ },
334
344
  ...badge !== null && { label: badge.text, labelColor: badge.color }
335
345
  }
336
346
  ),
@@ -43,9 +43,16 @@ export type ChartFrameProps = {
43
43
  */
44
44
  isPending?: boolean;
45
45
  /**
46
- * Accessible text alternative for the chart, applied as `aria-label` (+ `role="img"`) on the
46
+ * Accessible text alternative for the chart, applied as `aria-label` (+ `role="group"`) on the
47
47
  * outer container so screen readers announce something other than an unlabeled graphic. Every
48
48
  * kind composing `ChartFrame` should accept and forward this from its own props.
49
+ *
50
+ * MUST stay `role="group"`, never `role="img"`. Per the ARIA spec, every descendant of an
51
+ * `role="img"` element is presentational, which erases the `HoverOverlay`'s `role="slider"` from
52
+ * the accessibility tree entirely — a screen reader announces the label and then the
53
+ * keyboard-scrubbable slider underneath it is simply unreachable, silently, with no error
54
+ * anywhere. `role="group"` announces the same label while keeping descendants exposed. Do not
55
+ * "simplify" this back to `img` — it looks like a no-op refactor and it is not.
49
56
  */
50
57
  ariaLabel?: string;
51
58
  /** Draw the SVG marks given the plot rect that already excludes the legend band, plus the set
@@ -1 +1 @@
1
- {"version":3,"file":"ChartFrame.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartFrame.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAIrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAOhF;0EAC0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,wBAAwB;IACxB,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC1C;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,uGAAuG;IACvG,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;IAC9B,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,gBAAgB,GAAG,KAAK,CAAA;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;oDACgD;IAChD,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,SAAS,CAAA;CACxC,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAC5B,CAAA;AAcD;oFACoF;AACpF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;CAC1C,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,iBAAiB,GAAG,KAAK,GAAG,SAAS,EAC7C,KAAK,CAAC,EAAE,qBAAqB,GAC5B,gBAAgB,GAAG,KAAK,CAS1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,MAAM,EACN,WAAW,EACX,IAAY,EACZ,QAA4B,EAC5B,OAAO,EACP,MAAW,EACX,SAAS,EACT,SAAiB,EACjB,QAAQ,GACT,EAAE,eAAe,GAAG,SAAS,CAsE7B"}
1
+ {"version":3,"file":"ChartFrame.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartFrame.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAIrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAOhF;0EAC0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,wBAAwB;IACxB,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC1C;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,uGAAuG;IACvG,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;IAC9B,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,gBAAgB,GAAG,KAAK,CAAA;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;oDACgD;IAChD,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,SAAS,CAAA;CACxC,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAC5B,CAAA;AAcD;oFACoF;AACpF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;CAC1C,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,iBAAiB,GAAG,KAAK,GAAG,SAAS,EAC7C,KAAK,CAAC,EAAE,qBAAqB,GAC5B,gBAAgB,GAAG,KAAK,CAS1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,MAAM,EACN,WAAW,EACX,IAAY,EACZ,QAA4B,EAC5B,OAAO,EACP,MAAW,EACX,SAAS,EACT,SAAiB,EACjB,QAAQ,GACT,EAAE,eAAe,GAAG,SAAS,CAsE7B"}
@@ -80,7 +80,7 @@ function ChartFrame({
80
80
  {
81
81
  ref: containerRef,
82
82
  style: outerStyle(fill, vertical),
83
- ...ariaLabel !== void 0 && { role: "img", "aria-label": ariaLabel },
83
+ ...ariaLabel !== void 0 && { role: "group", "aria-label": ariaLabel },
84
84
  ...isPending && { "aria-busy": "true" },
85
85
  children: [
86
86
  legendNode !== null && (placement === "top" || placement === "left") && legendNode,
@@ -1,9 +1,14 @@
1
1
  import type { ReactNode } from 'react';
2
2
  /** Tooltip header — shows formatted date + optional right-aligned label with color. */
3
- export declare function TooltipHeader({ date, label, labelColor, }: {
3
+ export declare function TooltipHeader({ date, label, labelColor, format, }: {
4
4
  date: string;
5
5
  label?: string;
6
6
  labelColor?: string;
7
+ /** Overrides `fmtTooltipDate` for the header text. Default: today's `fmtTooltipDate` behavior,
8
+ * unchanged. The seam exists because `fmtTooltipDate` regexes `YYYY-MM-DD` out of the key and
9
+ * builds a LOCAL `Date`, so a UTC ISO domain key names the wrong day next to `formatX`/the
10
+ * tooltip badge, which both resolve locally — a caller with a UTC key needs to supply its own. */
11
+ format?: (date: string) => string;
7
12
  }): import("react").JSX.Element;
8
13
  /** Tooltip row — swatch + label + value. */
9
14
  export declare function TooltipRow({ color, label, value, valueColor, shape, strokeWidth, dashed, }: {
@@ -27,11 +32,16 @@ export declare function TooltipBody({ children }: {
27
32
  * The box is measured after mount via `useLayoutEffect`, so the first paint of a given tooltip is
28
33
  * hidden rather than misplaced — a tooltip that flashes at the wrong corner reads as a bug.
29
34
  */
30
- export declare function ChartTooltipFloat({ anchor, children, }: {
35
+ export declare function ChartTooltipFloat({ anchor, ariaLive, children, }: {
31
36
  anchor: {
32
37
  x: number;
33
38
  y: number;
34
39
  } | null;
40
+ /** Whether this tooltip announces itself to screen readers on every position change. Default
41
+ * true. Pass false for a cursor FOLLOWER's tooltip — N followers on a shared-cursor page all
42
+ * announcing on every pointer move would make the page unusable with a screen reader; only the
43
+ * cursor SOURCE should be `aria-live`. */
44
+ ariaLive?: boolean;
35
45
  children: ReactNode;
36
46
  }): import("react").ReactPortal | null;
37
47
  //# sourceMappingURL=ChartTooltip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChartTooltip.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAuBrD,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,UAAU,GACX,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,+BAoCA;AAED,4CAA4C;AAC5C,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,WAAW,EACX,MAAM,GACP,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,+BA0CA;AAED,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAEhE;AAOD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACvC,QAAQ,EAAE,SAAS,CAAA;CACpB,sCA4CA"}
1
+ {"version":3,"file":"ChartTooltip.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAuBrD,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,UAAU,EACV,MAAuB,GACxB,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;sGAGkG;IAClG,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAClC,+BAoCA;AAED,4CAA4C;AAC5C,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,WAAW,EACX,MAAM,GACP,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,+BA0CA;AAED,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAEhE;AAOD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,QAAe,EACf,QAAQ,GACT,EAAE;IACD,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACvC;;;8CAG0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB,sCA4CA"}
@@ -19,7 +19,8 @@ const TOOLTIP_STYLES = {
19
19
  function TooltipHeader({
20
20
  date,
21
21
  label,
22
- labelColor
22
+ labelColor,
23
+ format = fmtTooltipDate
23
24
  }) {
24
25
  return /* @__PURE__ */ jsxs(
25
26
  "div",
@@ -42,7 +43,7 @@ function TooltipHeader({
42
43
  fontFamily: "var(--basalt-font-mono)",
43
44
  color: VX.ink
44
45
  },
45
- children: fmtTooltipDate(date)
46
+ children: format(date)
46
47
  }
47
48
  ),
48
49
  label !== void 0 && /* @__PURE__ */ jsx(
@@ -120,6 +121,7 @@ const TOOLTIP_GAP = 12;
120
121
  const VIEWPORT_MARGIN = 8;
121
122
  function ChartTooltipFloat({
122
123
  anchor,
124
+ ariaLive = true,
123
125
  children
124
126
  }) {
125
127
  const ref = useRef(null);
@@ -150,7 +152,7 @@ function ChartTooltipFloat({
150
152
  {
151
153
  ref,
152
154
  role: "tooltip",
153
- "aria-live": "polite",
155
+ ...ariaLive && { "aria-live": "polite" },
154
156
  style: { ...TOOLTIP_STYLES, left, top, visibility: box === null ? "hidden" : "visible" },
155
157
  children
156
158
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ChartTooltip.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartTooltip.test.d.ts","sourceRoot":"","sources":["../../../src/charts/primitives/ChartTooltip.test.tsx"],"names":[],"mappings":""}
@@ -58,6 +58,11 @@ export type SeriesStyle = {
58
58
  * that lies is the thing the derived-legend rule exists to prevent). The TOOLTIP ROW swatch and
59
59
  * the CROSSHAIR DOT deliberately do NOT honor it: those are 12px value-readout chips where a
60
60
  * sub-1 opacity reads as a rendering bug, not as data.
61
+ *
62
+ * Applies to STROKES only, so it silently no-ops on a `mark: 'bar'`/`'area'` series — a bar
63
+ * swatch has no stroke to dim. Dim those with `fillOpacity` instead. This bites the
64
+ * zone/reference-legend idiom in particular (`mark: 'bar'`, `getValue: () => null`), where
65
+ * reaching for `strokeOpacity` looks right and does nothing.
61
66
  */
62
67
  strokeOpacity?: number;
63
68
  /** Which y-axis this series is measured against. Default 'left'. `'right'` is what makes a
@@ -87,10 +92,13 @@ export type ChartSeries<T> = SeriesStyle & {
87
92
  * alongside the value so a row can read fields beyond the plotted number (e.g. `97.5 kg (92.5 ×
88
93
  * 3)`). */
89
94
  formatValue?: (v: number, d: T) => string;
90
- /** PR star / status dot. Return null for no marker at that point. */
95
+ /** PR star / status dot. Return null for no marker at that point. `ring` defaults true (today's
96
+ * punched-out stroke, unchanged); `false` omits the stroke entirely. `fillOpacity` defaults 1. */
91
97
  getMarker?: (d: T) => {
92
98
  color?: string;
93
99
  r?: number;
100
+ fillOpacity?: number;
101
+ ring?: boolean;
94
102
  } | null;
95
103
  };
96
104
  /** A single derived tooltip row, ready for `TooltipRow`. */
@@ -1 +1 @@
1
- {"version":3,"file":"series.d.ts","sourceRoot":"","sources":["../../src/charts/series.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"series.d.ts","sourceRoot":"","sources":["../../src/charts/series.ts"],"names":[],"mappings":"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"}
@@ -17,4 +17,19 @@
17
17
  * pre-existing, still-correct behavior for genuinely negative-swinging metrics.
18
18
  */
19
19
  export declare function padAutoLower(candidate: number, pad: number): number;
20
+ /**
21
+ * Auto y-domain upper-bound padding — the exact mirror of {@link padAutoLower}, sharing its
22
+ * sign-safety: pad AWAY from zero (`upper >= candidate`), never toward it. `candidate` is the
23
+ * caller's `Math.max(dataMax, floor)` — the `autoMaxFloor` clamp has already been applied, so
24
+ * padding runs AFTER the floor, not before it. Applying the floor post-pad (the pre-existing bug)
25
+ * lands a floored axis top exactly on the floor value with zero headroom — a target line pinned to
26
+ * that floor then sits glued to the plot edge instead of getting the same breathing room every
27
+ * other bound gets.
28
+ *
29
+ * - `candidate === 0` stays exactly 0 — never pushed positive.
30
+ * - `candidate > 0` multiplies by `pad`, moving the ceiling further UP (away from zero).
31
+ * - `candidate < 0` divides by `pad`, moving the ceiling UP toward (and past) zero — the mirror of
32
+ * `padAutoLower`'s `candidate > 0` branch.
33
+ */
34
+ export declare function padAutoUpper(candidate: number, pad: number): number;
20
35
  //# sourceMappingURL=domain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/charts/utils/domain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnE"}
1
+ {"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/charts/utils/domain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnE"}
@@ -2,6 +2,11 @@ function padAutoLower(candidate, pad) {
2
2
  if (candidate === 0) return 0;
3
3
  return candidate > 0 ? candidate / pad : candidate * pad;
4
4
  }
5
+ function padAutoUpper(candidate, pad) {
6
+ if (candidate === 0) return 0;
7
+ return candidate > 0 ? candidate * pad : candidate / pad;
8
+ }
5
9
  export {
6
- padAutoLower
10
+ padAutoLower,
11
+ padAutoUpper
7
12
  };
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # basalt-ui v1.16.0
1
+ # basalt-ui v1.18.0
2
2
  # Opinionated framework for Mantine-based React apps — theme, app shell, visx charts, toolchain presets
3
3
  #
4
4
  # basalt-ui is an opinionated framework for Mantine-based React apps.
@@ -19,7 +19,7 @@
19
19
  # ./tokens.css subpath. Guide: docs/FRAMEWORK-FREE.md in the repo.
20
20
 
21
21
  Package: basalt-ui
22
- Version: 1.16.0
22
+ Version: 1.18.0
23
23
 
24
24
  ## basalt-ui
25
25
  Import: import { ... } from 'basalt-ui'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "basalt-ui",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "Opinionated framework for Mantine-based React apps — theme, app shell, visx charts, toolchain presets",
5
5
  "keywords": [
6
6
  "charts",