@x-plat/design-system 0.5.32 → 0.5.33
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 +121 -61
- package/dist/components/Chart/index.css +54 -10
- package/dist/components/Chart/index.js +121 -61
- package/dist/components/index.cjs +121 -61
- package/dist/components/index.css +54 -10
- package/dist/components/index.js +121 -61
- package/dist/index.cjs +121 -61
- package/dist/index.css +54 -10
- package/dist/index.js +121 -61
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6351,40 +6351,28 @@ var useChartAnimation = (containerRef, dataKey) => {
|
|
|
6351
6351
|
}, [dataKey]);
|
|
6352
6352
|
return animate || prefersReducedMotion();
|
|
6353
6353
|
};
|
|
6354
|
+
var TOOLTIP_OFFSET = 12;
|
|
6354
6355
|
var useChartTooltip = (enabled) => {
|
|
6355
6356
|
const [tooltip, setTooltip] = React6.useState({
|
|
6356
6357
|
visible: false,
|
|
6357
|
-
|
|
6358
|
-
|
|
6358
|
+
clientX: 0,
|
|
6359
|
+
clientY: 0,
|
|
6359
6360
|
content: ""
|
|
6360
6361
|
});
|
|
6361
6362
|
const containerRef = React6.useRef(null);
|
|
6362
6363
|
const rafRef = React6.useRef(0);
|
|
6363
6364
|
const move = React6.useCallback((e) => {
|
|
6364
6365
|
if (!enabled) return;
|
|
6365
|
-
const
|
|
6366
|
-
const
|
|
6366
|
+
const cx = e.clientX;
|
|
6367
|
+
const cy = e.clientY;
|
|
6367
6368
|
cancelAnimationFrame(rafRef.current);
|
|
6368
6369
|
rafRef.current = requestAnimationFrame(() => {
|
|
6369
|
-
|
|
6370
|
-
if (!rect) return;
|
|
6371
|
-
setTooltip((prev) => ({
|
|
6372
|
-
...prev,
|
|
6373
|
-
x: clientX - rect.left,
|
|
6374
|
-
y: clientY - rect.top - 12
|
|
6375
|
-
}));
|
|
6370
|
+
setTooltip((prev) => ({ ...prev, clientX: cx, clientY: cy }));
|
|
6376
6371
|
});
|
|
6377
6372
|
}, [enabled]);
|
|
6378
6373
|
const show = React6.useCallback((e, content) => {
|
|
6379
6374
|
if (!enabled) return;
|
|
6380
|
-
|
|
6381
|
-
if (!rect) return;
|
|
6382
|
-
setTooltip({
|
|
6383
|
-
visible: true,
|
|
6384
|
-
x: e.clientX - rect.left,
|
|
6385
|
-
y: e.clientY - rect.top - 12,
|
|
6386
|
-
content
|
|
6387
|
-
});
|
|
6375
|
+
setTooltip({ visible: true, clientX: e.clientX, clientY: e.clientY, content });
|
|
6388
6376
|
}, [enabled]);
|
|
6389
6377
|
const hide = React6.useCallback(() => {
|
|
6390
6378
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -6418,14 +6406,14 @@ var AxisLabels = React6.memo(({ labels, count, chartW, height }) => {
|
|
|
6418
6406
|
AxisLabels.displayName = "AxisLabels";
|
|
6419
6407
|
var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
6420
6408
|
const [activeIndex, setActiveIndex] = React6.useState(null);
|
|
6421
|
-
const [mouseX, setMouseX] = React6.useState(null);
|
|
6422
6409
|
const handleMouseMove = React6.useCallback((e) => {
|
|
6423
6410
|
const svg = e.currentTarget;
|
|
6424
6411
|
const rect = svg.getBoundingClientRect();
|
|
6425
6412
|
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
6426
|
-
setMouseX(mx);
|
|
6427
6413
|
if (seriesPoints.length === 0 || seriesPoints[0].length === 0) return;
|
|
6428
6414
|
const points = seriesPoints[0];
|
|
6415
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
6416
|
+
const threshold = step / 2;
|
|
6429
6417
|
let closest = 0;
|
|
6430
6418
|
let minDist = Math.abs(points[0].x - mx);
|
|
6431
6419
|
for (let i = 1; i < points.length; i++) {
|
|
@@ -6435,11 +6423,10 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
6435
6423
|
closest = i;
|
|
6436
6424
|
}
|
|
6437
6425
|
}
|
|
6438
|
-
setActiveIndex(closest);
|
|
6426
|
+
setActiveIndex(minDist <= threshold ? closest : null);
|
|
6439
6427
|
}, [seriesPoints]);
|
|
6440
6428
|
const handleMouseLeave = React6.useCallback(() => {
|
|
6441
6429
|
setActiveIndex(null);
|
|
6442
|
-
setMouseX(null);
|
|
6443
6430
|
}, []);
|
|
6444
6431
|
const tooltipContent = React6.useMemo(() => {
|
|
6445
6432
|
if (activeIndex === null) return "";
|
|
@@ -6448,7 +6435,13 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
6448
6435
|
return p ? `${key}: ${p.v}` : "";
|
|
6449
6436
|
}).filter(Boolean).join(" / ");
|
|
6450
6437
|
}, [activeIndex, entries, seriesPoints]);
|
|
6451
|
-
|
|
6438
|
+
const getTooltipAt = React6.useCallback((idx) => {
|
|
6439
|
+
return entries.map(([key], di) => {
|
|
6440
|
+
const p = seriesPoints[di]?.[idx];
|
|
6441
|
+
return p ? `${key}: ${p.v}` : "";
|
|
6442
|
+
}).filter(Boolean).join(" / ");
|
|
6443
|
+
}, [entries, seriesPoints]);
|
|
6444
|
+
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
6452
6445
|
};
|
|
6453
6446
|
var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
6454
6447
|
const entries = React6.useMemo(() => Object.entries(data), [data]);
|
|
@@ -6471,7 +6464,7 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6471
6464
|
);
|
|
6472
6465
|
const lineRefs = React6.useRef([]);
|
|
6473
6466
|
const clipRef = React6.useRef(null);
|
|
6474
|
-
const { activeIndex,
|
|
6467
|
+
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
6475
6468
|
React6.useEffect(() => {
|
|
6476
6469
|
if (!animate) return;
|
|
6477
6470
|
lineRefs.current.forEach((el) => {
|
|
@@ -6494,8 +6487,7 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6494
6487
|
});
|
|
6495
6488
|
}
|
|
6496
6489
|
}, [animate, seriesPoints, width]);
|
|
6497
|
-
const
|
|
6498
|
-
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x : null;
|
|
6490
|
+
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
6499
6491
|
const lineClipId = "line-area-clip";
|
|
6500
6492
|
return /* @__PURE__ */ jsxs197(
|
|
6501
6493
|
"svg",
|
|
@@ -6504,7 +6496,26 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6504
6496
|
className: "chart-svg",
|
|
6505
6497
|
onMouseMove: (e) => {
|
|
6506
6498
|
handleMouseMove(e);
|
|
6507
|
-
|
|
6499
|
+
const svg = e.currentTarget;
|
|
6500
|
+
const rect = svg.getBoundingClientRect();
|
|
6501
|
+
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
6502
|
+
const points = seriesPoints[0];
|
|
6503
|
+
if (!points || points.length === 0) return;
|
|
6504
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
6505
|
+
let closest = 0;
|
|
6506
|
+
let minDist = Math.abs(points[0].x - mx);
|
|
6507
|
+
for (let i = 1; i < points.length; i++) {
|
|
6508
|
+
const dist = Math.abs(points[i].x - mx);
|
|
6509
|
+
if (dist < minDist) {
|
|
6510
|
+
minDist = dist;
|
|
6511
|
+
closest = i;
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
if (minDist <= step / 2) {
|
|
6515
|
+
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
6516
|
+
} else {
|
|
6517
|
+
onLeave();
|
|
6518
|
+
}
|
|
6508
6519
|
},
|
|
6509
6520
|
onMouseLeave: () => {
|
|
6510
6521
|
handleMouseLeave();
|
|
@@ -6559,21 +6570,16 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6559
6570
|
)
|
|
6560
6571
|
] }, di);
|
|
6561
6572
|
}),
|
|
6562
|
-
|
|
6573
|
+
activeX !== null && /* @__PURE__ */ jsx307(
|
|
6563
6574
|
"line",
|
|
6564
6575
|
{
|
|
6565
|
-
x1:
|
|
6576
|
+
x1: activeX,
|
|
6566
6577
|
y1: PADDING.top,
|
|
6567
|
-
x2:
|
|
6578
|
+
x2: activeX,
|
|
6568
6579
|
y2: PADDING.top + chartH,
|
|
6569
6580
|
className: "chart-crosshair"
|
|
6570
6581
|
}
|
|
6571
6582
|
),
|
|
6572
|
-
activeIndex !== null && activeX !== null && /* @__PURE__ */ jsx307("foreignObject", { x: activeX - 100, y: 0, width: "200", height: PADDING.top, children: /* @__PURE__ */ jsxs197("div", { className: "chart-crosshair-label", children: [
|
|
6573
|
-
labels[activeIndex],
|
|
6574
|
-
" \u2014 ",
|
|
6575
|
-
tooltipContent
|
|
6576
|
-
] }) }),
|
|
6577
6583
|
/* @__PURE__ */ jsx307(
|
|
6578
6584
|
"rect",
|
|
6579
6585
|
{
|
|
@@ -6611,7 +6617,7 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6611
6617
|
);
|
|
6612
6618
|
const lineRefs = React6.useRef([]);
|
|
6613
6619
|
const curveClipRef = React6.useRef(null);
|
|
6614
|
-
const { activeIndex,
|
|
6620
|
+
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
6615
6621
|
React6.useEffect(() => {
|
|
6616
6622
|
if (!animate) return;
|
|
6617
6623
|
lineRefs.current.forEach((el) => {
|
|
@@ -6634,8 +6640,7 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6634
6640
|
});
|
|
6635
6641
|
}
|
|
6636
6642
|
}, [animate, seriesPoints, width]);
|
|
6637
|
-
const
|
|
6638
|
-
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x : null;
|
|
6643
|
+
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
6639
6644
|
const curveClipId = "curve-area-clip";
|
|
6640
6645
|
return /* @__PURE__ */ jsxs197(
|
|
6641
6646
|
"svg",
|
|
@@ -6644,7 +6649,26 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6644
6649
|
className: "chart-svg",
|
|
6645
6650
|
onMouseMove: (e) => {
|
|
6646
6651
|
handleMouseMove(e);
|
|
6647
|
-
|
|
6652
|
+
const svg = e.currentTarget;
|
|
6653
|
+
const rect = svg.getBoundingClientRect();
|
|
6654
|
+
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
6655
|
+
const points = seriesPoints[0];
|
|
6656
|
+
if (!points || points.length === 0) return;
|
|
6657
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
6658
|
+
let closest = 0;
|
|
6659
|
+
let minDist = Math.abs(points[0].x - mx);
|
|
6660
|
+
for (let i = 1; i < points.length; i++) {
|
|
6661
|
+
const dist = Math.abs(points[i].x - mx);
|
|
6662
|
+
if (dist < minDist) {
|
|
6663
|
+
minDist = dist;
|
|
6664
|
+
closest = i;
|
|
6665
|
+
}
|
|
6666
|
+
}
|
|
6667
|
+
if (minDist <= step / 2) {
|
|
6668
|
+
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
6669
|
+
} else {
|
|
6670
|
+
onLeave();
|
|
6671
|
+
}
|
|
6648
6672
|
},
|
|
6649
6673
|
onMouseLeave: () => {
|
|
6650
6674
|
handleMouseLeave();
|
|
@@ -6699,21 +6723,16 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6699
6723
|
)
|
|
6700
6724
|
] }, di);
|
|
6701
6725
|
}),
|
|
6702
|
-
|
|
6726
|
+
activeX !== null && /* @__PURE__ */ jsx307(
|
|
6703
6727
|
"line",
|
|
6704
6728
|
{
|
|
6705
|
-
x1:
|
|
6729
|
+
x1: activeX,
|
|
6706
6730
|
y1: PADDING.top,
|
|
6707
|
-
x2:
|
|
6731
|
+
x2: activeX,
|
|
6708
6732
|
y2: PADDING.top + chartH,
|
|
6709
6733
|
className: "chart-crosshair"
|
|
6710
6734
|
}
|
|
6711
6735
|
),
|
|
6712
|
-
activeIndex !== null && activeX !== null && /* @__PURE__ */ jsx307("foreignObject", { x: activeX - 100, y: 0, width: "200", height: PADDING.top, children: /* @__PURE__ */ jsxs197("div", { className: "chart-crosshair-label", children: [
|
|
6713
|
-
labels[activeIndex],
|
|
6714
|
-
" \u2014 ",
|
|
6715
|
-
tooltipContent
|
|
6716
|
-
] }) }),
|
|
6717
6736
|
/* @__PURE__ */ jsx307(
|
|
6718
6737
|
"rect",
|
|
6719
6738
|
{
|
|
@@ -6892,30 +6911,70 @@ var PieDonutChart = React6.memo(
|
|
|
6892
6911
|
}
|
|
6893
6912
|
);
|
|
6894
6913
|
PieDonutChart.displayName = "PieDonutChart";
|
|
6895
|
-
var
|
|
6914
|
+
var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
|
|
6896
6915
|
const ref = React6.useRef(null);
|
|
6897
|
-
const [
|
|
6898
|
-
React6.
|
|
6916
|
+
const [pos, setPos] = React6.useState({ left: 0, top: 0 });
|
|
6917
|
+
React6.useLayoutEffect(() => {
|
|
6899
6918
|
const el = ref.current;
|
|
6900
6919
|
if (!el) return;
|
|
6901
6920
|
const w = el.offsetWidth;
|
|
6902
|
-
const
|
|
6903
|
-
const
|
|
6904
|
-
let
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6921
|
+
const h = el.offsetHeight;
|
|
6922
|
+
const vw = window.innerWidth;
|
|
6923
|
+
let left = clientX + TOOLTIP_OFFSET;
|
|
6924
|
+
let top = clientY - h - TOOLTIP_OFFSET;
|
|
6925
|
+
if (left + w > vw - 8) left = clientX - w - TOOLTIP_OFFSET;
|
|
6926
|
+
if (top < 8) top = clientY + TOOLTIP_OFFSET;
|
|
6927
|
+
if (left < 8) left = 8;
|
|
6928
|
+
setPos({ left, top });
|
|
6929
|
+
}, [clientX, clientY]);
|
|
6909
6930
|
return /* @__PURE__ */ jsx307(
|
|
6910
6931
|
"div",
|
|
6911
6932
|
{
|
|
6912
6933
|
ref,
|
|
6913
|
-
className: "chart-tooltip"
|
|
6914
|
-
style: { left:
|
|
6934
|
+
className: `chart-tooltip ${visible ? "chart-tooltip-show" : "chart-tooltip-hide"}`,
|
|
6935
|
+
style: { position: "fixed", left: pos.left, top: pos.top, zIndex: 1100 },
|
|
6915
6936
|
children
|
|
6916
6937
|
}
|
|
6917
6938
|
);
|
|
6918
6939
|
};
|
|
6940
|
+
var ChartLegend = ({ data, labels, type }) => {
|
|
6941
|
+
const entries = Object.entries(data);
|
|
6942
|
+
if (type === "pie" || type === "doughnut") {
|
|
6943
|
+
const values = entries.flatMap(([, v]) => v);
|
|
6944
|
+
const total = values.reduce((a, b) => a + b, 0) || 1;
|
|
6945
|
+
const firstKey = entries[0]?.[0] ?? "";
|
|
6946
|
+
const colorOffset = hashString(firstKey);
|
|
6947
|
+
return /* @__PURE__ */ jsx307("div", { className: "chart-legend", children: values.map((v, i) => {
|
|
6948
|
+
const pct = Math.round(v / total * 100);
|
|
6949
|
+
const color = PIE_COLORS[(i + colorOffset) % PIE_COLORS.length];
|
|
6950
|
+
return /* @__PURE__ */ jsxs197("div", { className: "chart-legend-item", children: [
|
|
6951
|
+
/* @__PURE__ */ jsx307("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
6952
|
+
/* @__PURE__ */ jsxs197("div", { className: "chart-legend-text", children: [
|
|
6953
|
+
/* @__PURE__ */ jsx307("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
|
|
6954
|
+
/* @__PURE__ */ jsxs197("span", { className: "chart-legend-value", children: [
|
|
6955
|
+
v.toLocaleString(),
|
|
6956
|
+
"(",
|
|
6957
|
+
pct,
|
|
6958
|
+
"%)"
|
|
6959
|
+
] })
|
|
6960
|
+
] })
|
|
6961
|
+
] }, i);
|
|
6962
|
+
}) });
|
|
6963
|
+
}
|
|
6964
|
+
return /* @__PURE__ */ jsx307("div", { className: "chart-legend", children: entries.map(([key], di) => {
|
|
6965
|
+
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
6966
|
+
const color = palette[2];
|
|
6967
|
+
const values = entries[di][1];
|
|
6968
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
6969
|
+
return /* @__PURE__ */ jsxs197("div", { className: "chart-legend-item", children: [
|
|
6970
|
+
/* @__PURE__ */ jsx307("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
6971
|
+
/* @__PURE__ */ jsxs197("div", { className: "chart-legend-text", children: [
|
|
6972
|
+
/* @__PURE__ */ jsx307("span", { className: "chart-legend-label", children: key }),
|
|
6973
|
+
/* @__PURE__ */ jsx307("span", { className: "chart-legend-value", children: sum.toLocaleString() })
|
|
6974
|
+
] })
|
|
6975
|
+
] }, di);
|
|
6976
|
+
}) });
|
|
6977
|
+
};
|
|
6919
6978
|
var Chart = React6.memo((props) => {
|
|
6920
6979
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
6921
6980
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
@@ -6931,7 +6990,8 @@ var Chart = React6.memo((props) => {
|
|
|
6931
6990
|
ready && type === "bar" && /* @__PURE__ */ jsx307(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
6932
6991
|
ready && type === "pie" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
6933
6992
|
ready && type === "doughnut" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
6934
|
-
|
|
6993
|
+
ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx307(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
6994
|
+
tooltip.content && /* @__PURE__ */ jsx307(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content })
|
|
6935
6995
|
] });
|
|
6936
6996
|
});
|
|
6937
6997
|
Chart.displayName = "Chart";
|