@x-plat/design-system 0.5.32 → 0.5.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2256,45 +2256,35 @@ var useChartAnimation = (containerRef, dataKey) => {
2256
2256
  prevDataKey.current = dataKey;
2257
2257
  if (prefersReducedMotion()) return;
2258
2258
  setAnimate(false);
2259
- requestAnimationFrame(() => setAnimate(true));
2259
+ requestAnimationFrame(() => {
2260
+ requestAnimationFrame(() => setAnimate(true));
2261
+ });
2260
2262
  }
2261
2263
  }, [dataKey]);
2262
2264
  return animate || prefersReducedMotion();
2263
2265
  };
2266
+ var TOOLTIP_OFFSET = 12;
2264
2267
  var useChartTooltip = (enabled) => {
2265
2268
  const [tooltip, setTooltip] = React6.useState({
2266
2269
  visible: false,
2267
- x: 0,
2268
- y: 0,
2270
+ clientX: 0,
2271
+ clientY: 0,
2269
2272
  content: ""
2270
2273
  });
2271
2274
  const containerRef = React6.useRef(null);
2272
2275
  const rafRef = React6.useRef(0);
2273
2276
  const move = React6.useCallback((e) => {
2274
2277
  if (!enabled) return;
2275
- const clientX = e.clientX;
2276
- const clientY = e.clientY;
2278
+ const cx = e.clientX;
2279
+ const cy = e.clientY;
2277
2280
  cancelAnimationFrame(rafRef.current);
2278
2281
  rafRef.current = requestAnimationFrame(() => {
2279
- const rect = containerRef.current?.getBoundingClientRect();
2280
- if (!rect) return;
2281
- setTooltip((prev) => ({
2282
- ...prev,
2283
- x: clientX - rect.left,
2284
- y: clientY - rect.top - 12
2285
- }));
2282
+ setTooltip((prev) => ({ ...prev, clientX: cx, clientY: cy }));
2286
2283
  });
2287
2284
  }, [enabled]);
2288
2285
  const show = React6.useCallback((e, content) => {
2289
2286
  if (!enabled) return;
2290
- const rect = containerRef.current?.getBoundingClientRect();
2291
- if (!rect) return;
2292
- setTooltip({
2293
- visible: true,
2294
- x: e.clientX - rect.left,
2295
- y: e.clientY - rect.top - 12,
2296
- content
2297
- });
2287
+ setTooltip({ visible: true, clientX: e.clientX, clientY: e.clientY, content });
2298
2288
  }, [enabled]);
2299
2289
  const hide = React6.useCallback(() => {
2300
2290
  cancelAnimationFrame(rafRef.current);
@@ -2328,14 +2318,14 @@ var AxisLabels = React6.memo(({ labels, count, chartW, height }) => {
2328
2318
  AxisLabels.displayName = "AxisLabels";
2329
2319
  var useCrosshair = (seriesPoints, entries, labels, chartH) => {
2330
2320
  const [activeIndex, setActiveIndex] = React6.useState(null);
2331
- const [mouseX, setMouseX] = React6.useState(null);
2332
2321
  const handleMouseMove = React6.useCallback((e) => {
2333
2322
  const svg = e.currentTarget;
2334
2323
  const rect = svg.getBoundingClientRect();
2335
2324
  const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
2336
- setMouseX(mx);
2337
2325
  if (seriesPoints.length === 0 || seriesPoints[0].length === 0) return;
2338
2326
  const points = seriesPoints[0];
2327
+ const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
2328
+ const threshold = step / 2;
2339
2329
  let closest = 0;
2340
2330
  let minDist = Math.abs(points[0].x - mx);
2341
2331
  for (let i = 1; i < points.length; i++) {
@@ -2345,11 +2335,10 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
2345
2335
  closest = i;
2346
2336
  }
2347
2337
  }
2348
- setActiveIndex(closest);
2338
+ setActiveIndex(minDist <= threshold ? closest : null);
2349
2339
  }, [seriesPoints]);
2350
2340
  const handleMouseLeave = React6.useCallback(() => {
2351
2341
  setActiveIndex(null);
2352
- setMouseX(null);
2353
2342
  }, []);
2354
2343
  const tooltipContent = React6.useMemo(() => {
2355
2344
  if (activeIndex === null) return "";
@@ -2358,7 +2347,13 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
2358
2347
  return p ? `${key}: ${p.v}` : "";
2359
2348
  }).filter(Boolean).join(" / ");
2360
2349
  }, [activeIndex, entries, seriesPoints]);
2361
- return { activeIndex, mouseX, handleMouseMove, handleMouseLeave, tooltipContent };
2350
+ const getTooltipAt = React6.useCallback((idx) => {
2351
+ return entries.map(([key], di) => {
2352
+ const p = seriesPoints[di]?.[idx];
2353
+ return p ? `${key}: ${p.v}` : "";
2354
+ }).filter(Boolean).join(" / ");
2355
+ }, [entries, seriesPoints]);
2356
+ return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
2362
2357
  };
2363
2358
  var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
2364
2359
  const entries = React6.useMemo(() => Object.entries(data), [data]);
@@ -2379,33 +2374,19 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
2379
2374
  ),
2380
2375
  [entries, count, chartW, chartH, maxVal]
2381
2376
  );
