@x-plat/design-system 0.5.12 → 0.5.14
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 +63 -38
- package/dist/components/Chart/index.css +2 -0
- package/dist/components/Chart/index.d.cts +1 -1
- package/dist/components/Chart/index.d.ts +1 -1
- package/dist/components/Chart/index.js +63 -38
- package/dist/components/DatePicker/index.cjs +2 -6
- package/dist/components/DatePicker/index.js +2 -6
- package/dist/components/Dropdown/index.cjs +6 -10
- package/dist/components/Dropdown/index.js +6 -10
- package/dist/components/Modal/index.cjs +2 -6
- package/dist/components/Modal/index.js +2 -6
- package/dist/components/PopOver/index.cjs +6 -10
- package/dist/components/PopOver/index.js +6 -10
- package/dist/components/Select/index.cjs +6 -10
- package/dist/components/Select/index.js +6 -10
- package/dist/components/index.cjs +69 -48
- package/dist/components/index.css +2 -0
- package/dist/components/index.js +69 -48
- package/dist/index.cjs +69 -48
- package/dist/index.css +2 -0
- package/dist/index.js +69 -48
- package/package.json +1 -1
|
@@ -2151,29 +2151,50 @@ var toSmoothPath = (points) => {
|
|
|
2151
2151
|
}
|
|
2152
2152
|
return d;
|
|
2153
2153
|
};
|
|
2154
|
+
var RESIZE_SETTLE_MS = 150;
|
|
2154
2155
|
var useChartSize = (ref) => {
|
|
2155
2156
|
const [size, setSize] = import_react5.default.useState({ width: 0, height: 0 });
|
|
2157
|
+
const isResizing = import_react5.default.useRef(false);
|
|
2158
|
+
const settleTimer = import_react5.default.useRef(0);
|
|
2159
|
+
const lastSize = import_react5.default.useRef({ width: 0, height: 0 });
|
|
2160
|
+
const initialRef = import_react5.default.useRef(true);
|
|
2156
2161
|
import_react5.default.useEffect(() => {
|
|
2157
2162
|
const el = ref.current;
|
|
2158
2163
|
if (!el) return;
|
|
2159
|
-
let rafId = 0;
|
|
2160
2164
|
const observer = new ResizeObserver((entries) => {
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2165
|
+
const entry = entries[0];
|
|
2166
|
+
if (!entry) return;
|
|
2167
|
+
const { width, height } = entry.contentRect;
|
|
2168
|
+
const w = Math.floor(width);
|
|
2169
|
+
const h = Math.floor(height);
|
|
2170
|
+
if (w === lastSize.current.width && h === lastSize.current.height) return;
|
|
2171
|
+
lastSize.current = { width: w, height: h };
|
|
2172
|
+
if (initialRef.current) {
|
|
2173
|
+
initialRef.current = false;
|
|
2174
|
+
setSize({ width: w, height: h });
|
|
2175
|
+
return;
|
|
2176
|
+
}
|
|
2177
|
+
isResizing.current = true;
|
|
2178
|
+
if (el.firstElementChild) {
|
|
2179
|
+
const svg = el.firstElementChild;
|
|
2180
|
+
svg.style.transformOrigin = "0 0";
|
|
2181
|
+
svg.style.transform = `scale(${w / (size.width || w)}, ${h / (size.height || h)})`;
|
|
2182
|
+
}
|
|
2183
|
+
window.clearTimeout(settleTimer.current);
|
|
2184
|
+
settleTimer.current = window.setTimeout(() => {
|
|
2185
|
+
isResizing.current = false;
|
|
2186
|
+
if (el.firstElementChild) {
|
|
2187
|
+
el.firstElementChild.style.transform = "";
|
|
2188
|
+
}
|
|
2189
|
+
setSize({ width: w, height: h });
|
|
2190
|
+
}, RESIZE_SETTLE_MS);
|
|
2170
2191
|
});
|
|
2171
2192
|
observer.observe(el);
|
|
2172
2193
|
return () => {
|
|
2173
|
-
|
|
2194
|
+
window.clearTimeout(settleTimer.current);
|
|
2174
2195
|
observer.disconnect();
|
|
2175
2196
|
};
|
|
2176
|
-
}, [ref]);
|
|
2197
|
+
}, [ref, size.width, size.height]);
|
|
2177
2198
|
return size;
|
|
2178
2199
|
};
|
|
2179
2200
|
var useChartTooltip = (enabled) => {
|
|
@@ -2365,17 +2386,19 @@ var BarChart = import_react5.default.memo(({ data, labels, width, height, onHove
|
|
|
2365
2386
|
const chartW = width - PADDING.left - PADDING.right;
|
|
2366
2387
|
const chartH = height - PADDING.top - PADDING.bottom;
|
|
2367
2388
|
const groupW = chartW / count;
|
|
2368
|
-
const
|
|
2389
|
+
const barGap = groupCount > 1 ? 2 : 0;
|
|
2390
|
+
const barW = Math.max(1, Math.min(32, (groupW * 0.7 - barGap * (groupCount - 1)) / groupCount));
|
|
2369
2391
|
const bars = import_react5.default.useMemo(
|
|
2370
2392
|
() => entries.map(
|
|
2371
2393
|
([, values], di) => values.map((v, i) => {
|
|
2394
|
+
const totalBarsW = barW * groupCount + barGap * (groupCount - 1);
|
|
2372
2395
|
const h = Math.max(0, v / maxVal * chartH);
|
|
2373
|
-
const x = PADDING.left + groupW * i + (groupW -
|
|
2396
|
+
const x = PADDING.left + groupW * i + (groupW - totalBarsW) / 2 + (barW + barGap) * di;
|
|
2374
2397
|
const y = PADDING.top + chartH - h;
|
|
2375
2398
|
return { x, y, w: barW, h, v };
|
|
2376
2399
|
})
|
|
2377
2400
|
),
|
|
2378
|
-
[entries, maxVal, chartH, groupW, barW, groupCount]
|
|
2401
|
+
[entries, maxVal, chartH, groupW, barW, barGap, groupCount]
|
|
2379
2402
|
);
|
|
2380
2403
|
const barLabelStep = getLabelStep(count, chartW);
|
|
2381
2404
|
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("svg", { viewBox: `0 0 ${width} ${height}`, className: "chart-svg", children: [
|
|
@@ -2387,22 +2410,22 @@ var BarChart = import_react5.default.memo(({ data, labels, width, height, onHove
|
|
|
2387
2410
|
entries.map(([key], di) => {
|
|
2388
2411
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
2389
2412
|
const color = palette[2];
|
|
2390
|
-
return bars[di].map((b, i) =>
|
|
2391
|
-
|
|
2392
|
-
{
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
)
|
|
2413
|
+
return bars[di].map((b, i) => {
|
|
2414
|
+
const r2 = Math.min(4, b.w / 2);
|
|
2415
|
+
const d = b.h <= r2 ? `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 + r2} Q ${b.x} ${b.y} ${b.x + r2} ${b.y} H ${b.x + b.w - r2} Q ${b.x + b.w} ${b.y} ${b.x + b.w} ${b.y + r2} V ${b.y + b.h} Z`;
|
|
2416
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2417
|
+
"path",
|
|
2418
|
+
{
|
|
2419
|
+
d,
|
|
2420
|
+
fill: color,
|
|
2421
|
+
className: "chart-bar",
|
|
2422
|
+
onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${b.v}`),
|
|
2423
|
+
onMouseMove: onMove,
|
|
2424
|
+
onMouseLeave: onLeave
|
|
2425
|
+
},
|
|
2426
|
+
`${di}-${i}`
|
|
2427
|
+
);
|
|
2428
|
+
});
|
|
2406
2429
|
})
|
|
2407
2430
|
] });
|
|
2408
2431
|
});
|
|
@@ -2489,20 +2512,22 @@ var TooltipBubble = ({ x, y, containerWidth, children }) => {
|
|
|
2489
2512
|
}
|
|
2490
2513
|
);
|
|
2491
2514
|
};
|
|
2492
|
-
var Chart = (props) => {
|
|
2515
|
+
var Chart = import_react5.default.memo((props) => {
|
|
2493
2516
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
2494
2517
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
2495
2518
|
const { width, height } = useChartSize(containerRef);
|
|
2519
|
+
const stableData = import_react5.default.useMemo(() => data, [JSON.stringify(data)]);
|
|
2520
|
+
const stableLabels = import_react5.default.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
2496
2521
|
const ready = width > 0 && height > 0;
|
|
2497
2522
|
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
2498
|
-
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(LineChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2499
|
-
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(CurveChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2500
|
-
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(BarChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2501
|
-
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2502
|
-
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data, labels, width, height, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
2523
|
+
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2524
|
+
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2525
|
+
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2526
|
+
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2527
|
+
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
2503
2528
|
tooltip.visible && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(TooltipBubble, { x: tooltip.x, y: tooltip.y, containerWidth: width, children: tooltip.content })
|
|
2504
2529
|
] });
|
|
2505
|
-
};
|
|
2530
|
+
});
|
|
2506
2531
|
Chart.displayName = "Chart";
|
|
2507
2532
|
var Chart_default = Chart;
|
|
2508
2533
|
|
|
@@ -2764,12 +2789,8 @@ var PortalContainerContext = import_react9.default.createContext(null);
|
|
|
2764
2789
|
var PortalProvider = ({ container, children }) => /* @__PURE__ */ (0, import_jsx_runtime311.jsx)(PortalContainerContext.Provider, { value: container, children });
|
|
2765
2790
|
var Portal = ({ children }) => {
|
|
2766
2791
|
const contextContainer = import_react9.default.useContext(PortalContainerContext);
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
if (!contextContainer) setFallback(document.body);
|
|
2770
|
-
}, [contextContainer]);
|
|
2771
|
-
const container = contextContainer ?? fallback;
|
|
2772
|
-
if (!container) return null;
|
|
2792
|
+
if (typeof document === "undefined") return null;
|
|
2793
|
+
const container = contextContainer ?? document.body;
|
|
2773
2794
|
return import_react_dom.default.createPortal(children, container);
|
|
2774
2795
|
};
|
|
2775
2796
|
Portal.displayName = "Portal";
|
|
@@ -3397,15 +3418,15 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3397
3418
|
direction
|
|
3398
3419
|
});
|
|
3399
3420
|
}, [triggerRef, popRef]);
|
|
3421
|
+
import_react18.default.useLayoutEffect(() => {
|
|
3422
|
+
if (!enabled) return;
|
|
3423
|
+
calculatePosition();
|
|
3424
|
+
}, [calculatePosition, enabled]);
|
|
3400
3425
|
import_react18.default.useEffect(() => {
|
|
3401
3426
|
if (!enabled) return;
|
|
3402
|
-
const raf = requestAnimationFrame(() => {
|
|
3403
|
-
calculatePosition();
|
|
3404
|
-
});
|
|
3405
3427
|
window.addEventListener("resize", calculatePosition);
|
|
3406
3428
|
window.addEventListener("scroll", calculatePosition, true);
|
|
3407
3429
|
return () => {
|
|
3408
|
-
cancelAnimationFrame(raf);
|
|
3409
3430
|
window.removeEventListener("resize", calculatePosition);
|
|
3410
3431
|
window.removeEventListener("scroll", calculatePosition, true);
|
|
3411
3432
|
};
|
package/dist/components/index.js
CHANGED
|
@@ -2063,29 +2063,50 @@ var toSmoothPath = (points) => {
|
|
|
2063
2063
|
}
|
|
2064
2064
|
return d;
|
|
2065
2065
|
};
|
|
2066
|
+
var RESIZE_SETTLE_MS = 150;
|
|
2066
2067
|
var useChartSize = (ref) => {
|
|
2067
2068
|
const [size, setSize] = React5.useState({ width: 0, height: 0 });
|
|
2069
|
+
const isResizing = React5.useRef(false);
|
|
2070
|
+
const settleTimer = React5.useRef(0);
|
|
2071
|
+
const lastSize = React5.useRef({ width: 0, height: 0 });
|
|
2072
|
+
const initialRef = React5.useRef(true);
|
|
2068
2073
|
React5.useEffect(() => {
|
|
2069
2074
|
const el = ref.current;
|
|
2070
2075
|
if (!el) return;
|
|
2071
|
-
let rafId = 0;
|
|
2072
2076
|
const observer = new ResizeObserver((entries) => {
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2077
|
+
const entry = entries[0];
|
|
2078
|
+
if (!entry) return;
|
|
2079
|
+
const { width, height } = entry.contentRect;
|
|
2080
|
+
const w = Math.floor(width);
|
|
2081
|
+
const h = Math.floor(height);
|
|
2082
|
+
if (w === lastSize.current.width && h === lastSize.current.height) return;
|
|
2083
|
+
lastSize.current = { width: w, height: h };
|
|
2084
|
+
if (initialRef.current) {
|
|
2085
|
+
initialRef.current = false;
|
|
2086
|
+
setSize({ width: w, height: h });
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
isResizing.current = true;
|
|
2090
|
+
if (el.firstElementChild) {
|
|
2091
|
+
const svg = el.firstElementChild;
|
|
2092
|
+
svg.style.transformOrigin = "0 0";
|
|
2093
|
+
svg.style.transform = `scale(${w / (size.width || w)}, ${h / (size.height || h)})`;
|
|
2094
|
+
}
|
|
2095
|
+
window.clearTimeout(settleTimer.current);
|
|
2096
|
+
settleTimer.current = window.setTimeout(() => {
|
|
2097
|
+
isResizing.current = false;
|
|
2098
|
+
if (el.firstElementChild) {
|
|
2099
|
+
el.firstElementChild.style.transform = "";
|
|
2100
|
+
}
|
|
2101
|
+
setSize({ width: w, height: h });
|
|
2102
|
+
}, RESIZE_SETTLE_MS);
|
|
2082
2103
|
});
|
|
2083
2104
|
observer.observe(el);
|
|
2084
2105
|
return () => {
|
|
2085
|
-
|
|
2106
|
+
window.clearTimeout(settleTimer.current);
|
|
2086
2107
|
observer.disconnect();
|
|
2087
2108
|
};
|
|
2088
|
-
}, [ref]);
|
|
2109
|
+
}, [ref, size.width, size.height]);
|
|
2089
2110
|
return size;
|
|
2090
2111
|
};
|
|
2091
2112
|
var useChartTooltip = (enabled) => {
|
|
@@ -2277,17 +2298,19 @@ var BarChart = React5.memo(({ data, labels, width, height, onHover, onMove, onLe
|
|
|
2277
2298
|
const chartW = width - PADDING.left - PADDING.right;
|
|
2278
2299
|
const chartH = height - PADDING.top - PADDING.bottom;
|
|
2279
2300
|
const groupW = chartW / count;
|
|
2280
|
-
const
|
|
2301
|
+
const barGap = groupCount > 1 ? 2 : 0;
|
|
2302
|
+
const barW = Math.max(1, Math.min(32, (groupW * 0.7 - barGap * (groupCount - 1)) / groupCount));
|
|
2281
2303
|
const bars = React5.useMemo(
|
|
2282
2304
|
() => entries.map(
|
|
2283
2305
|
([, values], di) => values.map((v, i) => {
|
|
2306
|
+
const totalBarsW = barW * groupCount + barGap * (groupCount - 1);
|
|
2284
2307
|
const h = Math.max(0, v / maxVal * chartH);
|
|
2285
|
-
const x = PADDING.left + groupW * i + (groupW -
|
|
2308
|
+
const x = PADDING.left + groupW * i + (groupW - totalBarsW) / 2 + (barW + barGap) * di;
|
|
2286
2309
|
const y = PADDING.top + chartH - h;
|
|
2287
2310
|
return { x, y, w: barW, h, v };
|
|
2288
2311
|
})
|
|
2289
2312
|
),
|
|
2290
|
-
[entries, maxVal, chartH, groupW, barW, groupCount]
|
|
2313
|
+
[entries, maxVal, chartH, groupW, barW, barGap, groupCount]
|
|
2291
2314
|
);
|
|
2292
2315
|
const barLabelStep = getLabelStep(count, chartW);
|
|
2293
2316
|
return /* @__PURE__ */ jsxs196("svg", { viewBox: `0 0 ${width} ${height}`, className: "chart-svg", children: [
|
|
@@ -2299,22 +2322,22 @@ var BarChart = React5.memo(({ data, labels, width, height, onHover, onMove, onLe
|
|
|
2299
2322
|
entries.map(([key], di) => {
|
|
2300
2323
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
2301
2324
|
const color = palette[2];
|
|
2302
|
-
return bars[di].map((b, i) =>
|
|
2303
|
-
|
|
2304
|
-
{
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
)
|
|
2325
|
+
return bars[di].map((b, i) => {
|
|
2326
|
+
const r2 = Math.min(4, b.w / 2);
|
|
2327
|
+
const d = b.h <= r2 ? `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 + r2} Q ${b.x} ${b.y} ${b.x + r2} ${b.y} H ${b.x + b.w - r2} Q ${b.x + b.w} ${b.y} ${b.x + b.w} ${b.y + r2} V ${b.y + b.h} Z`;
|
|
2328
|
+
return /* @__PURE__ */ jsx305(
|
|
2329
|
+
"path",
|
|
2330
|
+
{
|
|
2331
|
+
d,
|
|
2332
|
+
fill: color,
|
|
2333
|
+
className: "chart-bar",
|
|
2334
|
+
onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${b.v}`),
|
|
2335
|
+
onMouseMove: onMove,
|
|
2336
|
+
onMouseLeave: onLeave
|
|
2337
|
+
},
|
|
2338
|
+
`${di}-${i}`
|
|
2339
|
+
);
|
|
2340
|
+
});
|
|
2318
2341
|
})
|
|
2319
2342
|
] });
|
|
2320
2343
|
});
|
|
@@ -2401,20 +2424,22 @@ var TooltipBubble = ({ x, y, containerWidth, children }) => {
|
|
|
2401
2424
|
}
|
|
2402
2425
|
);
|
|
2403
2426
|
};
|
|
2404
|
-
var Chart = (props) => {
|
|
2427
|
+
var Chart = React5.memo((props) => {
|
|
2405
2428
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
2406
2429
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
2407
2430
|
const { width, height } = useChartSize(containerRef);
|
|
2431
|
+
const stableData = React5.useMemo(() => data, [JSON.stringify(data)]);
|
|
2432
|
+
const stableLabels = React5.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
2408
2433
|
const ready = width > 0 && height > 0;
|
|
2409
2434
|
return /* @__PURE__ */ jsxs196("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
2410
|
-
ready && type === "line" && /* @__PURE__ */ jsx305(LineChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2411
|
-
ready && type === "curve" && /* @__PURE__ */ jsx305(CurveChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2412
|
-
ready && type === "bar" && /* @__PURE__ */ jsx305(BarChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2413
|
-
ready && type === "pie" && /* @__PURE__ */ jsx305(PieDonutChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2414
|
-
ready && type === "doughnut" && /* @__PURE__ */ jsx305(PieDonutChart, { data, labels, width, height, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
2435
|
+
ready && type === "line" && /* @__PURE__ */ jsx305(LineChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2436
|
+
ready && type === "curve" && /* @__PURE__ */ jsx305(CurveChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2437
|
+
ready && type === "bar" && /* @__PURE__ */ jsx305(BarChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2438
|
+
ready && type === "pie" && /* @__PURE__ */ jsx305(PieDonutChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
2439
|
+
ready && type === "doughnut" && /* @__PURE__ */ jsx305(PieDonutChart, { data: stableData, labels: stableLabels, width, height, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
2415
2440
|
tooltip.visible && /* @__PURE__ */ jsx305(TooltipBubble, { x: tooltip.x, y: tooltip.y, containerWidth: width, children: tooltip.content })
|
|
2416
2441
|
] });
|
|
2417
|
-
};
|
|
2442
|
+
});
|
|
2418
2443
|
Chart.displayName = "Chart";
|
|
2419
2444
|
var Chart_default = Chart;
|
|
2420
2445
|
|
|
@@ -2676,12 +2701,8 @@ var PortalContainerContext = React8.createContext(null);
|
|
|
2676
2701
|
var PortalProvider = ({ container, children }) => /* @__PURE__ */ jsx311(PortalContainerContext.Provider, { value: container, children });
|
|
2677
2702
|
var Portal = ({ children }) => {
|
|
2678
2703
|
const contextContainer = React8.useContext(PortalContainerContext);
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
if (!contextContainer) setFallback(document.body);
|
|
2682
|
-
}, [contextContainer]);
|
|
2683
|
-
const container = contextContainer ?? fallback;
|
|
2684
|
-
if (!container) return null;
|
|
2704
|
+
if (typeof document === "undefined") return null;
|
|
2705
|
+
const container = contextContainer ?? document.body;
|
|
2685
2706
|
return ReactDOM.createPortal(children, container);
|
|
2686
2707
|
};
|
|
2687
2708
|
Portal.displayName = "Portal";
|
|
@@ -3309,15 +3330,15 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3309
3330
|
direction
|
|
3310
3331
|
});
|
|
3311
3332
|
}, [triggerRef, popRef]);
|
|
3333
|
+
React17.useLayoutEffect(() => {
|
|
3334
|
+
if (!enabled) return;
|
|
3335
|
+
calculatePosition();
|
|
3336
|
+
}, [calculatePosition, enabled]);
|
|
3312
3337
|
React17.useEffect(() => {
|
|
3313
3338
|
if (!enabled) return;
|
|
3314
|
-
const raf = requestAnimationFrame(() => {
|
|
3315
|
-
calculatePosition();
|
|
3316
|
-
});
|
|
3317
3339
|
window.addEventListener("resize", calculatePosition);
|
|
3318
3340
|
window.addEventListener("scroll", calculatePosition, true);
|
|
3319
3341
|
return () => {
|
|
3320
|
-
cancelAnimationFrame(raf);
|
|
3321
3342
|
window.removeEventListener("resize", calculatePosition);
|
|
3322
3343
|
window.removeEventListener("scroll", calculatePosition, true);
|
|
3323
3344
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -6562,29 +6562,50 @@ var toSmoothPath = (points) => {
|
|
|
6562
6562
|
}
|
|
6563
6563
|
return d;
|
|
6564
6564
|
};
|
|
6565
|
+
var RESIZE_SETTLE_MS = 150;
|
|
6565
6566
|
var useChartSize = (ref) => {
|
|
6566
6567
|
const [size, setSize] = import_react5.default.useState({ width: 0, height: 0 });
|
|
6568
|
+
const isResizing = import_react5.default.useRef(false);
|
|
6569
|
+
const settleTimer = import_react5.default.useRef(0);
|
|
6570
|
+
const lastSize = import_react5.default.useRef({ width: 0, height: 0 });
|
|
6571
|
+
const initialRef = import_react5.default.useRef(true);
|
|
6567
6572
|
import_react5.default.useEffect(() => {
|
|
6568
6573
|
const el = ref.current;
|
|
6569
6574
|
if (!el) return;
|
|
6570
|
-
let rafId = 0;
|
|
6571
6575
|
const observer = new ResizeObserver((entries) => {
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6576
|
+
const entry = entries[0];
|
|
6577
|
+
if (!entry) return;
|
|
6578
|
+
const { width, height } = entry.contentRect;
|
|
6579
|
+
const w = Math.floor(width);
|
|
6580
|
+
const h = Math.floor(height);
|
|
6581
|
+
if (w === lastSize.current.width && h === lastSize.current.height) return;
|
|
6582
|
+
lastSize.current = { width: w, height: h };
|
|
6583
|
+
if (initialRef.current) {
|
|
6584
|
+
initialRef.current = false;
|
|
6585
|
+
setSize({ width: w, height: h });
|
|
6586
|
+
return;
|
|
6587
|
+
}
|
|
6588
|
+
isResizing.current = true;
|
|
6589
|
+
if (el.firstElementChild) {
|
|
6590
|
+
const svg = el.firstElementChild;
|
|
6591
|
+
svg.style.transformOrigin = "0 0";
|
|
6592
|
+
svg.style.transform = `scale(${w / (size.width || w)}, ${h / (size.height || h)})`;
|
|
6593
|
+
}
|
|
6594
|
+
window.clearTimeout(settleTimer.current);
|
|
6595
|
+
settleTimer.current = window.setTimeout(() => {
|
|
6596
|
+
isResizing.current = false;
|
|
6597
|
+
if (el.firstElementChild) {
|
|
6598
|
+
el.firstElementChild.style.transform = "";
|
|
6599
|
+
}
|
|
6600
|
+
setSize({ width: w, height: h });
|
|
6601
|
+
}, RESIZE_SETTLE_MS);
|
|
6581
6602
|
});
|
|
6582
6603
|
observer.observe(el);
|
|
6583
6604
|
return () => {
|
|
6584
|
-
|
|
6605
|
+
window.clearTimeout(settleTimer.current);
|
|
6585
6606
|
observer.disconnect();
|
|
6586
6607
|
};
|
|
6587
|
-
}, [ref]);
|
|
6608
|
+
}, [ref, size.width, size.height]);
|
|
6588
6609
|
return size;
|
|
6589
6610
|
};
|
|
6590
6611
|
var useChartTooltip = (enabled) => {
|
|
@@ -6776,17 +6797,19 @@ var BarChart = import_react5.default.memo(({ data, labels, width, height, onHove
|
|
|
6776
6797
|
const chartW = width - PADDING.left - PADDING.right;
|
|
6777
6798
|
const chartH = height - PADDING.top - PADDING.bottom;
|
|
6778
6799
|
const groupW = chartW / count;
|
|
6779
|
-
const
|
|
6800
|
+
const barGap = groupCount > 1 ? 2 : 0;
|
|
6801
|
+
const barW = Math.max(1, Math.min(32, (groupW * 0.7 - barGap * (groupCount - 1)) / groupCount));
|
|
6780
6802
|
const bars = import_react5.default.useMemo(
|
|
6781
6803
|
() => entries.map(
|
|
6782
6804
|
([, values], di) => values.map((v, i) => {
|
|
6805
|
+
const totalBarsW = barW * groupCount + barGap * (groupCount - 1);
|
|
6783
6806
|
const h = Math.max(0, v / maxVal * chartH);
|
|
6784
|
-
const x = PADDING.left + groupW * i + (groupW -
|
|
6807
|
+
const x = PADDING.left + groupW * i + (groupW - totalBarsW) / 2 + (barW + barGap) * di;
|
|
6785
6808
|
const y = PADDING.top + chartH - h;
|
|
6786
6809
|
return { x, y, w: barW, h, v };
|
|
6787
6810
|
})
|
|
6788
6811
|
),
|
|
6789
|
-
[entries, maxVal, chartH, groupW, barW, groupCount]
|
|
6812
|
+
[entries, maxVal, chartH, groupW, barW, barGap, groupCount]
|
|
6790
6813
|
);
|
|
6791
6814
|
const barLabelStep = getLabelStep(count, chartW);
|
|
6792
6815
|
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("svg", { viewBox: `0 0 ${width} ${height}`, className: "chart-svg", children: [
|
|
@@ -6798,22 +6821,22 @@ var BarChart = import_react5.default.memo(({ data, labels, width, height, onHove
|
|
|
6798
6821
|
entries.map(([key], di) => {
|
|
6799
6822
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
6800
6823
|
const color = palette[2];
|
|
6801
|
-
return bars[di].map((b, i) =>
|
|
6802
|
-
|
|
6803
|
-
{
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
)
|
|
6824
|
+
return bars[di].map((b, i) => {
|
|
6825
|
+
const r2 = Math.min(4, b.w / 2);
|
|
6826
|
+
const d = b.h <= r2 ? `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 + r2} Q ${b.x} ${b.y} ${b.x + r2} ${b.y} H ${b.x + b.w - r2} Q ${b.x + b.w} ${b.y} ${b.x + b.w} ${b.y + r2} V ${b.y + b.h} Z`;
|
|
6827
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
6828
|
+
"path",
|
|
6829
|
+
{
|
|
6830
|
+
d,
|
|
6831
|
+
fill: color,
|
|
6832
|
+
className: "chart-bar",
|
|
6833
|
+
onMouseEnter: (e) => onHover(e, `${key}: ${labels[i]} \u2014 ${b.v}`),
|
|
6834
|
+
onMouseMove: onMove,
|
|
6835
|
+
onMouseLeave: onLeave
|
|
6836
|
+
},
|
|
6837
|
+
`${di}-${i}`
|
|
6838
|
+
);
|
|
6839
|
+
});
|
|
6817
6840
|
})
|
|
6818
6841
|
] });
|
|
6819
6842
|
});
|
|
@@ -6900,20 +6923,22 @@ var TooltipBubble = ({ x, y, containerWidth, children }) => {
|
|
|
6900
6923
|
}
|
|
6901
6924
|
);
|
|
6902
6925
|
};
|
|
6903
|
-
var Chart = (props) => {
|
|
6926
|
+
var Chart = import_react5.default.memo((props) => {
|
|
6904
6927
|
const { type, data, labels, tooltip: showTooltip = true } = props;
|
|
6905
6928
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
6906
6929
|
const { width, height } = useChartSize(containerRef);
|
|
6930
|
+
const stableData = import_react5.default.useMemo(() => data, [JSON.stringify(data)]);
|
|
6931
|
+
const stableLabels = import_react5.default.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
6907
6932
|
const ready = width > 0 && height > 0;
|
|
6908
6933
|
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
6909
|
-
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(LineChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6910
|
-
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(CurveChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6911
|
-
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(BarChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6912
|
-
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data, labels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6913
|
-
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data, labels, width, height, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
6934
|
+
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6935
|
+
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6936
|
+
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6937
|
+
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, onHover: show, onMove: move, onLeave: hide }),
|
|
6938
|
+
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
6914
6939
|
tooltip.visible && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(TooltipBubble, { x: tooltip.x, y: tooltip.y, containerWidth: width, children: tooltip.content })
|
|
6915
6940
|
] });
|
|
6916
|
-
};
|
|
6941
|
+
});
|
|
6917
6942
|
Chart.displayName = "Chart";
|
|
6918
6943
|
var Chart_default = Chart;
|
|
6919
6944
|
|
|
@@ -7188,12 +7213,8 @@ var PortalContainerContext = import_react9.default.createContext(null);
|
|
|
7188
7213
|
var PortalProvider = ({ container, children }) => /* @__PURE__ */ (0, import_jsx_runtime311.jsx)(PortalContainerContext.Provider, { value: container, children });
|
|
7189
7214
|
var Portal = ({ children }) => {
|
|
7190
7215
|
const contextContainer = import_react9.default.useContext(PortalContainerContext);
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
if (!contextContainer) setFallback(document.body);
|
|
7194
|
-
}, [contextContainer]);
|
|
7195
|
-
const container = contextContainer ?? fallback;
|
|
7196
|
-
if (!container) return null;
|
|
7216
|
+
if (typeof document === "undefined") return null;
|
|
7217
|
+
const container = contextContainer ?? document.body;
|
|
7197
7218
|
return import_react_dom.default.createPortal(children, container);
|
|
7198
7219
|
};
|
|
7199
7220
|
Portal.displayName = "Portal";
|
|
@@ -7821,15 +7842,15 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7821
7842
|
direction
|
|
7822
7843
|
});
|
|
7823
7844
|
}, [triggerRef, popRef]);
|
|
7845
|
+
import_react18.default.useLayoutEffect(() => {
|
|
7846
|
+
if (!enabled) return;
|
|
7847
|
+
calculatePosition();
|
|
7848
|
+
}, [calculatePosition, enabled]);
|
|
7824
7849
|
import_react18.default.useEffect(() => {
|
|
7825
7850
|
if (!enabled) return;
|
|
7826
|
-
const raf = requestAnimationFrame(() => {
|
|
7827
|
-
calculatePosition();
|
|
7828
|
-
});
|
|
7829
7851
|
window.addEventListener("resize", calculatePosition);
|
|
7830
7852
|
window.addEventListener("scroll", calculatePosition, true);
|
|
7831
7853
|
return () => {
|
|
7832
|
-
cancelAnimationFrame(raf);
|
|
7833
7854
|
window.removeEventListener("resize", calculatePosition);
|
|
7834
7855
|
window.removeEventListener("scroll", calculatePosition, true);
|
|
7835
7856
|
};
|