@x-plat/design-system 0.5.34 → 0.5.36

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/index.cjs CHANGED
@@ -6756,8 +6756,8 @@ var TOOLTIP_OFFSET = 12;
6756
6756
  var useChartTooltip = (enabled) => {
6757
6757
  const [tooltip, setTooltip] = import_react6.default.useState({
6758
6758
  visible: false,
6759
- clientX: 0,
6760
- clientY: 0,
6759
+ x: 0,
6760
+ y: 0,
6761
6761
  content: ""
6762
6762
  });
6763
6763
  const containerRef = import_react6.default.useRef(null);
@@ -6768,18 +6768,26 @@ var useChartTooltip = (enabled) => {
6768
6768
  const cy = e.clientY;
6769
6769
  cancelAnimationFrame(rafRef.current);
6770
6770
  rafRef.current = requestAnimationFrame(() => {
6771
- setTooltip((prev) => ({ ...prev, clientX: cx, clientY: cy }));
6771
+ const rect = containerRef.current?.getBoundingClientRect();
6772
+ if (!rect) return;
6773
+ setTooltip((prev) => ({ ...prev, x: cx - rect.left, y: cy - rect.top }));
6772
6774
  });
6773
6775
  }, [enabled]);
6774
6776
  const show = import_react6.default.useCallback((e, content) => {
6775
6777
  if (!enabled) return;
6776
- setTooltip({ visible: true, clientX: e.clientX, clientY: e.clientY, content });
6778
+ const rect = containerRef.current?.getBoundingClientRect();
6779
+ if (!rect) return;
6780
+ setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
6781
+ }, [enabled]);
6782
+ const showAt = import_react6.default.useCallback((x, y, content) => {
6783
+ if (!enabled) return;
6784
+ setTooltip({ visible: true, x, y, content });
6777
6785
  }, [enabled]);
6778
6786
  const hide = import_react6.default.useCallback(() => {
6779
6787
  cancelAnimationFrame(rafRef.current);
6780
6788
  setTooltip((prev) => ({ ...prev, visible: false }));
6781
6789
  }, []);
6782
- return { tooltip, show, hide, move, containerRef };
6790
+ return { tooltip, show, showAt, hide, move, containerRef };
6783
6791
  };
6784
6792
  var GridLines = import_react6.default.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(import_jsx_runtime307.Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
6785
6793
  const y = PADDING.top + (1 - ratio) * chartH;
@@ -6844,7 +6852,7 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
6844
6852
  }, [entries, seriesPoints]);
6845
6853
  return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
6846
6854
  };
6847
- var LineChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
6855
+ var LineChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
6848
6856
  const entries = import_react6.default.useMemo(() => Object.entries(data), [data]);
6849
6857
  const maxVal = import_react6.default.useMemo(() => {
6850
6858
  const allValues = entries.flatMap(([, v]) => v);
@@ -6884,23 +6892,9 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
6884
6892
  className: "chart-svg",
6885
6893
  onMouseMove: (e) => {
6886
6894
  handleMouseMove(e);
6887
- const svg = e.currentTarget;
6888
- const rect = svg.getBoundingClientRect();
6889
- const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
6890
- const points = seriesPoints[0];
6891
- if (!points || points.length === 0) return;
6892
- const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
6893
- let closest = 0;
6894
- let minDist = Math.abs(points[0].x - mx);
6895
- for (let i = 1; i < points.length; i++) {
6896
- const dist = Math.abs(points[i].x - mx);
6897
- if (dist < minDist) {
6898
- minDist = dist;
6899
- closest = i;
6900
- }
6901
- }
6902
- if (minDist <= step / 2) {
6903
- onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
6895
+ if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
6896
+ const p = seriesPoints[0][activeIndex];
6897
+ onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
6904
6898
  } else {
6905
6899
  onLeave();
6906
6900
  }
@@ -6968,7 +6962,7 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
6968
6962
  );
6969
6963
  });
6970
6964
  LineChart.displayName = "LineChart";
6971
- var CurveChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
6965
+ var CurveChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
6972
6966
  const entries = import_react6.default.useMemo(() => Object.entries(data), [data]);
