@hsu-react/ui 2.5.3 → 2.5.5
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/es/components/ChainGraph/_hooks/useChainGraphData.js +29 -8
- package/es/components/ChainGraph/_hooks/useChainGraphLayout.js +14 -3
- package/es/components/Chart/Bar/index.js +49 -19
- package/es/components/Chart/Bubble/index.js +21 -6
- package/es/components/Chart/Common/index.js +7 -2
- package/es/components/Chart/Heatmap/index.js +21 -6
- package/es/components/Chart/Line/index.js +49 -19
- package/es/components/Chart/Pie/Pie3D/index.js +22 -6
- package/es/components/Chart/Pie/index.js +21 -6
- package/es/components/Chart/Sankey/index.js +11 -2
- package/es/components/Chart/Tree/index.js +11 -2
- package/es/components/Chat/ChatInput/index.js +7 -2
- package/es/components/Icon/index.js +8 -2
- package/es/components/Input/Number/index.js +28 -21
- package/es/components/Input/Password/index.js +44 -36
- package/es/components/Input/Search/index.js +44 -36
- package/es/components/Input/TextArea/index.js +64 -42
- package/es/components/Input/index.js +40 -34
- package/es/components/Select/_hooks/useSelectComposition.js +6 -2
- package/es/components/Select/_hooks/useSelectInputOptions.js +8 -2
- package/es/components/Slider/index.js +24 -15
- package/es/components/Table/_hooks/useAutoScrolling.js +16 -7
- package/es/components/Upload/_hooks/useUploadFileList.js +8 -2
- package/es/components/Upload/_hooks/useUploadOperations.js +8 -2
- package/es/hooks/useLatestRef.d.ts +24 -0
- package/es/hooks/useLatestRef.js +29 -0
- package/es/layout/Menu/_hooks/useOnlyLvOneMenu.js +9 -2
- package/lib/components/ChainGraph/_hooks/useChainGraphData.js +24 -7
- package/lib/components/ChainGraph/_hooks/useChainGraphLayout.js +12 -2
- package/lib/components/Chart/Bar/index.js +45 -18
- package/lib/components/Chart/Bubble/index.js +19 -6
- package/lib/components/Chart/Common/index.js +6 -2
- package/lib/components/Chart/Heatmap/index.js +19 -6
- package/lib/components/Chart/Line/index.js +45 -18
- package/lib/components/Chart/Pie/Pie3D/index.js +20 -6
- package/lib/components/Chart/Pie/index.js +19 -6
- package/lib/components/Chart/Sankey/index.js +10 -2
- package/lib/components/Chart/Tree/index.js +10 -2
- package/lib/components/Chat/ChatInput/index.js +6 -2
- package/lib/components/Icon/index.js +7 -2
- package/lib/components/Input/Number/index.js +27 -18
- package/lib/components/Input/Password/index.js +40 -26
- package/lib/components/Input/Search/index.js +42 -26
- package/lib/components/Input/TextArea/index.js +54 -26
- package/lib/components/Input/index.js +37 -24
- package/lib/components/Select/_hooks/useSelectComposition.js +6 -2
- package/lib/components/Select/_hooks/useSelectInputOptions.js +7 -2
- package/lib/components/Slider/index.js +23 -11
- package/lib/components/Table/_hooks/useAutoScrolling.js +16 -7
- package/lib/components/Upload/_hooks/useUploadFileList.js +7 -2
- package/lib/components/Upload/_hooks/useUploadOperations.js +7 -2
- package/lib/hooks/useLatestRef.d.ts +24 -0
- package/lib/hooks/useLatestRef.js +35 -0
- package/lib/layout/Menu/_hooks/useOnlyLvOneMenu.js +8 -2
- package/package.json +9 -3
- package/src/__tests__/callbackDepsGuard.test.ts +119 -0
- package/src/__tests__/setup.ts +26 -0
- package/src/components/ChainGraph/_hooks/callbacks.test.tsx +155 -0
- package/src/components/ChainGraph/_hooks/useChainGraphData.ts +38 -10
- package/src/components/ChainGraph/_hooks/useChainGraphLayout.ts +16 -3
- package/src/components/Chart/Bar/index.tsx +59 -21
- package/src/components/Chart/Bubble/index.tsx +22 -7
- package/src/components/Chart/Common/index.tsx +7 -2
- package/src/components/Chart/Heatmap/index.tsx +25 -6
- package/src/components/Chart/Line/index.tsx +59 -21
- package/src/components/Chart/Pie/Pie3D/index.tsx +22 -7
- package/src/components/Chart/Pie/index.tsx +22 -7
- package/src/components/Chart/Sankey/index.tsx +10 -4
- package/src/components/Chart/Tree/index.tsx +10 -4
- package/src/components/Chart/callbacks.test.tsx +315 -0
- package/src/components/Chat/ChatInput/index.tsx +7 -2
- package/src/components/Icon/index.tsx +7 -2
- package/src/components/Input/Number/index.tsx +25 -23
- package/src/components/Input/Password/index.tsx +37 -26
- package/src/components/Input/Search/index.tsx +39 -26
- package/src/components/Input/TextArea/index.test.tsx +208 -0
- package/src/components/Input/TextArea/index.tsx +56 -30
- package/src/components/Input/index.test.tsx +189 -0
- package/src/components/Input/index.tsx +36 -29
- package/src/components/Select/_hooks/useSelectComposition.test.ts +47 -0
- package/src/components/Select/_hooks/useSelectComposition.ts +6 -2
- package/src/components/Select/_hooks/useSelectInputOptions.ts +6 -9
- package/src/components/Slider/index.tsx +22 -12
- package/src/components/Table/_hooks/useAutoScrolling.test.tsx +95 -0
- package/src/components/Table/_hooks/useAutoScrolling.ts +16 -7
- package/src/components/Upload/_hooks/useUploadFileList.ts +6 -2
- package/src/components/Upload/_hooks/useUploadOperations.ts +7 -2
- package/src/hooks/useLatestRef.ts +31 -0
- package/src/layout/Menu/_hooks/useOnlyLvOneMenu.test.tsx +56 -0
- package/src/layout/Menu/_hooks/useOnlyLvOneMenu.ts +8 -2
|
@@ -4,8 +4,9 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
|
|
|
4
4
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
5
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
6
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
-
import { useEffect, useState } from "react";
|
|
7
|
+
import { useCallback, useEffect, useState } from "react";
|
|
8
8
|
import { Equal } from "hsu-utils";
|
|
9
|
+
import { useLatestRef } from "../../../hooks/useLatestRef";
|
|
9
10
|
export function useChainGraphData(props) {
|
|
10
11
|
var graph = props.graph,
|
|
11
12
|
data = props.data,
|
|
@@ -22,6 +23,29 @@ export function useChainGraphData(props) {
|
|
|
22
23
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
23
24
|
isLayouting = _useState4[0],
|
|
24
25
|
setIsLayouting = _useState4[1];
|
|
26
|
+
|
|
27
|
+
// 这三个回调都是「交给图实例、由它在后续事件里回调」的出口,不是数据本身。
|
|
28
|
+
// 它们进依赖数组是条死依赖:effect 体被 ObjEqual(lastData, data) 挡住,
|
|
29
|
+
// 引用变了也不会重新 setData —— 图里存的还是首次 setData 时那个闭包,
|
|
30
|
+
// 换了引用永远调不到(stale closure)。改成引用恒定的转发函数:
|
|
31
|
+
// 依赖数组只留真正的输入(graph/data/level/rootLevel),调用时总是取到最新的回调。
|
|
32
|
+
var getImageRef = useLatestRef(getImage);
|
|
33
|
+
var labelRenderRef = useLatestRef(labelRender);
|
|
34
|
+
var onLayoutingChangeRef = useLatestRef(onLayoutingChange);
|
|
35
|
+
var emitImage = useCallback(function (img) {
|
|
36
|
+
var _getImageRef$current;
|
|
37
|
+
(_getImageRef$current = getImageRef.current) === null || _getImageRef$current === void 0 || _getImageRef$current.call(getImageRef, img);
|
|
38
|
+
}, [getImageRef]);
|
|
39
|
+
// labelRender 在 ChainGraphServices.setData 里是「传了才改写 label」的真值判断,
|
|
40
|
+
// 所以这里保留「有没有传」的语义:没传就传 undefined,传了才给转发函数。
|
|
41
|
+
var renderLabel = useCallback(function (label) {
|
|
42
|
+
return labelRenderRef.current(label);
|
|
43
|
+
}, [labelRenderRef]);
|
|
44
|
+
var emitLayouting = useCallback(function (value) {
|
|
45
|
+
var _onLayoutingChangeRef;
|
|
46
|
+
setIsLayouting(value);
|
|
47
|
+
(_onLayoutingChangeRef = onLayoutingChangeRef.current) === null || _onLayoutingChangeRef === void 0 || _onLayoutingChangeRef.call(onLayoutingChangeRef, value);
|
|
48
|
+
}, [onLayoutingChangeRef]);
|
|
25
49
|
useEffect(function () {
|
|
26
50
|
if (graph && !Equal.ObjEqual(lastData, data)) {
|
|
27
51
|
setLastData(data);
|
|
@@ -29,15 +53,12 @@ export function useChainGraphData(props) {
|
|
|
29
53
|
data: data,
|
|
30
54
|
level: level,
|
|
31
55
|
rootLevel: rootLevel,
|
|
32
|
-
getImage:
|
|
33
|
-
isLayouting:
|
|
34
|
-
|
|
35
|
-
onLayoutingChange === null || onLayoutingChange === void 0 || onLayoutingChange(value);
|
|
36
|
-
},
|
|
37
|
-
labelRender: labelRender
|
|
56
|
+
getImage: emitImage,
|
|
57
|
+
isLayouting: emitLayouting,
|
|
58
|
+
labelRender: labelRenderRef.current ? renderLabel : undefined
|
|
38
59
|
});
|
|
39
60
|
}
|
|
40
|
-
}, [graph, data, level, rootLevel,
|
|
61
|
+
}, [graph, data, level, rootLevel, lastData, emitImage, emitLayouting, renderLabel, labelRenderRef]);
|
|
41
62
|
return {
|
|
42
63
|
isLayouting: isLayouting
|
|
43
64
|
};
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
1
|
+
import { useCallback, useEffect } from "react";
|
|
2
|
+
import { useLatestRef } from "../../../hooks/useLatestRef";
|
|
2
3
|
export function useChainGraphLayout(props) {
|
|
3
4
|
var graph = props.graph,
|
|
4
5
|
octopus = props.octopus,
|
|
5
6
|
rootLevel = props.rootLevel,
|
|
6
7
|
getImage = props.getImage;
|
|
8
|
+
|
|
9
|
+
// getImage 只是「布局完成后把截图 dataURL 交出去」的出口,不是布局的输入。
|
|
10
|
+
// 它进依赖数组会让消费方每传一次内联箭头就重新 changeLayout 一次 —— 整张图重排;
|
|
11
|
+
// 消费方再把截图存进 state,就变成「重排 → 出图 → setState → 新引用 → 再重排」的死循环。
|
|
12
|
+
// 用引用恒定的转发函数注册,调用时再取最新的 getImage。
|
|
13
|
+
var getImageRef = useLatestRef(getImage);
|
|
14
|
+
var emitImage = useCallback(function (img) {
|
|
15
|
+
var _getImageRef$current;
|
|
16
|
+
(_getImageRef$current = getImageRef.current) === null || _getImageRef$current === void 0 || _getImageRef$current.call(getImageRef, img);
|
|
17
|
+
}, [getImageRef]);
|
|
7
18
|
useEffect(function () {
|
|
8
19
|
if (graph && octopus !== undefined) {
|
|
9
|
-
graph.changeLayout(octopus, rootLevel,
|
|
20
|
+
graph.changeLayout(octopus, rootLevel, emitImage);
|
|
10
21
|
}
|
|
11
|
-
}, [graph, octopus, rootLevel,
|
|
22
|
+
}, [graph, octopus, rootLevel, emitImage]);
|
|
12
23
|
}
|
|
@@ -16,6 +16,7 @@ import { autoScrollByItem } from "../_utils/autoSmooth";
|
|
|
16
16
|
import { buildCartesianSeriesOptions, createDefaultCategoryXAxis, createDefaultValueYAxis, getSliderShow, percentWindowToIndexWindow, resolveScrollConfig } from "../_utils/cartesian";
|
|
17
17
|
import { resolveChartChrome } from "../_utils/chartTheme";
|
|
18
18
|
import useIsDark from "../../../hooks/useIsDark";
|
|
19
|
+
import useLatestRef from "../../../hooks/useLatestRef";
|
|
19
20
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
21
|
var ChartBar = function ChartBar(props) {
|
|
21
22
|
var className = props.className,
|
|
@@ -62,6 +63,30 @@ var ChartBar = function ChartBar(props) {
|
|
|
62
63
|
return resolveChartChrome(isDark);
|
|
63
64
|
}, [isDark]);
|
|
64
65
|
|
|
66
|
+
// 回调 prop 一律走 useLatestRef,不进依赖数组:消费方传内联箭头(React 里最常见的
|
|
67
|
+
// 写法)时每次渲染都是新引用,进依赖数组会让「init + setOption(notMerge)」整段重跑,
|
|
68
|
+
// 还会把当前可视窗口再同步一次给父级 —— 父级据此改 state 就是死循环。
|
|
69
|
+
// 但「有没有传回调」决定要不要注册监听,所以单独拆成布尔量进依赖数组,
|
|
70
|
+
// 这样「从无到有传入回调」仍会重新注册,不会漏。
|
|
71
|
+
var onClickRef = useLatestRef(onClick);
|
|
72
|
+
var onLegendSelectChangedRef = useLatestRef(onLegendSelectChanged);
|
|
73
|
+
var onDataZoomWindowChangedRef = useLatestRef(onDataZoomWindowChanged);
|
|
74
|
+
var hasOnClick = !!onClick;
|
|
75
|
+
var hasOnLegendSelectChanged = !!onLegendSelectChanged;
|
|
76
|
+
var hasOnDataZoomWindowChanged = !!onDataZoomWindowChanged;
|
|
77
|
+
// 已通知过父级的窗口用 ref 记账(不参与渲染):窗口没变就不再通知,
|
|
78
|
+
// 掐断「通知 → 父级重算坐标轴 → chartOption 变 → effect 重跑 → 再通知」的自激回路
|
|
79
|
+
var notifiedZoomWindowRef = useRef(null);
|
|
80
|
+
var emitZoomWindow = useCallback(function (next) {
|
|
81
|
+
var _onDataZoomWindowChan;
|
|
82
|
+
var prev = notifiedZoomWindowRef.current;
|
|
83
|
+
if (prev && prev.startIndex === next.startIndex && prev.endIndex === next.endIndex) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
notifiedZoomWindowRef.current = next;
|
|
87
|
+
(_onDataZoomWindowChan = onDataZoomWindowChangedRef.current) === null || _onDataZoomWindowChan === void 0 || _onDataZoomWindowChan.call(onDataZoomWindowChangedRef, next);
|
|
88
|
+
}, [onDataZoomWindowChangedRef]);
|
|
89
|
+
|
|
65
90
|
// Cache the chart option with useMemo
|
|
66
91
|
var chartOption = useMemo(function () {
|
|
67
92
|
var _xAxisData$length, _ref, _ref2;
|
|
@@ -239,16 +264,16 @@ var ChartBar = function ChartBar(props) {
|
|
|
239
264
|
}
|
|
240
265
|
|
|
241
266
|
// Sync the current visible window to the caller (on initial render and after restore), used to recalculate axes based on the displayed portion
|
|
242
|
-
if (
|
|
267
|
+
if (hasOnDataZoomWindowChanged) {
|
|
243
268
|
var _chart$getOption3, _xAxisData$length2;
|
|
244
269
|
var zooms = (_chart$getOption3 = chart.getOption()) === null || _chart$getOption3 === void 0 ? void 0 : _chart$getOption3.dataZoom;
|
|
245
270
|
var zoom = zooms === null || zooms === void 0 ? void 0 : zooms[0];
|
|
246
271
|
var totalLen = (_xAxisData$length2 = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.length) !== null && _xAxisData$length2 !== void 0 ? _xAxisData$length2 : 0;
|
|
247
272
|
if (typeof (zoom === null || zoom === void 0 ? void 0 : zoom.start) === "number" && typeof (zoom === null || zoom === void 0 ? void 0 : zoom.end) === "number") {
|
|
248
|
-
|
|
273
|
+
emitZoomWindow(percentWindowToIndexWindow(zoom.start, zoom.end, totalLen));
|
|
249
274
|
} else {
|
|
250
275
|
// Without dataZoom (e.g. scrolling not enabled due to insufficient data) the window is the full range; sync once to avoid a stale old window
|
|
251
|
-
|
|
276
|
+
emitZoomWindow({
|
|
252
277
|
startIndex: 0,
|
|
253
278
|
endIndex: Math.max(0, totalLen - 1)
|
|
254
279
|
});
|
|
@@ -264,17 +289,22 @@ var ChartBar = function ChartBar(props) {
|
|
|
264
289
|
resizeObserverRef.current.observe(chartRef.current);
|
|
265
290
|
}
|
|
266
291
|
|
|
267
|
-
// Add click event
|
|
268
|
-
|
|
292
|
+
// Add click event(注册与否看布尔量,实际调用取最新引用)
|
|
293
|
+
var handleClick = function handleClick(event) {
|
|
294
|
+
var _onClickRef$current;
|
|
295
|
+
(_onClickRef$current = onClickRef.current) === null || _onClickRef$current === void 0 || _onClickRef$current.call(onClickRef, event);
|
|
296
|
+
};
|
|
297
|
+
if (hasOnClick) {
|
|
269
298
|
var _chartInstanceRef$cur2;
|
|
270
|
-
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click",
|
|
299
|
+
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click", handleClick);
|
|
271
300
|
}
|
|
272
301
|
|
|
273
302
|
// Legend selection event
|
|
274
303
|
var handleLegendSelectChanged = function handleLegendSelectChanged(params) {
|
|
275
|
-
|
|
304
|
+
var _onLegendSelectChange;
|
|
305
|
+
(_onLegendSelectChange = onLegendSelectChangedRef.current) === null || _onLegendSelectChange === void 0 || _onLegendSelectChange.call(onLegendSelectChangedRef, params.selected);
|
|
276
306
|
};
|
|
277
|
-
if (
|
|
307
|
+
if (hasOnLegendSelectChanged) {
|
|
278
308
|
var _chartInstanceRef$cur3;
|
|
279
309
|
(_chartInstanceRef$cur3 = chartInstanceRef.current) === null || _chartInstanceRef$cur3 === void 0 || _chartInstanceRef$cur3.on("legendselectchanged", handleLegendSelectChanged);
|
|
280
310
|
}
|
|
@@ -285,16 +315,16 @@ var ChartBar = function ChartBar(props) {
|
|
|
285
315
|
var raw = params;
|
|
286
316
|
var info = (_raw$batch$ = raw === null || raw === void 0 || (_raw$batch = raw.batch) === null || _raw$batch === void 0 ? void 0 : _raw$batch[0]) !== null && _raw$batch$ !== void 0 ? _raw$batch$ : raw;
|
|
287
317
|
if (typeof (info === null || info === void 0 ? void 0 : info.startValue) === "number" && typeof (info === null || info === void 0 ? void 0 : info.endValue) === "number") {
|
|
288
|
-
|
|
318
|
+
emitZoomWindow({
|
|
289
319
|
startIndex: Math.max(0, Math.round(info.startValue)),
|
|
290
320
|
endIndex: Math.max(0, Math.round(info.endValue))
|
|
291
321
|
});
|
|
292
322
|
} else if (typeof (info === null || info === void 0 ? void 0 : info.start) === "number" && typeof (info === null || info === void 0 ? void 0 : info.end) === "number") {
|
|
293
323
|
var _xAxisData$length3;
|
|
294
|
-
|
|
324
|
+
emitZoomWindow(percentWindowToIndexWindow(info.start, info.end, (_xAxisData$length3 = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.length) !== null && _xAxisData$length3 !== void 0 ? _xAxisData$length3 : 0));
|
|
295
325
|
}
|
|
296
326
|
};
|
|
297
|
-
if (
|
|
327
|
+
if (hasOnDataZoomWindowChanged) {
|
|
298
328
|
var _chartInstanceRef$cur4;
|
|
299
329
|
(_chartInstanceRef$cur4 = chartInstanceRef.current) === null || _chartInstanceRef$cur4 === void 0 || _chartInstanceRef$cur4.on("datazoom", handleDataZoom);
|
|
300
330
|
}
|
|
@@ -322,15 +352,15 @@ var ChartBar = function ChartBar(props) {
|
|
|
322
352
|
// Cleanup function
|
|
323
353
|
return function () {
|
|
324
354
|
window.removeEventListener("resize", handleResize);
|
|
325
|
-
if (
|
|
355
|
+
if (hasOnClick) {
|
|
326
356
|
var _chartInstanceRef$cur5;
|
|
327
|
-
(_chartInstanceRef$cur5 = chartInstanceRef.current) === null || _chartInstanceRef$cur5 === void 0 || _chartInstanceRef$cur5.off("click",
|
|
357
|
+
(_chartInstanceRef$cur5 = chartInstanceRef.current) === null || _chartInstanceRef$cur5 === void 0 || _chartInstanceRef$cur5.off("click", handleClick);
|
|
328
358
|
}
|
|
329
|
-
if (
|
|
359
|
+
if (hasOnLegendSelectChanged) {
|
|
330
360
|
var _chartInstanceRef$cur6;
|
|
331
361
|
(_chartInstanceRef$cur6 = chartInstanceRef.current) === null || _chartInstanceRef$cur6 === void 0 || _chartInstanceRef$cur6.off("legendselectchanged", handleLegendSelectChanged);
|
|
332
362
|
}
|
|
333
|
-
if (
|
|
363
|
+
if (hasOnDataZoomWindowChanged) {
|
|
334
364
|
var _chartInstanceRef$cur7;
|
|
335
365
|
(_chartInstanceRef$cur7 = chartInstanceRef.current) === null || _chartInstanceRef$cur7 === void 0 || _chartInstanceRef$cur7.off("datazoom", handleDataZoom);
|
|
336
366
|
}
|
|
@@ -339,7 +369,7 @@ var ChartBar = function ChartBar(props) {
|
|
|
339
369
|
legendScrollRef.current = null;
|
|
340
370
|
}
|
|
341
371
|
};
|
|
342
|
-
}, [chartOption, handleResize,
|
|
372
|
+
}, [chartOption, handleResize, onClickRef, onLegendSelectChangedRef, hasOnClick, hasOnLegendSelectChanged, hasOnDataZoomWindowChanged, emitZoomWindow, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval,
|
|
343
373
|
// 图例是否接管滚轮由它推导,漏了会拿到过期的滚动配置
|
|
344
374
|
normalizedScroll, containerReady]);
|
|
345
375
|
|
|
@@ -359,13 +389,13 @@ var ChartBar = function ChartBar(props) {
|
|
|
359
389
|
startIndex: normalizedScroll.startIndex,
|
|
360
390
|
autoPlay: normalizedScroll.autoScroll,
|
|
361
391
|
enableWheelScroll: enableWheelScroll,
|
|
362
|
-
onWindowChange:
|
|
363
|
-
return
|
|
392
|
+
onWindowChange: hasOnDataZoomWindowChanged ? function (startPercent, endPercent) {
|
|
393
|
+
return emitZoomWindow(percentWindowToIndexWindow(startPercent, endPercent, xAxisData.length));
|
|
364
394
|
} : undefined
|
|
365
395
|
}),
|
|
366
396
|
dispose = _autoScrollByItem.dispose;
|
|
367
397
|
return dispose;
|
|
368
|
-
}, [dataZoom, normalizedScroll, sliderDataZoom, xAxisData,
|
|
398
|
+
}, [dataZoom, normalizedScroll, sliderDataZoom, xAxisData, hasOnDataZoomWindowChanged, emitZoomWindow]);
|
|
369
399
|
|
|
370
400
|
// Clean up resources when the component unmounts
|
|
371
401
|
useEffect(function () {
|
|
@@ -21,6 +21,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
|
|
21
21
|
import styles from "../index.module.scss";
|
|
22
22
|
import * as echarts from "echarts";
|
|
23
23
|
import { defaultBubbleColorList, drawCircles } from "../_utils/bubble";
|
|
24
|
+
import { useLatestRef } from "../../../hooks/useLatestRef";
|
|
24
25
|
|
|
25
26
|
// Extended data item type containing all properties the chart needs
|
|
26
27
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -276,7 +277,16 @@ var Bubble = function Bubble(props) {
|
|
|
276
277
|
chartInstanceRef.current.setOption(chartOption, true);
|
|
277
278
|
}
|
|
278
279
|
}, [chartOption, data]);
|
|
280
|
+
var onChartRef = useLatestRef(onChart);
|
|
279
281
|
|
|
282
|
+
// onClick 不进依赖数组:消费方传内联箭头时每次渲染都是新引用,effect 跟着重跑就会
|
|
283
|
+
// 再走一遍 setOption(notMerge),动画重播、悬浮/高亮态被清掉。注册与否看布尔量,
|
|
284
|
+
// 这样「从无到有传入 onClick」仍会注册;实际调用取 ref 里的最新引用。
|
|
285
|
+
var onClickRef = useLatestRef(onClick);
|
|
286
|
+
var hasOnClick = !!onClick;
|
|
287
|
+
|
|
288
|
+
// 回调 prop 不进依赖数组:消费方传内联箭头时每次渲染都是新引用,effect 会跟着
|
|
289
|
+
// 重跑并再调一次回调 —— 回调里 setState 就是死循环(详见 Input/TextArea 的说明)
|
|
280
290
|
// Initialize the chart
|
|
281
291
|
useEffect(function () {
|
|
282
292
|
if (!chartRef.current) return;
|
|
@@ -286,10 +296,11 @@ var Bubble = function Bubble(props) {
|
|
|
286
296
|
// Initialize or reuse the existing instance
|
|
287
297
|
var chart = chartInstanceRef.current;
|
|
288
298
|
if (!chart) {
|
|
299
|
+
var _onChartRef$current;
|
|
289
300
|
chart = echarts.init(chartRef.current);
|
|
290
301
|
chartInstanceRef.current = chart;
|
|
291
302
|
// Call the onChart callback on first initialization
|
|
292
|
-
|
|
303
|
+
(_onChartRef$current = onChartRef.current) === null || _onChartRef$current === void 0 || _onChartRef$current.call(onChartRef, chart);
|
|
293
304
|
}
|
|
294
305
|
|
|
295
306
|
// Resize first so echarts picks up the correct container size, then apply the option
|
|
@@ -300,20 +311,24 @@ var Bubble = function Bubble(props) {
|
|
|
300
311
|
window.addEventListener("resize", handleResize);
|
|
301
312
|
|
|
302
313
|
// Add click event
|
|
303
|
-
|
|
314
|
+
var handleClick = function handleClick(event) {
|
|
315
|
+
var _onClickRef$current;
|
|
316
|
+
(_onClickRef$current = onClickRef.current) === null || _onClickRef$current === void 0 || _onClickRef$current.call(onClickRef, event);
|
|
317
|
+
};
|
|
318
|
+
if (hasOnClick) {
|
|
304
319
|
var _chartInstanceRef$cur2;
|
|
305
|
-
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click",
|
|
320
|
+
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click", handleClick);
|
|
306
321
|
}
|
|
307
322
|
|
|
308
323
|
// Cleanup function
|
|
309
324
|
return function () {
|
|
310
325
|
window.removeEventListener("resize", handleResize);
|
|
311
|
-
if (
|
|
326
|
+
if (hasOnClick) {
|
|
312
327
|
var _chartInstanceRef$cur3;
|
|
313
|
-
(_chartInstanceRef$cur3 = chartInstanceRef.current) === null || _chartInstanceRef$cur3 === void 0 || _chartInstanceRef$cur3.off("click",
|
|
328
|
+
(_chartInstanceRef$cur3 = chartInstanceRef.current) === null || _chartInstanceRef$cur3 === void 0 || _chartInstanceRef$cur3.off("click", handleClick);
|
|
314
329
|
}
|
|
315
330
|
};
|
|
316
|
-
}, [chartOption, containerSize.width, containerSize.height, handleResize,
|
|
331
|
+
}, [chartOption, containerSize.width, containerSize.height, handleResize, onChartRef, onClickRef, hasOnClick]);
|
|
317
332
|
|
|
318
333
|
// Dispose the chart instance when the component unmounts
|
|
319
334
|
useEffect(function () {
|
|
@@ -11,6 +11,7 @@ import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
|
|
11
11
|
import useContainerReady from "../_hooks/useContainerReady";
|
|
12
12
|
import styles from "../index.module.scss";
|
|
13
13
|
import * as echarts from "echarts";
|
|
14
|
+
import { useLatestRef } from "../../../hooks/useLatestRef";
|
|
14
15
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
15
16
|
var Common = function Common(props) {
|
|
16
17
|
var className = props.className,
|
|
@@ -38,9 +39,13 @@ var Common = function Common(props) {
|
|
|
38
39
|
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
39
40
|
(_chartInstanceRef$cur = chartInstanceRef.current) === null || _chartInstanceRef$cur === void 0 || _chartInstanceRef$cur.resize();
|
|
40
41
|
}, []);
|
|
42
|
+
var onChartRef = useLatestRef(onChart);
|
|
41
43
|
|
|
44
|
+
// 回调 prop 不进依赖数组:消费方传内联箭头时每次渲染都是新引用,effect 会跟着
|
|
45
|
+
// 重跑并再调一次回调 —— 回调里 setState 就是死循环(详见 Input/TextArea 的说明)
|
|
42
46
|
// Initialize the chart
|
|
43
47
|
useEffect(function () {
|
|
48
|
+
var _onChartRef$current;
|
|
44
49
|
if (!chartRef.current || !containerReady) return;
|
|
45
50
|
|
|
46
51
|
// Initialize or reuse an existing instance
|
|
@@ -54,7 +59,7 @@ var Common = function Common(props) {
|
|
|
54
59
|
chart.setOption(chartOption, true);
|
|
55
60
|
|
|
56
61
|
// Chart-ready callback (can be used for legend auto-scroll, etc.)
|
|
57
|
-
|
|
62
|
+
(_onChartRef$current = onChartRef.current) === null || _onChartRef$current === void 0 || _onChartRef$current.call(onChartRef, chart);
|
|
58
63
|
|
|
59
64
|
// Add resize listener
|
|
60
65
|
window.addEventListener("resize", handleResize);
|
|
@@ -69,7 +74,7 @@ var Common = function Common(props) {
|
|
|
69
74
|
return function () {
|
|
70
75
|
window.removeEventListener("resize", handleResize);
|
|
71
76
|
};
|
|
72
|
-
}, [chartOption, handleResize,
|
|
77
|
+
}, [chartOption, handleResize, onChartRef, containerReady]);
|
|
73
78
|
|
|
74
79
|
// Clean up resources on component unmount
|
|
75
80
|
useEffect(function () {
|
|
@@ -20,6 +20,7 @@ import * as echarts from "echarts";
|
|
|
20
20
|
import { createDefaultHeatmapXAxis, createDefaultHeatmapYAxis } from "../_utils/heatmap";
|
|
21
21
|
import { resolveChartChrome } from "../_utils/chartTheme";
|
|
22
22
|
import useIsDark from "../../../hooks/useIsDark";
|
|
23
|
+
import { useLatestRef } from "../../../hooks/useLatestRef";
|
|
23
24
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
25
|
var Heatmap = function Heatmap(props) {
|
|
25
26
|
var className = props.className,
|
|
@@ -192,7 +193,16 @@ var Heatmap = function Heatmap(props) {
|
|
|
192
193
|
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
193
194
|
(_chartInstanceRef$cur = chartInstanceRef.current) === null || _chartInstanceRef$cur === void 0 || _chartInstanceRef$cur.resize();
|
|
194
195
|
}, []);
|
|
196
|
+
var onChartRef = useLatestRef(onChart);
|
|
195
197
|
|
|
198
|
+
// onClick 不进依赖数组:消费方传内联箭头时每次渲染都是新引用,effect 跟着重跑就会
|
|
199
|
+
// 再走一遍 setOption(notMerge),动画重播、悬浮/高亮态被清掉。注册与否看布尔量,
|
|
200
|
+
// 这样「从无到有传入 onClick」仍会注册;实际调用取 ref 里的最新引用。
|
|
201
|
+
var onClickRef = useLatestRef(onClick);
|
|
202
|
+
var hasOnClick = !!onClick;
|
|
203
|
+
|
|
204
|
+
// 回调 prop 不进依赖数组:消费方传内联箭头时每次渲染都是新引用,effect 会跟着
|
|
205
|
+
// 重跑并再调一次回调 —— 回调里 setState 就是死循环(详见 Input/TextArea 的说明)
|
|
196
206
|
// Initialize the chart
|
|
197
207
|
useEffect(function () {
|
|
198
208
|
if (!chartRef.current || !containerReady) return;
|
|
@@ -200,10 +210,11 @@ var Heatmap = function Heatmap(props) {
|
|
|
200
210
|
// Initialize or reuse the existing instance
|
|
201
211
|
var chart = chartInstanceRef.current;
|
|
202
212
|
if (!chart) {
|
|
213
|
+
var _onChartRef$current;
|
|
203
214
|
chart = echarts.init(chartRef.current);
|
|
204
215
|
chartInstanceRef.current = chart;
|
|
205
216
|
// Call the onChart callback on first initialization
|
|
206
|
-
|
|
217
|
+
(_onChartRef$current = onChartRef.current) === null || _onChartRef$current === void 0 || _onChartRef$current.call(onChartRef, chart);
|
|
207
218
|
}
|
|
208
219
|
|
|
209
220
|
// Apply the option
|
|
@@ -219,20 +230,24 @@ var Heatmap = function Heatmap(props) {
|
|
|
219
230
|
}
|
|
220
231
|
|
|
221
232
|
// Add click event
|
|
222
|
-
|
|
233
|
+
var handleClick = function handleClick(event) {
|
|
234
|
+
var _onClickRef$current;
|
|
235
|
+
(_onClickRef$current = onClickRef.current) === null || _onClickRef$current === void 0 || _onClickRef$current.call(onClickRef, event);
|
|
236
|
+
};
|
|
237
|
+
if (hasOnClick) {
|
|
223
238
|
var _chartInstanceRef$cur2;
|
|
224
|
-
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click",
|
|
239
|
+
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click", handleClick);
|
|
225
240
|
}
|
|
226
241
|
|
|
227
242
|
// Cleanup function
|
|
228
243
|
return function () {
|
|
229
244
|
window.removeEventListener("resize", handleResize);
|
|
230
|
-
if (
|
|
245
|
+
if (hasOnClick) {
|
|
231
246
|
var _chartInstanceRef$cur3;
|
|
232
|
-
(_chartInstanceRef$cur3 = chartInstanceRef.current) === null || _chartInstanceRef$cur3 === void 0 || _chartInstanceRef$cur3.off("click",
|
|
247
|
+
(_chartInstanceRef$cur3 = chartInstanceRef.current) === null || _chartInstanceRef$cur3 === void 0 || _chartInstanceRef$cur3.off("click", handleClick);
|
|
233
248
|
}
|
|
234
249
|
};
|
|
235
|
-
}, [chartOption, handleResize,
|
|
250
|
+
}, [chartOption, handleResize, onChartRef, onClickRef, hasOnClick, containerReady]);
|
|
236
251
|
|
|
237
252
|
// Clean up resources when the component unmounts
|
|
238
253
|
useEffect(function () {
|
|
@@ -16,6 +16,7 @@ import { autoScrollByItem } from "../_utils/autoSmooth";
|
|
|
16
16
|
import { buildCartesianSeriesOptions, createDefaultCategoryXAxis, createDefaultValueYAxis, getSliderShow, percentWindowToIndexWindow, resolveScrollConfig } from "../_utils/cartesian";
|
|
17
17
|
import { resolveChartChrome } from "../_utils/chartTheme";
|
|
18
18
|
import useIsDark from "../../../hooks/useIsDark";
|
|
19
|
+
import useLatestRef from "../../../hooks/useLatestRef";
|
|
19
20
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
21
|
var ChartLine = function ChartLine(props) {
|
|
21
22
|
var className = props.className,
|
|
@@ -62,6 +63,30 @@ var ChartLine = function ChartLine(props) {
|
|
|
62
63
|
return resolveChartChrome(isDark);
|
|
63
64
|
}, [isDark]);
|
|
64
65
|
|
|
66
|
+
// 回调 prop 一律走 useLatestRef,不进依赖数组:消费方传内联箭头(React 里最常见的
|
|
67
|
+
// 写法)时每次渲染都是新引用,进依赖数组会让「init + setOption(notMerge)」整段重跑,
|
|
68
|
+
// 还会把当前可视窗口再同步一次给父级 —— 父级据此改 state 就是死循环。
|
|
69
|
+
// 但「有没有传回调」决定要不要注册监听,所以单独拆成布尔量进依赖数组,
|
|
70
|
+
// 这样「从无到有传入回调」仍会重新注册,不会漏。
|
|
71
|
+
var onClickRef = useLatestRef(onClick);
|
|
72
|
+
var onLegendSelectChangedRef = useLatestRef(onLegendSelectChanged);
|
|
73
|
+
var onDataZoomWindowChangedRef = useLatestRef(onDataZoomWindowChanged);
|
|
74
|
+
var hasOnClick = !!onClick;
|
|
75
|
+
var hasOnLegendSelectChanged = !!onLegendSelectChanged;
|
|
76
|
+
var hasOnDataZoomWindowChanged = !!onDataZoomWindowChanged;
|
|
77
|
+
// 已通知过父级的窗口用 ref 记账(不参与渲染):窗口没变就不再通知,
|
|
78
|
+
// 掐断「通知 → 父级重算坐标轴 → chartOption 变 → effect 重跑 → 再通知」的自激回路
|
|
79
|
+
var notifiedZoomWindowRef = useRef(null);
|
|
80
|
+
var emitZoomWindow = useCallback(function (next) {
|
|
81
|
+
var _onDataZoomWindowChan;
|
|
82
|
+
var prev = notifiedZoomWindowRef.current;
|
|
83
|
+
if (prev && prev.startIndex === next.startIndex && prev.endIndex === next.endIndex) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
notifiedZoomWindowRef.current = next;
|
|
87
|
+
(_onDataZoomWindowChan = onDataZoomWindowChangedRef.current) === null || _onDataZoomWindowChan === void 0 || _onDataZoomWindowChan.call(onDataZoomWindowChangedRef, next);
|
|
88
|
+
}, [onDataZoomWindowChangedRef]);
|
|
89
|
+
|
|
65
90
|
// Cache the chart option with useMemo
|
|
66
91
|
var chartOption = useMemo(function () {
|
|
67
92
|
var _xAxisData$length, _ref, _ref2;
|
|
@@ -236,16 +261,16 @@ var ChartLine = function ChartLine(props) {
|
|
|
236
261
|
}
|
|
237
262
|
|
|
238
263
|
// Sync the current visible window to the caller (on initial render and after restore), used to recalculate axes based on the displayed portion
|
|
239
|
-
if (
|
|
264
|
+
if (hasOnDataZoomWindowChanged) {
|
|
240
265
|
var _chart$getOption3, _xAxisData$length2;
|
|
241
266
|
var zooms = (_chart$getOption3 = chart.getOption()) === null || _chart$getOption3 === void 0 ? void 0 : _chart$getOption3.dataZoom;
|
|
242
267
|
var zoom = zooms === null || zooms === void 0 ? void 0 : zooms[0];
|
|
243
268
|
var totalLen = (_xAxisData$length2 = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.length) !== null && _xAxisData$length2 !== void 0 ? _xAxisData$length2 : 0;
|
|
244
269
|
if (typeof (zoom === null || zoom === void 0 ? void 0 : zoom.start) === "number" && typeof (zoom === null || zoom === void 0 ? void 0 : zoom.end) === "number") {
|
|
245
|
-
|
|
270
|
+
emitZoomWindow(percentWindowToIndexWindow(zoom.start, zoom.end, totalLen));
|
|
246
271
|
} else {
|
|
247
272
|
// Without dataZoom (e.g. scrolling not enabled due to insufficient data) the window is the full range; sync once to avoid a stale old window
|
|
248
|
-
|
|
273
|
+
emitZoomWindow({
|
|
249
274
|
startIndex: 0,
|
|
250
275
|
endIndex: Math.max(0, totalLen - 1)
|
|
251
276
|
});
|
|
@@ -261,17 +286,22 @@ var ChartLine = function ChartLine(props) {
|
|
|
261
286
|
resizeObserverRef.current.observe(chartRef.current);
|
|
262
287
|
}
|
|
263
288
|
|
|
264
|
-
// Add click event
|
|
265
|
-
|
|
289
|
+
// Add click event(注册与否看布尔量,实际调用取最新引用)
|
|
290
|
+
var handleClick = function handleClick(event) {
|
|
291
|
+
var _onClickRef$current;
|
|
292
|
+
(_onClickRef$current = onClickRef.current) === null || _onClickRef$current === void 0 || _onClickRef$current.call(onClickRef, event);
|
|
293
|
+
};
|
|
294
|
+
if (hasOnClick) {
|
|
266
295
|
var _chartInstanceRef$cur2;
|
|
267
|
-
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click",
|
|
296
|
+
(_chartInstanceRef$cur2 = chartInstanceRef.current) === null || _chartInstanceRef$cur2 === void 0 || _chartInstanceRef$cur2.on("click", handleClick);
|
|
268
297
|
}
|
|
269
298
|
|
|
270
299
|
// Legend selection event
|
|
271
300
|
var handleLegendSelectChanged = function handleLegendSelectChanged(params) {
|
|
272
|
-
|
|
301
|
+
var _onLegendSelectChange;
|
|
302
|
+
(_onLegendSelectChange = onLegendSelectChangedRef.current) === null || _onLegendSelectChange === void 0 || _onLegendSelectChange.call(onLegendSelectChangedRef, params.selected);
|
|
273
303
|
};
|
|
274
|
-
if (
|
|
304
|
+
if (hasOnLegendSelectChanged) {
|
|
275
305
|
var _chartInstanceRef$cur3;
|
|
276
306
|
(_chartInstanceRef$cur3 = chartInstanceRef.current) === null || _chartInstanceRef$cur3 === void 0 || _chartInstanceRef$cur3.on("legendselectchanged", handleLegendSelectChanged);
|
|
277
307
|
}
|
|
@@ -282,16 +312,16 @@ var ChartLine = function ChartLine(props) {
|
|
|
282
312
|
var raw = params;
|
|
283
313
|
var info = (_raw$batch$ = raw === null || raw === void 0 || (_raw$batch = raw.batch) === null || _raw$batch === void 0 ? void 0 : _raw$batch[0]) !== null && _raw$batch$ !== void 0 ? _raw$batch$ : raw;
|
|
284
314
|
if (typeof (info === null || info === void 0 ? void 0 : info.startValue) === "number" && typeof (info === null || info === void 0 ? void 0 : info.endValue) === "number") {
|
|
285
|
-
|
|
315
|
+
emitZoomWindow({
|
|
286
316
|
startIndex: Math.max(0, Math.round(info.startValue)),
|
|
287
317
|
endIndex: Math.max(0, Math.round(info.endValue))
|
|
288
318
|
});
|
|
289
319
|
} else if (typeof (info === null || info === void 0 ? void 0 : info.start) === "number" && typeof (info === null || info === void 0 ? void 0 : info.end) === "number") {
|
|
290
320
|
var _xAxisData$length3;
|
|
291
|
-
|
|
321
|
+
emitZoomWindow(percentWindowToIndexWindow(info.start, info.end, (_xAxisData$length3 = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.length) !== null && _xAxisData$length3 !== void 0 ? _xAxisData$length3 : 0));
|
|
292
322
|
}
|
|
293
323
|
};
|
|
294
|
-
if (
|
|
324
|
+
if (hasOnDataZoomWindowChanged) {
|
|
295
325
|
var _chartInstanceRef$cur4;
|
|
296
326
|
(_chartInstanceRef$cur4 = chartInstanceRef.current) === null || _chartInstanceRef$cur4 === void 0 || _chartInstanceRef$cur4.on("datazoom", handleDataZoom);
|
|
297
327
|
}
|
|
@@ -319,15 +349,15 @@ var ChartLine = function ChartLine(props) {
|
|
|
319
349
|
// Cleanup function
|
|
320
350
|
return function () {
|
|
321
351
|
window.removeEventListener("resize", handleResize);
|
|
322
|
-
if (
|
|
352
|
+
if (hasOnClick) {
|
|
323
353
|
var _chartInstanceRef$cur5;
|
|
324
|
-
(_chartInstanceRef$cur5 = chartInstanceRef.current) === null || _chartInstanceRef$cur5 === void 0 || _chartInstanceRef$cur5.off("click",
|
|
354
|
+
(_chartInstanceRef$cur5 = chartInstanceRef.current) === null || _chartInstanceRef$cur5 === void 0 || _chartInstanceRef$cur5.off("click", handleClick);
|
|
325
355
|
}
|
|
326
|
-
if (
|
|
356
|
+
if (hasOnLegendSelectChanged) {
|
|
327
357
|
var _chartInstanceRef$cur6;
|
|
328
358
|
(_chartInstanceRef$cur6 = chartInstanceRef.current) === null || _chartInstanceRef$cur6 === void 0 || _chartInstanceRef$cur6.off("legendselectchanged", handleLegendSelectChanged);
|
|
329
359
|
}
|
|
330
|
-
if (
|
|
360
|
+
if (hasOnDataZoomWindowChanged) {
|
|
331
361
|
var _chartInstanceRef$cur7;
|
|
332
362
|
(_chartInstanceRef$cur7 = chartInstanceRef.current) === null || _chartInstanceRef$cur7 === void 0 || _chartInstanceRef$cur7.off("datazoom", handleDataZoom);
|
|
333
363
|
}
|
|
@@ -336,7 +366,7 @@ var ChartLine = function ChartLine(props) {
|
|
|
336
366
|
legendScrollRef.current = null;
|
|
337
367
|
}
|
|
338
368
|
};
|
|
339
|
-
}, [chartOption, handleResize,
|
|
369
|
+
}, [chartOption, handleResize, onClickRef, onLegendSelectChangedRef, hasOnClick, hasOnLegendSelectChanged, hasOnDataZoomWindowChanged, emitZoomWindow, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval,
|
|
340
370
|
// 图例是否接管滚轮由它推导,漏了会拿到过期的滚动配置
|
|
341
371
|
normalizedScroll, containerReady]);
|
|
342
372
|
|
|
@@ -356,13 +386,13 @@ var ChartLine = function ChartLine(props) {
|
|
|
356
386
|
startIndex: normalizedScroll.startIndex,
|
|
357
387
|
autoPlay: normalizedScroll.autoScroll,
|
|
358
388
|
enableWheelScroll: enableWheelScroll,
|
|
359
|
-
onWindowChange:
|
|
360
|
-
return
|
|
389
|
+
onWindowChange: hasOnDataZoomWindowChanged ? function (startPercent, endPercent) {
|
|
390
|
+
return emitZoomWindow(percentWindowToIndexWindow(startPercent, endPercent, xAxisData.length));
|
|
361
391
|
} : undefined
|
|
362
392
|
}),
|
|
363
393
|
dispose = _autoScrollByItem.dispose;
|
|
364
394
|
return dispose;
|
|
365
|
-
}, [dataZoom, normalizedScroll, sliderDataZoom, xAxisData,
|
|
395
|
+
}, [dataZoom, normalizedScroll, sliderDataZoom, xAxisData, hasOnDataZoomWindowChanged, emitZoomWindow]);
|
|
366
396
|
|
|
367
397
|
// Clean up resources when the component unmounts
|
|
368
398
|
useEffect(function () {
|
|
@@ -8,6 +8,7 @@ import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
|
|
8
8
|
import { useMouseOverHandler, useGlobalOutHandler } from "./_hooks";
|
|
9
9
|
import { getPie3DOption } from "./_utils/option";
|
|
10
10
|
import styles from "../../index.module.scss";
|
|
11
|
+
import { useLatestRef } from "../../../../hooks/useLatestRef";
|
|
11
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
13
|
var ChartPie3D = function ChartPie3D(props) {
|
|
13
14
|
var className = props.className,
|
|
@@ -89,13 +90,24 @@ var ChartPie3D = function ChartPie3D(props) {
|
|
|
89
90
|
yOffset: yOffset,
|
|
90
91
|
autoRotate: autoRotate
|
|
91
92
|
});
|
|
93
|
+
var onChartRef = useLatestRef(onChart);
|
|
94
|
+
|
|
95
|
+
// onClick 不进依赖数组:消费方传内联箭头时每次渲染都是新引用,effect 跟着重跑会重建
|
|
96
|
+
// 3D 饼的 option 并重播动画。注册与否看布尔量(保证「从无到有传入」仍会注册),
|
|
97
|
+
// 实际调用取 ref 里的最新引用。
|
|
98
|
+
var onClickRef = useLatestRef(onClick);
|
|
99
|
+
var hasOnClick = !!onClick;
|
|
100
|
+
|
|
101
|
+
// 回调 prop 不进依赖数组:消费方传内联箭头时每次渲染都是新引用,effect 会跟着
|
|
102
|
+
// 重跑并再调一次回调 —— 回调里 setState 就是死循环(详见 Input/TextArea 的说明)
|
|
92
103
|
useEffect(function () {
|
|
93
104
|
if (!chartRef.current || !containerReady) return;
|
|
94
105
|
var chart = chartInstanceRef.current;
|
|
95
106
|
if (!chart) {
|
|
107
|
+
var _onChartRef$current;
|
|
96
108
|
chart = echarts.init(chartRef.current);
|
|
97
109
|
chartInstanceRef.current = chart;
|
|
98
|
-
|
|
110
|
+
(_onChartRef$current = onChartRef.current) === null || _onChartRef$current === void 0 || _onChartRef$current.call(onChartRef, chart);
|
|
99
111
|
}
|
|
100
112
|
chart.setOption(chartOption, true);
|
|
101
113
|
optionRef.current = chartOption;
|
|
@@ -106,20 +118,24 @@ var ChartPie3D = function ChartPie3D(props) {
|
|
|
106
118
|
}
|
|
107
119
|
chart.on("mouseover", handleMouseOver);
|
|
108
120
|
chart.on("globalout", handleGlobalOut);
|
|
109
|
-
|
|
110
|
-
|
|
121
|
+
var handleClick = function handleClick(event) {
|
|
122
|
+
var _onClickRef$current;
|
|
123
|
+
(_onClickRef$current = onClickRef.current) === null || _onClickRef$current === void 0 || _onClickRef$current.call(onClickRef, event);
|
|
124
|
+
};
|
|
125
|
+
if (hasOnClick) {
|
|
126
|
+
chart.on("click", handleClick);
|
|
111
127
|
}
|
|
112
128
|
return function () {
|
|
113
129
|
window.removeEventListener("resize", handleResize);
|
|
114
130
|
if (chart) {
|
|
115
131
|
chart.off("mouseover", handleMouseOver);
|
|
116
132
|
chart.off("globalout", handleGlobalOut);
|
|
117
|
-
if (
|
|
118
|
-
chart.off("click",
|
|
133
|
+
if (hasOnClick) {
|
|
134
|
+
chart.off("click", handleClick);
|
|
119
135
|
}
|
|
120
136
|
}
|
|
121
137
|
};
|
|
122
|
-
}, [chartOption, handleResize, handleMouseOver, handleGlobalOut,
|
|
138
|
+
}, [chartOption, handleResize, handleMouseOver, handleGlobalOut, onChartRef, onClickRef, hasOnClick, containerReady]);
|
|
123
139
|
useEffect(function () {
|
|
124
140
|
return function () {
|
|
125
141
|
if (resizeObserverRef.current) {
|