@x-plat/design-system 0.5.32 → 0.5.34
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 +148 -144
- package/dist/components/Chart/index.css +54 -10
- package/dist/components/Chart/index.js +148 -144
- package/dist/components/index.cjs +148 -144
- package/dist/components/index.css +54 -10
- package/dist/components/index.js +148 -144
- package/dist/index.cjs +148 -144
- package/dist/index.css +54 -10
- package/dist/index.js +148 -144
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6745,45 +6745,35 @@ var useChartAnimation = (containerRef, dataKey) => {
|
|
|
6745
6745
|
prevDataKey.current = dataKey;
|
|
6746
6746
|
if (prefersReducedMotion()) return;
|
|
6747
6747
|
setAnimate(false);
|
|
6748
|
-
requestAnimationFrame(() =>
|
|
6748
|
+
requestAnimationFrame(() => {
|
|
6749
|
+
requestAnimationFrame(() => setAnimate(true));
|
|
6750
|
+
});
|
|
6749
6751
|
}
|
|
6750
6752
|
}, [dataKey]);
|
|
6751
6753
|
return animate || prefersReducedMotion();
|
|
6752
6754
|
};
|
|
6755
|
+
var TOOLTIP_OFFSET = 12;
|
|
6753
6756
|
var useChartTooltip = (enabled) => {
|
|
6754
6757
|
const [tooltip, setTooltip] = import_react6.default.useState({
|
|
6755
6758
|
visible: false,
|
|
6756
|
-
|
|
6757
|
-
|
|
6759
|
+
clientX: 0,
|
|
6760
|
+
clientY: 0,
|
|
6758
6761
|
content: ""
|
|
6759
6762
|
});
|
|
6760
6763
|
const containerRef = import_react6.default.useRef(null);
|
|
6761
6764
|
const rafRef = import_react6.default.useRef(0);
|
|
6762
6765
|
const move = import_react6.default.useCallback((e) => {
|
|
6763
6766
|
if (!enabled) return;
|
|
6764
|
-
const
|
|
6765
|
-
const
|
|
6767
|
+
const cx = e.clientX;
|
|
6768
|
+
const cy = e.clientY;
|
|
6766
6769
|
cancelAnimationFrame(rafRef.current);
|
|
6767
6770
|
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
|
-
}));
|
|
6771
|
+
setTooltip((prev) => ({ ...prev, clientX: cx, clientY: cy }));
|
|
6775
6772
|
});
|
|
6776
6773
|
}, [enabled]);
|
|
6777
6774
|
const show = import_react6.default.useCallback((e, content) => {
|
|
6778
6775
|
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
|
-
});
|
|
6776
|
+
setTooltip({ visible: true, clientX: e.clientX, clientY: e.clientY, content });
|
|
6787
6777
|
}, [enabled]);
|
|
6788
6778
|
const hide = import_react6.default.useCallback(() => {
|
|
6789
6779
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -6817,14 +6807,14 @@ var AxisLabels = import_react6.default.memo(({ labels, count, chartW, height })
|
|
|
6817
6807
|
AxisLabels.displayName = "AxisLabels";
|
|
6818
6808
|
var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
6819
6809
|
const [activeIndex, setActiveIndex] = import_react6.default.useState(null);
|
|
6820
|
-
const [mouseX, setMouseX] = import_react6.default.useState(null);
|
|
6821
6810
|
const handleMouseMove = import_react6.default.useCallback((e) => {
|
|
6822
6811
|
const svg = e.currentTarget;
|
|
6823
6812
|
const rect = svg.getBoundingClientRect();
|
|
6824
6813
|
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
6825
|
-
setMouseX(mx);
|
|
6826
6814
|
if (seriesPoints.length === 0 || seriesPoints[0].length === 0) return;
|
|
6827
6815
|
const points = seriesPoints[0];
|
|
6816
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
6817
|
+
const threshold = step / 2;
|
|
6828
6818
|
let closest = 0;
|
|
6829
6819
|
let minDist = Math.abs(points[0].x - mx);
|
|
6830
6820
|
for (let i = 1; i < points.length; i++) {
|
|
@@ -6834,11 +6824,10 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
6834
6824
|
closest = i;
|
|
6835
6825
|
}
|
|
6836
6826
|
}
|
|
6837
|
-
setActiveIndex(closest);
|
|
6827
|
+
setActiveIndex(minDist <= threshold ? closest : null);
|
|
6838
6828
|
}, [seriesPoints]);
|
|
6839
6829
|
const handleMouseLeave = import_react6.default.useCallback(() => {
|
|
6840
6830
|
setActiveIndex(null);
|
|
6841
|
-
setMouseX(null);
|
|
6842
6831
|
}, []);
|
|
6843
6832
|
const tooltipContent = import_react6.default.useMemo(() => {
|
|
6844
6833
|
if (activeIndex === null) return "";
|
|
@@ -6847,7 +6836,13 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
6847
6836
|
return p ? `${key}: ${p.v}` : "";
|
|
6848
6837
|
}).filter(Boolean).join(" / ");
|
|
6849
6838
|
}, [activeIndex, entries, seriesPoints]);
|
|
6850
|
-
|
|
6839
|
+
const getTooltipAt = import_react6.default.useCallback((idx) => {
|
|
6840
|
+
return entries.map(([key], di) => {
|
|
6841
|
+
const p = seriesPoints[di]?.[idx];
|
|
6842
|
+
return p ? `${key}: ${p.v}` : "";
|
|
6843
|
+
}).filter(Boolean).join(" / ");
|
|
6844
|
+
}, [entries, seriesPoints]);
|
|
6845
|
+
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
6851
6846
|
};
|
|
6852
6847
|
var LineChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
6853
6848
|
const entries = import_react6.default.useMemo(() => Object.entries(data), [data]);
|
|
@@ -6868,33 +6863,19 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
6868
6863
|
),
|
|
6869
6864
|
[entries, count, chartW, chartH, maxVal]
|
|
6870
6865
|
);
|
|
6871
|
-
const lineRefs = import_react6.default.useRef([]);
|
|
6872
6866
|
const clipRef = import_react6.default.useRef(null);
|
|
6873
|
-
const { activeIndex,
|
|
6867
|
+
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
6874
6868
|
import_react6.default.useEffect(() => {
|
|
6875
|
-
if (!animate) return;
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
el.style.transition = "stroke-dashoffset 1200ms ease-out 200ms";
|
|
6883
|
-
el.style.strokeDashoffset = "0";
|
|
6884
|
-
});
|
|
6869
|
+
if (!animate || !clipRef.current) return;
|
|
6870
|
+
clipRef.current.setAttribute("width", "0");
|
|
6871
|
+
requestAnimationFrame(() => {
|
|
6872
|
+
if (clipRef.current) {
|
|
6873
|
+
clipRef.current.style.transition = "width 1200ms ease-out 200ms";
|
|
6874
|
+
clipRef.current.setAttribute("width", `${width}`);
|
|
6875
|
+
}
|
|
6885
6876
|
});
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
requestAnimationFrame(() => {
|
|
6889
|
-
if (clipRef.current) {
|
|
6890
|
-
clipRef.current.style.transition = "width 1200ms ease-out 200ms";
|
|
6891
|
-
clipRef.current.setAttribute("width", `${width}`);
|
|
6892
|
-
}
|
|
6893
|
-
});
|
|
6894
|
-
}
|
|
6895
|
-
}, [animate, seriesPoints, width]);
|
|
6896
|
-
const guideX = mouseX != null && mouseX >= PADDING.left && mouseX <= width - PADDING.right ? mouseX : null;
|
|
6897
|
-
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x : null;
|
|
6877
|
+
}, [animate, width]);
|
|
6878
|
+
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
6898
6879
|
const lineClipId = "line-area-clip";
|
|
6899
6880
|
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)(
|
|
6900
6881
|
"svg",
|
|
@@ -6903,7 +6884,26 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
6903
6884
|
className: "chart-svg",
|
|
6904
6885
|
onMouseMove: (e) => {
|
|
6905
6886
|
handleMouseMove(e);
|
|
6906
|
-
|
|
6887
|
+
const svg = e.currentTarget;
|
|
6888
|
+
const rect = svg.getBoundingClientRect();
|
|
6889
|
+
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
6890
|
+
const points = seriesPoints[0];
|
|
6891
|
+
if (!points || points.length === 0) return;
|
|
6892
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
6893
|
+
let closest = 0;
|
|
6894
|
+
let minDist = Math.abs(points[0].x - mx);
|
|
6895
|
+
for (let i = 1; i < points.length; i++) {
|
|
6896
|
+
const dist = Math.abs(points[i].x - mx);
|
|
6897
|
+
if (dist < minDist) {
|
|
6898
|
+
minDist = dist;
|
|
6899
|
+
closest = i;
|
|
6900
|
+
}
|
|
6901
|
+
}
|
|
6902
|
+
if (minDist <= step / 2) {
|
|
6903
|
+
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
6904
|
+
} else {
|
|
6905
|
+
onLeave();
|
|
6906
|
+
}
|
|
6907
6907
|
},
|
|
6908
6908
|
onMouseLeave: () => {
|
|
6909
6909
|
handleMouseLeave();
|
|
@@ -6926,26 +6926,10 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
6926
6926
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.2" }),
|
|
6927
6927
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0" })
|
|
6928
6928
|
] }) }),
|
|
6929
|
-
/* @__PURE__ */ (0, import_jsx_runtime307.
|
|
6930
|
-
"path",
|
|
6931
|
-
{
|
|
6932
|
-
|
|
6933
|
-
fill: `url(#${gradientId})`,
|
|
6934
|
-
clipPath: animate ? `url(#${lineClipId})` : void 0
|
|
6935
|
-
}
|
|
6936
|
-
),
|
|
6937
|
-
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6938
|
-
"polyline",
|
|
6939
|
-
{
|
|
6940
|
-
ref: (el) => {
|
|
6941
|
-
lineRefs.current[di] = el;
|
|
6942
|
-
},
|
|
6943
|
-
points: polyPoints,
|
|
6944
|
-
fill: "none",
|
|
6945
|
-
stroke: color,
|
|
6946
|
-
strokeWidth: "2"
|
|
6947
|
-
}
|
|
6948
|
-
),
|
|
6929
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("g", { clipPath: animate ? `url(#${lineClipId})` : void 0, children: [
|
|
6930
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("path", { d: areaD, fill: `url(#${gradientId})` }),
|
|
6931
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("polyline", { points: polyPoints, fill: "none", stroke: color, strokeWidth: "2" })
|
|
6932
|
+
] }),
|
|
6949
6933
|
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6950
6934
|
"circle",
|
|
6951
6935
|
{
|
|
@@ -6958,21 +6942,16 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
6958
6942
|
)
|
|
6959
6943
|
] }, di);
|
|
6960
6944
|
}),
|
|
6961
|
-
|
|
6945
|
+
activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6962
6946
|
"line",
|
|
6963
6947
|
{
|
|
6964
|
-
x1:
|
|
6948
|
+
x1: activeX,
|
|
6965
6949
|
y1: PADDING.top,
|
|
6966
|
-
x2:
|
|
6950
|
+
x2: activeX,
|
|
6967
6951
|
y2: PADDING.top + chartH,
|
|
6968
6952
|
className: "chart-crosshair"
|
|
6969
6953
|
}
|
|
6970
6954
|
),
|
|
6971
|
-
activeIndex !== null && activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("foreignObject", { x: activeX - 100, y: 0, width: "200", height: PADDING.top, children: /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-crosshair-label", children: [
|
|
6972
|
-
labels[activeIndex],
|
|
6973
|
-
" \u2014 ",
|
|
6974
|
-
tooltipContent
|
|
6975
|
-
] }) }),
|
|
6976
6955
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
6977
6956
|
"rect",
|
|
6978
6957
|
{
|
|
@@ -7008,33 +6987,19 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
7008
6987
|
),
|
|
7009
6988
|
[entries, count, chartW, chartH, maxVal]
|
|
7010
6989
|
);
|
|
7011
|
-
const lineRefs = import_react6.default.useRef([]);
|
|
7012
6990
|
const curveClipRef = import_react6.default.useRef(null);
|
|
7013
|
-
const { activeIndex,
|
|
6991
|
+
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
7014
6992
|
import_react6.default.useEffect(() => {
|
|
7015
|
-
if (!animate) return;
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
el.style.transition = "stroke-dashoffset 1200ms ease-out 200ms";
|
|
7023
|
-
el.style.strokeDashoffset = "0";
|
|
7024
|
-
});
|
|
6993
|
+
if (!animate || !curveClipRef.current) return;
|
|
6994
|
+
curveClipRef.current.setAttribute("width", "0");
|
|
6995
|
+
requestAnimationFrame(() => {
|
|
6996
|
+
if (curveClipRef.current) {
|
|
6997
|
+
curveClipRef.current.style.transition = "width 1200ms ease-out 200ms";
|
|
6998
|
+
curveClipRef.current.setAttribute("width", `${width}`);
|
|
6999
|
+
}
|
|
7025
7000
|
});
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
requestAnimationFrame(() => {
|
|
7029
|
-
if (curveClipRef.current) {
|
|
7030
|
-
curveClipRef.current.style.transition = "width 1200ms ease-out 200ms";
|
|
7031
|
-
curveClipRef.current.setAttribute("width", `${width}`);
|
|
7032
|
-
}
|
|
7033
|
-
});
|
|
7034
|
-
}
|
|
7035
|
-
}, [animate, seriesPoints, width]);
|
|
7036
|
-
const guideX = mouseX != null && mouseX >= PADDING.left && mouseX <= width - PADDING.right ? mouseX : null;
|
|
7037
|
-
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x : null;
|
|
7001
|
+
}, [animate, width]);
|
|
7002
|
+
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
7038
7003
|
const curveClipId = "curve-area-clip";
|
|
7039
7004
|
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)(
|
|
7040
7005
|
"svg",
|
|
@@ -7043,7 +7008,26 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
7043
7008
|
className: "chart-svg",
|
|
7044
7009
|
onMouseMove: (e) => {
|
|
7045
7010
|
handleMouseMove(e);
|
|
7046
|
-
|
|
7011
|
+
const svg = e.currentTarget;
|
|
7012
|
+
const rect = svg.getBoundingClientRect();
|
|
7013
|
+
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
7014
|
+
const points = seriesPoints[0];
|
|
7015
|
+
if (!points || points.length === 0) return;
|
|
7016
|
+
const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
|
|
7017
|
+
let closest = 0;
|
|
7018
|
+
let minDist = Math.abs(points[0].x - mx);
|
|
7019
|
+
for (let i = 1; i < points.length; i++) {
|
|
7020
|
+
const dist = Math.abs(points[i].x - mx);
|
|
7021
|
+
if (dist < minDist) {
|
|
7022
|
+
minDist = dist;
|
|
7023
|
+
closest = i;
|
|
7024
|
+
}
|
|
7025
|
+
}
|
|
7026
|
+
if (minDist <= step / 2) {
|
|
7027
|
+
onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
|
|
7028
|
+
} else {
|
|
7029
|
+
onLeave();
|
|
7030
|
+
}
|
|
7047
7031
|
},
|
|
7048
7032
|
onMouseLeave: () => {
|
|
7049
7033
|
handleMouseLeave();
|
|
@@ -7066,26 +7050,10 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
7066
7050
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.4" }),
|
|
7067
7051
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0.02" })
|
|
7068
7052
|
] }) }),
|
|
7069
|
-
/* @__PURE__ */ (0, import_jsx_runtime307.
|
|
7070
|
-
"path",
|
|
7071
|
-
{
|
|
7072
|
-
|
|
7073
|
-
fill: `url(#${gradientId})`,
|
|
7074
|
-
clipPath: animate ? `url(#${curveClipId})` : void 0
|
|
7075
|
-
}
|
|
7076
|
-
),
|
|
7077
|
-
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7078
|
-
"path",
|
|
7079
|
-
{
|
|
7080
|
-
ref: (el) => {
|
|
7081
|
-
lineRefs.current[di] = el;
|
|
7082
|
-
},
|
|
7083
|
-
d: linePath,
|
|
7084
|
-
fill: "none",
|
|
7085
|
-
stroke: color,
|
|
7086
|
-
strokeWidth: "2"
|
|
7087
|
-
}
|
|
7088
|
-
),
|
|
7053
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("g", { clipPath: animate ? `url(#${curveClipId})` : void 0, children: [
|
|
7054
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("path", { d: areaPath, fill: `url(#${gradientId})` }),
|
|
7055
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("path", { d: linePath, fill: "none", stroke: color, strokeWidth: "2" })
|
|
7056
|
+
] }),
|
|
7089
7057
|
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7090
7058
|
"circle",
|
|
7091
7059
|
{
|
|
@@ -7098,21 +7066,16 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
7098
7066
|
)
|
|
7099
7067
|
] }, di);
|
|
7100
7068
|
}),
|
|
7101
|
-
|
|
7069
|
+
activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7102
7070
|
"line",
|
|
7103
7071
|
{
|
|
7104
|
-
x1:
|
|
7072
|
+
x1: activeX,
|
|
7105
7073
|
y1: PADDING.top,
|
|
7106
|
-
x2:
|
|
7074
|
+
x2: activeX,
|
|
7107
7075
|
y2: PADDING.top + chartH,
|
|
7108
7076
|
className: "chart-crosshair"
|
|
7109
7077
|
}
|
|
7110
7078
|
),
|
|
7111
|
-
activeIndex !== null && activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("foreignObject", { x: activeX - 100, y: 0, width: "200", height: PADDING.top, children: /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-crosshair-label", children: [
|
|
7112
|
-
labels[activeIndex],
|
|
7113
|
-
" \u2014 ",
|
|
7114
|
-
tooltipContent
|
|
7115
|
-
] }) }),
|
|
7116
7079
|
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7117
7080
|
"rect",
|
|
7118
7081
|
{
|
|
@@ -7291,30 +7254,70 @@ var PieDonutChart = import_react6.default.memo(
|
|
|
7291
7254
|
}
|
|
7292
7255
|
);
|
|
7293
7256
|
PieDonutChart.displayName = "PieDonutChart";
|
|
7294
|
-
var
|
|
7257
|
+
var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
|
|
7295
7258
|
const ref = import_react6.default.useRef(null);
|
|
7296
|
-
const [
|
|
7297
|
-
import_react6.default.
|
|
7259
|
+
const [pos, setPos] = import_react6.default.useState({ left: 0, top: 0 });
|
|
7260
|
+
import_react6.default.useLayoutEffect(() => {
|
|
7298
7261
|
const el = ref.current;
|
|
7299
7262
|
if (!el) return;
|
|
7300
7263
|
const w = el.offsetWidth;
|
|
7301
|
-
const
|
|
7302
|
-
const
|
|
7303
|
-
let
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7264
|
+
const h = el.offsetHeight;
|
|
7265
|
+
const vw = window.innerWidth;
|
|
7266
|
+
let left = clientX + TOOLTIP_OFFSET;
|
|
7267
|
+
let top = clientY - h - TOOLTIP_OFFSET;
|
|
7268
|
+
if (left + w > vw - 8) left = clientX - w - TOOLTIP_OFFSET;
|
|
7269
|
+
if (top < 8) top = clientY + TOOLTIP_OFFSET;
|
|
7270
|
+
if (left < 8) left = 8;
|
|
7271
|
+
setPos({ left, top });
|
|
7272
|
+
}, [clientX, clientY]);
|
|
7308
7273
|
return /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
7309
7274
|
"div",
|
|
7310
7275
|
{
|
|
7311
7276
|
ref,
|
|
7312
|
-
className: "chart-tooltip"
|
|
7313
|
-
style: { left:
|
|
7277
|
+
className: `chart-tooltip ${visible ? "chart-tooltip-show" : "chart-tooltip-hide"}`,
|
|
7278
|
+
style: { position: "fixed", left: pos.left, top: pos.top, zIndex: 1100 },
|
|
7314
7279
|
children
|
|
7315
7280
|
}
|
|
7316
7281
|
);
|
|
7317
7282
|
};
|
|
7283
|
+
var ChartLegend = ({ data, labels, type }) => {
|
|
7284
|
+
const entries = Object.entries(data);
|
|
7285
|
+
if (type === "pie" || type === "doughnut") {
|
|
7286
|
+
const values = entries.flatMap(([, v]) => v);
|
|
7287
|
+
const total = values.reduce((a, b) => a + b, 0) || 1;
|
|
7288
|
+
const firstKey = entries[0]?.[0] ?? "";
|
|
7289
|
+
const colorOffset = hashString(firstKey);
|
|
7290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("div", { className: "chart-legend", children: values.map((v, i) => {
|
|
7291
|
+
const pct = Math.round(v / total * 100);
|
|
7292
|
+
const color = PIE_COLORS[(i + colorOffset) % PIE_COLORS.length];
|
|
7293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-item", children: [
|
|
7294
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
7295
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-text", children: [
|
|
7296
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
|
|
7297
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("span", { className: "chart-legend-value", children: [
|
|
7298
|
+
v.toLocaleString(),
|
|
7299
|
+
"(",
|
|
7300
|
+
pct,
|
|
7301
|
+
"%)"
|
|
7302
|
+
] })
|
|
7303
|
+
] })
|
|
7304
|
+
] }, i);
|
|
7305
|
+
}) });
|
|
7306
|
+
}
|
|
7307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsx)("div", { className: "chart-legend", children: entries.map(([key], di) => {
|
|
7308
|
+
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
7309
|
+
const color = palette[2];
|
|
7310
|
+
const values = entries[di][1];
|
|
7311
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
7312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-item", children: [
|
|
7313
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
7314
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "chart-legend-text", children: [
|
|
7315
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-label", children: key }),
|
|
7316
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)("span", { className: "chart-legend-value", children: sum.toLocaleString() })
|
|
7317
|
+
] })
|
|
7318
|
+
] }, di);
|
|
7319
|
+
}) });
|
|
7320
|
+
};
|
|
7318
7321
|
var Chart = import_react6.default.memo((props) => {
|
|
7319
7322
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
7320
7323
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
@@ -7330,7 +7333,8 @@ var Chart = import_react6.default.memo((props) => {
|
|
|
7330
7333
|
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
7331
7334
|
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
7332
7335
|
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 }),
|
|
7333
|
-
|
|
7336
|
+
ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
7337
|
+
tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content })
|
|
7334
7338
|
] });
|
|
7335
7339
|
});
|
|
7336
7340
|
Chart.displayName = "Chart";
|
package/dist/index.css
CHANGED
|
@@ -2000,9 +2000,9 @@
|
|
|
2000
2000
|
opacity: 1;
|
|
2001
2001
|
}
|
|
2002
2002
|
.lib-xplat-chart .chart-crosshair {
|
|
2003
|
-
stroke: var(--semantic-border-
|
|
2003
|
+
stroke: var(--semantic-border-strong);
|
|
2004
2004
|
stroke-width: 1;
|
|
2005
|
-
stroke-dasharray: 4
|
|
2005
|
+
stroke-dasharray: 4 3;
|
|
2006
2006
|
pointer-events: none;
|
|
2007
2007
|
}
|
|
2008
2008
|
.lib-xplat-chart .chart-point-active {
|
|
@@ -2018,18 +2018,24 @@
|
|
|
2018
2018
|
overflow: visible;
|
|
2019
2019
|
}
|
|
2020
2020
|
.lib-xplat-chart .chart-tooltip {
|
|
2021
|
-
|
|
2022
|
-
transform: translate(-50%, -100%);
|
|
2023
|
-
padding: var(--spacing-space-2) var(--spacing-space-3);
|
|
2021
|
+
padding: var(--spacing-space-3);
|
|
2024
2022
|
background-color: var(--semantic-surface-neutral-strong);
|
|
2025
2023
|
color: var(--semantic-text-inverse);
|
|
2026
2024
|
font-size: 12px;
|
|
2025
|
+
line-height: 18px;
|
|
2027
2026
|
font-weight: 500;
|
|
2028
2027
|
border-radius: var(--spacing-radius-md);
|
|
2029
|
-
|
|
2028
|
+
max-width: 240px;
|
|
2030
2029
|
pointer-events: none;
|
|
2031
|
-
|
|
2032
|
-
|
|
2030
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
2031
|
+
}
|
|
2032
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-show {
|
|
2033
|
+
opacity: 1;
|
|
2034
|
+
animation: chart-tooltip-in 120ms ease-out;
|
|
2035
|
+
}
|
|
2036
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-hide {
|
|
2037
|
+
opacity: 0;
|
|
2038
|
+
animation: chart-tooltip-out 80ms ease-in;
|
|
2033
2039
|
}
|
|
2034
2040
|
.lib-xplat-chart .chart-bar-animate {
|
|
2035
2041
|
animation: chart-bar-grow 800ms ease-out both;
|
|
@@ -2041,6 +2047,38 @@
|
|
|
2041
2047
|
.lib-xplat-chart .chart-area[style*=animationDelay] {
|
|
2042
2048
|
animation: chart-fade-in 800ms ease-out both;
|
|
2043
2049
|
}
|
|
2050
|
+
.lib-xplat-chart .chart-legend {
|
|
2051
|
+
display: flex;
|
|
2052
|
+
flex-wrap: wrap;
|
|
2053
|
+
justify-content: center;
|
|
2054
|
+
gap: var(--spacing-space-4);
|
|
2055
|
+
padding: var(--spacing-space-3) 0;
|
|
2056
|
+
}
|
|
2057
|
+
.lib-xplat-chart .chart-legend-item {
|
|
2058
|
+
display: flex;
|
|
2059
|
+
align-items: flex-start;
|
|
2060
|
+
gap: var(--spacing-space-2);
|
|
2061
|
+
}
|
|
2062
|
+
.lib-xplat-chart .chart-legend-dot {
|
|
2063
|
+
flex-shrink: 0;
|
|
2064
|
+
width: 10px;
|
|
2065
|
+
height: 10px;
|
|
2066
|
+
border-radius: 50%;
|
|
2067
|
+
margin-top: 3px;
|
|
2068
|
+
}
|
|
2069
|
+
.lib-xplat-chart .chart-legend-text {
|
|
2070
|
+
display: flex;
|
|
2071
|
+
flex-direction: column;
|
|
2072
|
+
}
|
|
2073
|
+
.lib-xplat-chart .chart-legend-label {
|
|
2074
|
+
font-size: 12px;
|
|
2075
|
+
color: var(--semantic-text-muted);
|
|
2076
|
+
}
|
|
2077
|
+
.lib-xplat-chart .chart-legend-value {
|
|
2078
|
+
font-size: 14px;
|
|
2079
|
+
font-weight: 600;
|
|
2080
|
+
color: var(--semantic-text-strong);
|
|
2081
|
+
}
|
|
2044
2082
|
@keyframes chart-bar-grow {
|
|
2045
2083
|
from {
|
|
2046
2084
|
transform: scaleY(0);
|
|
@@ -2060,11 +2098,17 @@
|
|
|
2060
2098
|
@keyframes chart-tooltip-in {
|
|
2061
2099
|
from {
|
|
2062
2100
|
opacity: 0;
|
|
2063
|
-
transform: translate(-50%, -90%);
|
|
2064
2101
|
}
|
|
2065
2102
|
to {
|
|
2066
2103
|
opacity: 1;
|
|
2067
|
-
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
@keyframes chart-tooltip-out {
|
|
2107
|
+
from {
|
|
2108
|
+
opacity: 1;
|
|
2109
|
+
}
|
|
2110
|
+
to {
|
|
2111
|
+
opacity: 0;
|
|
2068
2112
|
}
|
|
2069
2113
|
}
|
|
2070
2114
|
@media (prefers-reduced-motion: reduce) {
|