2382
- const lineRefs = React6.useRef([]);
2383
2377
  const clipRef = React6.useRef(null);
2384
- const { activeIndex, mouseX, handleMouseMove, handleMouseLeave, tooltipContent } = useCrosshair(seriesPoints, entries, labels, chartH);
2378
+ const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
2385
2379
  React6.useEffect(() => {
2386
- if (!animate) return;
2387
- lineRefs.current.forEach((el) => {
2388
- if (!el) return;
2389
- const len = el.getTotalLength();
2390
- el.style.strokeDasharray = `${len}`;
2391
- el.style.strokeDashoffset = `${len}`;
2392
- requestAnimationFrame(() => {
2393
- el.style.transition = "stroke-dashoffset 1200ms ease-out 200ms";
2394
- el.style.strokeDashoffset = "0";
2395
- });
2380
+ if (!animate || !clipRef.current) return;
2381
+ clipRef.current.setAttribute("width", "0");
2382
+ requestAnimationFrame(() => {
2383
+ if (clipRef.current) {
2384
+ clipRef.current.style.transition = "width 1200ms ease-out 200ms";
2385
+ clipRef.current.setAttribute("width", `${width}`);
2386
+ }
2396
2387
  });
2397
- if (clipRef.current) {
2398
- clipRef.current.setAttribute("width", "0");
2399
- requestAnimationFrame(() => {
2400
- if (clipRef.current) {
2401
- clipRef.current.style.transition = "width 1200ms ease-out 200ms";
2402
- clipRef.current.setAttribute("width", `${width}`);
2403
- }
2404
- });
2405
- }
2406
- }, [animate, seriesPoints, width]);
2407
- const guideX = mouseX != null && mouseX >= PADDING.left && mouseX <= width - PADDING.right ? mouseX : null;
2408
- const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x : null;
2388
+ }, [animate, width]);
2389
+ const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
2409
2390
  const lineClipId = "line-area-clip";
2410
2391
  return /* @__PURE__ */ jsxs197(
2411
2392
  "svg",
@@ -2414,7 +2395,26 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
2414
2395
  className: "chart-svg",
2415
2396
  onMouseMove: (e) => {
2416
2397
  handleMouseMove(e);
2417
- onMove(e);
2398
+ const svg = e.currentTarget;
2399
+ const rect = svg.getBoundingClientRect();
2400
+ const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
2401
+ const points = seriesPoints[0];
2402
+ if (!points || points.length === 0) return;
2403
+ const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
2404
+ let closest = 0;
2405
+ let minDist = Math.abs(points[0].x - mx);
2406
+ for (let i = 1; i < points.length; i++) {
2407
+ const dist = Math.abs(points[i].x - mx);
2408
+ if (dist < minDist) {
2409
+ minDist = dist;
2410
+ closest = i;
2411
+ }
2412
+ }
2413
+ if (minDist <= step / 2) {
2414
+ onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
2415
+ } else {
2416
+ onLeave();
2417
+ }
2418
2418
  },
2419
2419
  onMouseLeave: () => {
2420
2420
  handleMouseLeave();
@@ -2437,26 +2437,10 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
2437
2437
  /* @__PURE__ */ jsx307("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.2" }),
2438
2438
  /* @__PURE__ */ jsx307("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0" })
2439
2439
  ] }) }),
