@epilot/spark-ui 1.0.0-alpha.3 → 1.0.0-alpha.4

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 (92) hide show
  1. package/dist/components/attachment.d.cts +1 -1
  2. package/dist/components/attachment.d.ts +1 -1
  3. package/dist/components/bar-chart.cjs +48 -47
  4. package/dist/components/bar-chart.cjs.map +1 -1
  5. package/dist/components/bar-chart.d.cts +7 -2
  6. package/dist/components/bar-chart.d.ts +7 -2
  7. package/dist/components/bar-chart.js +48 -47
  8. package/dist/components/bar-chart.js.map +1 -1
  9. package/dist/components/bubble.d.cts +1 -1
  10. package/dist/components/bubble.d.ts +1 -1
  11. package/dist/components/button.cjs +1 -1
  12. package/dist/components/button.cjs.map +1 -1
  13. package/dist/components/button.d.cts +8 -0
  14. package/dist/components/button.d.ts +8 -0
  15. package/dist/components/button.js +1 -1
  16. package/dist/components/button.js.map +1 -1
  17. package/dist/components/callout.d.cts +1 -1
  18. package/dist/components/callout.d.ts +1 -1
  19. package/dist/components/energy-bar-chart.cjs +2 -1
  20. package/dist/components/energy-bar-chart.cjs.map +1 -1
  21. package/dist/components/energy-bar-chart.js +2 -1
  22. package/dist/components/energy-bar-chart.js.map +1 -1
  23. package/dist/components/energy-history-chart.cjs +14 -6
  24. package/dist/components/energy-history-chart.cjs.map +1 -1
  25. package/dist/components/energy-history-chart.d.cts +11 -3
  26. package/dist/components/energy-history-chart.d.ts +11 -3
  27. package/dist/components/energy-history-chart.js +14 -6
  28. package/dist/components/energy-history-chart.js.map +1 -1
  29. package/dist/components/field.cjs +1 -1
  30. package/dist/components/field.js +1 -1
  31. package/dist/components/input-group.cjs +1 -1
  32. package/dist/components/input-group.js +1 -1
  33. package/dist/components/line-chart.cjs +55 -15
  34. package/dist/components/line-chart.cjs.map +1 -1
  35. package/dist/components/line-chart.d.cts +7 -0
  36. package/dist/components/line-chart.d.ts +7 -0
  37. package/dist/components/line-chart.js +55 -15
  38. package/dist/components/line-chart.js.map +1 -1
  39. package/dist/components/power-history-chart.cjs +14 -37
  40. package/dist/components/power-history-chart.cjs.map +1 -1
  41. package/dist/components/power-history-chart.d.cts +10 -1
  42. package/dist/components/power-history-chart.d.ts +10 -1
  43. package/dist/components/power-history-chart.js +15 -38
  44. package/dist/components/power-history-chart.js.map +1 -1
  45. package/dist/components/sankey-chart.cjs +8 -41
  46. package/dist/components/sankey-chart.cjs.map +1 -1
  47. package/dist/components/sankey-chart.d.cts +8 -0
  48. package/dist/components/sankey-chart.d.ts +8 -0
  49. package/dist/components/sankey-chart.js +8 -41
  50. package/dist/components/sankey-chart.js.map +1 -1
  51. package/dist/components/segmented-control.cjs +44 -0
  52. package/dist/components/segmented-control.cjs.map +1 -0
  53. package/dist/components/segmented-control.d.cts +33 -0
  54. package/dist/components/segmented-control.d.ts +33 -0
  55. package/dist/components/segmented-control.js +40 -0
  56. package/dist/components/segmented-control.js.map +1 -0
  57. package/dist/components/separator.cjs +1 -1
  58. package/dist/components/separator.cjs.map +1 -1
  59. package/dist/components/separator.js +1 -1
  60. package/dist/components/separator.js.map +1 -1
  61. package/dist/components/solar-forecast-chart.cjs +4 -3
  62. package/dist/components/solar-forecast-chart.cjs.map +1 -1
  63. package/dist/components/solar-forecast-chart.d.cts +4 -1
  64. package/dist/components/solar-forecast-chart.d.ts +4 -1
  65. package/dist/components/solar-forecast-chart.js +4 -3
  66. package/dist/components/solar-forecast-chart.js.map +1 -1
  67. package/dist/components/theme.cjs +1 -1
  68. package/dist/components/theme.js +1 -1
  69. package/dist/components/tooltip.cjs +1 -1
  70. package/dist/components/tooltip.cjs.map +1 -1
  71. package/dist/components/tooltip.js +1 -1
  72. package/dist/components/tooltip.js.map +1 -1
  73. package/dist/styles/index.css +37 -0
  74. package/dist/styles/spark-default.css +45 -40
  75. package/dist/styles/theme.css +78 -0
  76. package/dist/{theme-B3WtiByA.js → theme-C19BbKfO.js} +2 -2
  77. package/dist/theme-C19BbKfO.js.map +1 -0
  78. package/dist/{theme-C9_OSe0S.cjs → theme-CfFWrMEF.cjs} +2 -2
  79. package/dist/theme-CfFWrMEF.cjs.map +1 -0
  80. package/dist/utils/build-sankey-nodes.cjs +16 -3
  81. package/dist/utils/build-sankey-nodes.cjs.map +1 -1
  82. package/dist/utils/build-sankey-nodes.js +16 -3
  83. package/dist/utils/build-sankey-nodes.js.map +1 -1
  84. package/dist/utils/chart-scale.cjs +43 -0
  85. package/dist/utils/chart-scale.cjs.map +1 -0
  86. package/dist/utils/chart-scale.d.cts +22 -0
  87. package/dist/utils/chart-scale.d.ts +22 -0
  88. package/dist/utils/chart-scale.js +41 -0
  89. package/dist/utils/chart-scale.js.map +1 -0
  90. package/package.json +1 -1
  91. package/dist/theme-B3WtiByA.js.map +0 -1
  92. package/dist/theme-C9_OSe0S.cjs.map +0 -1
@@ -22,7 +22,7 @@ declare function Attachment({
22
22
  state?: 'idle' | 'uploading' | 'processing' | 'error' | 'done';
23
23
  }): _$react_jsx_runtime0.JSX.Element;
