@x-plat/design-system 0.5.31 → 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 +326 -132
- package/dist/components/Chart/index.css +70 -8
- package/dist/components/Chart/index.js +326 -132
- package/dist/components/Table/index.css +4 -0
- package/dist/components/index.cjs +326 -132
- package/dist/components/index.css +74 -8
- package/dist/components/index.js +326 -132
- package/dist/index.cjs +326 -132
- package/dist/index.css +74 -8
- package/dist/index.js +326 -132
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6750,40 +6750,28 @@ var useChartAnimation = (containerRef, dataKey) => {
|
|
|
6750
6750
|
}, [dataKey]);
|
|
6751
6751
|
return animate || prefersReducedMotion();
|
|
6752
6752
|
};
|
|
6753
|
+
var TOOLTIP_OFFSET = 12;
|
|
6753
6754
|
var useChartTooltip = (enabled) => {
|
|
6754
6755
|
const [tooltip, setTooltip] = import_react6.default.useState({
|
|
6755
6756
|
visible: false,
|
|
6756
|
-
|
|
6757
|
-
|
|
6757
|
+
clientX: 0,
|
|
6758
|
+
clientY: 0,
|
|
6758
6759
|
content: ""
|
|
6759
6760
|
});
|
|
6760
6761
|
const containerRef = import_react6.default.useRef(null);
|
|
6761
6762
|
const rafRef = import_react6.default.useRef(0);
|
|
6762
6763
|
const move = import_react6.default.useCallback((e) => {
|
|
6763
6764
|
if (!enabled) return;
|
|
6764
|
-
const
|
|
6765
|
-
const
|
|
6765
|
+
const cx = e.clientX;
|
|
6766
|
+
const cy = e.clientY;
|
|
6766
6767
|
cancelAnimationFrame(rafRef.current);
|
|
6767
6768
|
rafRef.current = requestAnimationFrame(() => {
|
|
6768
|
-
|
|
6769
|
-
if (!rect) return;
|
|
6770
|
-
setTooltip((prev) => ({
|
|
6771
|
-
...prev,
|
|
6772
|
-
x: clientX - rect.left,
|
|
6773
|
-
y: clientY - rect.top - 12
|
|
6774
|
-
}));
|
|
6769
|
+
setTooltip((prev) => ({ ...prev, clientX: cx, clientY: cy }));
|
|
6775
6770
|
});
|
|
6776
6771
|
}, [enabled]);
|
|
6777
6772
|
const show = import_react6.default.useCallback((e, content) => {
|
|
6778
6773
|
if (!enabled) return;
|
|
6779
|
-
|
|
6780
|
-
if (!rect) return;
|
|
6781
|
-
setTooltip({
|
|
6782
|
-
visible: true,
|
|
6783
|
-
x: e.clientX - rect.left,
|
|
6784
|
-
y: e.clientY - rect.top - 12,
|
|
6785
|
-
content
|
|
6786
|
-
});
|
|
6774
|
+
setTooltip({ visible: true, clientX: e.clientX, clientY: e.clientY, content });
|
|
6787
6775
|
}, [enabled]);
|
|
6788
6776
|
const hide = import_react6.default.useCallback(() => {
|
|
6789
6777
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -6815,6 +6803,45 @@ var AxisLabels = import_react6.default.memo(({ labels, count, chartW, height })
|
|
|
6815
6803
|
}) });
|
|
6816
6804
|
});
|
|
6817
6805
|
AxisLabels.displayName = "AxisLabels";
|
|
6806
|
+
var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
6807
|
+
const [activeIndex, setActiveIndex] = import_react6.default.useState(null);
|
|
6808
|
+
const handleMouseMove = import_react6.default.useCallback((e) => {
|
|
6809
|
+
const svg = e.currentTarget;
|
|
6810
|
+
const rect = svg.getBoundingClientRect();
|
|
6811
|
+
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
6812
|
+
if (seriesPoints.length === 0 || seriesPoints[0].length === 0) return;
|
|
6813
|
+
const points = seriesPoints[0];
|
|
6814
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
6815
|
+
const threshold = step / 2;
|
|
6816
|
+
let closest = 0;
|
|
6817
|
+
let minDist = Math.abs(points[0].x - mx);
|
|
6818
|
+
for (let i = 1; i < points.length; i++) {
|
|
6819
|
+
const dist = Math.abs(points[i].x - mx);
|
|
6820
|
+
if (dist < minDist) {
|
|
6821
|
+
minDist = dist;
|
|
6822
|
+
closest = i;
|
|
6823
|
+
}
|
|
6824
|
+
}
|
|
6825
|
+
setActiveIndex(minDist <= threshold ? closest : null);
|
|
6826
|
+
}, [seriesPoints]);
|
|
6827
|
+
const handleMouseLeave = import_react6.default.useCallback(() => {
|
|
6828
|
+
setActiveIndex(null);
|
|
6829
|
+
}, []);
|
|
6830
|
+
const tooltipContent = import_react6.default.useMemo(() => {
|
|
6831
|
+
if (activeIndex === null) return "";
|
|
6832
|
+
return entries.map(([key], di) => {
|
|
6833
|
+
const p = seriesPoints[di]?.[activeIndex];
|
|
6834
|
+
return p ? `${key}: ${p.v}` : "";
|
|
6835
|
+
}).filter(Boolean).join(" / ");
|
|
6836
|
+
}, [activeIndex, entries, seriesPoints]);
|
|
6837
|
+
const getTooltipAt = import_react6.default.useCallback((idx) => {
|
|
6838
|
+
return entries.map(([key], di) => {
|
|
6839
|
+
const p = seriesPoints[di]?.[idx];
|
|
6840
|
+
return p ? `${key}: ${p.v}` : "";
|
|
6841
|
+
}).filter(Boolean).join(" / ");
|
|
6842
|
+
}, [entries, seriesPoints]);
|
|
6843
|
+
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
6844
|
+
};
|
|
6818
6845
|
var LineChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
6819
6846
|
const entries = import_react6.default.useMemo(() => Object.entries(data), [data]);
|
|
6820
6847
|
const maxVal = import_react6.default.useMemo(() => {
|
|
@@ -6834,8 +6861,9 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
6834
6861
|
),
|
|
6835
6862
|
[entries, count, chartW, chartH, maxVal]
|
|
6836
6863
|
);
|
|
6837
|
-
const showPoints = count <= 100;
|
|
6838
6864
|
const lineRefs = import_react6.default.useRef([]);
|
|
6865
|
+
const clipRef = import_react6.default.useRef(null);
|
|
6866
|
+
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
6839
6867
|
import_react6.default.useEffect(() => {
|
|
6840
6868
|
if (!animate) return;
|
|
6841
6869
|
lineRefs.current.forEach((el) => {
|
|
@@ -6848,61 +6876,123 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
6848
6876
|
el.style.strokeDashoffset = "0";
|
|
6849
6877
|
});
|
|
6850
6878
|
});
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6879
|
+
if (clipRef.current) {
|
|
6880
|
+
clipRef.current.setAttribute("width", "0");
|
|
6881
|
+
requestAnimationFrame(() => {
|
|
6882
|
+
if (clipRef.current) {
|
|
6883
|
+
clipRef.current.style.transition = "width 1200ms ease-out 200ms";
|
|
6884
|
+
clipRef.current.setAttribute("width", `${width}`);
|
|
6885
|
+
}
|
|
6886
|
+
});
|
|
6887
|
+
}
|
|
6888
|
+
}, [animate, seriesPoints, width]);
|
|
6889
|
+
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
6890
|
+
const lineClipId = "line-area-clip";
|
|
6891
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)(
|
|
6892
|
+
"svg",
|
|
6893
|
+
{
|
|
6894
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
6895
|
+
className: "chart-svg",
|
|
6896
|
+
onMouseMove: (e) => {
|
|
6897
|
+
handleMouseMove(e);
|
|
6898
|
+
const svg = e.currentTarget;
|
|
6899
|
+
const rect = svg.getBoundingClientRect();
|
|
6900
|
+
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
6901
|
+
const points = seriesPoints[0];
|
|
6902
|
+
if (!points || points.length === 0) return;
|
|
6903
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
6904
|
+
let closest = 0;
|
|
6905
|
+
let minDist = Math.abs(points[0].x - mx);
|
|
6906
|
+
for (let i = 1; i < points.length; i++) {
|
|
6907
|
+
const dist = Math.abs(points[i].x - mx);
|
|
6908
|
+
if (dist < minDist) {
|
|
6909
|
+
minDist = dist;
|
|
6910
|
+
closest = i;
|
|
6911
|
+
}
|
|
6912
|
+
}
|
|
6913
|
+
if (minDist <= step / 2) {
|
|
6914
|
+
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
6915
|
+
} else {
|
|
6916
|
+
onLeave();
|
|
6917
|
+
}
|
|
6918
|
+
},
|
|
6919
|
+
onMouseLeave: () => {
|
|
6920
|
+
handleMouseLeave();
|
|
6921
|
+
onLeave();
|
|
6922
|
+
},
|
|
6923
|
+
children: [
|
|
6924
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("clipPath", { id: lineClipId, children: /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("rect", { ref: clipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
|
|
6925
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(GridLines, { width, height, chartH, maxVal }),
|
|
6926
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(AxisLabels, { labels, count, chartW, height }),
|
|
6927
|
+
entries.map(([key], di) => {
|
|
6928
|
+
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
6929
|
+
const color = palette[2];
|
|
6930
|
+
const areaColor = palette[0];
|
|
6931
|
+
const points = seriesPoints[di];
|
|
6932
|
+
const gradientId = `line-gradient-${di}`;
|
|
6933
|
+
const polyPoints = points.map((p) => `${p.x},${p.y}`).join(" ");
|
|
6934
|
+
const areaD = `M ${points[0].x},${points[0].y} ${points.map((p) => `L ${p.x},${p.y}`).join(" ")} L ${points[points.length - 1].x},${PADDING.top + chartH} L ${points[0].x},${PADDING.top + chartH} Z`;
|
|
6935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("g", { children: [
|
|
6936
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
6937
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.2" }),
|
|
6938
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0" })
|
|
6939
|
+
] }) }),
|
|
6940
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6941
|
+
"path",
|
|
6942
|
+
{
|
|
6943
|
+
d: areaD,
|
|
6944
|
+
fill: `url(#${gradientId})`,
|
|
6945
|
+
clipPath: animate ? `url(#${lineClipId})` : void 0
|
|
6946
|
+
}
|
|
6947
|
+
),
|
|
6948
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6949
|
+
"polyline",
|
|
6950
|
+
{
|
|
6951
|
+
ref: (el) => {
|
|
6952
|
+
lineRefs.current[di] = el;
|
|
6953
|
+
},
|
|
6954
|
+
points: polyPoints,
|
|
6955
|
+
fill: "none",
|
|
6956
|
+
stroke: color,
|
|
6957
|
+
strokeWidth: "2"
|
|
6958
|
+
}
|
|
6959
|
+
),
|
|
6960
|
+
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6961
|
+
"circle",
|
|
6962
|
+
{
|
|
6963
|
+
cx: points[activeIndex].x,
|
|
6964
|
+
cy: points[activeIndex].y,
|
|
6965
|
+
r: "5",
|
|
6966
|
+
fill: color,
|
|
6967
|
+
className: "chart-point-active"
|
|
6968
|
+
}
|
|
6969
|
+
)
|
|
6970
|
+
] }, di);
|
|
6971
|
+
}),
|
|
6972
|
+
activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6973
|
+
"line",
|
|
6870
6974
|
{
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6975
|
+
x1: activeX,
|
|
6976
|
+
y1: PADDING.top,
|
|
6977
|
+
x2: activeX,
|
|
6978
|
+
y2: PADDING.top + chartH,
|
|
6979
|
+
className: "chart-crosshair"
|
|
6875
6980
|
}
|
|
6876
6981
|
),
|
|
6877
6982
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6878
|
-
"
|
|
6983
|
+
"rect",
|
|
6879
6984
|
{
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
fill: "
|
|
6885
|
-
|
|
6886
|
-
strokeWidth: "2"
|
|
6985
|
+
x: PADDING.left,
|
|
6986
|
+
y: PADDING.top,
|
|
6987
|
+
width: chartW,
|
|
6988
|
+
height: chartH,
|
|
6989
|
+
fill: "transparent",
|
|
6990
|
+
style: { cursor: "crosshair" }
|
|
6887
6991
|
}
|
|
6888
|
-
)
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
cx: p.x,
|
|
6893
|
-
cy: p.y,
|
|
6894
|
-
r: "4",
|
|
6895
|
-
fill: color,
|
|
6896
|
-
className: "chart-point",
|
|
6897
|
-
onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${p.v}`),
|
|
6898
|
-
onMouseMove: onMove,
|
|
6899
|
-
onMouseLeave: onLeave
|
|
6900
|
-
},
|
|
6901
|
-
i
|
|
6902
|
-
))
|
|
6903
|
-
] }, di);
|
|
6904
|
-
})
|
|
6905
|
-
] });
|
|
6992
|
+
)
|
|
6993
|
+
]
|
|
6994
|
+
}
|
|
6995
|
+
);
|
|
6906
6996
|
});
|
|
6907
6997
|
LineChart.displayName = "LineChart";
|
|
6908
6998
|
var CurveChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
@@ -6924,8 +7014,9 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
6924
7014
|
),
|
|
6925
7015
|
[entries, count, chartW, chartH, maxVal]
|
|
6926
7016
|
);
|
|
6927
|
-
const showPoints = count <= 100;
|
|
6928
7017
|
const lineRefs = import_react6.default.useRef([]);
|
|
7018
|
+
const curveClipRef = import_react6.default.useRef(null);
|
|
7019
|
+
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
6929
7020
|
import_react6.default.useEffect(() => {
|
|
6930
7021
|
if (!animate) return;
|
|
6931
7022
|
lineRefs.current.forEach((el) => {
|
|
@@ -6938,61 +7029,123 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
6938
7029
|
el.style.strokeDashoffset = "0";
|
|
6939
7030
|
});
|
|
6940
7031
|
});
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
7032
|
+
if (curveClipRef.current) {
|
|
7033
|
+
curveClipRef.current.setAttribute("width", "0");
|
|
7034
|
+
requestAnimationFrame(() => {
|
|
7035
|
+
if (curveClipRef.current) {
|
|
7036
|
+
curveClipRef.current.style.transition = "width 1200ms ease-out 200ms";
|
|
7037
|
+
curveClipRef.current.setAttribute("width", `${width}`);
|
|
7038
|
+
}
|
|
7039
|
+
});
|
|
7040
|
+
}
|
|
7041
|
+
}, [animate, seriesPoints, width]);
|
|
7042
|
+
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
7043
|
+
const curveClipId = "curve-area-clip";
|
|
7044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)(
|
|
7045
|
+
"svg",
|
|
7046
|
+
{
|
|
7047
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
7048
|
+
className: "chart-svg",
|
|
7049
|
+
onMouseMove: (e) => {
|
|
7050
|
+
handleMouseMove(e);
|
|
7051
|
+
const svg = e.currentTarget;
|
|
7052
|
+
const rect = svg.getBoundingClientRect();
|
|
7053
|
+
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
7054
|
+
const points = seriesPoints[0];
|
|
7055
|
+
if (!points || points.length === 0) return;
|
|
7056
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
7057
|
+
let closest = 0;
|
|
7058
|
+
let minDist = Math.abs(points[0].x - mx);
|
|
7059
|
+
for (let i = 1; i < points.length; i++) {
|
|
7060
|
+
const dist = Math.abs(points[i].x - mx);
|
|
7061
|
+
if (dist < minDist) {
|
|
7062
|
+
minDist = dist;
|
|
7063
|
+
closest = i;
|
|
7064
|
+
}
|
|
7065
|
+
}
|
|
7066
|
+
if (minDist <= step / 2) {
|
|
7067
|
+
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
7068
|
+
} else {
|
|
7069
|
+
onLeave();
|
|
7070
|
+
}
|
|
7071
|
+
},
|
|
7072
|
+
onMouseLeave: () => {
|
|
7073
|
+
handleMouseLeave();
|
|
7074
|
+
onLeave();
|
|
7075
|
+
},
|
|
7076
|
+
children: [
|
|
7077
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("clipPath", { id: curveClipId, children: /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("rect", { ref: curveClipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
|
|
7078
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(GridLines, { width, height, chartH, maxVal }),
|
|
7079
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(AxisLabels, { labels, count, chartW, height }),
|
|
7080
|
+
entries.map(([key], di) => {
|
|
7081
|
+
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
7082
|
+
const color = palette[2];
|
|
7083
|
+
const areaColor = palette[0];
|
|
7084
|
+
const points = seriesPoints[di];
|
|
7085
|
+
const gradientId = `curve-gradient-${di}`;
|
|
7086
|
+
const linePath = toSmoothPath(points);
|
|
7087
|
+
const areaPath = linePath + ` L ${points[points.length - 1].x} ${PADDING.top + chartH} L ${points[0].x} ${PADDING.top + chartH} Z`;
|
|
7088
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("g", { children: [
|
|
7089
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
7090
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.4" }),
|
|
7091
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0.02" })
|
|
7092
|
+
] }) }),
|
|
7093
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7094
|
+
"path",
|
|
7095
|
+
{
|
|
7096
|
+
d: areaPath,
|
|
7097
|
+
fill: `url(#${gradientId})`,
|
|
7098
|
+
clipPath: animate ? `url(#${curveClipId})` : void 0
|
|
7099
|
+
}
|
|
7100
|
+
),
|
|
7101
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7102
|
+
"path",
|
|
7103
|
+
{
|
|
7104
|
+
ref: (el) => {
|
|
7105
|
+
lineRefs.current[di] = el;
|
|
7106
|
+
},
|
|
7107
|
+
d: linePath,
|
|
7108
|
+
fill: "none",
|
|
7109
|
+
stroke: color,
|
|
7110
|
+
strokeWidth: "2"
|
|
7111
|
+
}
|
|
7112
|
+
),
|
|
7113
|
+
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7114
|
+
"circle",
|
|
7115
|
+
{
|
|
7116
|
+
cx: points[activeIndex].x,
|
|
7117
|
+
cy: points[activeIndex].y,
|
|
7118
|
+
r: "5",
|
|
7119
|
+
fill: color,
|
|
7120
|
+
className: "chart-point-active"
|
|
7121
|
+
}
|
|
7122
|
+
)
|
|
7123
|
+
] }, di);
|
|
7124
|
+
}),
|
|
7125
|
+
activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7126
|
+
"line",
|
|
6960
7127
|
{
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
7128
|
+
x1: activeX,
|
|
7129
|
+
y1: PADDING.top,
|
|
7130
|
+
x2: activeX,
|
|
7131
|
+
y2: PADDING.top + chartH,
|
|
7132
|
+
className: "chart-crosshair"
|
|
6965
7133
|
}
|
|
6966
7134
|
),
|
|
6967
7135
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6968
|
-
"
|
|
7136
|
+
"rect",
|
|
6969
7137
|
{
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
fill: "
|
|
6975
|
-
|
|
6976
|
-
strokeWidth: "2"
|
|
7138
|
+
x: PADDING.left,
|
|
7139
|
+
y: PADDING.top,
|
|
7140
|
+
width: chartW,
|
|
7141
|
+
height: chartH,
|
|
7142
|
+
fill: "transparent",
|
|
7143
|
+
style: { cursor: "crosshair" }
|
|
6977
7144
|
}
|
|
6978
|
-
)
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
cx: p.x,
|
|
6983
|
-
cy: p.y,
|
|
6984
|
-
r: "4",
|
|
6985
|
-
fill: color,
|
|
6986
|
-
className: "chart-point",
|
|
6987
|
-
onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${p.v}`),
|
|
6988
|
-
onMouseMove: onMove,
|
|
6989
|
-
onMouseLeave: onLeave
|
|
6990
|
-
},
|
|
6991
|
-
i
|
|
6992
|
-
))
|
|
6993
|
-
] }, di);
|
|
6994
|
-
})
|
|
6995
|
-
] });
|
|
7145
|
+
)
|
|
7146
|
+
]
|
|
7147
|
+
}
|
|
7148
|
+
);
|
|
6996
7149
|
});
|
|
6997
7150
|
CurveChart.displayName = "CurveChart";
|
|
6998
7151
|
var BarChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
@@ -7157,30 +7310,70 @@ var PieDonutChart = import_react6.default.memo(
|
|
|
7157
7310
|
}
|
|
7158
7311
|
);
|
|
7159
7312
|
PieDonutChart.displayName = "PieDonutChart";
|
|
7160
|
-
var
|
|
7313
|
+
var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
|
|
7161
7314
|
const ref = import_react6.default.useRef(null);
|
|
7162
|
-
const [
|
|
7163
|
-
import_react6.default.
|
|
7315
|
+
const [pos, setPos] = import_react6.default.useState({ left: 0, top: 0 });
|
|
7316
|
+
import_react6.default.useLayoutEffect(() => {
|
|
7164
7317
|
const el = ref.current;
|
|
7165
7318
|
if (!el) return;
|
|
7166
7319
|
const w = el.offsetWidth;
|
|
7167
|
-
const
|
|
7168
|
-
const
|
|
7169
|
-
let
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7320
|
+
const h = el.offsetHeight;
|
|
7321
|
+
const vw = window.innerWidth;
|
|
7322
|
+
let left = clientX + TOOLTIP_OFFSET;
|
|
7323
|
+
let top = clientY - h - TOOLTIP_OFFSET;
|
|
7324
|
+
if (left + w > vw - 8) left = clientX - w - TOOLTIP_OFFSET;
|
|
7325
|
+
if (top < 8) top = clientY + TOOLTIP_OFFSET;
|
|
7326
|
+
if (left < 8) left = 8;
|
|
7327
|
+
setPos({ left, top });
|
|
7328
|
+
}, [clientX, clientY]);
|
|
7174
7329
|
return /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7175
7330
|
"div",
|
|
7176
7331
|
{
|
|
7177
7332
|
ref,
|
|
7178
|
-
className: "chart-tooltip"
|
|
7179
|
-
style: { left:
|
|
7333
|
+
className: `chart-tooltip ${visible ? "chart-tooltip-show" : "chart-tooltip-hide"}`,
|
|
7334
|
+
style: { position: "fixed", left: pos.left, top: pos.top, zIndex: 1100 },
|
|
7180
7335
|
children
|
|
7181
7336
|
}
|
|
7182
7337
|
);
|
|
7183
7338
|
};
|
|
7339
|
+
var ChartLegend = ({ data, labels, type }) => {
|
|
7340
|
+
const entries = Object.entries(data);
|
|
7341
|
+
if (type === "pie" || type === "doughnut") {
|
|
7342
|
+
const values = entries.flatMap(([, v]) => v);
|
|
7343
|
+
const total = values.reduce((a, b) => a + b, 0) || 1;
|
|
7344
|
+
const firstKey = entries[0]?.[0] ?? "";
|
|
7345
|
+
const colorOffset = hashString(firstKey);
|
|
7346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("div", { className: "chart-legend", children: values.map((v, i) => {
|
|
7347
|
+
const pct = Math.round(v / total * 100);
|
|
7348
|
+
const color = PIE_COLORS[(i + colorOffset) % PIE_COLORS.length];
|
|
7349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-item", children: [
|
|
7350
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
7351
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-text", children: [
|
|
7352
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
|
|
7353
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("span", { className: "chart-legend-value", children: [
|
|
7354
|
+
v.toLocaleString(),
|
|
7355
|
+
"(",
|
|
7356
|
+
pct,
|
|
7357
|
+
"%)"
|
|
7358
|
+
] })
|
|
7359
|
+
] })
|
|
7360
|
+
] }, i);
|
|
7361
|
+
}) });
|
|
7362
|
+
}
|
|
7363
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("div", { className: "chart-legend", children: entries.map(([key], di) => {
|
|
7364
|
+
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
7365
|
+
const color = palette[2];
|
|
7366
|
+
const values = entries[di][1];
|
|
7367
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
7368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-item", children: [
|
|
7369
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
7370
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-text", children: [
|
|
7371
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-label", children: key }),
|
|
7372
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-value", children: sum.toLocaleString() })
|
|
7373
|
+
] })
|
|
7374
|
+
] }, di);
|
|
7375
|
+
}) });
|
|
7376
|
+
};
|
|
7184
7377
|
var Chart = import_react6.default.memo((props) => {
|
|
7185
7378
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
7186
7379
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
@@ -7196,7 +7389,8 @@ var Chart = import_react6.default.memo((props) => {
|
|
|
7196
7389
|
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
7197
7390
|
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
7198
7391
|
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
7199
|
-
|
|
7392
|
+
ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
7393
|
+
tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content })
|
|
7200
7394
|
] });
|
|
7201
7395
|
});
|
|
7202
7396
|
Chart.displayName = "Chart";
|