2440
- /* @__PURE__ */ jsx307(
2441
- "path",
2442
- {
2443
- d: areaD,
2444
- fill: `url(#${gradientId})`,
2445
- clipPath: animate ? `url(#${lineClipId})` : void 0
2446
- }
2447
- ),
2448
- /* @__PURE__ */ jsx307(
2449
- "polyline",
2450
- {
2451
- ref: (el) => {
2452
- lineRefs.current[di] = el;
2453
- },
2454
- points: polyPoints,
2455
- fill: "none",
2456
- stroke: color,
2457
- strokeWidth: "2"
2458
- }
2459
- ),
2440
+ /* @__PURE__ */ jsxs197("g", { clipPath: animate ? `url(#${lineClipId})` : void 0, children: [
2441
+ /* @__PURE__ */ jsx307("path", { d: areaD, fill: `url(#${gradientId})` }),
2442
+ /* @__PURE__ */ jsx307("polyline", { points: polyPoints, fill: "none", stroke: color, strokeWidth: "2" })
2443
+ ] }),
2460
2444
  activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx307(
2461
2445
  "circle",
2462
2446
  {
@@ -2469,21 +2453,16 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
2469
2453
  )
2470
2454
  ] }, di);
2471
2455
  }),
2472
- guideX !== null && /* @__PURE__ */ jsx307(
2456
+ activeX !== null && /* @__PURE__ */ jsx307(
2473
2457
  "line",
2474
2458
  {
2475
- x1: guideX,
2459
+ x1: activeX,
2476
2460
  y1: PADDING.top,
2477
- x2: guideX,
2461
+ x2: activeX,
2478
2462
  y2: PADDING.top + chartH,
2479
2463
  className: "chart-crosshair"
2480
2464
  }
2481
2465
  ),
2482
- activeIndex !== null && activeX !== null && /* @__PURE__ */ jsx307("foreignObject", { x: activeX - 100, y: 0, width: "200", height: PADDING.top, children: /* @__PURE__ */ jsxs197("div", { className: "chart-crosshair-label", children: [
2483
- labels[activeIndex],
2484
- " \u2014 ",
2485
- tooltipContent
2486
- ] }) }),
2487
2466
  /* @__PURE__ */ jsx307(
2488
2467
  "rect",
2489
2468
  {
@@ -2519,33 +2498,19 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
2519
2498
  ),
2520
2499
  [entries, count, chartW, chartH, maxVal]
2521
2500
  );
2522
- const lineRefs = React6.useRef([]);
2523
2501
  const curveClipRef = React6.useRef(null);
2524
- const { activeIndex, mouseX, handleMouseMove, handleMouseLeave, tooltipContent } = useCrosshair(seriesPoints, entries, labels, chartH);
2502
+ const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
2525
2503
  React6.useEffect(() => {
2526
- if (!animate) return;
2527
- lineRefs.current.forEach((el) => {
2528
- if (!el) return;
2529
- const len = el.getTotalLength();
2530
- el.style.strokeDasharray = `${len}`;
2531
- el.style.strokeDashoffset = `${len}`;
2532
- requestAnimationFrame(() => {
2533
- el.style.transition = "stroke-dashoffset 1200ms ease-out 200ms";
2534
- el.style.strokeDashoffset = "0";
2535
- });
2504
+ if (!animate || !curveClipRef.current) return;
2505
+ curveClipRef.current.setAttribute("width", "0");
2506
+ requestAnimationFrame(() => {
2507
+ if (curveClipRef.current) {
2508
+ curveClipRef.current.style.transition = "width 1200ms ease-out 200ms";
2509
+ curveClipRef.current.setAttribute("width", `${width}`);
2510
+ }
2536
2511
  });
2537
- if (curveClipRef.current) {
2538
- curveClipRef.current.setAttribute("width", "0");
2539
- requestAnimationFrame(() => {
2540
- if (curveClipRef.current) {
2541
- curveClipRef.current.style.transition = "width 1200ms ease-out 200ms";
2542
- curveClipRef.current.setAttribute("width", `${width}`);
2543
- }
2544
- });
2545
- }
2546
- }, [animate, seriesPoints, width]);
2547
- const guideX = mouseX != null && mouseX >= PADDING.left && mouseX <= width - PADDING.right ? mouseX : null;
2548
- const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x : null;
2512
+ }, [animate, width]);
2513
+ const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
2549
2514
  const curveClipId = "curve-area-clip";
2550
2515
  return /* @__PURE__ */ jsxs197(
2551
2516
  "svg",
@@ -2554,7 +2519,26 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
2554
2519
  className: "chart-svg",
2555
2520
  onMouseMove: (e) => {
2556
2521
  handleMouseMove(e);
2557
- onMove(e);
2522
+ const svg = e.currentTarget;
2523
+ const rect = svg.getBoundingClientRect();
2524
+ const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
2525
+ const points = seriesPoints[0];
2526
+ if (!points || points.length === 0) return;
2527
+ const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
2528
+ let closest = 0;
2529
+ let minDist = Math.abs(points[0].x - mx);
2530
+ for (let i = 1; i < points.length; i++) {
2531
+ const dist = Math.abs(points[i].x - mx);
2532
+ if (dist < minDist) {
2533
+ minDist = dist;
2534
+ closest = i;
2535
+ }
2536
+ }
2537
+ if (minDist <= step / 2) {
2538
+ onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
2539
+ } else {
2540
+ onLeave();
2541
+ }
2558
2542
  },
2559
2543
  onMouseLeave: () => {
2560
2544
  handleMouseLeave();
@@ -2577,26 +2561,10 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
2577
2561
  /* @__PURE__ */ jsx307("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.4" }),
2578
2562
  /* @__PURE__ */ jsx307("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0.02" })
2579
2563
  ] }) }),
