@x-plat/design-system 0.5.36 → 0.5.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Chart/index.cjs +33 -27
- package/dist/components/Chart/index.css +26 -6
- package/dist/components/Chart/index.d.cts +1 -0
- package/dist/components/Chart/index.d.ts +1 -0
- package/dist/components/Chart/index.js +33 -27
- package/dist/components/Tooltip/index.cjs +98 -8
- package/dist/components/Tooltip/index.css +38 -38
- package/dist/components/Tooltip/index.d.cts +6 -8
- package/dist/components/Tooltip/index.d.ts +6 -8
- package/dist/components/Tooltip/index.js +98 -8
- package/dist/components/index.cjs +116 -34
- package/dist/components/index.css +61 -41
- package/dist/components/index.js +117 -35
- package/dist/index.cjs +116 -34
- package/dist/index.css +61 -41
- package/dist/index.js +119 -37
- package/package.json +1 -1
|
@@ -186,15 +186,11 @@ var useChartTooltip = (enabled) => {
|
|
|
186
186
|
if (!rect) return;
|
|
187
187
|
setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
|
|
188
188
|
}, [enabled]);
|
|
189
|
-
const showAt = import_react.default.useCallback((x, y, content) => {
|
|
190
|
-
if (!enabled) return;
|
|
191
|
-
setTooltip({ visible: true, x, y, content });
|
|
192
|
-
}, [enabled]);
|
|
193
189
|
const hide = import_react.default.useCallback(() => {
|
|
194
190
|
cancelAnimationFrame(rafRef.current);
|
|
195
191
|
setTooltip((prev) => ({ ...prev, visible: false }));
|
|
196
192
|
}, []);
|
|
197
|
-
return { tooltip, show,
|
|
193
|
+
return { tooltip, show, hide, move, containerRef };
|
|
198
194
|
};
|
|
199
195
|
var GridLines = import_react.default.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
|
|
200
196
|
const y = PADDING.top + (1 - ratio) * chartH;
|
|
@@ -259,7 +255,7 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
259
255
|
}, [entries, seriesPoints]);
|
|
260
256
|
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
261
257
|
};
|
|
262
|
-
var LineChart = import_react.default.memo(({ data, labels, width, height, animate, onHover,
|
|
258
|
+
var LineChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
263
259
|
const entries = import_react.default.useMemo(() => Object.entries(data), [data]);
|
|
264
260
|
const maxVal = import_react.default.useMemo(() => {
|
|
265
261
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -299,9 +295,8 @@ var LineChart = import_react.default.memo(({ data, labels, width, height, animat
|
|
|
299
295
|
className: "chart-svg",
|
|
300
296
|
onMouseMove: (e) => {
|
|
301
297
|
handleMouseMove(e);
|
|
302
|
-
if (activeIndex !== null
|
|
303
|
-
|
|
304
|
-
onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
298
|
+
if (activeIndex !== null) {
|
|
299
|
+
onHover(e, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
305
300
|
} else {
|
|
306
301
|
onLeave();
|
|
307
302
|
}
|
|
@@ -369,7 +364,7 @@ var LineChart = import_react.default.memo(({ data, labels, width, height, animat
|
|
|
369
364
|
);
|
|
370
365
|
});
|
|
371
366
|
LineChart.displayName = "LineChart";
|
|
372
|
-
var CurveChart = import_react.default.memo(({ data, labels, width, height, animate, onHover,
|
|
367
|
+
var CurveChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
373
368
|
const entries = import_react.default.useMemo(() => Object.entries(data), [data]);
|
|
374
369
|
const maxVal = import_react.default.useMemo(() => {
|
|
375
370
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -411,7 +406,7 @@ var CurveChart = import_react.default.memo(({ data, labels, width, height, anima
|
|
|
411
406
|
handleMouseMove(e);
|
|
412
407
|
if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
|
|
413
408
|
const p = seriesPoints[0][activeIndex];
|
|
414
|
-
|
|
409
|
+
onHover(e, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
415
410
|
} else {
|
|
416
411
|
onLeave();
|
|
417
412
|
}
|
|
@@ -479,7 +474,7 @@ var CurveChart = import_react.default.memo(({ data, labels, width, height, anima
|
|
|
479
474
|
);
|
|
480
475
|
});
|
|
481
476
|
CurveChart.displayName = "CurveChart";
|
|
482
|
-
var BarChart = import_react.default.memo(({ data, labels, width, height, animate, onHover,
|
|
477
|
+
var BarChart = import_react.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
483
478
|
const entries = import_react.default.useMemo(() => Object.entries(data), [data]);
|
|
484
479
|
const maxVal = import_react.default.useMemo(() => {
|
|
485
480
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -529,7 +524,8 @@ var BarChart = import_react.default.memo(({ data, labels, width, height, animate
|
|
|
529
524
|
transformOrigin: `${b.x + b.w / 2}px ${baseline}px`,
|
|
530
525
|
animationDelay: `${delay}ms`
|
|
531
526
|
} : void 0,
|
|
532
|
-
onMouseEnter: () =>
|
|
527
|
+
onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${b.v}`),
|
|
528
|
+
onMouseMove: onMove,
|
|
533
529
|
onMouseLeave: onLeave
|
|
534
530
|
},
|
|
535
531
|
`${di}-${i}`
|
|
@@ -617,14 +613,17 @@ var PieDonutChart = import_react.default.memo(
|
|
|
617
613
|
{
|
|
618
614
|
d: s.d,
|
|
619
615
|
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
620
|
-
className: "chart-slice"
|
|
616
|
+
className: "chart-slice",
|
|
617
|
+
onMouseEnter: (e) => onHover(e, `${s.label} \u2014 ${s.v.toLocaleString()} (${s.pct}%)`),
|
|
618
|
+
onMouseMove: onMove,
|
|
619
|
+
onMouseLeave: onLeave
|
|
621
620
|
}
|
|
622
621
|
) }, i)) })
|
|
623
622
|
] });
|
|
624
623
|
}
|
|
625
624
|
);
|
|
626
625
|
PieDonutChart.displayName = "PieDonutChart";
|
|
627
|
-
var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
|
|
626
|
+
var ChartTooltip = ({ x, y, containerWidth, containerHeight, tooltipType, children }) => {
|
|
628
627
|
const ref = import_react.default.useRef(null);
|
|
629
628
|
const [pos, setPos] = import_react.default.useState({ left: 0, top: 0 });
|
|
630
629
|
import_react.default.useLayoutEffect(() => {
|
|
@@ -639,13 +638,20 @@ var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
|
|
|
639
638
|
if (left < 0) left = 0;
|
|
640
639
|
setPos({ left, top });
|
|
641
640
|
}, [x, y, containerWidth, containerHeight]);
|
|
642
|
-
|
|
641
|
+
const content = typeof children === "string" ? children : "";
|
|
642
|
+
const sepIdx = content.indexOf(" \u2014 ");
|
|
643
|
+
const title = sepIdx >= 0 ? content.slice(0, sepIdx) : content;
|
|
644
|
+
const desc = sepIdx >= 0 ? content.slice(sepIdx + 3) : "";
|
|
645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
643
646
|
"div",
|
|
644
647
|
{
|
|
645
648
|
ref,
|
|
646
|
-
className:
|
|
649
|
+
className: `chart-tooltip chart-tooltip-show chart-tooltip-${tooltipType}`,
|
|
647
650
|
style: { left: pos.left, top: pos.top },
|
|
648
|
-
children
|
|
651
|
+
children: [
|
|
652
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "chart-tooltip-title", children: title }),
|
|
653
|
+
desc && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "chart-tooltip-desc", children: desc })
|
|
654
|
+
]
|
|
649
655
|
}
|
|
650
656
|
);
|
|
651
657
|
};
|
|
@@ -688,8 +694,8 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
688
694
|
}) });
|
|
689
695
|
};
|
|
690
696
|
var Chart = import_react.default.memo((props) => {
|
|
691
|
-
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
692
|
-
const { tooltip, show,
|
|
697
|
+
const { type, data, labels, tooltip: showTooltip = true, tooltipType = "dark" } = props;
|
|
698
|
+
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
693
699
|
const { width, height } = useChartSize(containerRef);
|
|
694
700
|
const stableData = import_react.default.useMemo(() => data, [JSON.stringify(data)]);
|
|
695
701
|
const stableLabels = import_react.default.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
@@ -697,13 +703,13 @@ var Chart = import_react.default.memo((props) => {
|
|
|
697
703
|
const animate = useChartAnimation(containerRef, dataKey);
|
|
698
704
|
const ready = width > 0 && height > 0;
|
|
699
705
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
700
|
-
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
701
|
-
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
702
|
-
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
703
|
-
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
704
|
-
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show,
|
|
705
|
-
ready && (type === "
|
|
706
|
-
tooltip.visible && tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, children: tooltip.content })
|
|
706
|
+
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
707
|
+
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
708
|
+
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
709
|
+
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
710
|
+
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
711
|
+
ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
712
|
+
tooltip.visible && tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, tooltipType, children: tooltip.content })
|
|
707
713
|
] });
|
|
708
714
|
});
|
|
709
715
|
Chart.displayName = "Chart";
|
|
@@ -109,17 +109,37 @@
|
|
|
109
109
|
position: absolute;
|
|
110
110
|
z-index: 10;
|
|
111
111
|
padding: var(--spacing-space-3);
|
|
112
|
-
background-color: var(--semantic-surface-neutral-strong);
|
|
113
|
-
color: var(--semantic-text-inverse);
|
|
114
|
-
font-size: 12px;
|
|
115
|
-
line-height: 18px;
|
|
116
|
-
font-weight: 500;
|
|
117
112
|
border-radius: var(--spacing-radius-md);
|
|
118
113
|
max-width: 240px;
|
|
119
114
|
pointer-events: none;
|
|
120
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
121
115
|
animation: chart-tooltip-in 120ms ease-out;
|
|
122
116
|
}
|
|
117
|
+
.lib-xplat-chart .chart-tooltip .chart-tooltip-title {
|
|
118
|
+
font-size: 13px;
|
|
119
|
+
line-height: 18px;
|
|
120
|
+
font-weight: 400;
|
|
121
|
+
}
|
|
122
|
+
.lib-xplat-chart .chart-tooltip .chart-tooltip-desc {
|
|
123
|
+
font-size: 12px;
|
|
124
|
+
line-height: 18px;
|
|
125
|
+
font-weight: 400;
|
|
126
|
+
}
|
|
127
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-dark {
|
|
128
|
+
background-color: var(--semantic-surface-neutral-strong);
|
|
129
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
130
|
+
}
|
|
131
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-dark .chart-tooltip-title,
|
|
132
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-dark .chart-tooltip-desc {
|
|
133
|
+
color: var(--semantic-text-inverse);
|
|
134
|
+
}
|
|
135
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-light {
|
|
136
|
+
background-color: var(--semantic-surface-neutral-default);
|
|
137
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
138
|
+
}
|
|
139
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-light .chart-tooltip-title,
|
|
140
|
+
.lib-xplat-chart .chart-tooltip.chart-tooltip-light .chart-tooltip-desc {
|
|
141
|
+
color: var(--semantic-text-subtle);
|
|
142
|
+
}
|
|
123
143
|
.lib-xplat-chart .chart-legend {
|
|
124
144
|
display: flex;
|
|
125
145
|
flex-wrap: wrap;
|
|
@@ -150,15 +150,11 @@ var useChartTooltip = (enabled) => {
|
|
|
150
150
|
if (!rect) return;
|
|
151
151
|
setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
|
|
152
152
|
}, [enabled]);
|
|
153
|
-
const showAt = React.useCallback((x, y, content) => {
|
|
154
|
-
if (!enabled) return;
|
|
155
|
-
setTooltip({ visible: true, x, y, content });
|
|
156
|
-
}, [enabled]);
|
|
157
153
|
const hide = React.useCallback(() => {
|
|
158
154
|
cancelAnimationFrame(rafRef.current);
|
|
159
155
|
setTooltip((prev) => ({ ...prev, visible: false }));
|
|
160
156
|
}, []);
|
|
161
|
-
return { tooltip, show,
|
|
157
|
+
return { tooltip, show, hide, move, containerRef };
|
|
162
158
|
};
|
|
163
159
|
var GridLines = React.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ jsx(Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
|
|
164
160
|
const y = PADDING.top + (1 - ratio) * chartH;
|
|
@@ -223,7 +219,7 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
223
219
|
}, [entries, seriesPoints]);
|
|
224
220
|
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
225
221
|
};
|
|
226
|
-
var LineChart = React.memo(({ data, labels, width, height, animate, onHover,
|
|
222
|
+
var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
227
223
|
const entries = React.useMemo(() => Object.entries(data), [data]);
|
|
228
224
|
const maxVal = React.useMemo(() => {
|
|
229
225
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -263,9 +259,8 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onS
|
|
|
263
259
|
className: "chart-svg",
|
|
264
260
|
onMouseMove: (e) => {
|
|
265
261
|
handleMouseMove(e);
|
|
266
|
-
if (activeIndex !== null
|
|
267
|
-
|
|
268
|
-
onShowAt(p.x, p.y, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
262
|
+
if (activeIndex !== null) {
|
|
263
|
+
onHover(e, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
269
264
|
} else {
|
|
270
265
|
onLeave();
|
|
271
266
|
}
|
|
@@ -333,7 +328,7 @@ var LineChart = React.memo(({ data, labels, width, height, animate, onHover, onS
|
|
|
333
328
|
);
|
|
334
329
|
});
|
|
335
330
|
LineChart.displayName = "LineChart";
|
|
336
|
-
var CurveChart = React.memo(({ data, labels, width, height, animate, onHover,
|
|
331
|
+
var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
337
332
|
const entries = React.useMemo(() => Object.entries(data), [data]);
|
|
338
333
|
const maxVal = React.useMemo(() => {
|
|
339
334
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -375,7 +370,7 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
375
370
|
handleMouseMove(e);
|
|
376
371
|
if (activeIndex !== null && seriesPoints[0]?.[activeIndex]) {
|
|
377
372
|
const p = seriesPoints[0][activeIndex];
|
|
378
|
-
|
|
373
|
+
onHover(e, `${labels[activeIndex]} \u2014 ${getTooltipAt(activeIndex)}`);
|
|
379
374
|
} else {
|
|
380
375
|
onLeave();
|
|
381
376
|
}
|
|
@@ -443,7 +438,7 @@ var CurveChart = React.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
443
438
|
);
|
|
444
439
|
});
|
|
445
440
|
CurveChart.displayName = "CurveChart";
|
|
446
|
-
var BarChart = React.memo(({ data, labels, width, height, animate, onHover,
|
|
441
|
+
var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
447
442
|
const entries = React.useMemo(() => Object.entries(data), [data]);
|
|
448
443
|
const maxVal = React.useMemo(() => {
|
|
449
444
|
const allValues = entries.flatMap(([, v]) => v);
|
|
@@ -493,7 +488,8 @@ var BarChart = React.memo(({ data, labels, width, height, animate, onHover, onSh
|
|
|
493
488
|
transformOrigin: `${b.x + b.w / 2}px ${baseline}px`,
|
|
494
489
|
animationDelay: `${delay}ms`
|
|
495
490
|
} : void 0,
|
|
496
|
-
onMouseEnter: () =>
|
|
491
|
+
onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${b.v}`),
|
|
492
|
+
onMouseMove: onMove,
|
|
497
493
|
onMouseLeave: onLeave
|
|
498
494
|
},
|
|
499
495
|
`${di}-${i}`
|
|
@@ -581,14 +577,17 @@ var PieDonutChart = React.memo(
|
|
|
581
577
|
{
|
|
582
578
|
d: s.d,
|
|
583
579
|
fill: PIE_COLORS[(i + colorOffset) % PIE_COLORS.length],
|
|
584
|
-
className: "chart-slice"
|
|
580
|
+
className: "chart-slice",
|
|
581
|
+
onMouseEnter: (e) => onHover(e, `${s.label} \u2014 ${s.v.toLocaleString()} (${s.pct}%)`),
|
|
582
|
+
onMouseMove: onMove,
|
|
583
|
+
onMouseLeave: onLeave
|
|
585
584
|
}
|
|
586
585
|
) }, i)) })
|
|
587
586
|
] });
|
|
588
587
|
}
|
|
589
588
|
);
|
|
590
589
|
PieDonutChart.displayName = "PieDonutChart";
|
|
591
|
-
var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
|
|
590
|
+
var ChartTooltip = ({ x, y, containerWidth, containerHeight, tooltipType, children }) => {
|
|
592
591
|
const ref = React.useRef(null);
|
|
593
592
|
const [pos, setPos] = React.useState({ left: 0, top: 0 });
|
|
594
593
|
React.useLayoutEffect(() => {
|
|
@@ -603,13 +602,20 @@ var ChartTooltip = ({ x, y, containerWidth, containerHeight, children }) => {
|
|
|
603
602
|
if (left < 0) left = 0;
|
|
604
603
|
setPos({ left, top });
|
|
605
604
|
}, [x, y, containerWidth, containerHeight]);
|
|
606
|
-
|
|
605
|
+
const content = typeof children === "string" ? children : "";
|
|
606
|
+
const sepIdx = content.indexOf(" \u2014 ");
|
|
607
|
+
const title = sepIdx >= 0 ? content.slice(0, sepIdx) : content;
|
|
608
|
+
const desc = sepIdx >= 0 ? content.slice(sepIdx + 3) : "";
|
|
609
|
+
return /* @__PURE__ */ jsxs(
|
|
607
610
|
"div",
|
|
608
611
|
{
|
|
609
612
|
ref,
|
|
610
|
-
className:
|
|
613
|
+
className: `chart-tooltip chart-tooltip-show chart-tooltip-${tooltipType}`,
|
|
611
614
|
style: { left: pos.left, top: pos.top },
|
|
612
|
-
children
|
|
615
|
+
children: [
|
|
616
|
+
title && /* @__PURE__ */ jsx("div", { className: "chart-tooltip-title", children: title }),
|
|
617
|
+
desc && /* @__PURE__ */ jsx("div", { className: "chart-tooltip-desc", children: desc })
|
|
618
|
+
]
|
|
613
619
|
}
|
|
614
620
|
);
|
|
615
621
|
};
|
|
@@ -652,8 +658,8 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
652
658
|
}) });
|
|
653
659
|
};
|
|
654
660
|
var Chart = React.memo((props) => {
|
|
655
|
-
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
656
|
-
const { tooltip, show,
|
|
661
|
+
const { type, data, labels, tooltip: showTooltip = true, tooltipType = "dark" } = props;
|
|
662
|
+
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
657
663
|
const { width, height } = useChartSize(containerRef);
|
|
658
664
|
const stableData = React.useMemo(() => data, [JSON.stringify(data)]);
|
|
659
665
|
const stableLabels = React.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
@@ -661,13 +667,13 @@ var Chart = React.memo((props) => {
|
|
|
661
667
|
const animate = useChartAnimation(containerRef, dataKey);
|
|
662
668
|
const ready = width > 0 && height > 0;
|
|
663
669
|
return /* @__PURE__ */ jsxs("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
664
|
-
ready && type === "line" && /* @__PURE__ */ jsx(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
665
|
-
ready && type === "curve" && /* @__PURE__ */ jsx(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
666
|
-
ready && type === "bar" && /* @__PURE__ */ jsx(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
667
|
-
ready && type === "pie" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show,
|
|
668
|
-
ready && type === "doughnut" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show,
|
|
669
|
-
ready && (type === "
|
|
670
|
-
tooltip.visible && tooltip.content && /* @__PURE__ */ jsx(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, children: tooltip.content })
|
|
670
|
+
ready && type === "line" && /* @__PURE__ */ jsx(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
671
|
+
ready && type === "curve" && /* @__PURE__ */ jsx(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
672
|
+
ready && type === "bar" && /* @__PURE__ */ jsx(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
673
|
+
ready && type === "pie" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
674
|
+
ready && type === "doughnut" && /* @__PURE__ */ jsx(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
675
|
+
ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
676
|
+
tooltip.visible && tooltip.content && /* @__PURE__ */ jsx(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, tooltipType, children: tooltip.content })
|
|
671
677
|
] });
|
|
672
678
|
});
|
|
673
679
|
Chart.displayName = "Chart";
|
|
@@ -35,7 +35,21 @@ __export(Tooltip_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(Tooltip_exports);
|
|
36
36
|
|
|
37
37
|
// src/components/Tooltip/Tooltip.tsx
|
|
38
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
39
|
+
|
|
40
|
+
// src/tokens/hooks/Portal.tsx
|
|
38
41
|
var import_react = __toESM(require("react"), 1);
|
|
42
|
+
var import_react_dom = __toESM(require("react-dom"), 1);
|
|
43
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
44
|
+
var PortalContainerContext = import_react.default.createContext(null);
|
|
45
|
+
var Portal = ({ children }) => {
|
|
46
|
+
const contextContainer = import_react.default.useContext(PortalContainerContext);
|
|
47
|
+
if (typeof document === "undefined") return null;
|
|
48
|
+
const container = contextContainer ?? document.body;
|
|
49
|
+
return import_react_dom.default.createPortal(children, container);
|
|
50
|
+
};
|
|
51
|
+
Portal.displayName = "Portal";
|
|
52
|
+
var Portal_default = Portal;
|
|
39
53
|
|
|
40
54
|
// ../../node_modules/clsx/dist/clsx.mjs
|
|
41
55
|
function r(e) {
|
|
@@ -54,18 +68,94 @@ function clsx() {
|
|
|
54
68
|
var clsx_default = clsx;
|
|
55
69
|
|
|
56
70
|
// src/components/Tooltip/Tooltip.tsx
|
|
57
|
-
var
|
|
71
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
72
|
+
var OFFSET = 12;
|
|
73
|
+
var SHOW_DELAY = 300;
|
|
58
74
|
var Tooltip = (props) => {
|
|
59
75
|
const {
|
|
60
|
-
type = "
|
|
76
|
+
type = "dark",
|
|
77
|
+
title,
|
|
61
78
|
description,
|
|
62
|
-
children
|
|
79
|
+
children,
|
|
80
|
+
disabled = false
|
|
63
81
|
} = props;
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
82
|
+
const triggerRef = import_react2.default.useRef(null);
|
|
83
|
+
const tooltipRef = import_react2.default.useRef(null);
|
|
84
|
+
const [visible, setVisible] = import_react2.default.useState(false);
|
|
85
|
+
const [pos, setPos] = import_react2.default.useState({ left: 0, top: 0 });
|
|
86
|
+
const delayTimer = import_react2.default.useRef(0);
|
|
87
|
+
const calculatePos = import_react2.default.useCallback((clientX, clientY) => {
|
|
88
|
+
const el = tooltipRef.current;
|
|
89
|
+
if (!el) return;
|
|
90
|
+
const w = el.offsetWidth;
|
|
91
|
+
const h = el.offsetHeight;
|
|
92
|
+
const vw = window.innerWidth;
|
|
93
|
+
let left = clientX + OFFSET;
|
|
94
|
+
let top = clientY - h - OFFSET;
|
|
95
|
+
if (left + w > vw - 8) left = clientX - w - OFFSET;
|
|
96
|
+
if (top < 8) top = clientY + OFFSET;
|
|
97
|
+
if (left < 8) left = 8;
|
|
98
|
+
setPos({ left, top });
|
|
99
|
+
}, []);
|
|
100
|
+
const handleMouseEnter = import_react2.default.useCallback(() => {
|
|
101
|
+
if (disabled) return;
|
|
102
|
+
delayTimer.current = window.setTimeout(() => {
|
|
103
|
+
setVisible(true);
|
|
104
|
+
}, SHOW_DELAY);
|
|
105
|
+
}, [disabled]);
|
|
106
|
+
const handleMouseMove = import_react2.default.useCallback((e) => {
|
|
107
|
+
if (!visible) return;
|
|
108
|
+
calculatePos(e.clientX, e.clientY);
|
|
109
|
+
}, [visible, calculatePos]);
|
|
110
|
+
const handleMouseLeave = import_react2.default.useCallback(() => {
|
|
111
|
+
window.clearTimeout(delayTimer.current);
|
|
112
|
+
setVisible(false);
|
|
113
|
+
}, []);
|
|
114
|
+
const handleClick = import_react2.default.useCallback(() => {
|
|
115
|
+
window.clearTimeout(delayTimer.current);
|
|
116
|
+
setVisible(false);
|
|
117
|
+
}, []);
|
|
118
|
+
const handleFocus = import_react2.default.useCallback(() => {
|
|
119
|
+
if (disabled) return;
|
|
120
|
+
setVisible(true);
|
|
121
|
+
}, [disabled]);
|
|
122
|
+
const handleBlur = import_react2.default.useCallback(() => {
|
|
123
|
+
setVisible(false);
|
|
124
|
+
}, []);
|
|
125
|
+
import_react2.default.useLayoutEffect(() => {
|
|
126
|
+
if (!visible || !triggerRef.current) return;
|
|
127
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
128
|
+
calculatePos(rect.right, rect.top);
|
|
129
|
+
}, [visible, calculatePos]);
|
|
130
|
+
if (!title && !description) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
|
|
131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
132
|
+
"div",
|
|
133
|
+
{
|
|
134
|
+
ref: triggerRef,
|
|
135
|
+
className: "lib-xplat-tooltip-trigger",
|
|
136
|
+
onMouseEnter: handleMouseEnter,
|
|
137
|
+
onMouseMove: handleMouseMove,
|
|
138
|
+
onMouseLeave: handleMouseLeave,
|
|
139
|
+
onClick: handleClick,
|
|
140
|
+
onFocus: handleFocus,
|
|
141
|
+
onBlur: handleBlur,
|
|
142
|
+
children: [
|
|
143
|
+
children,
|
|
144
|
+
visible && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
145
|
+
"div",
|
|
146
|
+
{
|
|
147
|
+
ref: tooltipRef,
|
|
148
|
+
className: clsx_default("lib-xplat-tooltip", type),
|
|
149
|
+
style: { position: "fixed", left: pos.left, top: pos.top },
|
|
150
|
+
children: [
|
|
151
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "tooltip-title", children: title }),
|
|
152
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "tooltip-desc", children: description })
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
) })
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
);
|
|
69
159
|
};
|
|
70
160
|
Tooltip.displayName = "Tooltip";
|
|
71
161
|
var Tooltip_default = Tooltip;
|
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
/* src/components/Tooltip/tooltip.scss */
|
|
2
|
+
.lib-xplat-tooltip-trigger {
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
}
|
|
2
5
|
.lib-xplat-tooltip {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
width: fit-content;
|
|
8
|
-
height: fit-content;
|
|
9
|
-
}
|
|
10
|
-
.lib-xplat-tooltip > .tooltip-wrapper {
|
|
11
|
-
position: absolute;
|
|
12
|
-
transform: translateX(-50%) scale(0.5);
|
|
13
|
-
left: 50%;
|
|
14
|
-
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
|
15
|
-
white-space: nowrap;
|
|
16
|
-
border-radius: var(--spacing-radius-sm);
|
|
17
|
-
padding: var(--spacing-space-2) var(--spacing-space-2);
|
|
18
|
-
opacity: 0;
|
|
6
|
+
z-index: 1100;
|
|
7
|
+
padding: var(--spacing-space-3);
|
|
8
|
+
border-radius: var(--spacing-radius-md);
|
|
9
|
+
max-width: 240px;
|
|
19
10
|
pointer-events: none;
|
|
20
|
-
|
|
21
|
-
transition: opacity 0.12s ease, transform 0.15s cubic-bezier(0.16, 1, 0.3, 1);
|
|
11
|
+
animation: tooltip-show 120ms ease-out;
|
|
22
12
|
}
|
|
23
|
-
.lib-xplat-tooltip
|
|
24
|
-
|
|
13
|
+
.lib-xplat-tooltip .tooltip-title {
|
|
14
|
+
font-size: 13px;
|
|
15
|
+
line-height: 18px;
|
|
16
|
+
font-weight: 400;
|
|
17
|
+
}
|
|
18
|
+
.lib-xplat-tooltip .tooltip-desc {
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
line-height: 18px;
|
|
21
|
+
font-weight: 400;
|
|
22
|
+
}
|
|
23
|
+
.lib-xplat-tooltip.dark {
|
|
25
24
|
background-color: var(--semantic-surface-neutral-strong);
|
|
25
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
26
|
+
}
|
|
27
|
+
.lib-xplat-tooltip.dark .tooltip-title,
|
|
28
|
+
.lib-xplat-tooltip.dark .tooltip-desc {
|
|
29
|
+
color: var(--semantic-text-inverse);
|
|
26
30
|
}
|
|
27
|
-
.lib-xplat-tooltip
|
|
31
|
+
.lib-xplat-tooltip.light {
|
|
28
32
|
background-color: var(--semantic-surface-neutral-default);
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
.lib-xplat-tooltip.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.lib-xplat-tooltip > .tooltip-content:hover + .tooltip-wrapper {
|
|
43
|
-
opacity: 1;
|
|
44
|
-
pointer-events: auto;
|
|
45
|
-
transform: translateX(-50%) scale(1);
|
|
33
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
34
|
+
}
|
|
35
|
+
.lib-xplat-tooltip.light .tooltip-title,
|
|
36
|
+
.lib-xplat-tooltip.light .tooltip-desc {
|
|
37
|
+
color: var(--semantic-text-subtle);
|
|
38
|
+
}
|
|
39
|
+
@keyframes tooltip-show {
|
|
40
|
+
from {
|
|
41
|
+
opacity: 0;
|
|
42
|
+
}
|
|
43
|
+
to {
|
|
44
|
+
opacity: 1;
|
|
45
|
+
}
|
|
46
46
|
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import React from 'react';
|
|
3
2
|
|
|
4
3
|
interface TooltipProps {
|
|
5
|
-
type?: "
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
type?: "dark" | "light";
|
|
5
|
+
title?: React.ReactNode;
|
|
6
|
+
description?: React.ReactNode;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
disabled?: boolean;
|
|
8
9
|
}
|
|
9
|
-
declare const Tooltip:
|
|
10
|
-
(props: TooltipProps): react_jsx_runtime.JSX.Element;
|
|
11
|
-
displayName: string;
|
|
12
|
-
};
|
|
10
|
+
declare const Tooltip: React.FC<TooltipProps>;
|
|
13
11
|
|
|
14
12
|
export { Tooltip };
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import React from 'react';
|
|
3
2
|
|
|
4
3
|
interface TooltipProps {
|
|
5
|
-
type?: "
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
type?: "dark" | "light";
|
|
5
|
+
title?: React.ReactNode;
|
|
6
|
+
description?: React.ReactNode;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
disabled?: boolean;
|
|
8
9
|
}
|
|
9
|
-
declare const Tooltip:
|
|
10
|
-
(props: TooltipProps): react_jsx_runtime.JSX.Element;
|
|
11
|
-
displayName: string;
|
|
12
|
-
};
|
|
10
|
+
declare const Tooltip: React.FC<TooltipProps>;
|
|
13
11
|
|
|
14
12
|
export { Tooltip };
|