6973
6967
  const maxVal = import_react6.default.useMemo(() => {
6974
6968
  const allValues = entries.flatMap(([, v]) => v);
@@ -7008,23 +7002,9 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
7008
7002
  className: "chart-svg",
7009
7003
  onMouseMove: (e) => {
7010
7004
  handleMouseMove(e);
7011
- const svg = e.currentTarget;
7012
- const rect = svg.getBoundingClientRect();
7013
- const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
7014
- const points = seriesPoints[0];
7015
- if (!points || points.length === 0) return;
7016
- const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
7017
- let closest = 0;
7018
- let minDist = Math.abs(points[0].x - mx);
7019
- for (let i = 1; i < points.length; i++) {
7020
- const dist = Math.abs(points[i].x - mx);
7021
- if (dist < minDist) {
7022
- minDist = dist;
7023
- closest = i;
7024
- }
7025
- }
7026
- if (minDist <= step / 2) {
7027
- onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
7005
+ if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
7006
+ const p = seriesPoints[0][activeIndex];
7007
+ onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
7028
7008
  } else {
7029
7009
  onLeave();
7030
7010
  }
@@ -7092,7 +7072,7 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
7092
7072
  );
7093
7073
  });
7094
7074
  CurveChart.displayName = "CurveChart";
7095
- var BarChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
7075
+ var BarChart = import_react6.default.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
7096
7076
  const entries = import_react6.default.useMemo(() => Object.entries(data), [data]);
