@x-plat/design-system 0.5.33 → 0.5.35

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.
@@ -4,11 +4,14 @@
4
4
  width: 100%;
5
5
  height: 100%;
6
6
  position: relative;
7
+ display: flex;
8
+ flex-direction: column;
7
9
  }
8
10
  .lib-xplat-chart .chart-svg {
9
11
  display: block;
10
12
  width: 100%;
11
- height: 100%;
13
+ flex: 1;
14
+ min-height: 0;
12
15
  will-change: transform;
13
16
  contain: layout style paint;
14
17
  }
@@ -1,6 +1,22 @@
1
1
  // src/components/Chart/Chart.tsx
2
+ import React2 from "react";
3
+
4
+ // src/tokens/hooks/Portal.tsx
2
5
  import React from "react";
3
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import ReactDOM from "react-dom";
7
+ import { jsx } from "react/jsx-runtime";
8
+ var PortalContainerContext = React.createContext(null);
9
+ var Portal = ({ children }) => {
10
+ const contextContainer = React.useContext(PortalContainerContext);
11
+ if (typeof document === "undefined") return null;
12
+ const container = contextContainer ?? document.body;
13
+ return ReactDOM.createPortal(children, container);
14
+ };
15
+ Portal.displayName = "Portal";
16
+ var Portal_default = Portal;
17
+
18
+ // src/components/Chart/Chart.tsx
19
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
4
20
  var CATEGORICAL_COUNT = 8;
