@x-plat/design-system 0.5.20 → 0.5.21
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 +58 -29
- package/dist/components/Chart/index.css +2 -15
- package/dist/components/Chart/index.js +58 -29
- package/dist/components/Dropdown/index.cjs +9 -0
- package/dist/components/Dropdown/index.js +9 -0
- package/dist/components/PopOver/index.cjs +9 -0
- package/dist/components/PopOver/index.js +9 -0
- package/dist/components/Select/index.cjs +9 -0
- package/dist/components/Select/index.js +9 -0
- package/dist/components/index.cjs +67 -29
- package/dist/components/index.css +2 -15
- package/dist/components/index.js +67 -29
- package/dist/index.cjs +67 -29
- package/dist/index.css +2 -15
- package/dist/index.js +67 -29
- package/package.json +1 -1
|
@@ -475,8 +475,22 @@ var PieDonutChart = import_react.default.memo(
|
|
|
475
475
|
const innerR = isDoughnut ? r * 0.5 : 0;
|
|
476
476
|
const firstKey = entries[0]?.[0] ?? "";
|
|
477
477
|
const colorOffset = hashString(firstKey);
|
|
478
|
+
const maskRef = import_react.default.useRef(null);
|
|
479
|
+
const maskR = r + 10;
|
|
480
|
+
const maskCircumference = 2 * Math.PI * maskR;
|
|
481
|
+
import_react.default.useEffect(() => {
|
|
482
|
+
if (!animate || !maskRef.current) return;
|
|
483
|
+
const el = maskRef.current;
|
|
484
|
+
el.style.strokeDasharray = `${maskCircumference}`;
|
|
485
|
+
el.style.strokeDashoffset = `${maskCircumference}`;
|
|
486
|
+
requestAnimationFrame(() => {
|
|
487
|
+
el.style.transition = "stroke-dashoffset 1000ms ease-out";
|
|
488
|
+
el.style.strokeDashoffset = "0";
|
|
489
|
+
});
|
|
490
|
+
}, [animate, maskCircumference]);
|
|
478
491
|
const sliceData = import_react.default.useMemo(() => {
|
|
479
492
|
let angle0 = -Math.PI / 2;
|
|
493
|
+
let cumulativeAngle = 0;
|
|
480
494
|
return values.map((v, i) => {
|
|
481
495
|
const angle = v / total * Math.PI * 2;
|
|
482
496
|
const endAngle = angle0 + angle;
|
|
@@ -500,38 +514,53 @@ var PieDonutChart = import_react.default.memo(
|
|
|
500
514
|
const lx = cx + labelR * Math.cos(midAngle);
|
|
501
515
|
const ly = cy + labelR * Math.sin(midAngle);
|
|
502
516
|
const pct = Math.round(v / total * 100);
|
|
517
|
+
cumulativeAngle += angle;
|
|
518
|
+
const sliceEndRatio = cumulativeAngle / (Math.PI * 2);
|
|
519
|
+
const labelDelay = 1e3 * sliceEndRatio + 150;
|
|
503
520
|
angle0 = endAngle;
|
|
504
|
-
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}
|
|
521
|
+
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}`, labelDelay };
|
|
505
522
|
});
|
|
506
523
|
}, [values, total, cx, cy, r, innerR, labels]);
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
524
|
+
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
525
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
526
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("mask", { id: maskId, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
527
|
+
"circle",
|
|
528
|
+
{
|
|
529
|
+
ref: maskRef,
|
|
530
|
+
cx,
|
|
531
|
+
cy,
|
|
532
|
+
r: maskR,
|
|
533
|
+
fill: "none",
|
|
534
|
+
stroke: "white",
|
|
535
|
+
strokeWidth: maskR * 2,
|
|
536
|
+
transform: `rotate(-90 ${cx} ${cy})`
|
|
537
|
+
}
|
|
538
|
+
) }) }),
|
|
539
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("g", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
540
|
+
"path",
|
|
541
|
+
{
|
|
542
|
+
d: s.d,
|
|
543
|
+
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
544
|
+
className: "chart-slice",
|
|
545
|
+
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
546
|
+
onMouseMove: onMove,
|
|
547
|
+
onMouseLeave: onLeave
|
|
548
|
+
}
|
|
549
|
+
) }, i)) }),
|
|
550
|
+
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
551
|
+
"text",
|
|
552
|
+
{
|
|
553
|
+
x: s.lx,
|
|
554
|
+
y: s.ly,
|
|
555
|
+
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
556
|
+
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
557
|
+
textAnchor: "middle",
|
|
558
|
+
dominantBaseline: "central",
|
|
559
|
+
children: s.v
|
|
560
|
+
},
|
|
561
|
+
`label-${i}`
|
|
562
|
+
))
|
|
563
|
+
] });
|
|
535
564
|
}
|
|
536
565
|
);
|
|
537
566
|
PieDonutChart.displayName = "PieDonutChart";
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
transform 0.15s ease-out;
|
|
64
64
|
transform-origin: center;
|
|
65
65
|
}
|
|
66
|
-
.lib-xplat-chart .chart-
|
|
66
|
+
.lib-xplat-chart .chart-pie:has(.chart-slice:hover) .chart-slice {
|
|
67
67
|
opacity: 0.5;
|
|
68
68
|
}
|
|
69
69
|
.lib-xplat-chart .chart-slice:hover {
|
|
@@ -91,10 +91,8 @@
|
|
|
91
91
|
.lib-xplat-chart .chart-bar-animate {
|
|
92
92
|
animation: chart-bar-grow 800ms ease-out both;
|
|
93
93
|
}
|
|
94
|
-
.lib-xplat-chart .chart-slice-group-animate {
|
|
95
|
-
animation: chart-slice-in 1000ms ease-out both;
|
|
96
|
-
}
|
|
97
94
|
.lib-xplat-chart .chart-pie-label-animate {
|
|
95
|
+
opacity: 0;
|
|
98
96
|
animation: chart-fade-in 150ms ease-out both;
|
|
99
97
|
}
|
|
100
98
|
.lib-xplat-chart .chart-area[style*=animationDelay] {
|
|
@@ -108,16 +106,6 @@
|
|
|
108
106
|
transform: scaleY(1);
|
|
109
107
|
}
|
|
110
108
|
}
|
|
111
|
-
@keyframes chart-slice-in {
|
|
112
|
-
from {
|
|
113
|
-
opacity: 0;
|
|
114
|
-
transform: scale(0.8);
|
|
115
|
-
}
|
|
116
|
-
to {
|
|
117
|
-
opacity: 1;
|
|
118
|
-
transform: scale(1);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
109
|
@keyframes chart-fade-in {
|
|
122
110
|
from {
|
|
123
111
|
opacity: 0;
|
|
@@ -138,7 +126,6 @@
|
|
|
138
126
|
}
|
|
139
127
|
@media (prefers-reduced-motion: reduce) {
|
|
140
128
|
.lib-xplat-chart .chart-bar-animate,
|
|
141
|
-
.lib-xplat-chart .chart-slice-group-animate,
|
|
142
129
|
.lib-xplat-chart .chart-pie-label-animate,
|
|
143
130
|
.lib-xplat-chart .chart-area {
|
|
144
131
|
animation: none !important;
|
|
@@ -439,8 +439,22 @@ var PieDonutChart = React.memo(
|
|
|
439
439
|
const innerR = isDoughnut ? r * 0.5 : 0;
|
|
440
440
|
const firstKey = entries[0]?.[0] ?? "";
|
|
441
441
|
const colorOffset = hashString(firstKey);
|
|
442
|
+
const maskRef = React.useRef(null);
|
|
443
|
+
const maskR = r + 10;
|
|
444
|
+
const maskCircumference = 2 * Math.PI * maskR;
|
|
445
|
+
React.useEffect(() => {
|
|
446
|
+
if (!animate || !maskRef.current) return;
|
|
447
|
+
const el = maskRef.current;
|
|
448
|
+
el.style.strokeDasharray = `${maskCircumference}`;
|
|
449
|
+
el.style.strokeDashoffset = `${maskCircumference}`;
|
|
450
|
+
requestAnimationFrame(() => {
|
|
451
|
+
el.style.transition = "stroke-dashoffset 1000ms ease-out";
|
|
452
|
+
el.style.strokeDashoffset = "0";
|
|
453
|
+
});
|
|
454
|
+
}, [animate, maskCircumference]);
|
|
442
455
|
const sliceData = React.useMemo(() => {
|
|
443
456
|
let angle0 = -Math.PI / 2;
|
|
457
|
+
let cumulativeAngle = 0;
|
|
444
458
|
return values.map((v, i) => {
|
|
445
459
|
const angle = v / total * Math.PI * 2;
|
|
446
460
|
const endAngle = angle0 + angle;
|
|
@@ -464,38 +478,53 @@ var PieDonutChart = React.memo(
|
|
|
464
478
|
const lx = cx + labelR * Math.cos(midAngle);
|
|
465
479
|
const ly = cy + labelR * Math.sin(midAngle);
|
|
466
480
|
const pct = Math.round(v / total * 100);
|
|
481
|
+
cumulativeAngle += angle;
|
|
482
|
+
const sliceEndRatio = cumulativeAngle / (Math.PI * 2);
|
|
483
|
+
const labelDelay = 1e3 * sliceEndRatio + 150;
|
|
467
484
|
angle0 = endAngle;
|
|
468
|
-
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}
|
|
485
|
+
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}`, labelDelay };
|
|
469
486
|
});
|
|
470
487
|
}, [values, total, cx, cy, r, innerR, labels]);
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
488
|
+
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
489
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
490
|
+
animate && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("mask", { id: maskId, children: /* @__PURE__ */ jsx(
|
|
491
|
+
"circle",
|
|
492
|
+
{
|
|
493
|
+
ref: maskRef,
|
|
494
|
+
cx,
|
|
495
|
+
cy,
|
|
496
|
+
r: maskR,
|
|
497
|
+
fill: "none",
|
|
498
|
+
stroke: "white",
|
|
499
|
+
strokeWidth: maskR * 2,
|
|
500
|
+
transform: `rotate(-90 ${cx} ${cy})`
|
|
501
|
+
}
|
|
502
|
+
) }) }),
|
|
503
|
+
/* @__PURE__ */ jsx("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx(
|
|
504
|
+
"path",
|
|
505
|
+
{
|
|
506
|
+
d: s.d,
|
|
507
|
+
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
508
|
+
className: "chart-slice",
|
|
509
|
+
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
510
|
+
onMouseMove: onMove,
|
|
511
|
+
onMouseLeave: onLeave
|
|
512
|
+
}
|
|
513
|
+
) }, i)) }),
|
|
514
|
+
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ jsx(
|
|
515
|
+
"text",
|
|
516
|
+
{
|
|
517
|
+
x: s.lx,
|
|
518
|
+
y: s.ly,
|
|
519
|
+
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
520
|
+
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
521
|
+
textAnchor: "middle",
|
|
522
|
+
dominantBaseline: "central",
|
|
523
|
+
children: s.v
|
|
524
|
+
},
|
|
525
|
+
`label-${i}`
|
|
526
|
+
))
|
|
527
|
+
] });
|
|
499
528
|
}
|
|
500
529
|
);
|
|
501
530
|
PieDonutChart.displayName = "PieDonutChart";
|
|
@@ -51,6 +51,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
51
51
|
const popH = popRef.current.offsetHeight;
|
|
52
52
|
const viewportHeight = window.innerHeight;
|
|
53
53
|
const viewportWidth = window.innerWidth;
|
|
54
|
+
if (popH === 0 || popW === 0) return;
|
|
54
55
|
let direction = "bottom";
|
|
55
56
|
let top;
|
|
56
57
|
let left;
|
|
@@ -76,6 +77,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
76
77
|
const raf = requestAnimationFrame(calculatePosition);
|
|
77
78
|
return () => cancelAnimationFrame(raf);
|
|
78
79
|
}, [calculatePosition, enabled]);
|
|
80
|
+
import_react.default.useEffect(() => {
|
|
81
|
+
if (!enabled || !popRef.current) return;
|
|
82
|
+
const observer = new ResizeObserver(() => {
|
|
83
|
+
calculatePosition();
|
|
84
|
+
});
|
|
85
|
+
observer.observe(popRef.current);
|
|
86
|
+
return () => observer.disconnect();
|
|
87
|
+
}, [calculatePosition, enabled, popRef]);
|
|
79
88
|
import_react.default.useEffect(() => {
|
|
80
89
|
if (!enabled) return;
|
|
81
90
|
window.addEventListener("resize", calculatePosition);
|
|
@@ -15,6 +15,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
15
15
|
const popH = popRef.current.offsetHeight;
|
|
16
16
|
const viewportHeight = window.innerHeight;
|
|
17
17
|
const viewportWidth = window.innerWidth;
|
|
18
|
+
if (popH === 0 || popW === 0) return;
|
|
18
19
|
let direction = "bottom";
|
|
19
20
|
let top;
|
|
20
21
|
let left;
|
|
@@ -40,6 +41,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
40
41
|
const raf = requestAnimationFrame(calculatePosition);
|
|
41
42
|
return () => cancelAnimationFrame(raf);
|
|
42
43
|
}, [calculatePosition, enabled]);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (!enabled || !popRef.current) return;
|
|
46
|
+
const observer = new ResizeObserver(() => {
|
|
47
|
+
calculatePosition();
|
|
48
|
+
});
|
|
49
|
+
observer.observe(popRef.current);
|
|
50
|
+
return () => observer.disconnect();
|
|
51
|
+
}, [calculatePosition, enabled, popRef]);
|
|
43
52
|
React.useEffect(() => {
|
|
44
53
|
if (!enabled) return;
|
|
45
54
|
window.addEventListener("resize", calculatePosition);
|
|
@@ -51,6 +51,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
51
51
|
const popH = popRef.current.offsetHeight;
|
|
52
52
|
const viewportHeight = window.innerHeight;
|
|
53
53
|
const viewportWidth = window.innerWidth;
|
|
54
|
+
if (popH === 0 || popW === 0) return;
|
|
54
55
|
let direction = "bottom";
|
|
55
56
|
let top;
|
|
56
57
|
let left;
|
|
@@ -76,6 +77,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
76
77
|
const raf = requestAnimationFrame(calculatePosition);
|
|
77
78
|
return () => cancelAnimationFrame(raf);
|
|
78
79
|
}, [calculatePosition, enabled]);
|
|
80
|
+
import_react.default.useEffect(() => {
|
|
81
|
+
if (!enabled || !popRef.current) return;
|
|
82
|
+
const observer = new ResizeObserver(() => {
|
|
83
|
+
calculatePosition();
|
|
84
|
+
});
|
|
85
|
+
observer.observe(popRef.current);
|
|
86
|
+
return () => observer.disconnect();
|
|
87
|
+
}, [calculatePosition, enabled, popRef]);
|
|
79
88
|
import_react.default.useEffect(() => {
|
|
80
89
|
if (!enabled) return;
|
|
81
90
|
window.addEventListener("resize", calculatePosition);
|
|
@@ -15,6 +15,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
15
15
|
const popH = popRef.current.offsetHeight;
|
|
16
16
|
const viewportHeight = window.innerHeight;
|
|
17
17
|
const viewportWidth = window.innerWidth;
|
|
18
|
+
if (popH === 0 || popW === 0) return;
|
|
18
19
|
let direction = "bottom";
|
|
19
20
|
let top;
|
|
20
21
|
let left;
|
|
@@ -40,6 +41,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
40
41
|
const raf = requestAnimationFrame(calculatePosition);
|
|
41
42
|
return () => cancelAnimationFrame(raf);
|
|
42
43
|
}, [calculatePosition, enabled]);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (!enabled || !popRef.current) return;
|
|
46
|
+
const observer = new ResizeObserver(() => {
|
|
47
|
+
calculatePosition();
|
|
48
|
+
});
|
|
49
|
+
observer.observe(popRef.current);
|
|
50
|
+
return () => observer.disconnect();
|
|
51
|
+
}, [calculatePosition, enabled, popRef]);
|
|
43
52
|
React.useEffect(() => {
|
|
44
53
|
if (!enabled) return;
|
|
45
54
|
window.addEventListener("resize", calculatePosition);
|
|
@@ -52,6 +52,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
52
52
|
const popH = popRef.current.offsetHeight;
|
|
53
53
|
const viewportHeight = window.innerHeight;
|
|
54
54
|
const viewportWidth = window.innerWidth;
|
|
55
|
+
if (popH === 0 || popW === 0) return;
|
|
55
56
|
let direction = "bottom";
|
|
56
57
|
let top;
|
|
57
58
|
let left;
|
|
@@ -77,6 +78,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
77
78
|
const raf = requestAnimationFrame(calculatePosition);
|
|
78
79
|
return () => cancelAnimationFrame(raf);
|
|
79
80
|
}, [calculatePosition, enabled]);
|
|
81
|
+
import_react.default.useEffect(() => {
|
|
82
|
+
if (!enabled || !popRef.current) return;
|
|
83
|
+
const observer = new ResizeObserver(() => {
|
|
84
|
+
calculatePosition();
|
|
85
|
+
});
|
|
86
|
+
observer.observe(popRef.current);
|
|
87
|
+
return () => observer.disconnect();
|
|
88
|
+
}, [calculatePosition, enabled, popRef]);
|
|
80
89
|
import_react.default.useEffect(() => {
|
|
81
90
|
if (!enabled) return;
|
|
82
91
|
window.addEventListener("resize", calculatePosition);
|
|
@@ -15,6 +15,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
15
15
|
const popH = popRef.current.offsetHeight;
|
|
16
16
|
const viewportHeight = window.innerHeight;
|
|
17
17
|
const viewportWidth = window.innerWidth;
|
|
18
|
+
if (popH === 0 || popW === 0) return;
|
|
18
19
|
let direction = "bottom";
|
|
19
20
|
let top;
|
|
20
21
|
let left;
|
|
@@ -40,6 +41,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
40
41
|
const raf = requestAnimationFrame(calculatePosition);
|
|
41
42
|
return () => cancelAnimationFrame(raf);
|
|
42
43
|
}, [calculatePosition, enabled]);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (!enabled || !popRef.current) return;
|
|
46
|
+
const observer = new ResizeObserver(() => {
|
|
47
|
+
calculatePosition();
|
|
48
|
+
});
|
|
49
|
+
observer.observe(popRef.current);
|
|
50
|
+
return () => observer.disconnect();
|
|
51
|
+
}, [calculatePosition, enabled, popRef]);
|
|
43
52
|
React.useEffect(() => {
|
|
44
53
|
if (!enabled) return;
|
|
45
54
|
window.addEventListener("resize", calculatePosition);
|
|
@@ -2546,8 +2546,22 @@ var PieDonutChart = import_react5.default.memo(
|
|
|
2546
2546
|
const innerR = isDoughnut ? r2 * 0.5 : 0;
|
|
2547
2547
|
const firstKey = entries[0]?.[0] ?? "";
|
|
2548
2548
|
const colorOffset = hashString(firstKey);
|
|
2549
|
+
const maskRef = import_react5.default.useRef(null);
|
|
2550
|
+
const maskR = r2 + 10;
|
|
2551
|
+
const maskCircumference = 2 * Math.PI * maskR;
|
|
2552
|
+
import_react5.default.useEffect(() => {
|
|
2553
|
+
if (!animate || !maskRef.current) return;
|
|
2554
|
+
const el = maskRef.current;
|
|
2555
|
+
el.style.strokeDasharray = `${maskCircumference}`;
|
|
2556
|
+
el.style.strokeDashoffset = `${maskCircumference}`;
|
|
2557
|
+
requestAnimationFrame(() => {
|
|
2558
|
+
el.style.transition = "stroke-dashoffset 1000ms ease-out";
|
|
2559
|
+
el.style.strokeDashoffset = "0";
|
|
2560
|
+
});
|
|
2561
|
+
}, [animate, maskCircumference]);
|
|
2549
2562
|
const sliceData = import_react5.default.useMemo(() => {
|
|
2550
2563
|
let angle0 = -Math.PI / 2;
|
|
2564
|
+
let cumulativeAngle = 0;
|
|
2551
2565
|
return values.map((v, i) => {
|
|
2552
2566
|
const angle = v / total * Math.PI * 2;
|
|
2553
2567
|
const endAngle = angle0 + angle;
|
|
@@ -2571,38 +2585,53 @@ var PieDonutChart = import_react5.default.memo(
|
|
|
2571
2585
|
const lx = cx + labelR * Math.cos(midAngle);
|
|
2572
2586
|
const ly = cy + labelR * Math.sin(midAngle);
|
|
2573
2587
|
const pct = Math.round(v / total * 100);
|
|
2588
|
+
cumulativeAngle += angle;
|
|
2589
|
+
const sliceEndRatio = cumulativeAngle / (Math.PI * 2);
|
|
2590
|
+
const labelDelay = 1e3 * sliceEndRatio + 150;
|
|
2574
2591
|
angle0 = endAngle;
|
|
2575
|
-
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}
|
|
2592
|
+
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}`, labelDelay };
|
|
2576
2593
|
});
|
|
2577
2594
|
}, [values, total, cx, cy, r2, innerR, labels]);
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2595
|
+
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
2596
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
2597
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("mask", { id: maskId, children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2598
|
+
"circle",
|
|
2599
|
+
{
|
|
2600
|
+
ref: maskRef,
|
|
2601
|
+
cx,
|
|
2602
|
+
cy,
|
|
2603
|
+
r: maskR,
|
|
2604
|
+
fill: "none",
|
|
2605
|
+
stroke: "white",
|
|
2606
|
+
strokeWidth: maskR * 2,
|
|
2607
|
+
transform: `rotate(-90 ${cx} ${cy})`
|
|
2608
|
+
}
|
|
2609
|
+
) }) }),
|
|
2610
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("g", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2611
|
+
"path",
|
|
2612
|
+
{
|
|
2613
|
+
d: s.d,
|
|
2614
|
+
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
2615
|
+
className: "chart-slice",
|
|
2616
|
+
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
2617
|
+
onMouseMove: onMove,
|
|
2618
|
+
onMouseLeave: onLeave
|
|
2619
|
+
}
|
|
2620
|
+
) }, i)) }),
|
|
2621
|
+
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2622
|
+
"text",
|
|
2623
|
+
{
|
|
2624
|
+
x: s.lx,
|
|
2625
|
+
y: s.ly,
|
|
2626
|
+
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
2627
|
+
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
2628
|
+
textAnchor: "middle",
|
|
2629
|
+
dominantBaseline: "central",
|
|
2630
|
+
children: s.v
|
|
2631
|
+
},
|
|
2632
|
+
`label-${i}`
|
|
2633
|
+
))
|
|
2634
|
+
] });
|
|
2606
2635
|
}
|
|
2607
2636
|
);
|
|
2608
2637
|
PieDonutChart.displayName = "PieDonutChart";
|
|
@@ -3519,6 +3548,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3519
3548
|
const popH = popRef.current.offsetHeight;
|
|
3520
3549
|
const viewportHeight = window.innerHeight;
|
|
3521
3550
|
const viewportWidth = window.innerWidth;
|
|
3551
|
+
if (popH === 0 || popW === 0) return;
|
|
3522
3552
|
let direction = "bottom";
|
|
3523
3553
|
let top;
|
|
3524
3554
|
let left;
|
|
@@ -3544,6 +3574,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3544
3574
|
const raf = requestAnimationFrame(calculatePosition);
|
|
3545
3575
|
return () => cancelAnimationFrame(raf);
|
|
3546
3576
|
}, [calculatePosition, enabled]);
|
|
3577
|
+
import_react18.default.useEffect(() => {
|
|
3578
|
+
if (!enabled || !popRef.current) return;
|
|
3579
|
+
const observer = new ResizeObserver(() => {
|
|
3580
|
+
calculatePosition();
|
|
3581
|
+
});
|
|
3582
|
+
observer.observe(popRef.current);
|
|
3583
|
+
return () => observer.disconnect();
|
|
3584
|
+
}, [calculatePosition, enabled, popRef]);
|
|
3547
3585
|
import_react18.default.useEffect(() => {
|
|
3548
3586
|
if (!enabled) return;
|
|
3549
3587
|
window.addEventListener("resize", calculatePosition);
|
|
@@ -1864,7 +1864,7 @@
|
|
|
1864
1864
|
transform 0.15s ease-out;
|
|
1865
1865
|
transform-origin: center;
|
|
1866
1866
|
}
|
|
1867
|
-
.lib-xplat-chart .chart-
|
|
1867
|
+
.lib-xplat-chart .chart-pie:has(.chart-slice:hover) .chart-slice {
|
|
1868
1868
|
opacity: 0.5;
|
|
1869
1869
|
}
|
|
1870
1870
|
.lib-xplat-chart .chart-slice:hover {
|
|
@@ -1892,10 +1892,8 @@
|
|
|
1892
1892
|
.lib-xplat-chart .chart-bar-animate {
|
|
1893
1893
|
animation: chart-bar-grow 800ms ease-out both;
|
|
1894
1894
|
}
|
|
1895
|
-
.lib-xplat-chart .chart-slice-group-animate {
|
|
1896
|
-
animation: chart-slice-in 1000ms ease-out both;
|
|
1897
|
-
}
|
|
1898
1895
|
.lib-xplat-chart .chart-pie-label-animate {
|
|
1896
|
+
opacity: 0;
|
|
1899
1897
|
animation: chart-fade-in 150ms ease-out both;
|
|
1900
1898
|
}
|
|
1901
1899
|
.lib-xplat-chart .chart-area[style*=animationDelay] {
|
|
@@ -1909,16 +1907,6 @@
|
|
|
1909
1907
|
transform: scaleY(1);
|
|
1910
1908
|
}
|
|
1911
1909
|
}
|
|
1912
|
-
@keyframes chart-slice-in {
|
|
1913
|
-
from {
|
|
1914
|
-
opacity: 0;
|
|
1915
|
-
transform: scale(0.8);
|
|
1916
|
-
}
|
|
1917
|
-
to {
|
|
1918
|
-
opacity: 1;
|
|
1919
|
-
transform: scale(1);
|
|
1920
|
-
}
|
|
1921
|
-
}
|
|
1922
1910
|
@keyframes chart-fade-in {
|
|
1923
1911
|
from {
|
|
1924
1912
|
opacity: 0;
|
|
@@ -1939,7 +1927,6 @@
|
|
|
1939
1927
|
}
|
|
1940
1928
|
@media (prefers-reduced-motion: reduce) {
|
|
1941
1929
|
.lib-xplat-chart .chart-bar-animate,
|
|
1942
|
-
.lib-xplat-chart .chart-slice-group-animate,
|
|
1943
1930
|
.lib-xplat-chart .chart-pie-label-animate,
|
|
1944
1931
|
.lib-xplat-chart .chart-area {
|
|
1945
1932
|
animation: none !important;
|
package/dist/components/index.js
CHANGED
|
@@ -2458,8 +2458,22 @@ var PieDonutChart = React5.memo(
|
|
|
2458
2458
|
const innerR = isDoughnut ? r2 * 0.5 : 0;
|
|
2459
2459
|
const firstKey = entries[0]?.[0] ?? "";
|
|
2460
2460
|
const colorOffset = hashString(firstKey);
|
|
2461
|
+
const maskRef = React5.useRef(null);
|
|
2462
|
+
const maskR = r2 + 10;
|
|
2463
|
+
const maskCircumference = 2 * Math.PI * maskR;
|
|
2464
|
+
React5.useEffect(() => {
|
|
2465
|
+
if (!animate || !maskRef.current) return;
|
|
2466
|
+
const el = maskRef.current;
|
|
2467
|
+
el.style.strokeDasharray = `${maskCircumference}`;
|
|
2468
|
+
el.style.strokeDashoffset = `${maskCircumference}`;
|
|
2469
|
+
requestAnimationFrame(() => {
|
|
2470
|
+
el.style.transition = "stroke-dashoffset 1000ms ease-out";
|
|
2471
|
+
el.style.strokeDashoffset = "0";
|
|
2472
|
+
});
|
|
2473
|
+
}, [animate, maskCircumference]);
|
|
2461
2474
|
const sliceData = React5.useMemo(() => {
|
|
2462
2475
|
let angle0 = -Math.PI / 2;
|
|
2476
|
+
let cumulativeAngle = 0;
|
|
2463
2477
|
return values.map((v, i) => {
|
|
2464
2478
|
const angle = v / total * Math.PI * 2;
|
|
2465
2479
|
const endAngle = angle0 + angle;
|
|
@@ -2483,38 +2497,53 @@ var PieDonutChart = React5.memo(
|
|
|
2483
2497
|
const lx = cx + labelR * Math.cos(midAngle);
|
|
2484
2498
|
const ly = cy + labelR * Math.sin(midAngle);
|
|
2485
2499
|
const pct = Math.round(v / total * 100);
|
|
2500
|
+
cumulativeAngle += angle;
|
|
2501
|
+
const sliceEndRatio = cumulativeAngle / (Math.PI * 2);
|
|
2502
|
+
const labelDelay = 1e3 * sliceEndRatio + 150;
|
|
2486
2503
|
angle0 = endAngle;
|
|
2487
|
-
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}
|
|
2504
|
+
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}`, labelDelay };
|
|
2488
2505
|
});
|
|
2489
2506
|
}, [values, total, cx, cy, r2, innerR, labels]);
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
}
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2507
|
+
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
2508
|
+
return /* @__PURE__ */ jsxs196("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
2509
|
+
animate && /* @__PURE__ */ jsx305("defs", { children: /* @__PURE__ */ jsx305("mask", { id: maskId, children: /* @__PURE__ */ jsx305(
|
|
2510
|
+
"circle",
|
|
2511
|
+
{
|
|
2512
|
+
ref: maskRef,
|
|
2513
|
+
cx,
|
|
2514
|
+
cy,
|
|
2515
|
+
r: maskR,
|
|
2516
|
+
fill: "none",
|
|
2517
|
+
stroke: "white",
|
|
2518
|
+
strokeWidth: maskR * 2,
|
|
2519
|
+
transform: `rotate(-90 ${cx} ${cy})`
|
|
2520
|
+
}
|
|
2521
|
+
) }) }),
|
|
2522
|
+
/* @__PURE__ */ jsx305("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ jsx305("g", { children: /* @__PURE__ */ jsx305(
|
|
2523
|
+
"path",
|
|
2524
|
+
{
|
|
2525
|
+
d: s.d,
|
|
2526
|
+
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
2527
|
+
className: "chart-slice",
|
|
2528
|
+
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
2529
|
+
onMouseMove: onMove,
|
|
2530
|
+
onMouseLeave: onLeave
|
|
2531
|
+
}
|
|
2532
|
+
) }, i)) }),
|
|
2533
|
+
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ jsx305(
|
|
2534
|
+
"text",
|
|
2535
|
+
{
|
|
2536
|
+
x: s.lx,
|
|
2537
|
+
y: s.ly,
|
|
2538
|
+
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
2539
|
+
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
2540
|
+
textAnchor: "middle",
|
|
2541
|
+
dominantBaseline: "central",
|
|
2542
|
+
children: s.v
|
|
2543
|
+
},
|
|
2544
|
+
`label-${i}`
|
|
2545
|
+
))
|
|
2546
|
+
] });
|
|
2518
2547
|
}
|
|
2519
2548
|
);
|
|
2520
2549
|
PieDonutChart.displayName = "PieDonutChart";
|
|
@@ -3431,6 +3460,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3431
3460
|
const popH = popRef.current.offsetHeight;
|
|
3432
3461
|
const viewportHeight = window.innerHeight;
|
|
3433
3462
|
const viewportWidth = window.innerWidth;
|
|
3463
|
+
if (popH === 0 || popW === 0) return;
|
|
3434
3464
|
let direction = "bottom";
|
|
3435
3465
|
let top;
|
|
3436
3466
|
let left;
|
|
@@ -3456,6 +3486,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3456
3486
|
const raf = requestAnimationFrame(calculatePosition);
|
|
3457
3487
|
return () => cancelAnimationFrame(raf);
|
|
3458
3488
|
}, [calculatePosition, enabled]);
|
|
3489
|
+
React17.useEffect(() => {
|
|
3490
|
+
if (!enabled || !popRef.current) return;
|
|
3491
|
+
const observer = new ResizeObserver(() => {
|
|
3492
|
+
calculatePosition();
|
|
3493
|
+
});
|
|
3494
|
+
observer.observe(popRef.current);
|
|
3495
|
+
return () => observer.disconnect();
|
|
3496
|
+
}, [calculatePosition, enabled, popRef]);
|
|
3459
3497
|
React17.useEffect(() => {
|
|
3460
3498
|
if (!enabled) return;
|
|
3461
3499
|
window.addEventListener("resize", calculatePosition);
|
package/dist/index.cjs
CHANGED
|
@@ -6957,8 +6957,22 @@ var PieDonutChart = import_react5.default.memo(
|
|
|
6957
6957
|
const innerR = isDoughnut ? r2 * 0.5 : 0;
|
|
6958
6958
|
const firstKey = entries[0]?.[0] ?? "";
|
|
6959
6959
|
const colorOffset = hashString(firstKey);
|
|
6960
|
+
const maskRef = import_react5.default.useRef(null);
|
|
6961
|
+
const maskR = r2 + 10;
|
|
6962
|
+
const maskCircumference = 2 * Math.PI * maskR;
|
|
6963
|
+
import_react5.default.useEffect(() => {
|
|
6964
|
+
if (!animate || !maskRef.current) return;
|
|
6965
|
+
const el = maskRef.current;
|
|
6966
|
+
el.style.strokeDasharray = `${maskCircumference}`;
|
|
6967
|
+
el.style.strokeDashoffset = `${maskCircumference}`;
|
|
6968
|
+
requestAnimationFrame(() => {
|
|
6969
|
+
el.style.transition = "stroke-dashoffset 1000ms ease-out";
|
|
6970
|
+
el.style.strokeDashoffset = "0";
|
|
6971
|
+
});
|
|
6972
|
+
}, [animate, maskCircumference]);
|
|
6960
6973
|
const sliceData = import_react5.default.useMemo(() => {
|
|
6961
6974
|
let angle0 = -Math.PI / 2;
|
|
6975
|
+
let cumulativeAngle = 0;
|
|
6962
6976
|
return values.map((v, i) => {
|
|
6963
6977
|
const angle = v / total * Math.PI * 2;
|
|
6964
6978
|
const endAngle = angle0 + angle;
|
|
@@ -6982,38 +6996,53 @@ var PieDonutChart = import_react5.default.memo(
|
|
|
6982
6996
|
const lx = cx + labelR * Math.cos(midAngle);
|
|
6983
6997
|
const ly = cy + labelR * Math.sin(midAngle);
|
|
6984
6998
|
const pct = Math.round(v / total * 100);
|
|
6999
|
+
cumulativeAngle += angle;
|
|
7000
|
+
const sliceEndRatio = cumulativeAngle / (Math.PI * 2);
|
|
7001
|
+
const labelDelay = 1e3 * sliceEndRatio + 150;
|
|
6985
7002
|
angle0 = endAngle;
|
|
6986
|
-
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}
|
|
7003
|
+
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}`, labelDelay };
|
|
6987
7004
|
});
|
|
6988
7005
|
}, [values, total, cx, cy, r2, innerR, labels]);
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
}
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7006
|
+
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
7007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
7008
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("mask", { id: maskId, children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
7009
|
+
"circle",
|
|
7010
|
+
{
|
|
7011
|
+
ref: maskRef,
|
|
7012
|
+
cx,
|
|
7013
|
+
cy,
|
|
7014
|
+
r: maskR,
|
|
7015
|
+
fill: "none",
|
|
7016
|
+
stroke: "white",
|
|
7017
|
+
strokeWidth: maskR * 2,
|
|
7018
|
+
transform: `rotate(-90 ${cx} ${cy})`
|
|
7019
|
+
}
|
|
7020
|
+
) }) }),
|
|
7021
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("g", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
7022
|
+
"path",
|
|
7023
|
+
{
|
|
7024
|
+
d: s.d,
|
|
7025
|
+
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
7026
|
+
className: "chart-slice",
|
|
7027
|
+
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
7028
|
+
onMouseMove: onMove,
|
|
7029
|
+
onMouseLeave: onLeave
|
|
7030
|
+
}
|
|
7031
|
+
) }, i)) }),
|
|
7032
|
+
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
7033
|
+
"text",
|
|
7034
|
+
{
|
|
7035
|
+
x: s.lx,
|
|
7036
|
+
y: s.ly,
|
|
7037
|
+
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
7038
|
+
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
7039
|
+
textAnchor: "middle",
|
|
7040
|
+
dominantBaseline: "central",
|
|
7041
|
+
children: s.v
|
|
7042
|
+
},
|
|
7043
|
+
`label-${i}`
|
|
7044
|
+
))
|
|
7045
|
+
] });
|
|
7017
7046
|
}
|
|
7018
7047
|
);
|
|
7019
7048
|
PieDonutChart.displayName = "PieDonutChart";
|
|
@@ -7943,6 +7972,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7943
7972
|
const popH = popRef.current.offsetHeight;
|
|
7944
7973
|
const viewportHeight = window.innerHeight;
|
|
7945
7974
|
const viewportWidth = window.innerWidth;
|
|
7975
|
+
if (popH === 0 || popW === 0) return;
|
|
7946
7976
|
let direction = "bottom";
|
|
7947
7977
|
let top;
|
|
7948
7978
|
let left;
|
|
@@ -7968,6 +7998,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7968
7998
|
const raf = requestAnimationFrame(calculatePosition);
|
|
7969
7999
|
return () => cancelAnimationFrame(raf);
|
|
7970
8000
|
}, [calculatePosition, enabled]);
|
|
8001
|
+
import_react18.default.useEffect(() => {
|
|
8002
|
+
if (!enabled || !popRef.current) return;
|
|
8003
|
+
const observer = new ResizeObserver(() => {
|
|
8004
|
+
calculatePosition();
|
|
8005
|
+
});
|
|
8006
|
+
observer.observe(popRef.current);
|
|
8007
|
+
return () => observer.disconnect();
|
|
8008
|
+
}, [calculatePosition, enabled, popRef]);
|
|
7971
8009
|
import_react18.default.useEffect(() => {
|
|
7972
8010
|
if (!enabled) return;
|
|
7973
8011
|
window.addEventListener("resize", calculatePosition);
|
package/dist/index.css
CHANGED
|
@@ -1864,7 +1864,7 @@
|
|
|
1864
1864
|
transform 0.15s ease-out;
|
|
1865
1865
|
transform-origin: center;
|
|
1866
1866
|
}
|
|
1867
|
-
.lib-xplat-chart .chart-
|
|
1867
|
+
.lib-xplat-chart .chart-pie:has(.chart-slice:hover) .chart-slice {
|
|
1868
1868
|
opacity: 0.5;
|
|
1869
1869
|
}
|
|
1870
1870
|
.lib-xplat-chart .chart-slice:hover {
|
|
@@ -1892,10 +1892,8 @@
|
|
|
1892
1892
|
.lib-xplat-chart .chart-bar-animate {
|
|
1893
1893
|
animation: chart-bar-grow 800ms ease-out both;
|
|
1894
1894
|
}
|
|
1895
|
-
.lib-xplat-chart .chart-slice-group-animate {
|
|
1896
|
-
animation: chart-slice-in 1000ms ease-out both;
|
|
1897
|
-
}
|
|
1898
1895
|
.lib-xplat-chart .chart-pie-label-animate {
|
|
1896
|
+
opacity: 0;
|
|
1899
1897
|
animation: chart-fade-in 150ms ease-out both;
|
|
1900
1898
|
}
|
|
1901
1899
|
.lib-xplat-chart .chart-area[style*=animationDelay] {
|
|
@@ -1909,16 +1907,6 @@
|
|
|
1909
1907
|
transform: scaleY(1);
|
|
1910
1908
|
}
|
|
1911
1909
|
}
|
|
1912
|
-
@keyframes chart-slice-in {
|
|
1913
|
-
from {
|
|
1914
|
-
opacity: 0;
|
|
1915
|
-
transform: scale(0.8);
|
|
1916
|
-
}
|
|
1917
|
-
to {
|
|
1918
|
-
opacity: 1;
|
|
1919
|
-
transform: scale(1);
|
|
1920
|
-
}
|
|
1921
|
-
}
|
|
1922
1910
|
@keyframes chart-fade-in {
|
|
1923
1911
|
from {
|
|
1924
1912
|
opacity: 0;
|
|
@@ -1939,7 +1927,6 @@
|
|
|
1939
1927
|
}
|
|
1940
1928
|
@media (prefers-reduced-motion: reduce) {
|
|
1941
1929
|
.lib-xplat-chart .chart-bar-animate,
|
|
1942
|
-
.lib-xplat-chart .chart-slice-group-animate,
|
|
1943
1930
|
.lib-xplat-chart .chart-pie-label-animate,
|
|
1944
1931
|
.lib-xplat-chart .chart-area {
|
|
1945
1932
|
animation: none !important;
|
package/dist/index.js
CHANGED
|
@@ -6560,8 +6560,22 @@ var PieDonutChart = React5.memo(
|
|
|
6560
6560
|
const innerR = isDoughnut ? r2 * 0.5 : 0;
|
|
6561
6561
|
const firstKey = entries[0]?.[0] ?? "";
|
|
6562
6562
|
const colorOffset = hashString(firstKey);
|
|
6563
|
+
const maskRef = React5.useRef(null);
|
|
6564
|
+
const maskR = r2 + 10;
|
|
6565
|
+
const maskCircumference = 2 * Math.PI * maskR;
|
|
6566
|
+
React5.useEffect(() => {
|
|
6567
|
+
if (!animate || !maskRef.current) return;
|
|
6568
|
+
const el = maskRef.current;
|
|
6569
|
+
el.style.strokeDasharray = `${maskCircumference}`;
|
|
6570
|
+
el.style.strokeDashoffset = `${maskCircumference}`;
|
|
6571
|
+
requestAnimationFrame(() => {
|
|
6572
|
+
el.style.transition = "stroke-dashoffset 1000ms ease-out";
|
|
6573
|
+
el.style.strokeDashoffset = "0";
|
|
6574
|
+
});
|
|
6575
|
+
}, [animate, maskCircumference]);
|
|
6563
6576
|
const sliceData = React5.useMemo(() => {
|
|
6564
6577
|
let angle0 = -Math.PI / 2;
|
|
6578
|
+
let cumulativeAngle = 0;
|
|
6565
6579
|
return values.map((v, i) => {
|
|
6566
6580
|
const angle = v / total * Math.PI * 2;
|
|
6567
6581
|
const endAngle = angle0 + angle;
|
|
@@ -6585,38 +6599,53 @@ var PieDonutChart = React5.memo(
|
|
|
6585
6599
|
const lx = cx + labelR * Math.cos(midAngle);
|
|
6586
6600
|
const ly = cy + labelR * Math.sin(midAngle);
|
|
6587
6601
|
const pct = Math.round(v / total * 100);
|
|
6602
|
+
cumulativeAngle += angle;
|
|
6603
|
+
const sliceEndRatio = cumulativeAngle / (Math.PI * 2);
|
|
6604
|
+
const labelDelay = 1e3 * sliceEndRatio + 150;
|
|
6588
6605
|
angle0 = endAngle;
|
|
6589
|
-
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}
|
|
6606
|
+
return { d, lx, ly, v, pct, angle, label: labels[i] || `${i + 1}`, labelDelay };
|
|
6590
6607
|
});
|
|
6591
6608
|
}, [values, total, cx, cy, r2, innerR, labels]);
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
}
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6609
|
+
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
6610
|
+
return /* @__PURE__ */ jsxs196("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
6611
|
+
animate && /* @__PURE__ */ jsx305("defs", { children: /* @__PURE__ */ jsx305("mask", { id: maskId, children: /* @__PURE__ */ jsx305(
|
|
6612
|
+
"circle",
|
|
6613
|
+
{
|
|
6614
|
+
ref: maskRef,
|
|
6615
|
+
cx,
|
|
6616
|
+
cy,
|
|
6617
|
+
r: maskR,
|
|
6618
|
+
fill: "none",
|
|
6619
|
+
stroke: "white",
|
|
6620
|
+
strokeWidth: maskR * 2,
|
|
6621
|
+
transform: `rotate(-90 ${cx} ${cy})`
|
|
6622
|
+
}
|
|
6623
|
+
) }) }),
|
|
6624
|
+
/* @__PURE__ */ jsx305("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ jsx305("g", { children: /* @__PURE__ */ jsx305(
|
|
6625
|
+
"path",
|
|
6626
|
+
{
|
|
6627
|
+
d: s.d,
|
|
6628
|
+
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
6629
|
+
className: "chart-slice",
|
|
6630
|
+
onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
|
|
6631
|
+
onMouseMove: onMove,
|
|
6632
|
+
onMouseLeave: onLeave
|
|
6633
|
+
}
|
|
6634
|
+
) }, i)) }),
|
|
6635
|
+
sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ jsx305(
|
|
6636
|
+
"text",
|
|
6637
|
+
{
|
|
6638
|
+
x: s.lx,
|
|
6639
|
+
y: s.ly,
|
|
6640
|
+
className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
|
|
6641
|
+
style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
|
|
6642
|
+
textAnchor: "middle",
|
|
6643
|
+
dominantBaseline: "central",
|
|
6644
|
+
children: s.v
|
|
6645
|
+
},
|
|
6646
|
+
`label-${i}`
|
|
6647
|
+
))
|
|
6648
|
+
] });
|
|
6620
6649
|
}
|
|
6621
6650
|
);
|
|
6622
6651
|
PieDonutChart.displayName = "PieDonutChart";
|
|
@@ -7546,6 +7575,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7546
7575
|
const popH = popRef.current.offsetHeight;
|
|
7547
7576
|
const viewportHeight = window.innerHeight;
|
|
7548
7577
|
const viewportWidth = window.innerWidth;
|
|
7578
|
+
if (popH === 0 || popW === 0) return;
|
|
7549
7579
|
let direction = "bottom";
|
|
7550
7580
|
let top;
|
|
7551
7581
|
let left;
|
|
@@ -7571,6 +7601,14 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7571
7601
|
const raf = requestAnimationFrame(calculatePosition);
|
|
7572
7602
|
return () => cancelAnimationFrame(raf);
|
|
7573
7603
|
}, [calculatePosition, enabled]);
|
|
7604
|
+
React17.useEffect(() => {
|
|
7605
|
+
if (!enabled || !popRef.current) return;
|
|
7606
|
+
const observer = new ResizeObserver(() => {
|
|
7607
|
+
calculatePosition();
|
|
7608
|
+
});
|
|
7609
|
+
observer.observe(popRef.current);
|
|
7610
|
+
return () => observer.disconnect();
|
|
7611
|
+
}, [calculatePosition, enabled, popRef]);
|
|
7574
7612
|
React17.useEffect(() => {
|
|
7575
7613
|
if (!enabled) return;
|
|
7576
7614
|
window.addEventListener("resize", calculatePosition);
|