7097
7077
  const maxVal = import_react6.default.useMemo(() => {
7098
7078
  const allValues = entries.flatMap(([, v]) => v);
@@ -7142,8 +7122,7 @@ var BarChart = import_react6.default.memo(({ data, labels, width, height, animat
7142
7122
  transformOrigin: `${b.x + b.w / 2}px ${baseline}px`,
7143
7123
  animationDelay: `${delay}ms`
7144
7124
  } : void 0,
7145
- onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${b.v}`),
7146
- onMouseMove: onMove,
7125
+ onMouseEnter: () => onShowAt(b.x + b.w / 2, b.y, `${key}: ${labels[i]} \u2014 ${b.v}`),
7147
7126
  onMouseLeave: onLeave
7148
7127
  },
7149
7128
  `${di}-${i}`
@@ -7231,30 +7210,14 @@ var PieDonutChart = import_react6.default.memo(
7231
7210
  {
7232
7211
  d: s.d,
7233
7212
  fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
7234
- className: "chart-slice",
7235
- onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
7236
- onMouseMove: onMove,
7237
- onMouseLeave: onLeave
7213
+ className: "chart-slice"
7238
7214
  }
7239
- ) }, i)) }),
7240
- sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
7241
- "text",
7242
- {
7243
- x: s.lx,
7244
- y: s.ly,
7245
- className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
7246
- style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
7247
- textAnchor: "middle",
7248
- dominantBaseline: "central",
7249
- children: s.v
7250
- },
7251
- `label-${i}`
7252
- ))
7215
+ ) }, i)) })
7253
7216
  ] });
7254
7217
  }
7255
7218
  );
7256
7219
  PieDonutChart.displayName = "PieDonutChart";
7257
- var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
7220
+ var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
7258
7221
  const ref = import_react6.default.useRef(null);
7259
7222
  const [pos, setPos] = import_react6.default.useState({ left: 0, top: 0 });
7260
7223
  import_react6.default.useLayoutEffect(() => {
@@ -7262,20 +7225,19 @@ var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
7262
7225
  if (!el) return;
7263
7226
  const w = el.offsetWidth;
7264
7227
  const h = el.offsetHeight;
7265
- const vw = window.innerWidth;
7266
- let left = clientX + TOOLTIP_OFFSET;
7267
- let top = clientY - h - TOOLTIP_OFFSET;
7268
- if (left + w > vw - 8) left = clientX - w - TOOLTIP_OFFSET;
7269
- if (top < 8) top = clientY + TOOLTIP_OFFSET;
7270
- if (left < 8) left = 8;
7228
+ let left = x + TOOLTIP_OFFSET;
7229
+ let top = y - h - TOOLTIP_OFFSET;
7230
+ if (left + w > containerWidth) left = x - w - TOOLTIP_OFFSET;
7231
+ if (top < 0) top = y + TOOLTIP_OFFSET;
7232
+ if (left < 0) left = 0;
7271
7233
  setPos({ left, top });
7272
- }, [clientX, clientY]);
7234
+ }, [x, y, containerWidth, containerHeight]);
7273
7235
  return /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
7274
7236
  "div",
7275
7237
  {
7276
7238
  ref,
7277
- className: `chart-tooltip ${visible ? "chart-tooltip-show" : "chart-tooltip-hide"}`,
7278
- style: { position: "fixed", left: pos.left, top: pos.top, zIndex: 1100 },
7239
+ className: "chart-tooltip chart-tooltip-show",
7240
+ style: { left: pos.left, top: pos.top },
7279
7241
  children
7280
7242
  }
7281
7243
  );
@@ -7320,7 +7282,7 @@ var ChartLegend = ({ data, labels, type }) => {
7320
7282
  };
7321
7283
  var Chart = import_react6.default.memo((props) => {
7322
7284
  const { type, data, labels, tooltip: showTooltip = true } = props;
7323
- const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
7285
+ const { tooltip, show, showAt, hide, move, containerRef } = useChartTooltip(showTooltip);
7324
7286
  const { width, height } = useChartSize(containerRef);
7325
7287
  const stableData = import_react6.default.useMemo(() => data, [JSON.stringify(data)]);
7326
7288
  const stableLabels = import_react6.default.useMemo(() => labels, [JSON.stringify(labels)]);
@@ -7328,13 +7290,13 @@ var Chart = import_react6.default.memo((props) => {
7328
7290
  const animate = useChartAnimation(containerRef, dataKey);
7329
7291
  const ready = width > 0 && height > 0;
7330
7292
  return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: "lib-xplat-chart", ref: containerRef, children: [
7331
- ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
7332
- ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
7333
- ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
7334
- ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
7335
- ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
7293
+ ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
7294
+ ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
7295
+ ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
7296
+ ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
7297
+ ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
7336
7298
  ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(ChartLegend, { data: stableData, labels: stableLabels, type }),
7337
- tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content })
7299
+ tooltip.visible && tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, children: tooltip.content })
7338
7300
  ] });
7339
7301
  });
7340
7302
  Chart.displayName = "Chart";
package/dist/index.css CHANGED
@@ -1929,11 +1929,14 @@
1929
1929
  width: 100%;
1930
1930
  height: 100%;
1931
1931
  position: relative;
1932
+ display: flex;
1933
+ flex-direction: column;
1932
1934
  }
1933
1935
  .lib-xplat-chart .chart-svg {
1934
1936
  display: block;
1935
1937
  width: 100%;
1936
- height: 100%;
1938
+ flex: 1;
1939
+ min-height: 0;
1937
1940
  will-change: transform;
1938
1941
  contain: layout style paint;
1939
1942
  }
@@ -2017,7 +2020,19 @@
2017
2020
  white-space: nowrap;
2018
2021
  overflow: visible;
2019
2022
  }
2023
+ .lib-xplat-chart .chart-bar-animate {
2024
+ animation: chart-bar-grow 800ms ease-out both;
2025
+ }
2026
+ .lib-xplat-chart .chart-pie-label-animate {
2027
+ opacity: 0;
2028
+ animation: chart-fade-in 150ms ease-out both;
2029
+ }
2030
+ .lib-xplat-chart .chart-area[style*=animationDelay] {
2031
+ animation: chart-fade-in 800ms ease-out both;
2032
+ }
2020
2033
  .lib-xplat-chart .chart-tooltip {
2034
+ position: absolute;
2035
+ z-index: 10;
2021
2036
  padding: var(--spacing-space-3);
2022
2037
  background-color: var(--semantic-surface-neutral-strong);
2023
2038
  color: var(--semantic-text-inverse);
@@ -2028,25 +2043,8 @@
2028
2043
  max-width: 240px;
2029
2044
  pointer-events: none;
2030
2045
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
2031
- }
2032
- .lib-xplat-chart .chart-tooltip.chart-tooltip-show {
2033
- opacity: 1;
2034
2046
  animation: chart-tooltip-in 120ms ease-out;
2035
2047
  }
2036
- .lib-xplat-chart .chart-tooltip.chart-tooltip-hide {
2037
- opacity: 0;
2038
- animation: chart-tooltip-out 80ms ease-in;
2039
- }
2040
- .lib-xplat-chart .chart-bar-animate {
2041
- animation: chart-bar-grow 800ms ease-out both;
2042
- }
2043
- .lib-xplat-chart .chart-pie-label-animate {
2044
- opacity: 0;
2045
- animation: chart-fade-in 150ms ease-out both;
2046
- }
2047
- .lib-xplat-chart .chart-area[style*=animationDelay] {
2048
- animation: chart-fade-in 800ms ease-out both;
2049
- }
2050
2048
  .lib-xplat-chart .chart-legend {
2051
2049
  display: flex;
2052
2050
  flex-wrap: wrap;
@@ -2103,14 +2101,6 @@
2103
2101
  opacity: 1;
2104
2102
  }
2105
2103
  }
2106
- @keyframes chart-tooltip-out {
2107
- from {
2108
- opacity: 1;
2109
- }
2110
- to {
2111
- opacity: 0;
2112
- }
2113
- }
2114
2104
  @media (prefers-reduced-motion: reduce) {
2115
2105
  .lib-xplat-chart .chart-bar-animate,
2116
2106
  .lib-xplat-chart .chart-pie-label-animate,
package/dist/index.js CHANGED
@@ -6357,8 +6357,8 @@ var TOOLTIP_OFFSET = 12;
6357
6357
  var useChartTooltip = (enabled) => {
6358
6358
  const [tooltip, setTooltip] = React6.useState({
6359
6359
  visible: false,
6360
- clientX: 0,
6361
- clientY: 0,
6360
+ x: 0,
6361
+ y: 0,
6362
6362
  content: ""
6363
6363
  });
6364
6364
  const containerRef = React6.useRef(null);
@@ -6369,18 +6369,26 @@ var useChartTooltip = (enabled) => {
6369
6369
  const cy = e.clientY;
6370
6370
  cancelAnimationFrame(rafRef.current);
6371
6371
  rafRef.current = requestAnimationFrame(() => {
6372
- setTooltip((prev) => ({ ...prev, clientX: cx, clientY: cy }));
6372
+ const rect = containerRef.current?.getBoundingClientRect();
6373
+ if (!rect) return;
6374
+ setTooltip((prev) => ({ ...prev, x: cx - rect.left, y: cy - rect.top }));
6373
6375
  });
6374
6376
  }, [enabled]);
6375
6377
  const show = React6.useCallback((e, content) => {
6376
6378
  if (!enabled) return;
6377
- setTooltip({ visible: true, clientX: e.clientX, clientY: e.clientY, content });
6379
+ const rect = containerRef.current?.getBoundingClientRect();
6380
+ if (!rect) return;
6381
+ setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
6382
+ }, [enabled]);
6383
+ const showAt = React6.useCallback((x, y, content) => {
6384
+ if (!enabled) return;
6385
+ setTooltip({ visible: true, x, y, content });
6378
6386
  }, [enabled]);
6379
6387
  const hide = React6.useCallback(() => {
6380
6388
  cancelAnimationFrame(rafRef.current);
6381
6389
  setTooltip((prev) => ({ ...prev, visible: false }));
6382
6390
  }, []);
6383
- return { tooltip, show, hide, move, containerRef };
6391
+ return { tooltip, show, showAt, hide, move, containerRef };
6384
6392
  };
6385
6393
  var GridLines = React6.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ jsx307(Fragment2, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
6386
6394
  const y = PADDING.top + (1 - ratio) * chartH;
@@ -6445,7 +6453,7 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
6445
6453
  }, [entries, seriesPoints]);
6446
6454
  return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
6447
6455
  };
6448
- var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
6456
+ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
6449
6457
  const entries = React6.useMemo(() => Object.entries(data), [data]);
6450
6458
  const maxVal = React6.useMemo(() => {
6451
6459
  const allValues = entries.flatMap(([, v]) => v);
@@ -6485,23 +6493,9 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
6485
6493
  className: "chart-svg",
6486
6494
  onMouseMove: (e) => {
6487
6495
  handleMouseMove(e);
6488
- const svg = e.currentTarget;
6489
- const rect = svg.getBoundingClientRect();
6490
- const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
6491
- const points = seriesPoints[0];
6492
- if (!points || points.length === 0) return;
6493
- const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
6494
- let closest = 0;
6495
- let minDist = Math.abs(points[0].x - mx);
6496
- for (let i = 1; i < points.length; i++) {
6497
- const dist = Math.abs(points[i].x - mx);
6498
- if (dist < minDist) {
6499
- minDist = dist;
6500
- closest = i;
6501
- }
6502
- }
6503
- if (minDist <= step / 2) {
6504
- onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
6496
+ if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
6497
+ const p = seriesPoints[0][activeIndex];
6498
+ onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
6505
6499
  } else {
6506
6500
  onLeave();
6507
6501
  }
@@ -6569,7 +6563,7 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
6569
6563
  );
6570
6564
  });
6571
6565
  LineChart.displayName = "LineChart";
6572
- var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
6566
+ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
6573
6567
  const entries = React6.useMemo(() => Object.entries(data), [data]);
6574
6568
  const maxVal = React6.useMemo(() => {
6575
6569
  const allValues = entries.flatMap(([, v]) => v);
@@ -6609,23 +6603,9 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
6609
6603
  className: "chart-svg",
6610
6604
  onMouseMove: (e) => {
6611
6605
  handleMouseMove(e);
6612
- const svg = e.currentTarget;
6613
- const rect = svg.getBoundingClientRect();
6614
- const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
6615
- const points = seriesPoints[0];
6616
- if (!points || points.length === 0) return;
6617
- const step = points.length > 1 ? Math.abs(points[1].x - points[0].x) : 20;
6618
- let closest = 0;
6619
- let minDist = Math.abs(points[0].x - mx);
6620
- for (let i = 1; i < points.length; i++) {
6621
- const dist = Math.abs(points[i].x - mx);
6622
- if (dist < minDist) {
6623
- minDist = dist;
6624
- closest = i;
6625
- }
6626
- }
6627
- if (minDist <= step / 2) {
6628
- onHover(e, `${labels[closest]} \u2014 ${getTooltipAt(closest)}`);
6606
+ if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
6607
+ const p = seriesPoints[0][activeIndex];
6608
+ onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
6629
6609
  } else {
6630
6610
  onLeave();
6631
6611
  }
@@ -6693,7 +6673,7 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
6693
6673
  );
6694
6674
  });
6695
6675
  CurveChart.displayName = "CurveChart";
6696
- var BarChart = React6.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
6676
+ var BarChart = React6.memo(({ data, labels, width, height, animate, onHover, onShowAt, onMove, onLeave }) => {
6697
6677
  const entries = React6.useMemo(() => Object.entries(data), [data]);
6698
6678
  const maxVal = React6.useMemo(() => {
6699
6679
  const allValues = entries.flatMap(([, v]) => v);
@@ -6743,8 +6723,7 @@ var BarChart = React6.memo(({ data, labels, width, height, animate, onHover, onM
6743
6723
  transformOrigin: `${b.x + b.w / 2}px ${baseline}px`,
6744
6724
  animationDelay: `${delay}ms`
6745
6725
  } : void 0,
6746
- onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${b.v}`),
6747
- onMouseMove: onMove,
6726
+ onMouseEnter: () => onShowAt(b.x + b.w / 2, b.y, `${key}: ${labels[i]} \u2014 ${b.v}`),
6748
6727
  onMouseLeave: onLeave
6749
6728
  },
6750
6729
  `${di}-${i}`
@@ -6832,30 +6811,14 @@ var PieDonutChart = React6.memo(
6832
6811
  {
6833
6812
  d: s.d,
6834
6813
  fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
6835
- className: "chart-slice",
6836
- onMouseEnter: (e) => onHover(e, `${s.label}: ${s.v} (${s.pct}%)`),
6837
- onMouseMove: onMove,
6838
- onMouseLeave: onLeave
6814
+ className: "chart-slice"
6839
6815
  }
6840
- ) }, i)) }),
6841
- sliceData.map((s, i) => s.angle > 0.2 && /* @__PURE__ */ jsx307(
6842
- "text",
6843
- {
6844
- x: s.lx,
6845
- y: s.ly,
6846
- className: `chart-pie-label ${animate ? "chart-pie-label-animate" : ""}`,
6847
- style: animate ? { animationDelay: `${s.labelDelay}ms` } : void 0,
6848
- textAnchor: "middle",
6849
- dominantBaseline: "central",
6850
- children: s.v
6851
- },
6852
- `label-${i}`
6853
- ))
6816
+ ) }, i)) })
6854
6817
  ] });
6855
6818
  }
6856
6819
  );
6857
6820
  PieDonutChart.displayName = "PieDonutChart";
6858
- var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
6821
+ var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
6859
6822
  const ref = React6.useRef(null);
6860
6823
  const [pos, setPos] = React6.useState({ left: 0, top: 0 });
6861
6824
  React6.useLayoutEffect(() => {
@@ -6863,20 +6826,19 @@ var ChartTooltipPortal = ({ clientX, clientY, visible, children }) => {
6863
6826
  if (!el) return;
6864
6827
  const w = el.offsetWidth;
6865
6828
  const h = el.offsetHeight;
6866
- const vw = window.innerWidth;
6867
- let left = clientX + TOOLTIP_OFFSET;
6868
- let top = clientY - h - TOOLTIP_OFFSET;
6869
- if (left + w > vw - 8) left = clientX - w - TOOLTIP_OFFSET;
6870
- if (top < 8) top = clientY + TOOLTIP_OFFSET;
6871
- if (left < 8) left = 8;
6829
+ let left = x + TOOLTIP_OFFSET;
6830
+ let top = y - h - TOOLTIP_OFFSET;
6831
+ if (left + w > containerWidth) left = x - w - TOOLTIP_OFFSET;
6832
+ if (top < 0) top = y + TOOLTIP_OFFSET;
6833
+ if (left < 0) left = 0;
6872
6834
  setPos({ left, top });
6873
- }, [clientX, clientY]);
6835
+ }, [x, y, containerWidth, containerHeight]);
6874
6836
  return /* @__PURE__ */ jsx307(
6875
6837
  "div",
6876
6838
  {
6877
6839
  ref,
6878
- className: `chart-tooltip ${visible ? "chart-tooltip-show" : "chart-tooltip-hide"}`,
6879
- style: { position: "fixed", left: pos.left, top: pos.top, zIndex: 1100 },
6840
+ className: "chart-tooltip chart-tooltip-show",
6841
+ style: { left: pos.left, top: pos.top },
6880
6842
  children
6881
6843
  }
6882
6844
  );
