@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.
Files changed (42) hide show
  1. package/es/components/Chart/Bar/index.js +9 -2
  2. package/es/components/Chart/Common/index.js +9 -2
  3. package/es/components/Chart/Gauge/index.js +9 -2
  4. package/es/components/Chart/Heatmap/index.js +9 -2
  5. package/es/components/Chart/Line/index.js +9 -2
  6. package/es/components/Chart/Pie/Pie3D/index.js +9 -2
  7. package/es/components/Chart/Pie/index.js +9 -2
  8. package/es/components/Chart/Polar/index.js +9 -2
  9. package/es/components/Chart/Radar/index.js +9 -2
  10. package/es/components/Chart/Sankey/index.js +9 -2
  11. package/es/components/Chart/Tree/index.js +9 -2
  12. package/es/components/Chart/_hooks/useContainerReady.d.ts +18 -0
  13. package/es/components/Chart/_hooks/useContainerReady.js +56 -0
  14. package/es/layout/NavTabBar/_hooks/useTabPath.js +45 -8
  15. package/lib/components/Chart/Bar/index.js +9 -2
  16. package/lib/components/Chart/Common/index.js +9 -2
  17. package/lib/components/Chart/Gauge/index.js +9 -2
  18. package/lib/components/Chart/Heatmap/index.js +9 -2
  19. package/lib/components/Chart/Line/index.js +9 -2
  20. package/lib/components/Chart/Pie/Pie3D/index.js +9 -2
  21. package/lib/components/Chart/Pie/index.js +9 -2
  22. package/lib/components/Chart/Polar/index.js +9 -2
  23. package/lib/components/Chart/Radar/index.js +9 -2
  24. package/lib/components/Chart/Sankey/index.js +9 -2
  25. package/lib/components/Chart/Tree/index.js +9 -2
  26. package/lib/components/Chart/_hooks/useContainerReady.d.ts +18 -0
  27. package/lib/components/Chart/_hooks/useContainerReady.js +51 -0
  28. package/lib/layout/NavTabBar/_hooks/useTabPath.js +42 -7
  29. package/package.json +1 -1
  30. package/src/components/Chart/Bar/index.tsx +10 -1
  31. package/src/components/Chart/Common/index.tsx +12 -2
  32. package/src/components/Chart/Gauge/index.tsx +12 -2
  33. package/src/components/Chart/Heatmap/index.tsx +12 -2
  34. package/src/components/Chart/Line/index.tsx +10 -1
  35. package/src/components/Chart/Pie/Pie3D/index.tsx +10 -1
  36. package/src/components/Chart/Pie/index.tsx +10 -1
  37. package/src/components/Chart/Polar/index.tsx +12 -2
  38. package/src/components/Chart/Radar/index.tsx +10 -1
  39. package/src/components/Chart/Sankey/index.tsx +12 -2
  40. package/src/components/Chart/Tree/index.tsx +12 -2
  41. package/src/components/Chart/_hooks/useContainerReady.ts +50 -0
  42. 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 = affixRouter.includes(item.key) || item.affix;
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
- }, [affixRouter]);
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: "".concat(pathname).concat(search)
108
+ key: nextKey
89
109
  }) : i;
90
110
  });
91
111
  }
92
112
  return [].concat(_toConsumableArray(prev), [_objectSpread(_objectSpread({}, item), {}, {
93
- key: "".concat(pathname).concat(search)
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: "".concat(item.key).concat(search)
131
+ key: nextKey
107
132
  }) : i;
108
133
  });
109
134
  }
110
135
  return [].concat(_toConsumableArray(prev), [_objectSpread(_objectSpread({}, item), {}, {
111
- key: "".concat(item.key).concat(search)
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;