24
24
  declare const attachmentMediaVariants: (props?: ({
25
- variant?: "image" | "icon" | null | undefined;
25
+ variant?: "icon" | "image" | null | undefined;
26
26
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
27
27
  declare function AttachmentMedia({
28
28
  className,
@@ -22,7 +22,7 @@ declare function Attachment({
22
22
  state?: 'idle' | 'uploading' | 'processing' | 'error' | 'done';
23
23
  }): _$react_jsx_runtime0.JSX.Element;
24
24
  declare const attachmentMediaVariants: (props?: ({
25
- variant?: "image" | "icon" | null | undefined;
25
+ variant?: "icon" | "image" | null | undefined;
26
26
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
27
27
  declare function AttachmentMedia({
28
28
  className,
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("../chunk-aJGBMT86.cjs");
4
4
  const require_utils_format = require("../utils/format.cjs");
5
+ const require_utils_chart_scale = require("../utils/chart-scale.cjs");
5
6
  const require_components_chart = require("./chart.cjs");
6
7
  const require_components_series_legend = require("./series-legend.cjs");
7
8
  const require_components_typography = require("./typography.cjs");
@@ -21,25 +22,6 @@ const FOCUS_TRANSITION_MS = 180;
21
22
  const DEFAULT_HEIGHT = 220;
22
23
  const BAR_RADIUS = 2;
23
24
  const Y_AXIS_GUTTER = 34;
24
- function buildYAxisTicks(yMax) {
25
- const rawStep = yMax / 4;
26
- const normalized = rawStep === 0 ? 1 : rawStep;
27
- const magnitude = Math.pow(10, Math.floor(Math.log10(normalized)));
28
- const step = ([
29
- 1,
30
- 2,
31
- 2.5,
32
- 5,
33
- 10
34
- ].find((value) => value * magnitude >= normalized) ?? 10) * magnitude;
35
- const upper = Math.ceil(yMax / step) * step;
36
- const ticks = [];
37
- for (let value = 0; value <= upper + step * .001; value += step) ticks.push(Number(value.toFixed(6)));
38
- return ticks;
39
- }
40
- function formatYAxisTick(value) {
41
- return value >= 10 ? require_utils_format.integerFormat.format(value) : require_utils_format.oneDecimalFormat.format(value);
42
- }
43
25
  function buildBarPath(x, y, width, height, radius, roundTop, roundBottom) {
44
26
  const r = Math.max(0, Math.min(radius, width / 2, height / 2));
45
27
  if (r === 0 || !roundTop && !roundBottom) return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`;
@@ -69,15 +51,21 @@ function BarStackLayer({ stackData, series, seriesByKey, xScale, yScale, colorSc
69
51
  xScale,
70
52
  yScale,
71
53
  color: colorScale,
54
+ offset: "diverging",
72
55
  children: (barStacks) => barStacks.map((barStack) => barStack.bars.map((bar) => {
73
- if ((bar.bar.data.__values[barStack.key] ?? 0) === 0) return null;
56
+ const values = bar.bar.data.__values;
57
+ const segmentValue = values[barStack.key] ?? 0;
58
+ if (segmentValue === 0) return null;
74
59
  const strokeColor = seriesByKey.get(barStack.key)?.color ?? bar.color;
75
60
  const fillColor = strokeColor;
76
- const valueKeys = series.map((entry) => entry.key).filter((key) => (bar.bar.data.__values[key] ?? 0) > 0);
77
- const isBottomSegment = valueKeys[0] === barStack.key;
78
- const isTopSegment = valueKeys[valueKeys.length - 1] === barStack.key;
61
+ const positiveKeys = series.map((entry) => entry.key).filter((key) => (values[key] ?? 0) > 0);
62
+ const negativeKeys = series.map((entry) => entry.key).filter((key) => (values[key] ?? 0) < 0);
63
+ const roundTop = segmentValue > 0 && positiveKeys[positiveKeys.length - 1] === barStack.key;
64
+ const roundBottom = segmentValue > 0 ? positiveKeys[0] === barStack.key : negativeKeys[negativeKeys.length - 1] === barStack.key;
65
+ const top = bar.height < 0 ? bar.y + bar.height : bar.y;
66
+ const barHeight = Math.abs(bar.height);
79
67
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
80
- d: buildBarPath(bar.x, bar.y, bar.width, Math.max(0, bar.height), BAR_RADIUS, isTopSegment, isBottomSegment),
68
+ d: buildBarPath(bar.x, top, bar.width, Math.max(0, barHeight), BAR_RADIUS, roundTop, roundBottom),
81
69
  fill: fillColor,
82
70
  stroke: strokeColor,
83
71
  strokeWidth: 1,
@@ -90,9 +78,9 @@ function FocusBorder({ category, visible, stackData, series, xScale, yScale }) {
90
78
  const x = xScale(category);
91
79
  const datum = stackData.find((entry) => entry.__category === category);
92
80
  if (x === void 0 || !datum) return null;
93
- if (!series.some((entry) => (datum.__values[entry.key] ?? 0) > 0)) return null;
81
+ if (!series.some((entry) => (datum.__values[entry.key] ?? 0) !== 0)) return null;
94
82
  const topY = PADDING_TOP;
95
- const baselineY = yScale(0);
83
+ const bottomY = yScale(series.reduce((sum, entry) => sum + Math.min(0, datum.__values[entry.key] ?? 0), 0));
96
84
  const borderPaddingX = 4;
97
85
  const borderPaddingY = 3;
98
86
  const borderXRaw = x - borderPaddingX;
@@ -104,7 +92,7 @@ function FocusBorder({ category, visible, stackData, series, xScale, yScale }) {
104
92
  const borderX = Math.max(minX, borderXRaw);
105
93
  const borderRight = Math.min(maxX, borderXRaw + borderWidthRaw);
106
94
  const borderWidth = Math.max(0, borderRight - borderX);
107
- const borderHeight = Math.max(1, baselineY - topY + borderPaddingY * 2);
95
+ const borderHeight = Math.max(1, bottomY - topY + borderPaddingY * 2);
108
96
  if (borderWidth <= 0) return null;
109
97
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
110
98
  x: borderX,
@@ -218,11 +206,12 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
218
206
  series,
219
207
  hiddenSeries
220
208
  ]);
221
- const yMax = (0, react.useMemo)(() => Math.max(1, referenceLine?.value ?? 0, ...stackData.map((record) => series.reduce((sum, entry) => sum + (record.__values[entry.key] ?? 0), 0))), [
209
+ const yMax = (0, react.useMemo)(() => Math.max(1, referenceLine?.value ?? 0, ...stackData.map((record) => series.reduce((sum, entry) => sum + Math.max(0, record.__values[entry.key] ?? 0), 0))), [
222
210
  referenceLine,
223
211
  series,
224
212
  stackData
225
213
  ]);
214
+ const yMin = (0, react.useMemo)(() => Math.min(0, ...stackData.map((record) => series.reduce((sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0), 0))), [series, stackData]);
226
215
  const xDomain = (0, react.useMemo)(() => categories ?? stackData.map((record) => record.__category), [categories, stackData]);
227
216
  const xScale = (0, react.useMemo)(() => (0, _visx_scale.scaleBand)({
228
217
  domain: xDomain,
@@ -230,9 +219,13 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
230
219
  padding: .32
231
220
  }), [xDomain, width]);
232
221
  const yScale = (0, react.useMemo)(() => (0, _visx_scale.scaleLinear)({
233
- domain: [0, yMax],
222
+ domain: [yMin, yMax],
234
223
  range: [height - PADDING_BOTTOM, PADDING_TOP]
235
- }), [height, yMax]);
224
+ }), [
225
+ height,
226
+ yMax,
227
+ yMin
228
+ ]);
236
229
  const colorScale = (0, react.useMemo)(() => (0, _visx_scale.scaleOrdinal)({
237
230
  domain: series.map((entry) => entry.key),
238
231
  range: series.map((entry) => entry.color)
@@ -283,8 +276,8 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
283
276
  const focusCategory = lastFocusCategoryRef.current;
284
277
  const focused = (0, react.useMemo)(() => hoveredCategory === null ? null : stackData.find((record) => record.__category === hoveredCategory) ?? null, [hoveredCategory, stackData]);
285
278
  const totalValue = (0, react.useMemo)(() => {
286
- if (focused) return series.reduce((sum, entry) => sum + (focused.__values[entry.key] ?? 0), 0);
287
- return stackData.reduce((sum, record) => sum + series.reduce((s, entry) => s + (record.__values[entry.key] ?? 0), 0), 0);
279
+ if (focused) return series.reduce((sum, entry) => sum + Math.max(0, focused.__values[entry.key] ?? 0), 0);
280
+ return stackData.reduce((sum, record) => sum + series.reduce((s, entry) => s + Math.max(0, record.__values[entry.key] ?? 0), 0), 0);
288
281
  }, [
289
282
  focused,
290
283
  series,
@@ -304,7 +297,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
304
297
  };
305
298
  }, [hoverLabel]);
306
299
  const ticks = categoryTicks ?? xDomain;
307
- const yTicks = (0, react.useMemo)(() => buildYAxisTicks(yMax), [yMax]);
300
+ const yTicks = (0, react.useMemo)(() => require_utils_chart_scale.buildYAxisScale(yMin, yMax).ticks, [yMin, yMax]);
308
301
  const highlightX = (0, react.useMemo)(() => {
309
302
  if (!showHighlightLine || highlightedCategory === void 0) return null;
310
303
  const x = xScale(highlightedCategory);
@@ -320,12 +313,27 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
320
313
  data,
321
314
  getCategory
322
315
  ]);
316
+ const barStackLayer = (0, react.useMemo)(() => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BarStackLayer, {
317
+ stackData,
318
+ series,
319
+ seriesByKey,
320
+ xScale,
321
+ yScale,
322
+ colorScale
323
+ }), [
324
+ stackData,
325
+ series,
326
+ seriesByKey,
327
+ xScale,
328
+ yScale,
329
+ colorScale
330
+ ]);
323
331
  const fmtTooltipValue = formatValue ?? formatTotal;
324
- const tooltipRows = focused ? [...series.filter((entry) => (focused.__values[entry.key] ?? 0) > 0).map((entry) => ({
332
+ const tooltipRows = focused ? [...series.filter((entry) => (focused.__values[entry.key] ?? 0) !== 0).map((entry) => ({
325
333
  key: entry.key,
326
334
  label: entry.label,
327
335
  color: entry.color,
328
- value: fmtTooltipValue(focused.__values[entry.key] ?? 0)
336
+ value: fmtTooltipValue(Math.abs(focused.__values[entry.key] ?? 0))
329
337
  })), ...(lines ?? []).filter((line) => !hiddenSeries.has(line.key)).flatMap((line) => {
330
338
  const value = focusedDatum === null ? null : line.getValue(focusedDatum);
331
339
  if (value === null || !Number.isFinite(value)) return [];
@@ -355,7 +363,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
355
363
  className: "flex items-baseline justify-between",
356
364
  children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_typography.SectionTitle, { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
357
365
  className: "tabular-nums",
358
- children: renderTotal ? renderTotal(totalValue) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
366
+ children: renderTotal ? renderTotal(totalValue, focused === null) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
359
367
  className: "text-base font-bold text-gray tabular-nums",
360
368
  children: formatTotal(totalValue)
361
369
  })
@@ -407,7 +415,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
407
415
  x1: Y_AXIS_GUTTER,
408
416
  x2: Y_AXIS_GUTTER,
409
417
  y1: PADDING_TOP,
410
- y2: yScale(0),
418
+ y2: height - PADDING_BOTTOM,
411
419
  stroke: "var(--gray-a6)",
412
420
  strokeWidth: 1
413
421
  }),
@@ -427,7 +435,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
427
435
  textAnchor: "end",
428
436
  fill: "var(--gray-a11)",
429
437
  fontSize: 10,
430
- children: formatYAxisTick(tick)
438
+ children: require_utils_chart_scale.formatYAxisTick(tick)
431
439
  })] }, `y-tick-${tick}`);
432
440
  }),
433
441
  yAxisUnit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
@@ -443,7 +451,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
443
451
  x1: highlightX,
444
452
  x2: highlightX,
445
453
  y1: PADDING_TOP,
446
- y2: yScale(0),
454
+ y2: height - PADDING_BOTTOM,
447
455
  stroke: "var(--spark-a9)",
448
456
  strokeWidth: 1.5,
449
457
  strokeDasharray: "5 4",
@@ -466,14 +474,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
466
474
  xScale,
467
475
  yScale
468
476
  }),
469
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BarStackLayer, {
470
- stackData,
471
- series,
472
- seriesByKey,
473
- xScale,
474
- yScale,
475
- colorScale
476
- }),
477
+ barStackLayer,
477
478
  referenceLine && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
478
479
  x1: Y_AXIS_GUTTER,
479
480
  x2: width,
@@ -1 +1 @@
1
- {"version":3,"file":"bar-chart.cjs","names":["localeNumberFormat","integerFormat","oneDecimalFormat","BarStack","useMeasuredSize","clampTooltipPosition","SectionTitle","SeriesLegend","ChartTooltipCard","Group"],"sources":["../../src/components/bar-chart.tsx"],"sourcesContent":["import { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale'\nimport { BarStack } from '@visx/shape'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { cn } from '../utils/cn'\nimport {\n integerFormat,\n localeNumberFormat,\n oneDecimalFormat,\n} from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend } from './series-legend'\nimport { SectionTitle } from './typography'\n\nconst defaultTotalFormat = localeNumberFormat()\n\nexport type BarChartCategory = string | number\n\nexport interface BarChartSeries<TDatum> {\n key: string\n label: string\n color: string\n hoverFill?: string\n getValue: (datum: TDatum) => number\n}\n\nexport interface BarChartLineSeries<TDatum> {\n key: string\n label: string\n color: string\n /** `null` gaps break the line (e.g. hours without a reading). */\n getValue: (datum: TDatum) => number | null\n /** Own y-domain for this line (e.g. `[0, 100]` for a percentage). Defaults to the bar scale. */\n domain?: [number, number]\n /** Start hidden; the user can enable the line from the legend. */\n hiddenByDefault?: boolean\n /** Formats this line's value in the hover tooltip. Defaults to `formatValue`. */\n formatValue?: (value: number) => string\n strokeDasharray?: string\n}\n\nexport interface BarChartProps<TDatum> {\n data: TDatum[]\n series: BarChartSeries<TDatum>[]\n /** Line overlays drawn on top of the bars, toggleable from the legend. */\n lines?: BarChartLineSeries<TDatum>[]\n getCategory: (datum: TDatum) => BarChartCategory\n /** Full ordered set of categories on the x-axis. Defaults to `data.map(getCategory)`. */\n categories?: BarChartCategory[]\n /** Subset of categories that should render an x-axis label. Defaults to every category. */\n categoryTicks?: BarChartCategory[]\n formatCategory?: (category: BarChartCategory) => string\n /** Formats the hovered category in the tooltip header. Defaults to `formatCategory`. */\n formatTooltipCategory?: (category: BarChartCategory) => string\n highlightedCategory?: BarChartCategory\n showHighlightLine?: boolean\n /**\n * Horizontal reference line drawn across the plot at a given y-value.\n * Useful for thresholds (e.g. price ceiling).\n */\n referenceLine?: { value: number; label?: string; color?: string }\n title?: string\n yAxisUnit?: string\n height?: number\n /** Override how the total value (sum of focused or all categories) is rendered. */\n renderTotal?: (value: number) => React.ReactNode\n /** Format function used when `renderTotal` is not provided. */\n formatTotal?: (value: number) => string\n /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */\n formatValue?: (value: number) => string\n className?: string\n}\n\ninterface StackDatum {\n __category: BarChartCategory\n __values: Record<string, number>\n}\n\ninterface BarStackLayerProps<TDatum> {\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n seriesByKey: Map<string, BarChartSeries<TDatum>>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n colorScale: ReturnType<typeof scaleOrdinal<string, string>>\n}\n\ninterface CategoryTicksProps {\n ticks: BarChartCategory[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n formatCategory: (category: BarChartCategory) => string\n}\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst HOVER_FADE_MS = 200\nconst FOCUS_TRANSITION_MS = 180\nconst DEFAULT_HEIGHT = 220\nconst BAR_RADIUS = 2\nconst Y_AXIS_GUTTER = 34\n\nfunction buildYAxisTicks(yMax: number) {\n const steps = 4\n const rawStep = yMax / steps\n const normalized = rawStep === 0 ? 1 : rawStep\n const magnitude = Math.pow(10, Math.floor(Math.log10(normalized)))\n const niceSteps = [1, 2, 2.5, 5, 10]\n const step =\n (niceSteps.find((value) => value * magnitude >= normalized) ?? 10) *\n magnitude\n const upper = Math.ceil(yMax / step) * step\n const ticks: number[] = []\n\n for (let value = 0; value <= upper + step * 0.001; value += step) {\n ticks.push(Number(value.toFixed(6)))\n }\n\n return ticks\n}\n\nfunction formatYAxisTick(value: number) {\n return value >= 10\n ? integerFormat.format(value)\n : oneDecimalFormat.format(value)\n}\n\nfunction buildBarPath(\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number,\n roundTop: boolean,\n roundBottom: boolean,\n) {\n const r = Math.max(0, Math.min(radius, width / 2, height / 2))\n\n if (r === 0 || (!roundTop && !roundBottom)) {\n return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`\n }\n\n const tl = roundTop ? r : 0\n const tr = roundTop ? r : 0\n const br = roundBottom ? r : 0\n const bl = roundBottom ? r : 0\n\n return [\n `M ${x + tl} ${y}`,\n `H ${x + width - tr}`,\n tr > 0\n ? `Q ${x + width} ${y} ${x + width} ${y + tr}`\n : `L ${x + width} ${y}`,\n `V ${y + height - br}`,\n br > 0\n ? `Q ${x + width} ${y + height} ${x + width - br} ${y + height}`\n : `L ${x + width} ${y + height}`,\n `H ${x + bl}`,\n bl > 0\n ? `Q ${x} ${y + height} ${x} ${y + height - bl}`\n : `L ${x} ${y + height}`,\n `V ${y + tl}`,\n tl > 0 ? `Q ${x} ${y} ${x + tl} ${y}` : `L ${x} ${y}`,\n 'Z',\n ].join(' ')\n}\n\nfunction BarStackLayer<TDatum>({\n stackData,\n series,\n seriesByKey,\n xScale,\n yScale,\n colorScale,\n}: BarStackLayerProps<TDatum>) {\n return (\n <BarStack<StackDatum, string>\n data={stackData}\n keys={series.map((entry) => entry.key)}\n x={(record) => record.__category}\n value={(record, key) => record.__values[key] ?? 0}\n xScale={xScale}\n yScale={yScale}\n color={colorScale}\n >\n {(barStacks) =>\n barStacks.map((barStack) =>\n barStack.bars.map((bar) => {\n const segmentValue = bar.bar.data.__values[barStack.key] ?? 0\n\n if (segmentValue === 0) {\n return null\n }\n\n const seriesEntry = seriesByKey.get(barStack.key)\n const strokeColor = seriesEntry?.color ?? bar.color\n const fillColor = strokeColor\n const valueKeys = series\n .map((entry) => entry.key)\n .filter((key) => (bar.bar.data.__values[key] ?? 0) > 0)\n const isBottomSegment = valueKeys[0] === barStack.key\n const isTopSegment =\n valueKeys[valueKeys.length - 1] === barStack.key\n\n return (\n <path\n key={`bar-${barStack.index}-${bar.index}`}\n d={buildBarPath(\n bar.x,\n bar.y,\n bar.width,\n Math.max(0, bar.height),\n BAR_RADIUS,\n isTopSegment,\n isBottomSegment,\n )}\n fill={fillColor}\n stroke={strokeColor}\n strokeWidth={1}\n style={{ transition: 'fill 180ms ease' }}\n />\n )\n }),\n )\n }\n </BarStack>\n )\n}\n\ninterface FocusBorderProps<TDatum> {\n category: BarChartCategory\n visible: boolean\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n}\n\nfunction FocusBorder<TDatum>({\n category,\n visible,\n stackData,\n series,\n xScale,\n yScale,\n}: FocusBorderProps<TDatum>) {\n const x = xScale(category)\n const datum = stackData.find((entry) => entry.__category === category)\n\n if (x === undefined || !datum) {\n return null\n }\n\n const hasAnyValue = series.some(\n (entry) => (datum.__values[entry.key] ?? 0) > 0,\n )\n\n if (!hasAnyValue) {\n return null\n }\n\n const topY = PADDING_TOP\n const baselineY = yScale(0)\n const borderPaddingX = 4\n const borderPaddingY = 3\n const borderXRaw = x - borderPaddingX\n const borderY = topY - borderPaddingY\n const borderWidthRaw = xScale.bandwidth() + borderPaddingX * 2\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n const borderX = Math.max(minX, borderXRaw)\n const borderRight = Math.min(maxX, borderXRaw + borderWidthRaw)\n const borderWidth = Math.max(0, borderRight - borderX)\n const borderHeight = Math.max(1, baselineY - topY + borderPaddingY * 2)\n\n if (borderWidth <= 0) {\n return null\n }\n\n return (\n <rect\n x={borderX}\n y={borderY}\n width={borderWidth}\n height={borderHeight}\n rx={6}\n fill=\"var(--spark-a2)\"\n stroke=\"var(--spark-a9)\"\n strokeWidth={2}\n pointerEvents=\"none\"\n style={{\n opacity: visible ? 1 : 0,\n transition: `x ${FOCUS_TRANSITION_MS}ms ease, y ${FOCUS_TRANSITION_MS}ms ease, width ${FOCUS_TRANSITION_MS}ms ease, height ${FOCUS_TRANSITION_MS}ms ease, opacity ${FOCUS_TRANSITION_MS}ms ease`,\n }}\n />\n )\n}\n\ninterface InteractionLayerProps {\n xDomain: BarChartCategory[]\n activeCategories: Set<BarChartCategory>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n onHoverChange: (category: BarChartCategory | null) => void\n}\n\nfunction InteractionLayer({\n xDomain,\n activeCategories,\n xScale,\n height,\n onHoverChange,\n}: InteractionLayerProps) {\n const bandwidth = xScale.bandwidth()\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n\n // A single overlay that maps the pointer to the nearest category with data,\n // so there are no dead zones between/around bars to break the hover.\n const handleMove = (\n event: React.MouseEvent<SVGRectElement> | React.TouchEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point) return\n\n let nearest: BarChartCategory | null = null\n let best = Infinity\n for (const category of xDomain) {\n if (!activeCategories.has(category)) continue\n const x = xScale(category)\n if (x === undefined) continue\n const distance = Math.abs(x + bandwidth / 2 - point.x)\n if (distance < best) {\n best = distance\n nearest = category\n }\n }\n\n if (nearest !== null) onHoverChange(nearest)\n }\n\n return (\n <rect\n x={minX}\n y={PADDING_TOP}\n width={Math.max(0, maxX - minX)}\n height={height - PADDING_TOP - PADDING_BOTTOM}\n fill=\"transparent\"\n onMouseMove={handleMove}\n onMouseLeave={() => onHoverChange(null)}\n onTouchMove={handleMove}\n onTouchEnd={() => onHoverChange(null)}\n />\n )\n}\n\nfunction CategoryTicks({\n ticks,\n xScale,\n height,\n formatCategory,\n}: CategoryTicksProps) {\n return (\n <>\n {ticks.map((category) => {\n const x = xScale(category)\n\n if (x === undefined) {\n return null\n }\n\n return (\n <text\n key={`tick-${String(category)}`}\n x={x + xScale.bandwidth() / 2}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n >\n {formatCategory(category)}\n </text>\n )\n })}\n </>\n )\n}\n\nfunction defaultFormatTotal(value: number) {\n return defaultTotalFormat.format(value)\n}\n\nexport function BarChart<TDatum>({\n data,\n series,\n lines,\n getCategory,\n categories,\n categoryTicks,\n formatCategory = (category) => String(category),\n formatTooltipCategory = formatCategory,\n highlightedCategory,\n showHighlightLine = false,\n referenceLine,\n title,\n yAxisUnit,\n height = DEFAULT_HEIGHT,\n renderTotal,\n formatTotal = defaultFormatTotal,\n formatValue,\n className,\n}: BarChartProps<TDatum>): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const [width, setWidth] = useState(0)\n const [hoveredCategory, setHoveredCategory] =\n useState<BarChartCategory | null>(null)\n const [trailingHoverLabel, setTrailingHoverLabel] = useState<string | null>(\n null,\n )\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () =>\n new Set(\n (lines ?? [])\n .filter((line) => line.hiddenByDefault)\n .map((line) => line.key),\n ),\n )\n\n const toggleSeries = useCallback((id: string) => {\n setHiddenSeries((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }, [])\n\n useEffect(() => {\n const element = containerRef.current\n\n if (!element) {\n return\n }\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n\n if (!entry) {\n return\n }\n\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [])\n\n const seriesByKey = useMemo(() => {\n const map = new Map<string, BarChartSeries<TDatum>>()\n\n for (const entry of series) {\n map.set(entry.key, entry)\n }\n\n return map\n }, [series])\n\n const stackData = useMemo<StackDatum[]>(\n () =>\n data.map((datum) => {\n const values: Record<string, number> = {}\n\n for (const entry of series) {\n values[entry.key] = hiddenSeries.has(entry.key)\n ? 0\n : entry.getValue(datum)\n }\n\n return { __category: getCategory(datum), __values: values }\n }),\n [data, getCategory, series, hiddenSeries],\n )\n\n const yMax = useMemo(\n () =>\n Math.max(\n 1,\n referenceLine?.value ?? 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + (record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [referenceLine, series, stackData],\n )\n\n const xDomain = useMemo(\n () => categories ?? stackData.map((record) => record.__category),\n [categories, stackData],\n )\n\n const xScale = useMemo(\n () =>\n scaleBand<BarChartCategory>({\n domain: xDomain,\n range: [Y_AXIS_GUTTER, Math.max(Y_AXIS_GUTTER, width)],\n padding: 0.32,\n }),\n [xDomain, width],\n )\n\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [0, yMax],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, yMax],\n )\n\n const colorScale = useMemo(\n () =>\n scaleOrdinal<string, string>({\n domain: series.map((entry) => entry.key),\n range: series.map((entry) => entry.color),\n }),\n [series],\n )\n\n const linePaths = useMemo(() => {\n if (!lines || width === 0) {\n return []\n }\n\n return lines\n .filter((line) => !hiddenSeries.has(line.key))\n .map((line) => {\n const lineScale = line.domain\n ? scaleLinear<number>({\n domain: line.domain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n })\n : yScale\n const segments: string[] = []\n let previous: { x: number; y: number } | null = null\n\n for (const datum of data) {\n const x = xScale(getCategory(datum))\n const value = line.getValue(datum)\n\n if (x === undefined || value === null || !Number.isFinite(value)) {\n previous = null\n continue\n }\n\n const point = {\n x: x + xScale.bandwidth() / 2,\n y: lineScale(value),\n }\n segments.push(\n previous === null\n ? `M ${point.x} ${point.y}`\n : `L ${point.x} ${point.y}`,\n )\n previous = point\n }\n\n return {\n key: line.key,\n d: segments.join(' '),\n color: line.color,\n strokeDasharray: line.strokeDasharray ?? '5 4',\n }\n })\n .filter((path) => path.d !== '')\n }, [lines, hiddenSeries, data, getCategory, xScale, yScale, height, width])\n\n const stackCategorySet = useMemo(\n () => new Set(stackData.map((record) => record.__category)),\n [stackData],\n )\n\n const lastFocusCategoryRef = useRef<BarChartCategory | null>(null)\n if (hoveredCategory !== null) {\n lastFocusCategoryRef.current = hoveredCategory\n }\n const focusCategory = lastFocusCategoryRef.current\n\n const focused = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (stackData.find((record) => record.__category === hoveredCategory) ??\n null),\n [hoveredCategory, stackData],\n )\n\n const totalValue = useMemo(() => {\n if (focused) {\n return series.reduce(\n (sum, entry) => sum + (focused.__values[entry.key] ?? 0),\n 0,\n )\n }\n\n return stackData.reduce(\n (sum, record) =>\n sum +\n series.reduce((s, entry) => s + (record.__values[entry.key] ?? 0), 0),\n 0,\n )\n }, [focused, series, stackData])\n\n const hoverLabel = focused ? formatTooltipCategory(focused.__category) : null\n\n useEffect(() => {\n if (hoverLabel) {\n setTrailingHoverLabel(hoverLabel)\n return\n }\n\n const timeoutId = window.setTimeout(() => {\n setTrailingHoverLabel(null)\n }, HOVER_FADE_MS)\n\n return () => {\n window.clearTimeout(timeoutId)\n }\n }, [hoverLabel])\n\n const ticks = categoryTicks ?? xDomain\n const yTicks = useMemo(() => buildYAxisTicks(yMax), [yMax])\n const highlightX = useMemo(() => {\n if (!showHighlightLine || highlightedCategory === undefined) {\n return null\n }\n\n const x = xScale(highlightedCategory)\n\n if (x === undefined) {\n return null\n }\n\n return x + xScale.bandwidth() / 2\n }, [highlightedCategory, showHighlightLine, xScale])\n\n const focusedDatum = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (data.find((datum) => getCategory(datum) === hoveredCategory) ??\n null),\n [hoveredCategory, data, getCategory],\n )\n\n const fmtTooltipValue = formatValue ?? formatTotal\n const tooltipRows: ChartTooltipRow[] = focused\n ? [\n ...series\n .filter((entry) => (focused.__values[entry.key] ?? 0) > 0)\n .map((entry) => ({\n key: entry.key,\n label: entry.label,\n color: entry.color,\n value: fmtTooltipValue(focused.__values[entry.key] ?? 0),\n })),\n ...(lines ?? [])\n .filter((line) => !hiddenSeries.has(line.key))\n .flatMap((line) => {\n const value =\n focusedDatum === null ? null : line.getValue(focusedDatum)\n\n if (value === null || !Number.isFinite(value)) {\n return []\n }\n\n return [\n {\n key: line.key,\n label: line.label,\n color: line.color,\n value: (line.formatValue ?? fmtTooltipValue)(value),\n },\n ]\n }),\n ]\n : []\n const tooltipActive = tooltipRows.length > 0\n const anchorX =\n focusCategory !== null\n ? (xScale(focusCategory) ?? 0) + xScale.bandwidth() / 2\n : 0\n const anchorY = yScale(totalValue)\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX,\n anchorY,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n })\n\n return (\n <div className={cn('flex w-full flex-col', className)}>\n <div className=\"flex items-baseline justify-between\">\n {title && <SectionTitle>{title}</SectionTitle>}\n <span className=\"tabular-nums\">\n {renderTotal ? (\n renderTotal(totalValue)\n ) : (\n <span className=\"text-base font-bold text-gray tabular-nums\">\n {formatTotal(totalValue)}\n </span>\n )}\n </span>\n </div>\n\n <div className=\"flex min-h-5 items-baseline justify-between gap-4\">\n <SeriesLegend\n items={[\n ...series.map((entry) => ({\n id: entry.key,\n label: entry.label,\n color: entry.color,\n })),\n ...(lines ?? []).map((line) => ({\n id: line.key,\n label: line.label,\n color: line.color,\n marker: 'dashed-line' as const,\n })),\n ]}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n className=\"gap-y-1\"\n />\n <span\n className={cn(\n 'text-xs text-gray-light transition-opacity duration-200',\n hoverLabel ? 'opacity-100' : 'opacity-0',\n )}\n >\n {trailingHoverLabel ?? ' '}\n </span>\n </div>\n\n <div\n ref={containerRef}\n className=\"relative mt-2 w-full\"\n style={{ height }}\n >\n <div\n ref={tooltipRef}\n className=\"pointer-events-none absolute z-10\"\n style={{\n left: tooltipPos.left,\n top: tooltipPos.top,\n opacity: tooltipActive ? 1 : 0,\n transition:\n 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {focusCategory !== null && (\n <ChartTooltipCard\n label={formatTooltipCategory(focusCategory)}\n rows={tooltipRows}\n />\n )}\n </div>\n {width > 0 && (\n <svg width={width} height={height}>\n <line\n x1={Y_AXIS_GUTTER}\n x2={Y_AXIS_GUTTER}\n y1={PADDING_TOP}\n y2={yScale(0)}\n stroke=\"var(--gray-a6)\"\n strokeWidth={1}\n />\n\n {yTicks.map((tick, index) => {\n const y = yScale(tick)\n const hideTickLabel =\n yAxisUnit !== undefined && index === yTicks.length - 1\n\n return (\n <g key={`y-tick-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={Y_AXIS_GUTTER - 4}\n x2={Y_AXIS_GUTTER}\n y1={y}\n y2={y}\n stroke=\"var(--gray-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={Y_AXIS_GUTTER - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n >\n {formatYAxisTick(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisUnit && (\n <text\n x={0}\n y={PADDING_TOP - 6}\n textAnchor=\"start\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisUnit}\n </text>\n )}\n\n {highlightX !== null && (\n <line\n x1={highlightX}\n x2={highlightX}\n y1={PADDING_TOP}\n y2={yScale(0)}\n stroke=\"var(--spark-a9)\"\n strokeWidth={1.5}\n strokeDasharray=\"5 4\"\n pointerEvents=\"none\"\n />\n )}\n\n <line\n x1={Y_AXIS_GUTTER}\n x2={width}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--gray-a5)\"\n strokeWidth={1}\n />\n\n <Group>\n {focusCategory !== null && (\n <FocusBorder\n category={focusCategory}\n visible={hoveredCategory !== null}\n stackData={stackData}\n series={series}\n xScale={xScale}\n yScale={yScale}\n />\n )}\n <BarStackLayer\n stackData={stackData}\n series={series}\n seriesByKey={seriesByKey}\n xScale={xScale}\n yScale={yScale}\n colorScale={colorScale}\n />\n\n {referenceLine && (\n <line\n x1={Y_AXIS_GUTTER}\n x2={width}\n y1={yScale(referenceLine.value)}\n y2={yScale(referenceLine.value)}\n stroke={referenceLine.color ?? 'var(--gray-a11)'}\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n\n {linePaths.map((path) => (\n <path\n key={`line-${path.key}`}\n d={path.d}\n fill=\"none\"\n stroke={path.color}\n strokeWidth={1.5}\n strokeDasharray={path.strokeDasharray}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n pointerEvents=\"none\"\n />\n ))}\n </Group>\n\n <InteractionLayer\n xDomain={xDomain}\n activeCategories={stackCategorySet}\n xScale={xScale}\n height={height}\n onHoverChange={setHoveredCategory}\n />\n\n <CategoryTicks\n ticks={ticks}\n xScale={xScale}\n height={height}\n formatCategory={formatCategory}\n />\n </svg>\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bar-chart.cjs","names":["localeNumberFormat","BarStack","buildYAxisScale","useMeasuredSize","clampTooltipPosition","SectionTitle","SeriesLegend","ChartTooltipCard","formatYAxisTick","Group"],"sources":["../../src/components/bar-chart.tsx"],"sourcesContent":["import { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale'\nimport { BarStack } from '@visx/shape'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { buildYAxisScale, formatYAxisTick } from '../utils/chart-scale'\nimport { cn } from '../utils/cn'\nimport { localeNumberFormat } from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend } from './series-legend'\nimport { SectionTitle } from './typography'\n\nconst defaultTotalFormat = localeNumberFormat()\n\nexport type BarChartCategory = string | number\n\nexport interface BarChartSeries<TDatum> {\n key: string\n label: string\n color: string\n hoverFill?: string\n getValue: (datum: TDatum) => number\n}\n\nexport interface BarChartLineSeries<TDatum> {\n key: string\n label: string\n color: string\n /** `null` gaps break the line (e.g. hours without a reading). */\n getValue: (datum: TDatum) => number | null\n /** Own y-domain for this line (e.g. `[0, 100]` for a percentage). Defaults to the bar scale. */\n domain?: [number, number]\n /** Start hidden; the user can enable the line from the legend. */\n hiddenByDefault?: boolean\n /** Formats this line's value in the hover tooltip. Defaults to `formatValue`. */\n formatValue?: (value: number) => string\n strokeDasharray?: string\n}\n\nexport interface BarChartProps<TDatum> {\n data: TDatum[]\n series: BarChartSeries<TDatum>[]\n /** Line overlays drawn on top of the bars, toggleable from the legend. */\n lines?: BarChartLineSeries<TDatum>[]\n getCategory: (datum: TDatum) => BarChartCategory\n /** Full ordered set of categories on the x-axis. Defaults to `data.map(getCategory)`. */\n categories?: BarChartCategory[]\n /** Subset of categories that should render an x-axis label. Defaults to every category. */\n categoryTicks?: BarChartCategory[]\n formatCategory?: (category: BarChartCategory) => string\n /** Formats the hovered category in the tooltip header. Defaults to `formatCategory`. */\n formatTooltipCategory?: (category: BarChartCategory) => string\n highlightedCategory?: BarChartCategory\n showHighlightLine?: boolean\n /**\n * Horizontal reference line drawn across the plot at a given y-value.\n * Useful for thresholds (e.g. price ceiling).\n */\n referenceLine?: { value: number; label?: string; color?: string }\n title?: string\n yAxisUnit?: string\n height?: number\n /**\n * Override how the total value (sum of focused or all categories) is\n * rendered. `animated` is false while a bar is focused (hover), so an\n * animated total can snap between hovered buckets instead of re-firing a\n * tween on every bar the pointer crosses.\n */\n renderTotal?: (value: number, animated: boolean) => React.ReactNode\n /** Format function used when `renderTotal` is not provided. */\n formatTotal?: (value: number) => string\n /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */\n formatValue?: (value: number) => string\n className?: string\n}\n\ninterface StackDatum {\n __category: BarChartCategory\n __values: Record<string, number>\n}\n\ninterface BarStackLayerProps<TDatum> {\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n seriesByKey: Map<string, BarChartSeries<TDatum>>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n colorScale: ReturnType<typeof scaleOrdinal<string, string>>\n}\n\ninterface CategoryTicksProps {\n ticks: BarChartCategory[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n formatCategory: (category: BarChartCategory) => string\n}\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst HOVER_FADE_MS = 200\nconst FOCUS_TRANSITION_MS = 180\nconst DEFAULT_HEIGHT = 220\nconst BAR_RADIUS = 2\nconst Y_AXIS_GUTTER = 34\n\nfunction buildBarPath(\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number,\n roundTop: boolean,\n roundBottom: boolean,\n) {\n const r = Math.max(0, Math.min(radius, width / 2, height / 2))\n\n if (r === 0 || (!roundTop && !roundBottom)) {\n return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`\n }\n\n const tl = roundTop ? r : 0\n const tr = roundTop ? r : 0\n const br = roundBottom ? r : 0\n const bl = roundBottom ? r : 0\n\n return [\n `M ${x + tl} ${y}`,\n `H ${x + width - tr}`,\n tr > 0\n ? `Q ${x + width} ${y} ${x + width} ${y + tr}`\n : `L ${x + width} ${y}`,\n `V ${y + height - br}`,\n br > 0\n ? `Q ${x + width} ${y + height} ${x + width - br} ${y + height}`\n : `L ${x + width} ${y + height}`,\n `H ${x + bl}`,\n bl > 0\n ? `Q ${x} ${y + height} ${x} ${y + height - bl}`\n : `L ${x} ${y + height}`,\n `V ${y + tl}`,\n tl > 0 ? `Q ${x} ${y} ${x + tl} ${y}` : `L ${x} ${y}`,\n 'Z',\n ].join(' ')\n}\n\nfunction BarStackLayer<TDatum>({\n stackData,\n series,\n seriesByKey,\n xScale,\n yScale,\n colorScale,\n}: BarStackLayerProps<TDatum>) {\n return (\n <BarStack<StackDatum, string>\n data={stackData}\n keys={series.map((entry) => entry.key)}\n x={(record) => record.__category}\n value={(record, key) => record.__values[key] ?? 0}\n xScale={xScale}\n yScale={yScale}\n color={colorScale}\n offset=\"diverging\"\n >\n {(barStacks) =>\n barStacks.map((barStack) =>\n barStack.bars.map((bar) => {\n const values = bar.bar.data.__values\n const segmentValue = values[barStack.key] ?? 0\n\n if (segmentValue === 0) {\n return null\n }\n\n const seriesEntry = seriesByKey.get(barStack.key)\n const strokeColor = seriesEntry?.color ?? bar.color\n const fillColor = strokeColor\n\n // Positive segments stack up from the baseline, negatives down.\n // Round only the outermost corner of each side of the axis.\n const positiveKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) > 0)\n const negativeKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) < 0)\n const roundTop =\n segmentValue > 0 &&\n positiveKeys[positiveKeys.length - 1] === barStack.key\n const roundBottom =\n segmentValue > 0\n ? positiveKeys[0] === barStack.key\n : negativeKeys[negativeKeys.length - 1] === barStack.key\n\n // visx returns a signed height for below-baseline bars; normalize\n // to a top-left origin with a positive height for the path.\n const top = bar.height < 0 ? bar.y + bar.height : bar.y\n const barHeight = Math.abs(bar.height)\n\n return (\n <path\n key={`bar-${barStack.index}-${bar.index}`}\n d={buildBarPath(\n bar.x,\n top,\n bar.width,\n Math.max(0, barHeight),\n BAR_RADIUS,\n roundTop,\n roundBottom,\n )}\n fill={fillColor}\n stroke={strokeColor}\n strokeWidth={1}\n style={{ transition: 'fill 180ms ease' }}\n />\n )\n }),\n )\n }\n </BarStack>\n )\n}\n\ninterface FocusBorderProps<TDatum> {\n category: BarChartCategory\n visible: boolean\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n}\n\nfunction FocusBorder<TDatum>({\n category,\n visible,\n stackData,\n series,\n xScale,\n yScale,\n}: FocusBorderProps<TDatum>) {\n const x = xScale(category)\n const datum = stackData.find((entry) => entry.__category === category)\n\n if (x === undefined || !datum) {\n return null\n }\n\n const hasAnyValue = series.some(\n (entry) => (datum.__values[entry.key] ?? 0) !== 0,\n )\n\n if (!hasAnyValue) {\n return null\n }\n\n const topY = PADDING_TOP\n // Extend past the baseline to cover any below-axis (feed-in) segment.\n const negativeSum = series.reduce(\n (sum, entry) => sum + Math.min(0, datum.__values[entry.key] ?? 0),\n 0,\n )\n const bottomY = yScale(negativeSum)\n const borderPaddingX = 4\n const borderPaddingY = 3\n const borderXRaw = x - borderPaddingX\n const borderY = topY - borderPaddingY\n const borderWidthRaw = xScale.bandwidth() + borderPaddingX * 2\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n const borderX = Math.max(minX, borderXRaw)\n const borderRight = Math.min(maxX, borderXRaw + borderWidthRaw)\n const borderWidth = Math.max(0, borderRight - borderX)\n const borderHeight = Math.max(1, bottomY - topY + borderPaddingY * 2)\n\n if (borderWidth <= 0) {\n return null\n }\n\n return (\n <rect\n x={borderX}\n y={borderY}\n width={borderWidth}\n height={borderHeight}\n rx={6}\n fill=\"var(--spark-a2)\"\n stroke=\"var(--spark-a9)\"\n strokeWidth={2}\n pointerEvents=\"none\"\n style={{\n opacity: visible ? 1 : 0,\n transition: `x ${FOCUS_TRANSITION_MS}ms ease, y ${FOCUS_TRANSITION_MS}ms ease, width ${FOCUS_TRANSITION_MS}ms ease, height ${FOCUS_TRANSITION_MS}ms ease, opacity ${FOCUS_TRANSITION_MS}ms ease`,\n }}\n />\n )\n}\n\ninterface InteractionLayerProps {\n xDomain: BarChartCategory[]\n activeCategories: Set<BarChartCategory>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n onHoverChange: (category: BarChartCategory | null) => void\n}\n\nfunction InteractionLayer({\n xDomain,\n activeCategories,\n xScale,\n height,\n onHoverChange,\n}: InteractionLayerProps) {\n const bandwidth = xScale.bandwidth()\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n\n // A single overlay that maps the pointer to the nearest category with data,\n // so there are no dead zones between/around bars to break the hover.\n const handleMove = (\n event: React.MouseEvent<SVGRectElement> | React.TouchEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point) return\n\n let nearest: BarChartCategory | null = null\n let best = Infinity\n for (const category of xDomain) {\n if (!activeCategories.has(category)) continue\n const x = xScale(category)\n if (x === undefined) continue\n const distance = Math.abs(x + bandwidth / 2 - point.x)\n if (distance < best) {\n best = distance\n nearest = category\n }\n }\n\n if (nearest !== null) onHoverChange(nearest)\n }\n\n return (\n <rect\n x={minX}\n y={PADDING_TOP}\n width={Math.max(0, maxX - minX)}\n height={height - PADDING_TOP - PADDING_BOTTOM}\n fill=\"transparent\"\n onMouseMove={handleMove}\n onMouseLeave={() => onHoverChange(null)}\n onTouchMove={handleMove}\n onTouchEnd={() => onHoverChange(null)}\n />\n )\n}\n\nfunction CategoryTicks({\n ticks,\n xScale,\n height,\n formatCategory,\n}: CategoryTicksProps) {\n return (\n <>\n {ticks.map((category) => {\n const x = xScale(category)\n\n if (x === undefined) {\n return null\n }\n\n return (\n <text\n key={`tick-${String(category)}`}\n x={x + xScale.bandwidth() / 2}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n >\n {formatCategory(category)}\n </text>\n )\n })}\n </>\n )\n}\n\nfunction defaultFormatTotal(value: number) {\n return defaultTotalFormat.format(value)\n}\n\nexport function BarChart<TDatum>({\n data,\n series,\n lines,\n getCategory,\n categories,\n categoryTicks,\n formatCategory = (category) => String(category),\n formatTooltipCategory = formatCategory,\n highlightedCategory,\n showHighlightLine = false,\n referenceLine,\n title,\n yAxisUnit,\n height = DEFAULT_HEIGHT,\n renderTotal,\n formatTotal = defaultFormatTotal,\n formatValue,\n className,\n}: BarChartProps<TDatum>): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const [width, setWidth] = useState(0)\n const [hoveredCategory, setHoveredCategory] =\n useState<BarChartCategory | null>(null)\n const [trailingHoverLabel, setTrailingHoverLabel] = useState<string | null>(\n null,\n )\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () =>\n new Set(\n (lines ?? [])\n .filter((line) => line.hiddenByDefault)\n .map((line) => line.key),\n ),\n )\n\n const toggleSeries = useCallback((id: string) => {\n setHiddenSeries((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }, [])\n\n useEffect(() => {\n const element = containerRef.current\n\n if (!element) {\n return\n }\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n\n if (!entry) {\n return\n }\n\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [])\n\n const seriesByKey = useMemo(() => {\n const map = new Map<string, BarChartSeries<TDatum>>()\n\n for (const entry of series) {\n map.set(entry.key, entry)\n }\n\n return map\n }, [series])\n\n const stackData = useMemo<StackDatum[]>(\n () =>\n data.map((datum) => {\n const values: Record<string, number> = {}\n\n for (const entry of series) {\n values[entry.key] = hiddenSeries.has(entry.key)\n ? 0\n : entry.getValue(datum)\n }\n\n return { __category: getCategory(datum), __values: values }\n }),\n [data, getCategory, series, hiddenSeries],\n )\n\n const yMax = useMemo(\n () =>\n Math.max(\n 1,\n referenceLine?.value ?? 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [referenceLine, series, stackData],\n )\n\n // Most negative stack sum across buckets (0 when nothing dips below the axis).\n const yMin = useMemo(\n () =>\n Math.min(\n 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [series, stackData],\n )\n\n const xDomain = useMemo(\n () => categories ?? stackData.map((record) => record.__category),\n [categories, stackData],\n )\n\n const xScale = useMemo(\n () =>\n scaleBand<BarChartCategory>({\n domain: xDomain,\n range: [Y_AXIS_GUTTER, Math.max(Y_AXIS_GUTTER, width)],\n padding: 0.32,\n }),\n [xDomain, width],\n )\n\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [yMin, yMax],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, yMax, yMin],\n )\n\n const colorScale = useMemo(\n () =>\n scaleOrdinal<string, string>({\n domain: series.map((entry) => entry.key),\n range: series.map((entry) => entry.color),\n }),\n [series],\n )\n\n const linePaths = useMemo(() => {\n if (!lines || width === 0) {\n return []\n }\n\n return lines\n .filter((line) => !hiddenSeries.has(line.key))\n .map((line) => {\n const lineScale = line.domain\n ? scaleLinear<number>({\n domain: line.domain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n })\n : yScale\n const segments: string[] = []\n let previous: { x: number; y: number } | null = null\n\n for (const datum of data) {\n const x = xScale(getCategory(datum))\n const value = line.getValue(datum)\n\n if (x === undefined || value === null || !Number.isFinite(value)) {\n previous = null\n continue\n }\n\n const point = {\n x: x + xScale.bandwidth() / 2,\n y: lineScale(value),\n }\n segments.push(\n previous === null\n ? `M ${point.x} ${point.y}`\n : `L ${point.x} ${point.y}`,\n )\n previous = point\n }\n\n return {\n key: line.key,\n d: segments.join(' '),\n color: line.color,\n strokeDasharray: line.strokeDasharray ?? '5 4',\n }\n })\n .filter((path) => path.d !== '')\n }, [lines, hiddenSeries, data, getCategory, xScale, yScale, height, width])\n\n const stackCategorySet = useMemo(\n () => new Set(stackData.map((record) => record.__category)),\n [stackData],\n )\n\n const lastFocusCategoryRef = useRef<BarChartCategory | null>(null)\n if (hoveredCategory !== null) {\n lastFocusCategoryRef.current = hoveredCategory\n }\n const focusCategory = lastFocusCategoryRef.current\n\n const focused = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (stackData.find((record) => record.__category === hoveredCategory) ??\n null),\n [hoveredCategory, stackData],\n )\n\n // Below-baseline segments (feed-in) are context, not part of the headline\n // sum, so the total counts only the positive stack (energy consumed).\n const totalValue = useMemo(() => {\n if (focused) {\n return series.reduce(\n (sum, entry) => sum + Math.max(0, focused.__values[entry.key] ?? 0),\n 0,\n )\n }\n\n return stackData.reduce(\n (sum, record) =>\n sum +\n series.reduce(\n (s, entry) => s + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n 0,\n )\n }, [focused, series, stackData])\n\n const hoverLabel = focused ? formatTooltipCategory(focused.__category) : null\n\n useEffect(() => {\n if (hoverLabel) {\n setTrailingHoverLabel(hoverLabel)\n return\n }\n\n const timeoutId = window.setTimeout(() => {\n setTrailingHoverLabel(null)\n }, HOVER_FADE_MS)\n\n return () => {\n window.clearTimeout(timeoutId)\n }\n }, [hoverLabel])\n\n const ticks = categoryTicks ?? xDomain\n const yTicks = useMemo(() => buildYAxisScale(yMin, yMax).ticks, [yMin, yMax])\n const highlightX = useMemo(() => {\n if (!showHighlightLine || highlightedCategory === undefined) {\n return null\n }\n\n const x = xScale(highlightedCategory)\n\n if (x === undefined) {\n return null\n }\n\n return x + xScale.bandwidth() / 2\n }, [highlightedCategory, showHighlightLine, xScale])\n\n const focusedDatum = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (data.find((datum) => getCategory(datum) === hoveredCategory) ??\n null),\n [hoveredCategory, data, getCategory],\n )\n\n // The bars don't depend on hover state, so memoize the layer: hovering\n // across bars must not re-render (and re-stack) every bar path each move.\n const barStackLayer = useMemo(\n () => (\n <BarStackLayer\n stackData={stackData}\n series={series}\n seriesByKey={seriesByKey}\n xScale={xScale}\n yScale={yScale}\n colorScale={colorScale}\n />\n ),\n [stackData, series, seriesByKey, xScale, yScale, colorScale],\n )\n\n const fmtTooltipValue = formatValue ?? formatTotal\n const tooltipRows: ChartTooltipRow[] = focused\n ? [\n ...series\n .filter((entry) => (focused.__values[entry.key] ?? 0) !== 0)\n .map((entry) => ({\n key: entry.key,\n label: entry.label,\n color: entry.color,\n value: fmtTooltipValue(Math.abs(focused.__values[entry.key] ?? 0)),\n })),\n ...(lines ?? [])\n .filter((line) => !hiddenSeries.has(line.key))\n .flatMap((line) => {\n const value =\n focusedDatum === null ? null : line.getValue(focusedDatum)\n\n if (value === null || !Number.isFinite(value)) {\n return []\n }\n\n return [\n {\n key: line.key,\n label: line.label,\n color: line.color,\n value: (line.formatValue ?? fmtTooltipValue)(value),\n },\n ]\n }),\n ]\n : []\n const tooltipActive = tooltipRows.length > 0\n const anchorX =\n focusCategory !== null\n ? (xScale(focusCategory) ?? 0) + xScale.bandwidth() / 2\n : 0\n const anchorY = yScale(totalValue)\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX,\n anchorY,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n })\n\n return (\n <div className={cn('flex w-full flex-col', className)}>\n <div className=\"flex items-baseline justify-between\">\n {title && <SectionTitle>{title}</SectionTitle>}\n <span className=\"tabular-nums\">\n {renderTotal ? (\n renderTotal(totalValue, focused === null)\n ) : (\n <span className=\"text-base font-bold text-gray tabular-nums\">\n {formatTotal(totalValue)}\n </span>\n )}\n </span>\n </div>\n\n <div className=\"flex min-h-5 items-baseline justify-between gap-4\">\n <SeriesLegend\n items={[\n ...series.map((entry) => ({\n id: entry.key,\n label: entry.label,\n color: entry.color,\n })),\n ...(lines ?? []).map((line) => ({\n id: line.key,\n label: line.label,\n color: line.color,\n marker: 'dashed-line' as const,\n })),\n ]}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n className=\"gap-y-1\"\n />\n <span\n className={cn(\n 'text-xs text-gray-light transition-opacity duration-200',\n hoverLabel ? 'opacity-100' : 'opacity-0',\n )}\n >\n {trailingHoverLabel ?? ' '}\n </span>\n </div>\n\n <div\n ref={containerRef}\n className=\"relative mt-2 w-full\"\n style={{ height }}\n >\n <div\n ref={tooltipRef}\n className=\"pointer-events-none absolute z-10\"\n style={{\n left: tooltipPos.left,\n top: tooltipPos.top,\n opacity: tooltipActive ? 1 : 0,\n transition:\n 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {focusCategory !== null && (\n <ChartTooltipCard\n label={formatTooltipCategory(focusCategory)}\n rows={tooltipRows}\n />\n )}\n </div>\n {width > 0 && (\n <svg width={width} height={height}>\n <line\n x1={Y_AXIS_GUTTER}\n x2={Y_AXIS_GUTTER}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--gray-a6)\"\n strokeWidth={1}\n />\n\n {yTicks.map((tick, index) => {\n const y = yScale(tick)\n const hideTickLabel =\n yAxisUnit !== undefined && index === yTicks.length - 1\n\n return (\n <g key={`y-tick-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={Y_AXIS_GUTTER - 4}\n x2={Y_AXIS_GUTTER}\n y1={y}\n y2={y}\n stroke=\"var(--gray-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={Y_AXIS_GUTTER - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n >\n {formatYAxisTick(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisUnit && (\n <text\n x={0}\n y={PADDING_TOP - 6}\n textAnchor=\"start\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisUnit}\n </text>\n )}\n\n {highlightX !== null && (\n <line\n x1={highlightX}\n x2={highlightX}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--spark-a9)\"\n strokeWidth={1.5}\n strokeDasharray=\"5 4\"\n pointerEvents=\"none\"\n />\n )}\n\n <line\n x1={Y_AXIS_GUTTER}\n x2={width}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--gray-a5)\"\n strokeWidth={1}\n />\n\n <Group>\n {focusCategory !== null && (\n <FocusBorder\n category={focusCategory}\n visible={hoveredCategory !== null}\n stackData={stackData}\n series={series}\n xScale={xScale}\n yScale={yScale}\n />\n )}\n {barStackLayer}\n\n {referenceLine && (\n <line\n x1={Y_AXIS_GUTTER}\n x2={width}\n y1={yScale(referenceLine.value)}\n y2={yScale(referenceLine.value)}\n stroke={referenceLine.color ?? 'var(--gray-a11)'}\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n\n {linePaths.map((path) => (\n <path\n key={`line-${path.key}`}\n d={path.d}\n fill=\"none\"\n stroke={path.color}\n strokeWidth={1.5}\n strokeDasharray={path.strokeDasharray}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n pointerEvents=\"none\"\n />\n ))}\n </Group>\n\n <InteractionLayer\n xDomain={xDomain}\n activeCategories={stackCategorySet}\n xScale={xScale}\n height={height}\n onHoverChange={setHoveredCategory}\n />\n\n <CategoryTicks\n ticks={ticks}\n xScale={xScale}\n height={height}\n formatCategory={formatCategory}\n />\n </svg>\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -50,8 +50,13 @@ interface BarChartProps<TDatum> {
50
50
  title?: string;
51
51
  yAxisUnit?: string;
52
52
  height?: number;
53
- /** Override how the total value (sum of focused or all categories) is rendered. */
54
- renderTotal?: (value: number) => React.ReactNode;
53
+ /**
54
+ * Override how the total value (sum of focused or all categories) is
55
+ * rendered. `animated` is false while a bar is focused (hover), so an
56
+ * animated total can snap between hovered buckets instead of re-firing a
57
+ * tween on every bar the pointer crosses.
58
+ */
59
+ renderTotal?: (value: number, animated: boolean) => React.ReactNode;
55
60
  /** Format function used when `renderTotal` is not provided. */
56
61
  formatTotal?: (value: number) => string;
57
62
  /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */
@@ -50,8 +50,13 @@ interface BarChartProps<TDatum> {
50
50
  title?: string;
51
51
  yAxisUnit?: string;
52
52
  height?: number;
53
- /** Override how the total value (sum of focused or all categories) is rendered. */
54
- renderTotal?: (value: number) => React.ReactNode;
53
+ /**
54
+ * Override how the total value (sum of focused or all categories) is
55
+ * rendered. `animated` is false while a bar is focused (hover), so an
56
+ * animated total can snap between hovered buckets instead of re-firing a
57
+ * tween on every bar the pointer crosses.
58
+ */
59
+ renderTotal?: (value: number, animated: boolean) => React.ReactNode;
55
60
  /** Format function used when `renderTotal` is not provided. */
56
61
  formatTotal?: (value: number) => string;
57
62
  /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */