@hsu-react/ui 2.4.1 → 2.4.3
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/Chart/Bar/index.js +9 -2
- package/es/components/Chart/Common/index.js +9 -2
- package/es/components/Chart/Gauge/index.js +9 -2
- package/es/components/Chart/Heatmap/index.js +9 -2
- package/es/components/Chart/Line/index.js +9 -2
- package/es/components/Chart/Pie/Pie3D/index.js +9 -2
- package/es/components/Chart/Pie/index.js +9 -2
- package/es/components/Chart/Polar/index.js +9 -2
- package/es/components/Chart/Radar/index.js +9 -2
- package/es/components/Chart/Sankey/index.js +9 -2
- package/es/components/Chart/Tree/index.js +9 -2
- package/es/components/Chart/_hooks/useContainerReady.d.ts +18 -0
- package/es/components/Chart/_hooks/useContainerReady.js +56 -0
- package/es/layout/NavTabBar/_hooks/useTabPath.js +45 -8
- package/lib/components/Chart/Bar/index.js +9 -2
- package/lib/components/Chart/Common/index.js +9 -2
- package/lib/components/Chart/Gauge/index.js +9 -2
- package/lib/components/Chart/Heatmap/index.js +9 -2
- package/lib/components/Chart/Line/index.js +9 -2
- package/lib/components/Chart/Pie/Pie3D/index.js +9 -2
- package/lib/components/Chart/Pie/index.js +9 -2
- package/lib/components/Chart/Polar/index.js +9 -2
- package/lib/components/Chart/Radar/index.js +9 -2
- package/lib/components/Chart/Sankey/index.js +9 -2
- package/lib/components/Chart/Tree/index.js +9 -2
- package/lib/components/Chart/_hooks/useContainerReady.d.ts +18 -0
- package/lib/components/Chart/_hooks/useContainerReady.js +51 -0
- package/lib/layout/NavTabBar/_hooks/useTabPath.js +42 -7
- package/package.json +1 -1
- package/src/components/Chart/Bar/index.tsx +10 -1
- package/src/components/Chart/Common/index.tsx +12 -2
- package/src/components/Chart/Gauge/index.tsx +12 -2
- package/src/components/Chart/Heatmap/index.tsx +12 -2
- package/src/components/Chart/Line/index.tsx +10 -1
- package/src/components/Chart/Pie/Pie3D/index.tsx +10 -1
- package/src/components/Chart/Pie/index.tsx +10 -1
- package/src/components/Chart/Polar/index.tsx +12 -2
- package/src/components/Chart/Radar/index.tsx +10 -1
- package/src/components/Chart/Sankey/index.tsx +12 -2
- package/src/components/Chart/Tree/index.tsx +12 -2
- package/src/components/Chart/_hooks/useContainerReady.ts +50 -0
- package/src/layout/NavTabBar/_hooks/useTabPath.ts +43 -10
|
@@ -14,7 +14,7 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
|
|
|
14
14
|
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; }
|
|
15
15
|
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; } }
|
|
16
16
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
17
|
-
import { useCallback, useEffect, useState } from "react";
|
|
17
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
18
18
|
import { useLocation } from "react-router";
|
|
19
19
|
import { checkTabPathMatch } from "../_utils/pathMatch";
|
|
20
20
|
import { array_is_includes } from "hsu-utils";
|
|
@@ -25,6 +25,19 @@ export var useTabPath = function useTabPath(_ref) {
|
|
|
25
25
|
var items = _ref.items,
|
|
26
26
|
affixRouter = _ref.affixRouter;
|
|
27
27
|
var location = useLocation();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Keyed on the *contents* of `affixRouter`, not on the array itself.
|
|
31
|
+
*
|
|
32
|
+
* Callers pass an inline literal (`affixRouter={[HOME]}`), and omitting the prop hands the
|
|
33
|
+
* component a fresh `[]` default on every render — either way the array identity changes each
|
|
34
|
+
* time. Depending on it directly re-runs the effect below on every render, and that effect
|
|
35
|
+
* calls setState, so the whole thing becomes a render loop.
|
|
36
|
+
*/
|
|
37
|
+
var affixKey = affixRouter.join("\x01");
|
|
38
|
+
var affixSet = useMemo(function () {
|
|
39
|
+
return new Set(affixKey ? affixKey.split("\x01") : []);
|
|
40
|
+
}, [affixKey]);
|
|
28
41
|
var _useState = useState(""),
|
|
29
42
|
_useState2 = _slicedToArray(_useState, 2),
|
|
30
43
|
tabKey = _useState2[0],
|
|
@@ -43,7 +56,7 @@ export var useTabPath = function useTabPath(_ref) {
|
|
|
43
56
|
_checkAffix(item.children);
|
|
44
57
|
} else {
|
|
45
58
|
// Check whether it is an affixed route
|
|
46
|
-
var isAffix =
|
|
59
|
+
var isAffix = affixSet.has(item.key) || item.affix;
|
|
47
60
|
if (isAffix) {
|
|
48
61
|
setOpenkeys(function (prev) {
|
|
49
62
|
var find = prev.find(function (i) {
|
|
@@ -57,7 +70,7 @@ export var useTabPath = function useTabPath(_ref) {
|
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
});
|
|
60
|
-
}, [
|
|
73
|
+
}, [affixSet]);
|
|
61
74
|
var _checkPath = useCallback(function (items, parents) {
|
|
62
75
|
var pathname = decodeURI(location.pathname);
|
|
63
76
|
var search = location.search;
|
|
@@ -79,36 +92,48 @@ export var useTabPath = function useTabPath(_ref) {
|
|
|
79
92
|
// Handle param routes
|
|
80
93
|
setTabKey("".concat(pathname).concat(search));
|
|
81
94
|
setOpenkeys(function (prev) {
|
|
95
|
+
var nextKey = "".concat(pathname).concat(search);
|
|
82
96
|
var find = prev.find(function (i) {
|
|
83
97
|
return i.key.split("?")[0] === pathname;
|
|
84
98
|
});
|
|
85
99
|
if (find) {
|
|
100
|
+
// Already on this key: return `prev` untouched. `map` builds a new array
|
|
101
|
+
// every time, and React treats a new reference as a state change — which is
|
|
102
|
+
// the other half of the render loop above.
|
|
103
|
+
if (find.key === nextKey) {
|
|
104
|
+
return prev;
|
|
105
|
+
}
|
|
86
106
|
return prev.map(function (i) {
|
|
87
107
|
return i.key.split("?")[0] === pathname ? _objectSpread(_objectSpread({}, i), {}, {
|
|
88
|
-
key:
|
|
108
|
+
key: nextKey
|
|
89
109
|
}) : i;
|
|
90
110
|
});
|
|
91
111
|
}
|
|
92
112
|
return [].concat(_toConsumableArray(prev), [_objectSpread(_objectSpread({}, item), {}, {
|
|
93
|
-
key:
|
|
113
|
+
key: nextKey
|
|
94
114
|
})]);
|
|
95
115
|
});
|
|
96
116
|
} else {
|
|
97
117
|
// Handle plain routes
|
|
98
118
|
setTabKey("".concat(item.key).concat(search));
|
|
99
119
|
setOpenkeys(function (prev) {
|
|
120
|
+
var nextKey = "".concat(item.key).concat(search);
|
|
100
121
|
var find = prev.find(function (i) {
|
|
101
122
|
return i.key.split("?")[0] === item.key;
|
|
102
123
|
});
|
|
103
124
|
if (find) {
|
|
125
|
+
// Same as above: an unchanged tab must not produce a new reference
|
|
126
|
+
if (find.key === nextKey) {
|
|
127
|
+
return prev;
|
|
128
|
+
}
|
|
104
129
|
return prev.map(function (i) {
|
|
105
130
|
return i.key.split("?")[0] === item.key ? _objectSpread(_objectSpread({}, i), {}, {
|
|
106
|
-
key:
|
|
131
|
+
key: nextKey
|
|
107
132
|
}) : i;
|
|
108
133
|
});
|
|
109
134
|
}
|
|
110
135
|
return [].concat(_toConsumableArray(prev), [_objectSpread(_objectSpread({}, item), {}, {
|
|
111
|
-
key:
|
|
136
|
+
key: nextKey
|
|
112
137
|
})]);
|
|
113
138
|
});
|
|
114
139
|
}
|
|
@@ -116,12 +141,24 @@ export var useTabPath = function useTabPath(_ref) {
|
|
|
116
141
|
}
|
|
117
142
|
});
|
|
118
143
|
}, [location.pathname, location.search]);
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Closing the last tab navigates to `basePath` — but when that tab *was* `basePath`, the
|
|
147
|
+
* location never changes, so path matching would not re-run and the bar would be left empty
|
|
148
|
+
* while its page is still on screen. Going empty has to re-trigger the match on its own.
|
|
149
|
+
*
|
|
150
|
+
* This settles rather than looping: re-matching adds the tab back, which flips `isEmpty` and
|
|
151
|
+
* runs the effect once more, and that pass finds the tab already present and returns the same
|
|
152
|
+
* state object — so React stops there. (Only true because the setters below bail out when
|
|
153
|
+
* nothing changed; without that this would spin.)
|
|
154
|
+
*/
|
|
155
|
+
var isEmpty = openKeys.length === 0;
|
|
119
156
|
useEffect(function () {
|
|
120
157
|
// Handle affixed routes first to populate openKeys
|
|
121
158
|
_checkAffix(items);
|
|
122
159
|
// Then run path matching
|
|
123
160
|
_checkPath(items);
|
|
124
|
-
}, [_checkAffix, _checkPath, items]);
|
|
161
|
+
}, [_checkAffix, _checkPath, items, isEmpty]);
|
|
125
162
|
return {
|
|
126
163
|
tabKey: tabKey,
|
|
127
164
|
setTabKey: setTabKey,
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
10
11
|
var _autoScrollLegend = require("../_utils/autoScrollLegend");
|
|
@@ -45,6 +46,8 @@ const ChartBar = props => {
|
|
|
45
46
|
} = props;
|
|
46
47
|
const chartRef = (0, _react.useRef)(null);
|
|
47
48
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
49
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
50
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
48
51
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
49
52
|
const prevXAxisKeyRef = (0, _react.useRef)(null);
|
|
50
53
|
const legendScrollRef = (0, _react.useRef)(null);
|
|
@@ -192,12 +195,16 @@ const ChartBar = props => {
|
|
|
192
195
|
|
|
193
196
|
// Callback for handling chart resize
|
|
194
197
|
const handleResize = (0, _react.useCallback)(() => {
|
|
198
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
199
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
200
|
+
const el = chartRef.current;
|
|
201
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
195
202
|
chartInstanceRef.current?.resize();
|
|
196
203
|
}, []);
|
|
197
204
|
|
|
198
205
|
// Initialize the chart
|
|
199
206
|
(0, _react.useEffect)(() => {
|
|
200
|
-
if (!chartRef.current) return;
|
|
207
|
+
if (!chartRef.current || !containerReady) return;
|
|
201
208
|
|
|
202
209
|
// Initialize or reuse the existing instance
|
|
203
210
|
let chart = chartInstanceRef.current;
|
|
@@ -327,7 +334,7 @@ const ChartBar = props => {
|
|
|
327
334
|
};
|
|
328
335
|
}, [chartOption, handleResize, onClick, onLegendSelectChanged, onDataZoomWindowChanged, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval,
|
|
329
336
|
// 图例是否接管滚轮由它推导,漏了会拿到过期的滚动配置
|
|
330
|
-
normalizedScroll]);
|
|
337
|
+
normalizedScroll, containerReady]);
|
|
331
338
|
|
|
332
339
|
// Handle auto play
|
|
333
340
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
9
10
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
10
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -20,6 +21,8 @@ const Common = props => {
|
|
|
20
21
|
} = props;
|
|
21
22
|
const chartRef = (0, _react.useRef)(null);
|
|
22
23
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
24
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
25
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
23
26
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
24
27
|
|
|
25
28
|
// Cache the chart configuration with useMemo
|
|
@@ -32,12 +35,16 @@ const Common = props => {
|
|
|
32
35
|
|
|
33
36
|
// Callback that handles chart resize
|
|
34
37
|
const handleResize = (0, _react.useCallback)(() => {
|
|
38
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
39
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
40
|
+
const el = chartRef.current;
|
|
41
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
35
42
|
chartInstanceRef.current?.resize();
|
|
36
43
|
}, []);
|
|
37
44
|
|
|
38
45
|
// Initialize the chart
|
|
39
46
|
(0, _react.useEffect)(() => {
|
|
40
|
-
if (!chartRef.current) return;
|
|
47
|
+
if (!chartRef.current || !containerReady) return;
|
|
41
48
|
|
|
42
49
|
// Initialize or reuse an existing instance
|
|
43
50
|
let chart = chartInstanceRef.current;
|
|
@@ -65,7 +72,7 @@ const Common = props => {
|
|
|
65
72
|
return () => {
|
|
66
73
|
window.removeEventListener("resize", handleResize);
|
|
67
74
|
};
|
|
68
|
-
}, [chartOption, handleResize, onChart]);
|
|
75
|
+
}, [chartOption, handleResize, onChart, containerReady]);
|
|
69
76
|
|
|
70
77
|
// Clean up resources on component unmount
|
|
71
78
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
10
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -32,6 +33,8 @@ const Gauge = props => {
|
|
|
32
33
|
} = series;
|
|
33
34
|
const chartRef = (0, _react.useRef)(null);
|
|
34
35
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
36
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
37
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
35
38
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
36
39
|
|
|
37
40
|
// Cache the chart option with useMemo
|
|
@@ -92,12 +95,16 @@ const Gauge = props => {
|
|
|
92
95
|
|
|
93
96
|
// Callback for handling chart resize
|
|
94
97
|
const handleResize = (0, _react.useCallback)(() => {
|
|
98
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
99
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
100
|
+
const el = chartRef.current;
|
|
101
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
95
102
|
chartInstanceRef.current?.resize();
|
|
96
103
|
}, []);
|
|
97
104
|
|
|
98
105
|
// Initialize the chart
|
|
99
106
|
(0, _react.useEffect)(() => {
|
|
100
|
-
if (!chartRef.current) return;
|
|
107
|
+
if (!chartRef.current || !containerReady) return;
|
|
101
108
|
|
|
102
109
|
// Initialize or reuse the existing instance
|
|
103
110
|
let chart = chartInstanceRef.current;
|
|
@@ -122,7 +129,7 @@ const Gauge = props => {
|
|
|
122
129
|
return () => {
|
|
123
130
|
window.removeEventListener("resize", handleResize);
|
|
124
131
|
};
|
|
125
|
-
}, [chartOption, handleResize]);
|
|
132
|
+
}, [chartOption, handleResize, containerReady]);
|
|
126
133
|
|
|
127
134
|
// Clean up resources when the component unmounts
|
|
128
135
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
9
10
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
10
11
|
var _heatmap = require("../_utils/heatmap");
|
|
@@ -37,6 +38,8 @@ const Heatmap = props => {
|
|
|
37
38
|
} = props;
|
|
38
39
|
const chartRef = (0, _react.useRef)(null);
|
|
39
40
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
41
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
42
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
40
43
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
41
44
|
// echarts options are plain JS and cannot read the `--vita-*` variables, so the axis and legend
|
|
42
45
|
// colours have to be resolved against the active appearance here
|
|
@@ -182,12 +185,16 @@ const Heatmap = props => {
|
|
|
182
185
|
|
|
183
186
|
// Callback for handling chart resize
|
|
184
187
|
const handleResize = (0, _react.useCallback)(() => {
|
|
188
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
189
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
190
|
+
const el = chartRef.current;
|
|
191
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
185
192
|
chartInstanceRef.current?.resize();
|
|
186
193
|
}, []);
|
|
187
194
|
|
|
188
195
|
// Initialize the chart
|
|
189
196
|
(0, _react.useEffect)(() => {
|
|
190
|
-
if (!chartRef.current) return;
|
|
197
|
+
if (!chartRef.current || !containerReady) return;
|
|
191
198
|
|
|
192
199
|
// Initialize or reuse the existing instance
|
|
193
200
|
let chart = chartInstanceRef.current;
|
|
@@ -222,7 +229,7 @@ const Heatmap = props => {
|
|
|
222
229
|
chartInstanceRef.current?.off("click", onClick);
|
|
223
230
|
}
|
|
224
231
|
};
|
|
225
|
-
}, [chartOption, handleResize, onChart, onClick]);
|
|
232
|
+
}, [chartOption, handleResize, onChart, onClick, containerReady]);
|
|
226
233
|
|
|
227
234
|
// Clean up resources when the component unmounts
|
|
228
235
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
10
11
|
var _autoScrollLegend = require("../_utils/autoScrollLegend");
|
|
@@ -45,6 +46,8 @@ const ChartLine = props => {
|
|
|
45
46
|
} = props;
|
|
46
47
|
const chartRef = (0, _react.useRef)(null);
|
|
47
48
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
49
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
50
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
48
51
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
49
52
|
const prevXAxisKeyRef = (0, _react.useRef)(null);
|
|
50
53
|
const legendScrollRef = (0, _react.useRef)(null);
|
|
@@ -189,12 +192,16 @@ const ChartLine = props => {
|
|
|
189
192
|
|
|
190
193
|
// Callback for handling chart resize
|
|
191
194
|
const handleResize = (0, _react.useCallback)(() => {
|
|
195
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
196
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
197
|
+
const el = chartRef.current;
|
|
198
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
192
199
|
chartInstanceRef.current?.resize();
|
|
193
200
|
}, []);
|
|
194
201
|
|
|
195
202
|
// Initialize the chart
|
|
196
203
|
(0, _react.useEffect)(() => {
|
|
197
|
-
if (!chartRef.current) return;
|
|
204
|
+
if (!chartRef.current || !containerReady) return;
|
|
198
205
|
|
|
199
206
|
// Initialize or reuse the existing instance
|
|
200
207
|
let chart = chartInstanceRef.current;
|
|
@@ -324,7 +331,7 @@ const ChartLine = props => {
|
|
|
324
331
|
};
|
|
325
332
|
}, [chartOption, handleResize, onClick, onLegendSelectChanged, onDataZoomWindowChanged, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval,
|
|
326
333
|
// 图例是否接管滚轮由它推导,漏了会拿到过期的滚动配置
|
|
327
|
-
normalizedScroll]);
|
|
334
|
+
normalizedScroll, containerReady]);
|
|
328
335
|
|
|
329
336
|
// Handle auto play
|
|
330
337
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../../_hooks/useContainerReady"));
|
|
8
9
|
require("echarts-gl");
|
|
9
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
10
11
|
var _hooks = require("./_hooks");
|
|
@@ -41,6 +42,8 @@ const ChartPie3D = props => {
|
|
|
41
42
|
} = props;
|
|
42
43
|
const chartRef = (0, _react.useRef)(null);
|
|
43
44
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
45
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
46
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
44
47
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
45
48
|
const hoveredIndexRef = (0, _react.useRef)("");
|
|
46
49
|
const optionRef = (0, _react.useRef)(null);
|
|
@@ -62,6 +65,10 @@ const ChartPie3D = props => {
|
|
|
62
65
|
});
|
|
63
66
|
}, [pieData, internalDiameterRatio, tooltip, alpha, beta, autoRotate, distance, coreOption, minHeight, maxHeight, yOffset, label, enableMouseControl]);
|
|
64
67
|
const handleResize = (0, _react.useCallback)(() => {
|
|
68
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
69
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
70
|
+
const el = chartRef.current;
|
|
71
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
65
72
|
chartInstanceRef.current?.resize();
|
|
66
73
|
}, []);
|
|
67
74
|
const handleMouseOver = (0, _hooks.useMouseOverHandler)(optionRef, chartInstanceRef, hoveredIndexRef, {
|
|
@@ -78,7 +85,7 @@ const ChartPie3D = props => {
|
|
|
78
85
|
autoRotate
|
|
79
86
|
});
|
|
80
87
|
(0, _react.useEffect)(() => {
|
|
81
|
-
if (!chartRef.current) return;
|
|
88
|
+
if (!chartRef.current || !containerReady) return;
|
|
82
89
|
let chart = chartInstanceRef.current;
|
|
83
90
|
if (!chart) {
|
|
84
91
|
chart = echarts.init(chartRef.current);
|
|
@@ -107,7 +114,7 @@ const ChartPie3D = props => {
|
|
|
107
114
|
}
|
|
108
115
|
}
|
|
109
116
|
};
|
|
110
|
-
}, [chartOption, handleResize, handleMouseOver, handleGlobalOut, onChart, onClick]);
|
|
117
|
+
}, [chartOption, handleResize, handleMouseOver, handleGlobalOut, onChart, onClick, containerReady]);
|
|
111
118
|
(0, _react.useEffect)(() => {
|
|
112
119
|
return () => {
|
|
113
120
|
if (resizeObserverRef.current) {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _chartUtils = require("../chartUtils");
|
|
10
11
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
@@ -38,6 +39,8 @@ const ChartPie = props => {
|
|
|
38
39
|
} = props;
|
|
39
40
|
const chartRef = (0, _react.useRef)(null);
|
|
40
41
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
42
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
43
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
41
44
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
42
45
|
const legendScrollRef = (0, _react.useRef)(null);
|
|
43
46
|
|
|
@@ -191,12 +194,16 @@ const ChartPie = props => {
|
|
|
191
194
|
|
|
192
195
|
// Callback for handling chart resize
|
|
193
196
|
const handleResize = (0, _react.useCallback)(() => {
|
|
197
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
198
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
199
|
+
const el = chartRef.current;
|
|
200
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
194
201
|
chartInstanceRef.current?.resize();
|
|
195
202
|
}, []);
|
|
196
203
|
|
|
197
204
|
// Initialize the chart
|
|
198
205
|
(0, _react.useEffect)(() => {
|
|
199
|
-
if (!chartRef.current) return;
|
|
206
|
+
if (!chartRef.current || !containerReady) return;
|
|
200
207
|
|
|
201
208
|
// Initialize or reuse the existing instance
|
|
202
209
|
let chart = chartInstanceRef.current;
|
|
@@ -252,7 +259,7 @@ const ChartPie = props => {
|
|
|
252
259
|
legendScrollRef.current = null;
|
|
253
260
|
}
|
|
254
261
|
};
|
|
255
|
-
}, [chartOption, handleResize, onChart, onClick, enableLegendAutoScroll, seriesData, legendVisibleCount, legendScrollInterval]);
|
|
262
|
+
}, [chartOption, handleResize, onChart, onClick, enableLegendAutoScroll, seriesData, legendVisibleCount, legendScrollInterval, containerReady]);
|
|
256
263
|
|
|
257
264
|
// Clean up resources when the component unmounts
|
|
258
265
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
10
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -30,6 +31,8 @@ const Polar = props => {
|
|
|
30
31
|
} = props;
|
|
31
32
|
const chartRef = (0, _react.useRef)(null);
|
|
32
33
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
34
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
35
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
33
36
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
34
37
|
|
|
35
38
|
// Cache the chart option with useMemo
|
|
@@ -144,12 +147,16 @@ const Polar = props => {
|
|
|
144
147
|
|
|
145
148
|
// Callback handling chart resize
|
|
146
149
|
const handleResize = (0, _react.useCallback)(() => {
|
|
150
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
151
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
152
|
+
const el = chartRef.current;
|
|
153
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
147
154
|
chartInstanceRef.current?.resize();
|
|
148
155
|
}, []);
|
|
149
156
|
|
|
150
157
|
// Initialize the chart
|
|
151
158
|
(0, _react.useEffect)(() => {
|
|
152
|
-
if (!chartRef.current) return;
|
|
159
|
+
if (!chartRef.current || !containerReady) return;
|
|
153
160
|
|
|
154
161
|
// Initialize a new instance or reuse the existing one
|
|
155
162
|
let chart = chartInstanceRef.current;
|
|
@@ -174,7 +181,7 @@ const Polar = props => {
|
|
|
174
181
|
return () => {
|
|
175
182
|
window.removeEventListener("resize", handleResize);
|
|
176
183
|
};
|
|
177
|
-
}, [chartOption, handleResize]);
|
|
184
|
+
}, [chartOption, handleResize, containerReady]);
|
|
178
185
|
|
|
179
186
|
// Clean up resources on unmount
|
|
180
187
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
10
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -33,6 +34,8 @@ const Radar = props => {
|
|
|
33
34
|
} = props;
|
|
34
35
|
const chartRef = (0, _react.useRef)(null);
|
|
35
36
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
37
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
38
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
36
39
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
37
40
|
const hoveredIndicatorRef = (0, _react.useRef)(-1);
|
|
38
41
|
const singleIndicatorEnabled = Boolean(singleIndicatorTooltipProp) && singleIndicatorMode !== undefined;
|
|
@@ -144,10 +147,14 @@ const Radar = props => {
|
|
|
144
147
|
return option;
|
|
145
148
|
}, [indicators, data, color, name, radar, series, coreOption, singleIndicatorEnabled, singleIndicatorFormatter, singleIndicatorRegion]);
|
|
146
149
|
const handleResize = (0, _react.useCallback)(() => {
|
|
150
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
151
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
152
|
+
const el = chartRef.current;
|
|
153
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
147
154
|
chartInstanceRef.current?.resize();
|
|
148
155
|
}, []);
|
|
149
156
|
(0, _react.useEffect)(() => {
|
|
150
|
-
if (!chartRef.current) return;
|
|
157
|
+
if (!chartRef.current || !containerReady) return;
|
|
151
158
|
let chart = chartInstanceRef.current;
|
|
152
159
|
if (!chart) {
|
|
153
160
|
chart = echarts.init(chartRef.current);
|
|
@@ -263,7 +270,7 @@ const Radar = props => {
|
|
|
263
270
|
}
|
|
264
271
|
}
|
|
265
272
|
};
|
|
266
|
-
}, [chartOption, handleResize, singleIndicatorEnabled, singleIndicatorRegion, singleIndicatorHighlight, singleIndicatorHoverFill, color]);
|
|
273
|
+
}, [chartOption, handleResize, singleIndicatorEnabled, singleIndicatorRegion, singleIndicatorHighlight, singleIndicatorHoverFill, color, containerReady]);
|
|
267
274
|
(0, _react.useEffect)(() => {
|
|
268
275
|
return () => {
|
|
269
276
|
if (resizeObserverRef.current) {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
9
10
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
10
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -22,6 +23,8 @@ const Sankey = props => {
|
|
|
22
23
|
} = props;
|
|
23
24
|
const chartRef = (0, _react.useRef)(null);
|
|
24
25
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
26
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
27
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
25
28
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
26
29
|
|
|
27
30
|
// Cache the chart option with useMemo
|
|
@@ -103,12 +106,16 @@ const Sankey = props => {
|
|
|
103
106
|
|
|
104
107
|
// Callback handling chart resize
|
|
105
108
|
const handleResize = (0, _react.useCallback)(() => {
|
|
109
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
110
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
111
|
+
const el = chartRef.current;
|
|
112
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
106
113
|
chartInstanceRef.current?.resize();
|
|
107
114
|
}, []);
|
|
108
115
|
|
|
109
116
|
// Initialize the chart
|
|
110
117
|
(0, _react.useEffect)(() => {
|
|
111
|
-
if (!chartRef.current) return;
|
|
118
|
+
if (!chartRef.current || !containerReady) return;
|
|
112
119
|
|
|
113
120
|
// Initialize a new instance or reuse the existing one
|
|
114
121
|
let chart = chartInstanceRef.current;
|
|
@@ -142,7 +149,7 @@ const Sankey = props => {
|
|
|
142
149
|
return () => {
|
|
143
150
|
window.removeEventListener("resize", handleResize);
|
|
144
151
|
};
|
|
145
|
-
}, [chartOption, handleResize, getImage]);
|
|
152
|
+
}, [chartOption, handleResize, getImage, containerReady]);
|
|
146
153
|
|
|
147
154
|
// Clean up resources on unmount
|
|
148
155
|
(0, _react.useEffect)(() => {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
|
|
8
9
|
var _indexModule = _interopRequireDefault(require("../index.module.scss"));
|
|
9
10
|
var echarts = _interopRequireWildcard(require("echarts"));
|
|
10
11
|
var _hsuUtils = require("hsu-utils");
|
|
@@ -23,6 +24,8 @@ const Tree = props => {
|
|
|
23
24
|
} = props;
|
|
24
25
|
const chartRef = (0, _react.useRef)(null);
|
|
25
26
|
const chartInstanceRef = (0, _react.useRef)(null);
|
|
27
|
+
// Defers `echarts.init` until the container has a box — see the hook for why
|
|
28
|
+
const containerReady = (0, _useContainerReady.default)(chartRef);
|
|
26
29
|
const resizeObserverRef = (0, _react.useRef)(null);
|
|
27
30
|
|
|
28
31
|
// Cache the chart option with useMemo
|
|
@@ -43,12 +46,16 @@ const Tree = props => {
|
|
|
43
46
|
|
|
44
47
|
// Callback handling chart resize
|
|
45
48
|
const handleResize = (0, _react.useCallback)(() => {
|
|
49
|
+
// A keep-alive tab losing focus fires the observer with a 0×0 box; resizing to that throws
|
|
50
|
+
// the laid-out canvas away and it has to be rebuilt when the tab comes back
|
|
51
|
+
const el = chartRef.current;
|
|
52
|
+
if (!el || el.clientWidth === 0 || el.clientHeight === 0) return;
|
|
46
53
|
chartInstanceRef.current?.resize();
|
|
47
54
|
}, []);
|
|
48
55
|
|
|
49
56
|
// Initialize the chart
|
|
50
57
|
(0, _react.useEffect)(() => {
|
|
51
|
-
if (!chartRef.current) return;
|
|
58
|
+
if (!chartRef.current || !containerReady) return;
|
|
52
59
|
|
|
53
60
|
// Initialize a new instance or reuse the existing one
|
|
54
61
|
let chart = chartInstanceRef.current;
|
|
@@ -82,7 +89,7 @@ const Tree = props => {
|
|
|
82
89
|
return () => {
|
|
83
90
|
window.removeEventListener("resize", handleResize);
|
|
84
91
|
};
|
|
85
|
-
}, [chartOption, handleResize, getImage]);
|
|
92
|
+
}, [chartOption, handleResize, getImage, containerReady]);
|
|
86
93
|
|
|
87
94
|
// Clean up resources on unmount
|
|
88
95
|
(0, _react.useEffect)(() => {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Whether the referenced element has a non-zero box yet.
|
|
4
|
+
*
|
|
5
|
+
* `echarts.init` on a 0×0 element logs `Can't get DOM width or height` and builds a canvas with no
|
|
6
|
+
* size, recovering only on the next `resize()`. A chart hits that path whenever it mounts before
|
|
7
|
+
* layout has given it space — inside a keep-alive tab that is not the active one, a collapsed
|
|
8
|
+
* panel, a modal that has not opened yet — so consuming apps see the warning for charts that end
|
|
9
|
+
* up rendering perfectly well.
|
|
10
|
+
*
|
|
11
|
+
* Gating `init` on this flag defers it to the first frame the element actually occupies space.
|
|
12
|
+
*
|
|
13
|
+
* It **latches**: once measured, the element going back to 0×0 (a keep-alive tab losing focus)
|
|
14
|
+
* must not read as "not ready" again, or the init effect would tear the chart down and re-create
|
|
15
|
+
* it on every tab switch.
|
|
16
|
+
*/
|
|
17
|
+
declare const useContainerReady: (ref: RefObject<HTMLElement | null>) => boolean;
|
|
18
|
+
export default useContainerReady;
|