@@ -6921,7 +6883,7 @@ var ChartLegend = ({ data, labels, type }) => {
6921
6883
  };
6922
6884
  var Chart = React6.memo((props) => {
6923
6885
  const { type, data, labels, tooltip: showTooltip = true } = props;
6924
- const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
6886
+ const { tooltip, show, showAt, hide, move, containerRef } = useChartTooltip(showTooltip);
6925
6887
  const { width, height } = useChartSize(containerRef);
6926
6888
  const stableData = React6.useMemo(() => data, [JSON.stringify(data)]);
6927
6889
  const stableLabels = React6.useMemo(() => labels, [JSON.stringify(labels)]);
@@ -6929,13 +6891,13 @@ var Chart = React6.memo((props) => {
6929
6891
  const animate = useChartAnimation(containerRef, dataKey);
6930
6892
  const ready = width > 0 && height > 0;
6931
6893
  return /* @__PURE__ */ jsxs197("div", { className: "lib-xplat-chart", ref: containerRef, children: [
6932
- ready && type === "line" && /* @__PURE__ */ jsx307(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6933
- ready && type === "curve" && /* @__PURE__ */ jsx307(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6934
- ready && type === "bar" && /* @__PURE__ */ jsx307(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6935
- ready && type === "pie" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6936
- ready && type === "doughnut" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
6894
+ ready && type === "line" && /* @__PURE__ */ jsx307(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
6895
+ ready && type === "curve" && /* @__PURE__ */ jsx307(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
6896
+ ready && type === "bar" && /* @__PURE__ */ jsx307(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
6897
+ ready && type === "pie" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
6898
+ ready && type === "doughnut" && /* @__PURE__ */ jsx307(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onShowAt: showAt, onMove: move, onLeave: hide }),
6937
6899
  ready && (type === "bar" || type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx307(ChartLegend, { data: stableData, labels: stableLabels, type }),
6938
- tooltip.content && /* @__PURE__ */ jsx307(ChartTooltipPortal, { clientX: tooltip.clientX, clientY: tooltip.clientY, visible: tooltip.visible, children: tooltip.content })
6900
+ tooltip.visible && tooltip.content && /* @__PURE__ */ jsx307(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, children: tooltip.content })
6939
6901
  ] });
6940
6902
  });
6941
6903
  Chart.displayName = "Chart";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x-plat/design-system",
3
- "version": "0.5.34",
3
+ "version": "0.5.36",
4
4
  "description": "XPLAT UI Design System",
5
5
  "author": "XPLAT WOONG",
6
6
  "main": "dist/index.cjs",