2580
- /* @__PURE__ */ jsx307(
2581
- "path",
2582
- {
2583
- d: areaPath,
2584
- fill: `url(#${gradientId})`,
2585
- clipPath: animate ? `url(#${curveClipId})` : void 0
2586
- }
2587
- ),
2588
- /* @__PURE__ */ jsx307(
2589
- "path",
2590
- {
2591
- ref: (el) => {
2592
- lineRefs.current[di] = el;
2593
- },
2594
- d: linePath,
2595
- fill: "none",
2596
- stroke: color,
2597
- strokeWidth: "2"
2598
- }
2599
- ),
2564
+ /* @__PURE__ */ jsxs197("g", { clipPath: animate ? `url(#${curveClipId})` : void 0, children: [
2565
+ /* @__PURE__ */ jsx307("path", { d: areaPath, fill: `url(#${gradientId})` }),
2566
+ /* @__PURE__ */ jsx307("path", { d: linePath, fill: "none", stroke: color, strokeWidth: "2" })
2567
+ ] }),
2600
2568
  activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx307(
2601
2569
  "circle",
2602
2570
  {
@@ -2609,21 +2577,16 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
2609
2577
  )
2610
2578
  ] }, di);
2611
2579
  }),
2612
- guideX !== null && /* @__PURE__ */ jsx307(
2580
+ activeX !== null && /* @__PURE__ */ jsx307(
2613
2581
  "line",
2614
2582
  {
2615
- x1: guideX,
2583
+ x1: activeX,
2616
2584
  y1: PADDING.top,
2617
- x2: guideX,
2585
+ x2: activeX,
2618
2586
  y2: PADDING.top + chartH,
2619
2587
  className: "chart-crosshair"
2620
2588
  }
2621
2589
  ),
2622
- activeIndex !== null && activeX !== null && /* @__PURE__ */ jsx307("foreignObject", { x: activeX - 100, y: 0, width: "200", height: PADDING.top, children: /* @__PURE__ */ jsxs197("div", { className: "chart-crosshair-label", children: [
2623
- labels[activeIndex],
2624
- " \u2014 ",
2625
- tooltipContent
2626
- ] }) }),
2627
2590
  /* @__PURE__ */ jsx307(
2628
2591
  "rect",
2629
2592
  {
@@ -2802,30 +2765,70 @@ var PieDonutChart = React6.memo(
2802
2765
  }
2803
2766
  );
2804
2767
  PieDonutChart.displayName = "PieDonutChart";
2805
- var TooltipBubble = ({ x, y, containerWidth, children }) => {
2768
+ var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
2806
2769
  const ref = React6.useRef(null);
2807
- const [adjustedX, setAdjustedX] = React6.useState(x);
2808
- React6.useEffect(() => {
2770
+ const [pos, setPos] = React6.useState({ left: 0, top: 0 });
2771
+ React6.useLayoutEffect(() => {
2809
2772
  const el = ref.current;
2810
2773
  if (!el) return;
2811
2774
  const w = el.offsetWidth;
2812
- const half = w / 2;
2813
- const margin = 8;
2814
- let nx = x;
2815
- if (x - half < margin) nx = half + margin;
2816
- else if (x + half > containerWidth - margin) nx = containerWidth - half - margin;
2817
- setAdjustedX(nx);
2818
- }, [x, containerWidth]);
2775
+ const h = el.offsetHeight;
2776
+ const vw = window.innerWidth;
2777
+ let left = clientX + TOOLTIP_OFFSET;
2778
+ let top = clientY - h - TOOLTIP_OFFSET;
2779
+ if (left + w > vw - 8) left = clientX - w - TOOLTIP_OFFSET;
2780
+ if (top < 8) top = clientY + TOOLTIP_OFFSET;
2781
+ if (left < 8) left = 8;
2782
+ setPos({ left, top });
2783
+ }, [clientX, clientY]);
2819
2784
  return /* @__PURE__ */ jsx307(
2820
2785
  "div",
2821
2786
  {
2822
2787
  ref,
2823
- className: "chart-tooltip",
2824
- style: { left: adjustedX, top: y },
2788
+ className: `chart-tooltip ${visible ? "chart-tooltip-show" : "chart-tooltip-hide"}`,
2789
+ style: { position: "fixed", left: pos.left, top: pos.top, zIndex: 1100 },
2825
2790
  children
2826
2791
  }
2827
2792
  );
2828
2793
  };
2794
+ var ChartLegend = ({ data, labels, type }) => {
2795
+ const entries = Object.entries(data);
2796
+ if (type === "pie" || type === "doughnut") {
2797
+ const values = entries.flatMap(([, v]) => v);
2798
+ const total = values.reduce((a, b) => a + b, 0) || 1;
2799
+ const firstKey = entries[0]?.[0] ?? "";
2800
+ const colorOffset = hashString(firstKey);
2801
+ return /* @__PURE__ */ jsx307("div", { className: "chart-legend", children: values.map((v, i) => {
2802
+ const pct = Math.round(v / total * 100);
2803
+ const color = PIE_COLORS[(i + colorOffset) % PIE_COLORS.length];
2804
+ return /* @__PURE__ */ jsxs197("div", { className: "chart-legend-item", children: [
2805
+ /* @__PURE__ */ jsx307("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
2806
+ /* @__PURE__ */ jsxs197("div", { className: "chart-legend-text", children: [
2807
+ /* @__PURE__ */ jsx307("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
2808
+ /* @__PURE__ */ jsxs197("span", { className: "chart-legend-value", children: [
2809
+ v.toLocaleString(),
2810
+ "(",
2811
+ pct,
2812
+ "%)"
2813
+ ] })
2814
+ ] })
2815
+ ] }, i);
2816
+ }) });
2817
+ }
2818
+ return /* @__PURE__ */ jsx307("div", { className: "chart-legend", children: entries.map(([key], di) => {
2819
+ const palette = getPalette(LINE_BAR_PALETTES, di, key);
2820
+ const color = palette[2];
2821
+ const values = entries[di][1];
2822
+ const sum = values.reduce((a, b) => a + b, 0);
2823
+ return /* @__PURE__ */ jsxs197("div", { className: "chart-legend-item", children: [
2824
+ /* @__PURE__ */ jsx307("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
2825
+ /* @__PURE__ */ jsxs197("div", { className: "chart-legend-text", children: [
2826
+ /* @__PURE__ */ jsx307("span", { className: "chart-legend-label", children: key }),
2827
+ /* @__PURE__ */ jsx307("span", { className: "chart-legend-value", children: sum.toLocaleString() })
2828
+ ] })
2829
+ ] }, di);
2830
+ }) });
2831
+ };
2829
2832
  var Chart = React6.memo((props) => {
2830
2833
  const { type, data, labels, tooltip: showTooltip = true } = props;
2831
2834
  const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
@@ -2841,7 +2844,8 @@ var Chart = React6.memo((props) => {
2841
2844
  ready && type === "bar" && /* @__PURE__ */ jsx307(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2842
2845
  ready && type === "pie" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2843
2846
  ready && type === "doughnut" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
2844
- tooltip.visible && /* @__PURE__ */ jsx307(TooltipBubble, { x: tooltip.x, y: tooltip.y, containerWidth: width, children: tooltip.content })
2847
+ ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx307(ChartLegend, { data: stableData, labels: stableLabels, type }),
2848
+ tooltip.content && /* @__PURE__ */ jsx307(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content })
2845
2849
  ] });
2846
2850
  });
2847
2851
  Chart.displayName = "Chart";