@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.
- package/dist/components/attachment.d.cts +1 -1
- package/dist/components/attachment.d.ts +1 -1
- package/dist/components/bar-chart.cjs +48 -47
- package/dist/components/bar-chart.cjs.map +1 -1
- package/dist/components/bar-chart.d.cts +7 -2
- package/dist/components/bar-chart.d.ts +7 -2
- package/dist/components/bar-chart.js +48 -47
- package/dist/components/bar-chart.js.map +1 -1
- package/dist/components/bubble.d.cts +1 -1
- package/dist/components/bubble.d.ts +1 -1
- package/dist/components/button.cjs +1 -1
- package/dist/components/button.cjs.map +1 -1
- package/dist/components/button.d.cts +8 -0
- package/dist/components/button.d.ts +8 -0
- package/dist/components/button.js +1 -1
- package/dist/components/button.js.map +1 -1
- package/dist/components/callout.d.cts +1 -1
- package/dist/components/callout.d.ts +1 -1
- package/dist/components/energy-bar-chart.cjs +2 -1
- package/dist/components/energy-bar-chart.cjs.map +1 -1
- package/dist/components/energy-bar-chart.js +2 -1
- package/dist/components/energy-bar-chart.js.map +1 -1
- package/dist/components/energy-history-chart.cjs +14 -6
- package/dist/components/energy-history-chart.cjs.map +1 -1
- package/dist/components/energy-history-chart.d.cts +11 -3
- package/dist/components/energy-history-chart.d.ts +11 -3
- package/dist/components/energy-history-chart.js +14 -6
- package/dist/components/energy-history-chart.js.map +1 -1
- package/dist/components/field.cjs +1 -1
- package/dist/components/field.js +1 -1
- package/dist/components/input-group.cjs +1 -1
- package/dist/components/input-group.js +1 -1
- package/dist/components/line-chart.cjs +55 -15
- package/dist/components/line-chart.cjs.map +1 -1
- package/dist/components/line-chart.d.cts +7 -0
- package/dist/components/line-chart.d.ts +7 -0
- package/dist/components/line-chart.js +55 -15
- package/dist/components/line-chart.js.map +1 -1
- package/dist/components/power-history-chart.cjs +14 -37
- package/dist/components/power-history-chart.cjs.map +1 -1
- package/dist/components/power-history-chart.d.cts +10 -1
- package/dist/components/power-history-chart.d.ts +10 -1
- package/dist/components/power-history-chart.js +15 -38
- package/dist/components/power-history-chart.js.map +1 -1
- package/dist/components/sankey-chart.cjs +8 -41
- package/dist/components/sankey-chart.cjs.map +1 -1
- package/dist/components/sankey-chart.d.cts +8 -0
- package/dist/components/sankey-chart.d.ts +8 -0
- package/dist/components/sankey-chart.js +8 -41
- package/dist/components/sankey-chart.js.map +1 -1
- package/dist/components/segmented-control.cjs +44 -0
- package/dist/components/segmented-control.cjs.map +1 -0
- package/dist/components/segmented-control.d.cts +33 -0
- package/dist/components/segmented-control.d.ts +33 -0
- package/dist/components/segmented-control.js +40 -0
- package/dist/components/segmented-control.js.map +1 -0
- package/dist/components/separator.cjs +1 -1
- package/dist/components/separator.cjs.map +1 -1
- package/dist/components/separator.js +1 -1
- package/dist/components/separator.js.map +1 -1
- package/dist/components/solar-forecast-chart.cjs +4 -3
- package/dist/components/solar-forecast-chart.cjs.map +1 -1
- package/dist/components/solar-forecast-chart.d.cts +4 -1
- package/dist/components/solar-forecast-chart.d.ts +4 -1
- package/dist/components/solar-forecast-chart.js +4 -3
- package/dist/components/solar-forecast-chart.js.map +1 -1
- package/dist/components/theme.cjs +1 -1
- package/dist/components/theme.js +1 -1
- package/dist/components/tooltip.cjs +1 -1
- package/dist/components/tooltip.cjs.map +1 -1
- package/dist/components/tooltip.js +1 -1
- package/dist/components/tooltip.js.map +1 -1
- package/dist/styles/index.css +37 -0
- package/dist/styles/spark-default.css +45 -40
- package/dist/styles/theme.css +78 -0
- package/dist/{theme-B3WtiByA.js → theme-C19BbKfO.js} +2 -2
- package/dist/theme-C19BbKfO.js.map +1 -0
- package/dist/{theme-C9_OSe0S.cjs → theme-CfFWrMEF.cjs} +2 -2
- package/dist/theme-CfFWrMEF.cjs.map +1 -0
- package/dist/utils/build-sankey-nodes.cjs +16 -3
- package/dist/utils/build-sankey-nodes.cjs.map +1 -1
- package/dist/utils/build-sankey-nodes.js +16 -3
- package/dist/utils/build-sankey-nodes.js.map +1 -1
- package/dist/utils/chart-scale.cjs +43 -0
- package/dist/utils/chart-scale.cjs.map +1 -0
- package/dist/utils/chart-scale.d.cts +22 -0
- package/dist/utils/chart-scale.d.ts +22 -0
- package/dist/utils/chart-scale.js +41 -0
- package/dist/utils/chart-scale.js.map +1 -0
- package/package.json +1 -1
- package/dist/theme-B3WtiByA.js.map +0 -1
- 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?: "
|
|
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?: "
|
|
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
|
-
|
|
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
|
|
77
|
-
const
|
|
78
|
-
const
|
|
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,
|
|
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)
|
|
81
|
+
if (!series.some((entry) => (datum.__values[entry.key] ?? 0) !== 0)) return null;
|
|
94
82
|
const topY = PADDING_TOP;
|
|
95
|
-
const
|
|
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,
|
|
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: [
|
|
222
|
+
domain: [yMin, yMax],
|
|
234
223
|
range: [height - PADDING_BOTTOM, PADDING_TOP]
|
|
235
|
-
}), [
|
|
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)(() =>
|
|
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)
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
/**
|
|
54
|
-
|
|
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
|
-
/**
|
|
54
|
-
|
|
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`. */
|