@x-plat/design-system 0.5.34 → 0.5.36
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/Chart/index.cjs +41 -79
- package/dist/components/Chart/index.css +16 -26
- package/dist/components/Chart/index.js +41 -79
- package/dist/components/index.cjs +41 -79
- package/dist/components/index.css +16 -26
- package/dist/components/index.js +41 -79
- package/dist/index.cjs +41 -79
- package/dist/index.css +16 -26
- package/dist/index.js +41 -79
- package/package.json +1 -1
|
@@ -163,8 +163,8 @@ var TOOLTIP_OFFSET = 12;
|
|
|
163
163
|
var useChartTooltip = (enabled) => {
|
|
164
164
|
const [tooltip, setTooltip] = import_react.default.useState({
|
|
165
165
|
visible: false,
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
x: 0,
|
|
167
|
+
y: 0,
|
|
168
168
|
content: ""
|
|
169
169
|
});
|
|
170
170
|
const containerRef = import_react.default.useRef(null);
|
|
@@ -175,18 +175,26 @@ var useChartTooltip = (enabled) => {
|
|
|
175
175
|
const cy = e.clientY;
|
|
176
176
|
cancelAnimationFrame(rafRef.current);
|
|
177
177
|
rafRef.current = requestAnimationFrame(() => {
|
|
178
|
-
|
|
178
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
179
|
+
if (!rect) return;
|
|
180
|
+
setTooltip((prev) => ({ ...prev, x: cx - rect.left, y: cy - rect.top }));
|
|
179
181
|
});
|
|
180
182
|
}, [enabled]);
|
|
181
183
|
const show = import_react.default.useCallback((e, content) => {
|
|
182
184
|
if (!enabled) return;
|
|
183
|
-
|
|
185
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
186
|
+
if (!rect) return;
|
|
187
|
+
setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
|
|
188
|
+
}, [enabled]);
|
|
189
|
+
const showAt = import_react.default.useCallback((x, y, content) => {
|
|
190
|
+
if (!enabled) return;
|
|
191
|
+
setTooltip({ visible: true, x, y, content });
|
|
184
192
|
}, [enabled]);
|
|
185
193
|
const hide = import_react.default.useCallback(() => {
|
|
186
194
|
cancelAnimationFrame(rafRef.current);
|
|
187
195
|
setTooltip((prev) => ({ ...prev, visible: false }));
|
|
188
196
|
}, []);
|
|
189
|
-
return { tooltip, show, hide, move, containerRef };
|
|
197
|
+
return { tooltip, show, showAt, hide, move, containerRef };
|
|
190
198
|
};
|
|
191
199
|
var GridLines = import_react.default.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
|
|
192
200
|
const y = PADDING.top + (1 - ratio) * chartH;
|
|
@@ -251,7 +259,7 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
251
259
|
}, [entries, seriesPoints]);
|
|
252
260
|
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
253
261
|
};
|
|
254
|
-
var LineChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
262
|
+
var LineChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
|
|
255
263
|
const entries = import_react.default.useMemo(() => Object.entries(data), [data]);
|
|
256
264
|
const maxVal = import_react.default.useMemo(() => {
|
|
257
265
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -291,23 +299,9 @@ var LineChart = import_react.default.memo(({ data, labels, width, height, animat
|
|
|
291
299
|
className: "chart-svg",
|
|
292
300
|
onMouseMove: (e) => {
|
|
293
301
|
handleMouseMove(e);
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const points = seriesPoints[0];
|
|
298
|
-
if (!points || points.length === 0) return;
|
|
299
|
-
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
300
|
-
let closest = 0;
|
|
301
|
-
let minDist = Math.abs(points[0].x - mx);
|
|
302
|
-
for (let i = 1; i < points.length; i++) {
|
|
303
|
-
const dist = Math.abs(points[i].x - mx);
|
|
304
|
-
if (dist < minDist) {
|
|
305
|
-
minDist = dist;
|
|
306
|
-
closest = i;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
if (minDist <= step / 2) {
|
|
310
|
-
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
302
|
+
if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
|
|
303
|
+
const p = seriesPoints[0][activeIndex];
|
|
304
|
+
onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
311
305
|
} else {
|
|
312
306
|
onLeave();
|
|
313
307
|
}
|
|
@@ -375,7 +369,7 @@ var LineChart = import_react.default.memo(({ data, labels, width, height, animat
|
|
|
375
369
|
);
|
|
376
370
|
});
|
|
377
371
|
LineChart.displayName = "LineChart";
|
|
378
|
-
var CurveChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
372
|
+
var CurveChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
|
|
379
373
|
const entries = import_react.default.useMemo(() => Object.entries(data), [data]);
|
|
380
374
|
const maxVal = import_react.default.useMemo(() => {
|
|
381
375
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -415,23 +409,9 @@ var CurveChart = import_react.default.memo(({ data, labels, width, height, anima
|
|
|
415
409
|
className: "chart-svg",
|
|
416
410
|
onMouseMove: (e) => {
|
|
417
411
|
handleMouseMove(e);
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const points = seriesPoints[0];
|
|
422
|
-
if (!points || points.length === 0) return;
|
|
423
|
-
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
424
|
-
let closest = 0;
|
|
425
|
-
let minDist = Math.abs(points[0].x - mx);
|
|
426
|
-
for (let i = 1; i < points.length; i++) {
|
|
427
|
-
const dist = Math.abs(points[i].x - mx);
|
|
428
|
-
if (dist < minDist) {
|
|
429
|
-
minDist = dist;
|
|
430
|
-
closest = i;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
if (minDist <= step / 2) {
|
|
434
|
-
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
412
|
+
if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
|
|
413
|
+
const p = seriesPoints[0][activeIndex];
|
|
414
|
+
onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
435
415
|
} else {
|
|
436
416
|
onLeave();
|
|
437
417
|
}
|
|
@@ -499,7 +479,7 @@ var CurveChart = import_react.default.memo(({ data, labels, width, height, anima
|
|
|
499
479
|
);
|
|
500
480
|
});
|
|
501
481
|
CurveChart.displayName = "CurveChart";
|
|
502
|
-
var BarChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
482
|
+
var BarChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
|
|
503
483
|
const entries = import_react.default.useMemo(() => Object.entries(data), [data]);
|
|
504
484
|
const maxVal = import_react.default.useMemo(() => {
|
|
505
485
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -549,8 +529,7 @@ var BarChart = import_react.default.memo(({ data, labels, width, height, animate
|
|
|
549
529
|
transformOrigin: `${b.x + b.w / 2}px ${baseline}px`,
|
|
550
530
|
animationDelay: `${delay}ms`
|
|
551
531
|
} : void 0,
|
|
552
|
-
onMouseEnter: (
|
|
553
|
-
onMouseMove: onMove,
|
|
532
|
+
onMouseEnter: () => onShowAt(b.x + b.w / 2, b.y, `${key}: ${labels[i]} \u2014 ${b.v}`),
|
|
554
533
|
onMouseLeave: onLeave
|
|
555
534
|
},
|
|
556
535
|
`${di}-${i}`
|
|
@@ -638,30 +617,14 @@ var PieDonutChart = import_react.default.memo(
|
|
|
638
617
|
{
|
|
639
618
|
d: s.d,
|
|
640
619
|
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
641
|
-
className: "chart-slice"
|
|
642
|
-
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
643
|
-
onMouseMove: onMove,
|
|
644
|
-
onMouseLeave: onLeave
|
|
620
|
+
className: "chart-slice"
|
|
645
621
|
}
|
|
646
|
-
) }, i)) })
|
|
647
|
-
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
648
|
-
"text",
|
|
649
|
-
{
|
|
650
|
-
x: s.lx,
|
|
651
|
-
y: s.ly,
|
|
652
|
-
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
653
|
-
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
654
|
-
textAnchor: "middle",
|
|
655
|
-
dominantBaseline: "central",
|
|
656
|
-
children: s.v
|
|
657
|
-
},
|
|
658
|
-
`label-${i}`
|
|
659
|
-
))
|
|
622
|
+
) }, i)) })
|
|
660
623
|
] });
|
|
661
624
|
}
|
|
662
625
|
);
|
|
663
626
|
PieDonutChart.displayName = "PieDonutChart";
|
|
664
|
-
var
|
|
627
|
+
var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
|
|
665
628
|
const ref = import_react.default.useRef(null);
|
|
666
629
|
const [pos, setPos] = import_react.default.useState({ left: 0, top: 0 });
|
|
667
630
|
import_react.default.useLayoutEffect(() => {
|
|
@@ -669,20 +632,19 @@ var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
|
|
|
669
632
|
if (!el) return;
|
|
670
633
|
const w = el.offsetWidth;
|
|
671
634
|
const h = el.offsetHeight;
|
|
672
|
-
|
|
673
|
-
let
|
|
674
|
-
|
|
675
|
-
if (
|
|
676
|
-
if (
|
|
677
|
-
if (left < 8) left = 8;
|
|
635
|
+
let left = x + TOOLTIP_OFFSET;
|
|
636
|
+
let top = y - h - TOOLTIP_OFFSET;
|
|
637
|
+
if (left + w > containerWidth) left = x - w - TOOLTIP_OFFSET;
|
|
638
|
+
if (top < 0) top = y + TOOLTIP_OFFSET;
|
|
639
|
+
if (left < 0) left = 0;
|
|
678
640
|
setPos({ left, top });
|
|
679
|
-
}, [
|
|
641
|
+
}, [x, y, containerWidth, containerHeight]);
|
|
680
642
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
681
643
|
"div",
|
|
682
644
|
{
|
|
683
645
|
ref,
|
|
684
|
-
className:
|
|
685
|
-
style: {
|
|
646
|
+
className: "chart-tooltip chart-tooltip-show",
|
|
647
|
+
style: { left: pos.left, top: pos.top },
|
|
686
648
|
children
|
|
687
649
|
}
|
|
688
650
|
);
|
|
@@ -727,7 +689,7 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
727
689
|
};
|
|
728
690
|
var Chart = import_react.default.memo((props) => {
|
|
729
691
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
730
|
-
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
692
|
+
const { tooltip, show, showAt, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
731
693
|
const { width, height } = useChartSize(containerRef);
|
|
732
694
|
const stableData = import_react.default.useMemo(() => data, [JSON.stringify(data)]);
|
|
733
695
|
const stableLabels = import_react.default.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
@@ -735,13 +697,13 @@ var Chart = import_react.default.memo((props) => {
|
|
|
735
697
|
const animate = useChartAnimation(containerRef, dataKey);
|
|
736
698
|
const ready = width > 0 && height > 0;
|
|
737
699
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
738
|
-
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
739
|
-
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
740
|
-
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
741
|
-
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
742
|
-
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
700
|
+
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
701
|
+
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
702
|
+
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
703
|
+
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
704
|
+
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
743
705
|
ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
744
|
-
tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
706
|
+
tooltip.visible && tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, children: tooltip.content })
|
|
745
707
|
] });
|
|
746
708
|
});
|
|
747
709
|
Chart.displayName = "Chart";
|
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
width: 100%;
|
|
5
5
|
height: 100%;
|
|
6
6
|
position: relative;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
7
9
|
}
|
|
8
10
|
.lib-xplat-chart .chart-svg {
|
|
9
11
|
display: block;
|
|
10
12
|
width: 100%;
|
|
11
|
-
|
|
13
|
+
flex: 1;
|
|
14
|
+
min-height: 0;
|
|
12
15
|
will-change: transform;
|
|
13
16
|
contain: layout style paint;
|
|
14
17
|
}
|
|
@@ -92,7 +95,19 @@
|
|
|
92
95
|
white-space: nowrap;
|
|
93
96
|
overflow: visible;
|
|
94
97
|
}
|
|
98
|
+
.lib-xplat-chart .chart-bar-animate {
|
|
99
|
+
animation: chart-bar-grow 800ms ease-out both;
|
|
100
|
+
}
|
|
101
|
+
.lib-xplat-chart .chart-pie-label-animate {
|
|
102
|
+
opacity: 0;
|
|
103
|
+
animation: chart-fade-in 150ms ease-out both;
|
|
104
|
+
}
|
|
105
|
+
.lib-xplat-chart .chart-area[style*=animationDelay] {
|
|
106
|
+
animation: chart-fade-in 800ms ease-out both;
|
|
107
|
+
}
|
|
95
108
|
.lib-xplat-chart .chart-tooltip {
|
|
109
|
+
position: absolute;
|
|
110
|
+
z-index: 10;
|
|
96
111
|
padding: var(--spacing-space-3);
|
|
97
112
|
background-color: var(--semantic-surface-neutral-strong);
|
|
98
113
|
color: var(--semantic-text-inverse);
|
|
@@ -103,25 +118,8 @@
|
|
|
103
118
|
max-width: 240px;
|
|
104
119
|
pointer-events: none;
|
|
105
120
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
106
|
-
}
|
|
107
|
-
.lib-xplat-chart .chart-tooltip.chart-tooltip-show {
|
|
108
|
-
opacity: 1;
|
|
109
121
|
animation: chart-tooltip-in 120ms ease-out;
|
|
110
122
|
}
|
|
111
|
-
.lib-xplat-chart .chart-tooltip.chart-tooltip-hide {
|
|
112
|
-
opacity: 0;
|
|
113
|
-
animation: chart-tooltip-out 80ms ease-in;
|
|
114
|
-
}
|
|
115
|
-
.lib-xplat-chart .chart-bar-animate {
|
|
116
|
-
animation: chart-bar-grow 800ms ease-out both;
|
|
117
|
-
}
|
|
118
|
-
.lib-xplat-chart .chart-pie-label-animate {
|
|
119
|
-
opacity: 0;
|
|
120
|
-
animation: chart-fade-in 150ms ease-out both;
|
|
121
|
-
}
|
|
122
|
-
.lib-xplat-chart .chart-area[style*=animationDelay] {
|
|
123
|
-
animation: chart-fade-in 800ms ease-out both;
|
|
124
|
-
}
|
|
125
123
|
.lib-xplat-chart .chart-legend {
|
|
126
124
|
display: flex;
|
|
127
125
|
flex-wrap: wrap;
|
|
@@ -178,14 +176,6 @@
|
|
|
178
176
|
opacity: 1;
|
|
179
177
|
}
|
|
180
178
|
}
|
|
181
|
-
@keyframes chart-tooltip-out {
|
|
182
|
-
from {
|
|
183
|
-
opacity: 1;
|
|
184
|
-
}
|
|
185
|
-
to {
|
|
186
|
-
opacity: 0;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
179
|
@media (prefers-reduced-motion: reduce) {
|
|
190
180
|
.lib-xplat-chart .chart-bar-animate,
|
|
191
181
|
.lib-xplat-chart .chart-pie-label-animate,
|
|
@@ -127,8 +127,8 @@ var TOOLTIP_OFFSET = 12;
|
|
|
127
127
|
var useChartTooltip = (enabled) => {
|
|
128
128
|
const [tooltip, setTooltip] = React.useState({
|
|
129
129
|
visible: false,
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
x: 0,
|
|
131
|
+
y: 0,
|
|
132
132
|
content: ""
|
|
133
133
|
});
|
|
134
134
|
const containerRef = React.useRef(null);
|
|
@@ -139,18 +139,26 @@ var useChartTooltip = (enabled) => {
|
|
|
139
139
|
const cy = e.clientY;
|
|
140
140
|
cancelAnimationFrame(rafRef.current);
|
|
141
141
|
rafRef.current = requestAnimationFrame(() => {
|
|
142
|
-
|
|
142
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
143
|
+
if (!rect) return;
|
|
144
|
+
setTooltip((prev) => ({ ...prev, x: cx - rect.left, y: cy - rect.top }));
|
|
143
145
|
});
|
|
144
146
|
}, [enabled]);
|
|
145
147
|
const show = React.useCallback((e, content) => {
|
|
146
148
|
if (!enabled) return;
|
|
147
|
-
|
|
149
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
150
|
+
if (!rect) return;
|
|
151
|
+
setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
|
|
152
|
+
}, [enabled]);
|
|
153
|
+
const showAt = React.useCallback((x, y, content) => {
|
|
154
|
+
if (!enabled) return;
|
|
155
|
+
setTooltip({ visible: true, x, y, content });
|
|
148
156
|
}, [enabled]);
|
|
149
157
|
const hide = React.useCallback(() => {
|
|
150
158
|
cancelAnimationFrame(rafRef.current);
|
|
151
159
|
setTooltip((prev) => ({ ...prev, visible: false }));
|
|
152
160
|
}, []);
|
|
153
|
-
return { tooltip, show, hide, move, containerRef };
|
|
161
|
+
return { tooltip, show, showAt, hide, move, containerRef };
|
|
154
162
|
};
|
|
155
163
|
var GridLines = React.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ jsx(Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
|
|
156
164
|
const y = PADDING.top + (1 - ratio) * chartH;
|
|
@@ -215,7 +223,7 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
215
223
|
}, [entries, seriesPoints]);
|
|
216
224
|
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
217
225
|
};
|
|
218
|
-
var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
226
|
+
var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
|
|
219
227
|
const entries = React.useMemo(() => Object.entries(data), [data]);
|
|
220
228
|
const maxVal = React.useMemo(() => {
|
|
221
229
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -255,23 +263,9 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
|
|
|
255
263
|
className: "chart-svg",
|
|
256
264
|
onMouseMove: (e) => {
|
|
257
265
|
handleMouseMove(e);
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const points = seriesPoints[0];
|
|
262
|
-
if (!points || points.length === 0) return;
|
|
263
|
-
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
264
|
-
let closest = 0;
|
|
265
|
-
let minDist = Math.abs(points[0].x - mx);
|
|
266
|
-
for (let i = 1; i < points.length; i++) {
|
|
267
|
-
const dist = Math.abs(points[i].x - mx);
|
|
268
|
-
if (dist < minDist) {
|
|
269
|
-
minDist = dist;
|
|
270
|
-
closest = i;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (minDist <= step / 2) {
|
|
274
|
-
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
266
|
+
if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
|
|
267
|
+
const p = seriesPoints[0][activeIndex];
|
|
268
|
+
onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
275
269
|
} else {
|
|
276
270
|
onLeave();
|
|
277
271
|
}
|
|
@@ -339,7 +333,7 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
|
|
|
339
333
|
);
|
|
340
334
|
});
|
|
341
335
|
LineChart.displayName = "LineChart";
|
|
342
|
-
var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
336
|
+
var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
|
|
343
337
|
const entries = React.useMemo(() => Object.entries(data), [data]);
|
|
344
338
|
const maxVal = React.useMemo(() => {
|
|
345
339
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -379,23 +373,9 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
379
373
|
className: "chart-svg",
|
|
380
374
|
onMouseMove: (e) => {
|
|
381
375
|
handleMouseMove(e);
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const points = seriesPoints[0];
|
|
386
|
-
if (!points || points.length === 0) return;
|
|
387
|
-
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
388
|
-
let closest = 0;
|
|
389
|
-
let minDist = Math.abs(points[0].x - mx);
|
|
390
|
-
for (let i = 1; i < points.length; i++) {
|
|
391
|
-
const dist = Math.abs(points[i].x - mx);
|
|
392
|
-
if (dist < minDist) {
|
|
393
|
-
minDist = dist;
|
|
394
|
-
closest = i;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
if (minDist <= step / 2) {
|
|
398
|
-
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
376
|
+
if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
|
|
377
|
+
const p = seriesPoints[0][activeIndex];
|
|
378
|
+
onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
399
379
|
} else {
|
|
400
380
|
onLeave();
|
|
401
381
|
}
|
|
@@ -463,7 +443,7 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
463
443
|
);
|
|
464
444
|
});
|
|
465
445
|
CurveChart.displayName = "CurveChart";
|
|
466
|
-
var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
446
|
+
var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
|
|
467
447
|
const entries = React.useMemo(() => Object.entries(data), [data]);
|
|
468
448
|
const maxVal = React.useMemo(() => {
|
|
469
449
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -513,8 +493,7 @@ var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMo
|
|
|
513
493
|
transformOrigin: `${b.x + b.w / 2}px ${baseline}px`,
|
|
514
494
|
animationDelay: `${delay}ms`
|
|
515
495
|
} : void 0,
|
|
516
|
-
onMouseEnter: (
|
|
517
|
-
onMouseMove: onMove,
|
|
496
|
+
onMouseEnter: () => onShowAt(b.x + b.w / 2, b.y, `${key}: ${labels[i]} \u2014 ${b.v}`),
|
|
518
497
|
onMouseLeave: onLeave
|
|
519
498
|
},
|
|
520
499
|
`${di}-${i}`
|
|
@@ -602,30 +581,14 @@ var PieDonutChart = React.memo(
|
|
|
602
581
|
{
|
|
603
582
|
d: s.d,
|
|
604
583
|
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
605
|
-
className: "chart-slice"
|
|
606
|
-
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
607
|
-
onMouseMove: onMove,
|
|
608
|
-
onMouseLeave: onLeave
|
|
584
|
+
className: "chart-slice"
|
|
609
585
|
}
|
|
610
|
-
) }, i)) })
|
|
611
|
-
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ jsx(
|
|
612
|
-
"text",
|
|
613
|
-
{
|
|
614
|
-
x: s.lx,
|
|
615
|
-
y: s.ly,
|
|
616
|
-
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
617
|
-
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
618
|
-
textAnchor: "middle",
|
|
619
|
-
dominantBaseline: "central",
|
|
620
|
-
children: s.v
|
|
621
|
-
},
|
|
622
|
-
`label-${i}`
|
|
623
|
-
))
|
|
586
|
+
) }, i)) })
|
|
624
587
|
] });
|
|
625
588
|
}
|
|
626
589
|
);
|
|
627
590
|
PieDonutChart.displayName = "PieDonutChart";
|
|
628
|
-
var
|
|
591
|
+
var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
|
|
629
592
|
const ref = React.useRef(null);
|
|
630
593
|
const [pos, setPos] = React.useState({ left: 0, top: 0 });
|
|
631
594
|
React.useLayoutEffect(() => {
|
|
@@ -633,20 +596,19 @@ var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
|
|
|
633
596
|
if (!el) return;
|
|
634
597
|
const w = el.offsetWidth;
|
|
635
598
|
const h = el.offsetHeight;
|
|
636
|
-
|
|
637
|
-
let
|
|
638
|
-
|
|
639
|
-
if (
|
|
640
|
-
if (
|
|
641
|
-
if (left < 8) left = 8;
|
|
599
|
+
let left = x + TOOLTIP_OFFSET;
|
|
600
|
+
let top = y - h - TOOLTIP_OFFSET;
|
|
601
|
+
if (left + w > containerWidth) left = x - w - TOOLTIP_OFFSET;
|
|
602
|
+
if (top < 0) top = y + TOOLTIP_OFFSET;
|
|
603
|
+
if (left < 0) left = 0;
|
|
642
604
|
setPos({ left, top });
|
|
643
|
-
}, [
|
|
605
|
+
}, [x, y, containerWidth, containerHeight]);
|
|
644
606
|
return /* @__PURE__ */ jsx(
|
|
645
607
|
"div",
|
|
646
608
|
{
|
|
647
609
|
ref,
|
|
648
|
-
className:
|
|
649
|
-
style: {
|
|
610
|
+
className: "chart-tooltip chart-tooltip-show",
|
|
611
|
+
style: { left: pos.left, top: pos.top },
|
|
650
612
|
children
|
|
651
613
|
}
|
|
652
614
|
);
|
|
@@ -691,7 +653,7 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
691
653
|
};
|
|
692
654
|
var Chart = React.memo((props) => {
|
|
693
655
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
694
|
-
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
656
|
+
const { tooltip, show, showAt, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
695
657
|
const { width, height } = useChartSize(containerRef);
|
|
696
658
|
const stableData = React.useMemo(() => data, [JSON.stringify(data)]);
|
|
697
659
|
const stableLabels = React.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
@@ -699,13 +661,13 @@ var Chart = React.memo((props) => {
|
|
|
699
661
|
const animate = useChartAnimation(containerRef, dataKey);
|
|
700
662
|
const ready = width > 0 && height > 0;
|
|
701
663
|
return /* @__PURE__ */ jsxs("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
702
|
-
ready && type === "line" && /* @__PURE__ */ jsx(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
703
|
-
ready && type === "curve" && /* @__PURE__ */ jsx(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
704
|
-
ready && type === "bar" && /* @__PURE__ */ jsx(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
705
|
-
ready && type === "pie" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
706
|
-
ready && type === "doughnut" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
664
|
+
ready && type === "line" && /* @__PURE__ */ jsx(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
665
|
+
ready && type === "curve" && /* @__PURE__ */ jsx(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
666
|
+
ready && type === "bar" && /* @__PURE__ */ jsx(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
667
|
+
ready && type === "pie" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
668
|
+
ready && type === "doughnut" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
|
|
707
669
|
ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
708
|
-
tooltip.content && /* @__PURE__ */ jsx(
|
|
670
|
+
tooltip.visible && tooltip.content && /* @__PURE__ */ jsx(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, children: tooltip.content })
|
|
709
671
|
] });
|
|
710
672
|
});
|
|
711
673
|
Chart.displayName = "Chart";
|