5
21
  var LINE_BAR_PALETTES = Array.from({ length: CATEGORICAL_COUNT }, (_, i) => {
6
22
  const n = i + 1;
@@ -46,11 +62,11 @@ var toSmoothPath = (points) => {
46
62
  };
47
63
  var RESIZE_SETTLE_MS = 150;
48
64
  var useChartSize = (ref) => {
49
- const [size, setSize] = React.useState({ width: 0, height: 0 });
50
- const settleTimer = React.useRef(0);
51
- const committedSize = React.useRef({ width: 0, height: 0 });
52
- const initialRef = React.useRef(true);
53
- React.useEffect(() => {
65
+ const [size, setSize] = React2.useState({ width: 0, height: 0 });
66
+ const settleTimer = React2.useRef(0);
67
+ const committedSize = React2.useRef({ width: 0, height: 0 });
68
+ const initialRef = React2.useRef(true);
69
+ React2.useEffect(() => {
54
70
  const el = ref.current;
55
71
  if (!el) return;
56
72
  const observer = new ResizeObserver((entries) => {
@@ -92,10 +108,10 @@ var useChartSize = (ref) => {
92
108
  };
93
109
  var prefersReducedMotion = () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
94
110
  var useChartAnimation = (containerRef, dataKey) => {
95
- const [animate, setAnimate] = React.useState(false);
96
- const prevDataKey = React.useRef(dataKey);
97
- const hasAnimated = React.useRef(false);
98
- React.useEffect(() => {
111
+ const [animate, setAnimate] = React2.useState(false);
112
+ const prevDataKey = React2.useRef(dataKey);
113
+ const hasAnimated = React2.useRef(false);
114
+ React2.useEffect(() => {
99
115
  if (prefersReducedMotion()) return;
100
116
  const el = containerRef.current;
101
117
  if (!el) return;
@@ -111,27 +127,29 @@ var useChartAnimation = (containerRef, dataKey) => {
111
127
  observer.observe(el);
112
128
  return () => observer.disconnect();
113
129
  }, [containerRef]);
114
- React.useEffect(() => {
130
+ React2.useEffect(() => {
115
131
  if (dataKey !== prevDataKey.current) {
116
132
  prevDataKey.current = dataKey;
117
133
  if (prefersReducedMotion()) return;
118
134
  setAnimate(false);
119
- requestAnimationFrame(() => setAnimate(true));
135
+ requestAnimationFrame(() => {
136
+ requestAnimationFrame(() => setAnimate(true));
137
+ });
120
138
  }
121
139
  }, [dataKey]);
122
140
  return animate || prefersReducedMotion();
123
141
  };
124
142
  var TOOLTIP_OFFSET = 12;
125
143
  var useChartTooltip = (enabled) => {
126
- const [tooltip, setTooltip] = React.useState({
144
+ const [tooltip, setTooltip] = React2.useState({
127
145
  visible: false,
128
146
  clientX: 0,
129
147
  clientY: 0,
130
148
  content: ""
131
149
  });
132
- const containerRef = React.useRef(null);
133
- const rafRef = React.useRef(0);
134
- const move = React.useCallback((e) => {
150
+ const containerRef = React2.useRef(null);
151
+ const rafRef = React2.useRef(0);
152
+ const move = React2.useCallback((e) => {
135
153
  if (!enabled) return;
136
154
  const cx = e.clientX;
137
155
  const cy = e.clientY;
@@ -140,22 +158,22 @@ var useChartTooltip = (enabled) => {
140
158
  setTooltip((prev) => ({ ...prev, clientX: cx, clientY: cy }));
141
159
  });
142
160
  }, [enabled]);
143
- const show = React.useCallback((e, content) => {
161
+ const show = React2.useCallback((e, content) => {
144
162
  if (!enabled) return;
145
163
  setTooltip({ visible: true, clientX: e.clientX, clientY: e.clientY, content });
146
164
  }, [enabled]);
147
- const hide = React.useCallback(() => {
165
+ const hide = React2.useCallback(() => {
148
166
  cancelAnimationFrame(rafRef.current);
149
167
  setTooltip((prev) => ({ ...prev, visible: false }));
150
168
  }, []);
151
169
  return { tooltip, show, hide, move, containerRef };
152
170
  };
153
- var GridLines = React.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ jsx(Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
171
+ var GridLines = React2.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ jsx2(Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
154
172
  const y = PADDING.top + (1 - ratio) * chartH;
155
173
  const val = Math.round(maxVal * ratio);
156
174
  return /* @__PURE__ */ jsxs("g", { children: [
157
- /* @__PURE__ */ jsx("line", { x1: PADDING.left, y1: y, x2: width - PADDING.right, y2: y, className: "chart-grid" }),
158
- /* @__PURE__ */ jsx("text", { x: PADDING.left - 8, y: y + 4, className: "chart-axis-label", textAnchor: "end", children: val })
175
+ /* @__PURE__ */ jsx2("line", { x1: PADDING.left, y1: y, x2: width - PADDING.right, y2: y, className: "chart-grid" }),
176
+ /* @__PURE__ */ jsx2("text", { x: PADDING.left - 8, y: y + 4, className: "chart-axis-label", textAnchor: "end", children: val })
159
177
  ] }, ratio);
160
178
  }) }));
161
179
  GridLines.displayName = "GridLines";
@@ -165,18 +183,18 @@ var getLabelStep = (count, chartW) => {
165
183
  if (count <= maxLabels) return 1;
166
184
  return Math.ceil(count / maxLabels);
167
185
  };
168
- var AxisLabels = React.memo(({ labels, count, chartW, height }) => {
186
+ var AxisLabels = React2.memo(({ labels, count, chartW, height }) => {
169
187
  const step = getLabelStep(count, chartW);
170
- return /* @__PURE__ */ jsx(Fragment, { children: labels.map((label, i) => {
188
+ return /* @__PURE__ */ jsx2(Fragment, { children: labels.map((label, i) => {
171
189
  if (i % step !== 0) return null;
172
190
  const x = PADDING.left + i / (count - 1 || 1) * chartW;
173
- return /* @__PURE__ */ jsx("text", { x, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
191
+ return /* @__PURE__ */ jsx2("text", { x, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
174
192
  }) });
175
193
  });
176
194
  AxisLabels.displayName = "AxisLabels";
177
195
  var useCrosshair = (seriesPoints, entries, labels, chartH) => {
178
- const [activeIndex, setActiveIndex] = React.useState(null);
179
- const handleMouseMove = React.useCallback((e) => {
196
+ const [activeIndex, setActiveIndex] = React2.useState(null);
197
+ const handleMouseMove = React2.useCallback((e) => {
180
198
  const svg = e.currentTarget;
181
199
  const rect = svg.getBoundingClientRect();
182
200
  const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
@@ -195,17 +213,17 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
195
213
  }
196
214
  setActiveIndex(minDist <= threshold ? closest : null);
197
215
  }, [seriesPoints]);
198
- const handleMouseLeave = React.useCallback(() => {
216
+ const handleMouseLeave = React2.useCallback(() => {
199
217
  setActiveIndex(null);
200
218
  }, []);
201
- const tooltipContent = React.useMemo(() => {
219
+ const tooltipContent = React2.useMemo(() => {
202
220
  if (activeIndex === null) return "";
203
221
  return entries.map(([key], di) => {
204
222
  const p = seriesPoints[di]?.[activeIndex];
205
223
  return p ? `${key}: ${p.v}` : "";
206
224
  }).filter(Boolean).join(" / ");
207
225
  }, [activeIndex, entries, seriesPoints]);
208
- const getTooltipAt = React.useCallback((idx) => {
226
+ const getTooltipAt = React2.useCallback((idx) => {
209
227
  return entries.map(([key], di) => {
210
228
  const p = seriesPoints[di]?.[idx];
211
229
  return p ? `${key}: ${p.v}` : "";
@@ -213,16 +231,16 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
213
231
  }, [entries, seriesPoints]);
214
232
  return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
215
233
  };
216
- var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
217
- const entries = React.useMemo(() => Object.entries(data), [data]);
218
- const maxVal = React.useMemo(() => {
234
+ var LineChart = React2.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
235
+ const entries = React2.useMemo(() => Object.entries(data), [data]);
236
+ const maxVal = React2.useMemo(() => {
219
237
  const allValues = entries.flatMap(([, v]) => v);
220
238
  return Math.max(...allValues) * 1.2 || 1;
221
239
  }, [entries]);
222
240
  const count = labels.length;
223
241
  const chartW = width - PADDING.left - PADDING.right;
224
242
  const chartH = height - PADDING.top - PADDING.bottom;
225
- const seriesPoints = React.useMemo(
243
+ const seriesPoints = React2.useMemo(
226
244
  () => entries.map(
227
245
  ([, values]) => values.map((v, i) => ({
228
246
  x: PADDING.left + i / (count - 1 || 1) * chartW,
@@ -232,31 +250,18 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
232
250
  ),
233
251
  [entries, count, chartW, chartH, maxVal]
234
252
  );
235
- const lineRefs = React.useRef([]);
236
- const clipRef = React.useRef(null);
253
+ const clipRef = React2.useRef(null);
237
254
  const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
238
- React.useEffect(() => {
239
- if (!animate) return;
240
- lineRefs.current.forEach((el) => {
241
- if (!el) return;
242
- const len = el.getTotalLength();
243
- el.style.strokeDasharray = `${len}`;
244
- el.style.strokeDashoffset = `${len}`;
245
- requestAnimationFrame(() => {
246
- el.style.transition = "stroke-dashoffset 1200ms ease-out 200ms";
247
- el.style.strokeDashoffset = "0";
248
- });
255
+ React2.useEffect(() => {
256
+ if (!animate || !clipRef.current) return;
257
+ clipRef.current.setAttribute("width", "0");
258
+ requestAnimationFrame(() => {
259
+ if (clipRef.current) {
260
+ clipRef.current.style.transition = "width 1200ms ease-out 200ms";
261
+ clipRef.current.setAttribute("width", `${width}`);
262
+ }
249
263
  });
250
- if (clipRef.current) {
251
- clipRef.current.setAttribute("width", "0");
252
- requestAnimationFrame(() => {
253
- if (clipRef.current) {
254
- clipRef.current.style.transition = "width 1200ms ease-out 200ms";
255
- clipRef.current.setAttribute("width", `${width}`);
256
- }
257
- });
258
- }
259
- }, [animate, seriesPoints, width]);
264
+ }, [animate, width]);
260
265
  const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
261
266
  const lineClipId = "line-area-clip";
262
267
  return /* @__PURE__ */ jsxs(
@@ -292,9 +297,9 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
292
297
  onLeave();
293
298
  },
294
299
  children: [
295
- animate && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: lineClipId, children: /* @__PURE__ */ jsx("rect", { ref: clipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
296
- /* @__PURE__ */ jsx(GridLines, { width, height, chartH, maxVal }),
297
- /* @__PURE__ */ jsx(AxisLabels, { labels, count, chartW, height }),
300
+ animate && /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsx2("clipPath", { id: lineClipId, children: /* @__PURE__ */ jsx2("rect", { ref: clipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
301
+ /* @__PURE__ */ jsx2(GridLines, { width, height, chartH, maxVal }),
302
+ /* @__PURE__ */ jsx2(AxisLabels, { labels, count, chartW, height }),
298
303
  entries.map(([key], di) => {
299
304
  const palette = getPalette(LINE_BAR_PALETTES, di, key);
300
305
  const color = palette[2];
@@ -304,31 +309,15 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
304
309
  const polyPoints = points.map((p) => `${p.x},${p.y}`).join(" ");
305
310
  const areaD = `M ${points[0].x},${points[0].y} ${points.map((p) => `L ${p.x},${p.y}`).join(" ")} L ${points[points.length - 1].x},${PADDING.top + chartH} L ${points[0].x},${PADDING.top + chartH} Z`;
306
311
  return /* @__PURE__ */ jsxs("g", { children: [
307
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
308
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.2" }),
309
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0" })
312
+ /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
313
+ /* @__PURE__ */ jsx2("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.2" }),
314
+ /* @__PURE__ */ jsx2("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0" })
310
315
  ] }) }),
311
- /* @__PURE__ */ jsx(
312
- "path",
313
- {
314
- d: areaD,
315
- fill: `url(#${gradientId})`,
316
- clipPath: animate ? `url(#${lineClipId})` : void 0
317
- }
318
- ),
319
- /* @__PURE__ */ jsx(
320
- "polyline",
321
- {
322
- ref: (el) => {
323
- lineRefs.current[di] = el;
324
- },
325
- points: polyPoints,
326
- fill: "none",
327
- stroke: color,
328
- strokeWidth: "2"
329
- }
330
- ),
331
- activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx(
316
+ /* @__PURE__ */ jsxs("g", { clipPath: animate ? `url(#${lineClipId})` : void 0, children: [
317
+ /* @__PURE__ */ jsx2("path", { d: areaD, fill: `url(#${gradientId})` }),
318
+ /* @__PURE__ */ jsx2("polyline", { points: polyPoints, fill: "none", stroke: color, strokeWidth: "2" })
319
+ ] }),
320
+ activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx2(
332
321
  "circle",
333
322
  {
334
323
  cx: points[activeIndex].x,
@@ -340,7 +329,7 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
340
329
  )
341
330
  ] }, di);
342
331
  }),
343
- activeX !== null && /* @__PURE__ */ jsx(
332
+ activeX !== null && /* @__PURE__ */ jsx2(
344
333
  "line",
345
334
  {
346
335
  x1: activeX,
@@ -350,7 +339,7 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
350
339
  className: "chart-crosshair"
351
340
  }
352
341
  ),
353
- /* @__PURE__ */ jsx(
342
+ /* @__PURE__ */ jsx2(
354
343
  "rect",
355
344
  {
356
345
  x: PADDING.left,
@@ -366,16 +355,16 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onM
366
355
  );
367
356
  });
368
357
  LineChart.displayName = "LineChart";
369
- var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
370
- const entries = React.useMemo(() => Object.entries(data), [data]);
371
- const maxVal = React.useMemo(() => {
358
+ var CurveChart = React2.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
359
+ const entries = React2.useMemo(() => Object.entries(data), [data]);
360
+ const maxVal = React2.useMemo(() => {
372
361
  const allValues = entries.flatMap(([, v]) => v);
373
362
  return Math.max(...allValues) * 1.2 || 1;
374
363
  }, [entries]);
375
364
  const count = labels.length;
376
365
  const chartW = width - PADDING.left - PADDING.right;
377
366
  const chartH = height - PADDING.top - PADDING.bottom;
378
- const seriesPoints = React.useMemo(
367
+ const seriesPoints = React2.useMemo(
379
368
  () => entries.map(
380
369
  ([, values]) => values.map((v, i) => ({
381
370
  x: PADDING.left + i / (count - 1 || 1) * chartW,
@@ -385,31 +374,18 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
385
374
  ),
386
375
  [entries, count, chartW, chartH, maxVal]
387
376
  );
388
- const lineRefs = React.useRef([]);
389
- const curveClipRef = React.useRef(null);
377
+ const curveClipRef = React2.useRef(null);
390
378
  const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
391
- React.useEffect(() => {
392
- if (!animate) return;
393
- lineRefs.current.forEach((el) => {
394
- if (!el) return;
395
- const len = el.getTotalLength();
396
- el.style.strokeDasharray = `${len}`;
397
- el.style.strokeDashoffset = `${len}`;
398
- requestAnimationFrame(() => {
399
- el.style.transition = "stroke-dashoffset 1200ms ease-out 200ms";
400
- el.style.strokeDashoffset = "0";
401
- });
379
+ React2.useEffect(() => {
380
+ if (!animate || !curveClipRef.current) return;
381
+ curveClipRef.current.setAttribute("width", "0");
382
+ requestAnimationFrame(() => {
383
+ if (curveClipRef.current) {
384
+ curveClipRef.current.style.transition = "width 1200ms ease-out 200ms";
385
+ curveClipRef.current.setAttribute("width", `${width}`);
386
+ }
402
387
  });
403
- if (curveClipRef.current) {
404
- curveClipRef.current.setAttribute("width", "0");
405
- requestAnimationFrame(() => {
406
- if (curveClipRef.current) {
407
- curveClipRef.current.style.transition = "width 1200ms ease-out 200ms";
408
- curveClipRef.current.setAttribute("width", `${width}`);
409
- }
410
- });
411
- }
412
- }, [animate, seriesPoints, width]);
388
+ }, [animate, width]);
413
389
  const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
414
390
  const curveClipId = "curve-area-clip";
415
391
  return /* @__PURE__ */ jsxs(
@@ -445,9 +421,9 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
445
421
  onLeave();
446
422
  },
447
423
  children: [
448
- animate && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: curveClipId, children: /* @__PURE__ */ jsx("rect", { ref: curveClipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
449
- /* @__PURE__ */ jsx(GridLines, { width, height, chartH, maxVal }),
450
- /* @__PURE__ */ jsx(AxisLabels, { labels, count, chartW, height }),
424
+ animate && /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsx2("clipPath", { id: curveClipId, children: /* @__PURE__ */ jsx2("rect", { ref: curveClipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
425
+ /* @__PURE__ */ jsx2(GridLines, { width, height, chartH, maxVal }),
426
+ /* @__PURE__ */ jsx2(AxisLabels, { labels, count, chartW, height }),
451
427
  entries.map(([key], di) => {
452
428
  const palette = getPalette(LINE_BAR_PALETTES, di, key);
453
429
  const color = palette[2];
@@ -457,31 +433,15 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
457
433
  const linePath = toSmoothPath(points);
458
434
  const areaPath = linePath + ` L ${points[points.length - 1].x} ${PADDING.top + chartH} L ${points[0].x} ${PADDING.top + chartH} Z`;
459
435
  return /* @__PURE__ */ jsxs("g", { children: [
460
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
461
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.4" }),
462
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0.02" })
436
+ /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
437
+ /* @__PURE__ */ jsx2("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.4" }),
438
+ /* @__PURE__ */ jsx2("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0.02" })
463
439
  ] }) }),
464
- /* @__PURE__ */ jsx(
465
- "path",
466
- {
467
- d: areaPath,
468
- fill: `url(#${gradientId})`,
469
- clipPath: animate ? `url(#${curveClipId})` : void 0
470
- }
471
- ),
472
- /* @__PURE__ */ jsx(
473
- "path",
474
- {
475
- ref: (el) => {
476
- lineRefs.current[di] = el;
477
- },
478
- d: linePath,
479
- fill: "none",
480
- stroke: color,
481
- strokeWidth: "2"
482
- }
483
- ),
484
- activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx(
440
+ /* @__PURE__ */ jsxs("g", { clipPath: animate ? `url(#${curveClipId})` : void 0, children: [
441
+ /* @__PURE__ */ jsx2("path", { d: areaPath, fill: `url(#${gradientId})` }),
442
+ /* @__PURE__ */ jsx2("path", { d: linePath, fill: "none", stroke: color, strokeWidth: "2" })
443
+ ] }),
444
+ activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx2(
485
445
  "circle",
486
446
  {
487
447
  cx: points[activeIndex].x,
@@ -493,7 +453,7 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
493
453
  )
494
454
  ] }, di);
495
455
  }),
496
- activeX !== null && /* @__PURE__ */ jsx(
456
+ activeX !== null && /* @__PURE__ */ jsx2(
497
457
  "line",
498
458
  {
499
459
  x1: activeX,
@@ -503,7 +463,7 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
503
463
  className: "chart-crosshair"
504
464
  }
505
465
  ),
506
- /* @__PURE__ */ jsx(
466
+ /* @__PURE__ */ jsx2(
507
467
  "rect",
508
468
  {
509
469
  x: PADDING.left,
@@ -519,9 +479,9 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
519
479
  );
520
480
  });
521
481
  CurveChart.displayName = "CurveChart";
522
- var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
523
- const entries = React.useMemo(() => Object.entries(data), [data]);
524
- const maxVal = React.useMemo(() => {
482
+ var BarChart = React2.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
483
+ const entries = React2.useMemo(() => Object.entries(data), [data]);
484
+ const maxVal = React2.useMemo(() => {
525
485
  const allValues = entries.flatMap(([, v]) => v);
526
486
  return Math.max(...allValues) * 1.2 || 1;
527
487
  }, [entries]);
@@ -533,7 +493,7 @@ var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMo
533
493
  const barGap = groupCount > 1 ? 2 : 0;
534
494
  const barW = Math.max(1, Math.min(32, (groupW * 0.7 - barGap * (groupCount - 1)) / groupCount));
535
495
  const baseline = PADDING.top + chartH;
536
- const bars = React.useMemo(
496
+ const bars = React2.useMemo(
537
497
  () => entries.map(
538
498
  ([, values], di) => values.map((v, i) => {
539
499
  const totalBarsW = barW * groupCount + barGap * (groupCount - 1);
@@ -547,10 +507,10 @@ var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMo
547
507
  );
548
508
  const barLabelStep = getLabelStep(count, chartW);
549
509
  return /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${width} ${height}`, className: "chart-svg", children: [
550
- /* @__PURE__ */ jsx(GridLines, { width, height, chartH, maxVal }),
510
+ /* @__PURE__ */ jsx2(GridLines, { width, height, chartH, maxVal }),
551
511
  labels.map((label, i) => {
552
512
  if (i % barLabelStep !== 0) return null;
553
- return /* @__PURE__ */ jsx("text", { x: PADDING.left + groupW * i + groupW / 2, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
513
+ return /* @__PURE__ */ jsx2("text", { x: PADDING.left + groupW * i + groupW / 2, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
554
514
  }),
555
515
  entries.map(([key], di) => {
556
516
  const palette = getPalette(LINE_BAR_PALETTES, di, key);
@@ -559,7 +519,7 @@ var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMo
559
519
  const r = Math.min(4, b.w / 2);
560
520
  const d = b.h <= r ? `M ${b.x} ${b.y + b.h} V ${b.y} H ${b.x + b.w} V ${b.y + b.h} Z` : `M ${b.x} ${b.y + b.h} V ${b.y + r} Q ${b.x} ${b.y} ${b.x + r} ${b.y} H ${b.x + b.w - r} Q ${b.x + b.w} ${b.y} ${b.x + b.w} ${b.y + r} V ${b.y + b.h} Z`;
561
521
  const delay = 100 + i * 80;
562
- return /* @__PURE__ */ jsx(
522
+ return /* @__PURE__ */ jsx2(
563
523
  "path",
564
524
  {
565
525
  d,
@@ -580,11 +540,11 @@ var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMo
580
540
  ] });
581
541
  });
582
542
  BarChart.displayName = "BarChart";
583
- var PieDonutChart = React.memo(
543
+ var PieDonutChart = React2.memo(
584
544
  ({ data, labels, width, height, animate, isDoughnut, onHover, onMove, onLeave }) => {
585
- const entries = React.useMemo(() => Object.entries(data), [data]);
586
- const values = React.useMemo(() => entries.flatMap(([, v]) => v), [entries]);
587
- const total = React.useMemo(() => values.reduce((a, b) => a + b, 0) || 1, [values]);
545
+ const entries = React2.useMemo(() => Object.entries(data), [data]);
546
+ const values = React2.useMemo(() => entries.flatMap(([, v]) => v), [entries]);
547
+ const total = React2.useMemo(() => values.reduce((a, b) => a + b, 0) || 1, [values]);
588
548
  const size = Math.min(width, height);
589
549
  const cx = size / 2;
590
550
  const cy = size / 2;
@@ -592,10 +552,10 @@ var PieDonutChart = React.memo(
592
552
  const innerR = isDoughnut ? r * 0.5 : 0;
593
553
  const firstKey = entries[0]?.[0] ?? "";
594
554
  const colorOffset = hashString(firstKey);
595
- const maskRef = React.useRef(null);
555
+ const maskRef = React2.useRef(null);
596
556
  const maskR = r + 10;
597
557
  const maskCircumference = 2 * Math.PI * maskR;
598
- React.useEffect(() => {
558
+ React2.useEffect(() => {
599
559
  if (!animate || !maskRef.current) return;
600
560
  const el = maskRef.current;
601
561
  el.style.strokeDasharray = `${maskCircumference}`;
@@ -605,7 +565,7 @@ var PieDonutChart = React.memo(
605
565
  el.style.strokeDashoffset = "0";
606
566
  });
607
567
  }, [animate, maskCircumference]);
608
- const sliceData = React.useMemo(() => {
568
+ const sliceData = React2.useMemo(() => {
609
569
  let angle0 = -Math.PI / 2;
610
570
  let cumulativeAngle = 0;
611
571
  return values.map((v, i) => {
@@ -640,7 +600,7 @@ var PieDonutChart = React.memo(
640
600
  }, [values, total, cx, cy, r, innerR, labels]);
641
601
  const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
642
602
  return /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
643
- animate && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("mask", { id: maskId, children: /* @__PURE__ */ jsx(
603
+ animate && /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsx2("mask", { id: maskId, children: /* @__PURE__ */ jsx2(
644
604
  "circle",
645
605
  {
646
606
  ref: maskRef,
@@ -653,7 +613,7 @@ var PieDonutChart = React.memo(
653
613
  transform: `rotate(-90 ${cx} ${cy})`
654
614
  }
655
615
  ) }) }),
656
- /* @__PURE__ */ jsx("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx(
616
+ /* @__PURE__ */ jsx2("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ jsx2("g", { children: /* @__PURE__ */ jsx2(
657
617
  "path",
658
618
  {
659
619
  d: s.d,
@@ -664,7 +624,7 @@ var PieDonutChart = React.memo(
664
624
  onMouseLeave: onLeave
665
625
  }
666
626
  ) }, i)) }),
667
- sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ jsx(
627
+ sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ jsx2(
668
628
  "text",
669
629
  {
670
630
  x: s.lx,
@@ -682,9 +642,9 @@ var PieDonutChart = React.memo(
682
642
  );
683
643
  PieDonutChart.displayName = "PieDonutChart";
684
644
  var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
685
- const ref = React.useRef(null);
686
- const [pos, setPos] = React.useState({ left: 0, top: 0 });
687
- React.useLayoutEffect(() => {
645
+ const ref = React2.useRef(null);
646
+ const [pos, setPos] = React2.useState({ left: 0, top: 0 });
647
+ React2.useLayoutEffect(() => {
688
648
  const el = ref.current;
689
649
  if (!el) return;
690
650
  const w = el.offsetWidth;
@@ -697,7 +657,7 @@ var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
697
657
  if (left < 8) left = 8;
698
658
  setPos({ left, top });
699
659
  }, [clientX, clientY]);
700
- return /* @__PURE__ */ jsx(
660
+ return /* @__PURE__ */ jsx2(
701
661
  "div",
702
662
  {
703
663
  ref,
@@ -714,13 +674,13 @@ var ChartLegend = ({ data, labels, type }) => {
714
674
  const total = values.reduce((a, b) => a + b, 0) || 1;
715
675
  const firstKey = entries[0]?.[0] ?? "";
716
676
  const colorOffset = hashString(firstKey);
717
- return /* @__PURE__ */ jsx("div", { className: "chart-legend", children: values.map((v, i) => {
677
+ return /* @__PURE__ */ jsx2("div", { className: "chart-legend", children: values.map((v, i) => {
718
678
  const pct = Math.round(v / total * 100);
719
679
  const color = PIE_COLORS[(i + colorOffset) % PIE_COLORS.length];
720
680
  return /* @__PURE__ */ jsxs("div", { className: "chart-legend-item", children: [
721
- /* @__PURE__ */ jsx("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
681
+ /* @__PURE__ */ jsx2("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
722
682
  /* @__PURE__ */ jsxs("div", { className: "chart-legend-text", children: [
723
- /* @__PURE__ */ jsx("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
683
+ /* @__PURE__ */ jsx2("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
724
684
  /* @__PURE__ */ jsxs("span", { className: "chart-legend-value", children: [
725
685
  v.toLocaleString(),
726
686
  "(",
@@ -731,37 +691,37 @@ var ChartLegend = ({ data, labels, type }) => {
731
691
  ] }, i);
732
692
  }) });
733
693
  }
734
- return /* @__PURE__ */ jsx("div", { className: "chart-legend", children: entries.map(([key], di) => {
694
+ return /* @__PURE__ */ jsx2("div", { className: "chart-legend", children: entries.map(([key], di) => {
735
695
  const palette = getPalette(LINE_BAR_PALETTES, di, key);
736
696
  const color = palette[2];
737
697
  const values = entries[di][1];
738
698
  const sum = values.reduce((a, b) => a + b, 0);
739
699
  return /* @__PURE__ */ jsxs("div", { className: "chart-legend-item", children: [
740
- /* @__PURE__ */ jsx("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
700
+ /* @__PURE__ */ jsx2("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
741
701
  /* @__PURE__ */ jsxs("div", { className: "chart-legend-text", children: [
742
- /* @__PURE__ */ jsx("span", { className: "chart-legend-label", children: key }),
743
- /* @__PURE__ */ jsx("span", { className: "chart-legend-value", children: sum.toLocaleString() })
702
+ /* @__PURE__ */ jsx2("span", { className: "chart-legend-label", children: key }),
703
+ /* @__PURE__ */ jsx2("span", { className: "chart-legend-value", children: sum.toLocaleString() })
744
704
  ] })
745
705
  ] }, di);
746
706
  }) });
747
707
  };
748
- var Chart = React.memo((props) => {
708
+ var Chart = React2.memo((props) => {
749
709
  const { type, data, labels, tooltip: showTooltip = true } = props;
750
710
  const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
751
711
  const { width, height } = useChartSize(containerRef);
752
- const stableData = React.useMemo(() => data, [JSON.stringify(data)]);
753
- const stableLabels = React.useMemo(() => labels, [JSON.stringify(labels)]);
754
- const dataKey = React.useMemo(() => JSON.stringify(labels), [labels]);
712
+ const stableData = React2.useMemo(() => data, [JSON.stringify(data)]);
713
+ const stableLabels = React2.useMemo(() => labels, [JSON.stringify(labels)]);
714
+ const dataKey = React2.useMemo(() => JSON.stringify(labels), [labels]);
755
715
  const animate = useChartAnimation(containerRef, dataKey);
756
716
  const ready = width > 0 && height > 0;
757
717
  return /* @__PURE__ */ jsxs("div", { className: "lib-xplat-chart", ref: containerRef, children: [
758
- ready && type === "line" && /* @__PURE__ */ jsx(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
759
- ready && type === "curve" && /* @__PURE__ */ jsx(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
760
- ready && type === "bar" && /* @__PURE__ */ jsx(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
761
- ready && type === "pie" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
762
- ready && type === "doughnut" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
763
- ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx(ChartLegend, { data: stableData, labels: stableLabels, type }),
764
- tooltip.content && /* @__PURE__ */ jsx(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content })
718
+ ready && type === "line" && /* @__PURE__ */ jsx2(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
719
+ ready && type === "curve" && /* @__PURE__ */ jsx2(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
720
+ ready && type === "bar" && /* @__PURE__ */ jsx2(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
721
+ ready && type === "pie" && /* @__PURE__ */ jsx2(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
722
+ ready && type === "doughnut" && /* @__PURE__ */ jsx2(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
723
+ ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx2(ChartLegend, { data: stableData, labels: stableLabels, type }),
724
+ tooltip.content && /* @__PURE__ */ jsx2(Portal_default, { children: /* @__PURE__ */ jsx2(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content }) })
765
725
  ] });
766
726
  });
767
727
  Chart.displayName = "Chart";