@x-plat/design-system 0.5.19 → 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.
@@ -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
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: sliceData.map((s, i) => {
508
- const delay = i * 100;
509
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { className: animate ? "chart-slice-group-animate" : "", style: animate ? { animationDelay: `${delay}ms` } : void 0, children: [
510
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
511
- "path",
512
- {
513
- d: s.d,
514
- fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
515
- className: "chart-slice",
516
- onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
517
- onMouseMove: onMove,
518
- onMouseLeave: onLeave
519
- }
520
- ),
521
- s.angle > 0.2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
522
- "text",
523
- {
524
- x: s.lx,
525
- y: s.ly,
526
- className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
527
- style: animate ? { animationDelay: `${delay + 150}ms` } : void 0,
528
- textAnchor: "middle",
529
- dominantBaseline: "central",
530
- children: s.v
531
- }
532
- )
533
- ] }, i);
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-svg:hover .chart-slice {
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
- return /* @__PURE__ */ jsx("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: sliceData.map((s, i) => {
472
- const delay = i * 100;
473
- return /* @__PURE__ */ jsxs("g", { className: animate ? "chart-slice-group-animate" : "", style: animate ? { animationDelay: `${delay}ms` } : void 0, children: [
474
- /* @__PURE__ */ jsx(
475
- "path",
476
- {
477
- d: s.d,
478
- fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
479
- className: "chart-slice",
480
- onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
481
- onMouseMove: onMove,
482
- onMouseLeave: onLeave
483
- }
484
- ),
485
- s.angle > 0.2 && /* @__PURE__ */ jsx(
486
- "text",
487
- {
488
- x: s.lx,
489
- y: s.ly,
490
- className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
491
- style: animate ? { animationDelay: `${delay + 150}ms` } : void 0,
492
- textAnchor: "middle",
493
- dominantBaseline: "central",
494
- children: s.v
495
- }
496
- )
497
- ] }, i);
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);
@@ -42,12 +42,20 @@ var clsx_default = clsx;
42
42
 
43
43
  // src/components/Skeleton/Skeleton.tsx
44
44
  var import_jsx_runtime = require("react/jsx-runtime");
45
- var toSizeVar = (token) => token === "full" ? "100%" : `var(--spacing-size-${token})`;
45
+ var SIZE_MAP = {
46
+ xs: "var(--spacing-size-1)",
47
+ sm: "var(--spacing-size-2)",
48
+ md: "var(--spacing-size-4)",
49
+ lg: "var(--spacing-size-8)",
50
+ xl: "var(--spacing-size-12)",
51
+ "2xl": "var(--spacing-size-16)",
52
+ full: "100%"
53
+ };
46
54
  var Skeleton = (props) => {
47
55
  const { variant = "text", width, height } = props;
48
56
  const style = {
49
- ...width != null && { width: toSizeVar(width) },
50
- ...height != null && { height: toSizeVar(height) }
57
+ ...width != null && { width: SIZE_MAP[width] },
58
+ ...height != null && { height: SIZE_MAP[height] }
51
59
  };
52
60
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
53
61
  "div",
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
 
3
3
  type SkeletonVariant = "text" | "circular" | "rectangular";
4
- type SizeToken = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | "full";
4
+ type SizeToken = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "full";
5
5
  interface SkeletonProps {
6
6
  variant?: SkeletonVariant;
7
7
  width?: SizeToken;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
 
3
3
  type SkeletonVariant = "text" | "circular" | "rectangular";
4
- type SizeToken = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | "full";
4
+ type SizeToken = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "full";
5
5
  interface SkeletonProps {
6
6
  variant?: SkeletonVariant;
7
7
  width?: SizeToken;
@@ -16,12 +16,20 @@ var clsx_default = clsx;
16
16
 
17
17
  // src/components/Skeleton/Skeleton.tsx
18
18
  import { jsx } from "react/jsx-runtime";
19
- var toSizeVar = (token) => token === "full" ? "100%" : `var(--spacing-size-${token})`;
19
+ var SIZE_MAP = {
20
+ xs: "var(--spacing-size-1)",
21
+ sm: "var(--spacing-size-2)",
22
+ md: "var(--spacing-size-4)",
23
+ lg: "var(--spacing-size-8)",
24
+ xl: "var(--spacing-size-12)",
25
+ "2xl": "var(--spacing-size-16)",
26
+ full: "100%"
27
+ };
20
28
  var Skeleton = (props) => {
21
29
  const { variant = "text", width, height } = props;
22
30
  const style = {
23
- ...width != null && { width: toSizeVar(width) },
24
- ...height != null && { height: toSizeVar(height) }
31
+ ...width != null && { width: SIZE_MAP[width] },
32
+ ...height != null && { height: SIZE_MAP[height] }
25
33
  };
26
34
  return /* @__PURE__ */ jsx(
27
35
  "div",
@@ -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
- return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: sliceData.map((s, i) => {
2579
- const delay = i * 100;
2580
- return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("g", { className: animate ? "chart-slice-group-animate" : "", style: animate ? { animationDelay: `${delay}ms` } : void 0, children: [
2581
- /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
2582
- "path",
2583
- {
2584
- d: s.d,
2585
- fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
2586
- className: "chart-slice",
2587
- onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
2588
- onMouseMove: onMove,
2589
- onMouseLeave: onLeave
2590
- }
2591
- ),
2592
- s.angle > 0.2 && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
2593
- "text",
2594
- {
2595
- x: s.lx,
2596
- y: s.ly,
2597
- className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
2598
- style: animate ? { animationDelay: `${delay + 150}ms` } : void 0,
2599
- textAnchor: "middle",
2600
- dominantBaseline: "central",
2601
- children: s.v
2602
- }
2603
- )
2604
- ] }, i);
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);
@@ -4359,12 +4397,20 @@ var Select_default = Select;
4359
4397
 
4360
4398
  // src/components/Skeleton/Skeleton.tsx
4361
4399
  var import_jsx_runtime333 = require("react/jsx-runtime");
4362
- var toSizeVar = (token) => token === "full" ? "100%" : `var(--spacing-size-${token})`;
4400
+ var SIZE_MAP = {
4401
+ xs: "var(--spacing-size-1)",
4402
+ sm: "var(--spacing-size-2)",
4403
+ md: "var(--spacing-size-4)",
4404
+ lg: "var(--spacing-size-8)",
4405
+ xl: "var(--spacing-size-12)",
4406
+ "2xl": "var(--spacing-size-16)",
4407
+ full: "100%"
4408
+ };
4363
4409
  var Skeleton = (props) => {
4364
4410
  const { variant = "text", width, height } = props;
4365
4411
  const style = {
4366
- ...width != null && { width: toSizeVar(width) },
4367
- ...height != null && { height: toSizeVar(height) }
4412
+ ...width != null && { width: SIZE_MAP[width] },
4413
+ ...height != null && { height: SIZE_MAP[height] }
4368
4414
  };
4369
4415
  return /* @__PURE__ */ (0, import_jsx_runtime333.jsx)(
4370
4416
  "div",