@agions/taroviz 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +1 -1
- package/dist/esm/index.js +576 -33
- package/package.json +1 -1
- package/src/charts/boxplot/types.ts +5 -3
- package/src/charts/parallel/types.ts +6 -3
- package/src/charts/tree/types.ts +4 -4
- package/src/core/components/Annotation.tsx +12 -10
- package/src/core/components/BaseChart.tsx +3 -3
- package/src/core/components/ErrorBoundary.tsx +30 -17
- package/src/core/components/LazyChart.tsx +14 -9
- package/src/core/themes/ThemeManager.ts +33 -0
- package/src/core/utils/chartUtils.ts +8 -3
- package/src/hooks/index.ts +21 -0
- package/src/hooks/useChartHistory.ts +273 -0
- package/src/hooks/useChartSelection.ts +350 -0
package/dist/esm/index.js
CHANGED
|
@@ -49493,12 +49493,12 @@ function calculateDataLength(option) {
|
|
|
49493
49493
|
function filterDataByKeys(data, filters) {
|
|
49494
49494
|
if (!filters || Object.keys(filters).length === 0) return data;
|
|
49495
49495
|
return data.filter(function (item) {
|
|
49496
|
-
var
|
|
49497
|
-
|
|
49498
|
-
|
|
49499
|
-
|
|
49500
|
-
|
|
49501
|
-
if (
|
|
49496
|
+
for (var _i = 0, _a = Object.entries(filters); _i < _a.length; _i++) {
|
|
49497
|
+
var _b = _a[_i],
|
|
49498
|
+
key = _b[0],
|
|
49499
|
+
value = _b[1];
|
|
49500
|
+
var itemVal = item[key];
|
|
49501
|
+
if (itemVal !== value && !(Array.isArray(itemVal) && itemVal.includes(value))) return false;
|
|
49502
49502
|
}
|
|
49503
49503
|
return true;
|
|
49504
49504
|
});
|
|
@@ -52486,6 +52486,38 @@ var ThemeManager = /** @class */function () {
|
|
|
52486
52486
|
ThemeManager.prototype.isDarkMode = function () {
|
|
52487
52487
|
return this.currentTheme.isDark || this.currentTheme.type === 'dark';
|
|
52488
52488
|
};
|
|
52489
|
+
/**
|
|
52490
|
+
* 检测系统 prefers-color-scheme 是否为暗色
|
|
52491
|
+
*/
|
|
52492
|
+
ThemeManager.prototype.getSystemPrefersDark = function () {
|
|
52493
|
+
if (typeof window === 'undefined') return false;
|
|
52494
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
52495
|
+
};
|
|
52496
|
+
/**
|
|
52497
|
+
* 订阅系统主题变化,自动切换匹配的主题
|
|
52498
|
+
* @returns 取消订阅的函数
|
|
52499
|
+
*/
|
|
52500
|
+
ThemeManager.prototype.watchSystemTheme = function () {
|
|
52501
|
+
var _this = this;
|
|
52502
|
+
if (typeof window === 'undefined') return function () {};
|
|
52503
|
+
var mq = window.matchMedia('(prefers-color-scheme: dark)');
|
|
52504
|
+
var handler = function (e) {
|
|
52505
|
+
// 当系统主题切换时,自动应用对应主题
|
|
52506
|
+
_this.setTheme(e.matches ? 'dark' : 'default');
|
|
52507
|
+
};
|
|
52508
|
+
mq.addEventListener('change', handler);
|
|
52509
|
+
return function () {
|
|
52510
|
+
return mq.removeEventListener('change', handler);
|
|
52511
|
+
};
|
|
52512
|
+
};
|
|
52513
|
+
/**
|
|
52514
|
+
* 应用初始主题(根据系统偏好自动选择 dark/default)
|
|
52515
|
+
* 必须在 DOM 加载后调用
|
|
52516
|
+
*/
|
|
52517
|
+
ThemeManager.prototype.applyInitialTheme = function () {
|
|
52518
|
+
var prefersDark = this.getSystemPrefersDark();
|
|
52519
|
+
this.setTheme(prefersDark ? 'dark' : 'default');
|
|
52520
|
+
};
|
|
52489
52521
|
/**
|
|
52490
52522
|
* 注册主题变更监听器
|
|
52491
52523
|
*/
|
|
@@ -53842,51 +53874,58 @@ var ErrorBoundary = /** @class */function (_super) {
|
|
|
53842
53874
|
if (fallback) {
|
|
53843
53875
|
return fallback(error, this.handleReset);
|
|
53844
53876
|
}
|
|
53845
|
-
//
|
|
53877
|
+
// 默认错误展示(使用 CSS 变量,与 ThemeManager 对齐)
|
|
53846
53878
|
return /*#__PURE__*/external_react_default().createElement("div", {
|
|
53879
|
+
role: "alert",
|
|
53880
|
+
"aria-live": "assertive",
|
|
53847
53881
|
style: {
|
|
53848
53882
|
display: 'flex',
|
|
53849
53883
|
flexDirection: 'column',
|
|
53850
53884
|
alignItems: 'center',
|
|
53851
53885
|
justifyContent: 'center',
|
|
53852
|
-
padding: '
|
|
53853
|
-
backgroundColor: '#fff',
|
|
53854
|
-
border: '1px solid #ff4d4f',
|
|
53855
|
-
borderRadius: '8px',
|
|
53856
|
-
color: '#333',
|
|
53857
|
-
minHeight: '200px'
|
|
53886
|
+
padding: 'var(--tv-border-radius, 16px)',
|
|
53887
|
+
backgroundColor: 'var(--tv-bg-color, #fff)',
|
|
53888
|
+
border: '1px solid var(--tv-error-color, #ff4d4f)',
|
|
53889
|
+
borderRadius: 'var(--tv-border-radius, 8px)',
|
|
53890
|
+
color: 'var(--tv-text-color, #333)',
|
|
53891
|
+
minHeight: '200px',
|
|
53892
|
+
fontFamily: 'var(--tv-font-family, sans-serif)'
|
|
53858
53893
|
}
|
|
53859
53894
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
53860
53895
|
style: {
|
|
53861
53896
|
fontSize: '48px',
|
|
53862
53897
|
marginBottom: '16px'
|
|
53863
|
-
}
|
|
53898
|
+
},
|
|
53899
|
+
"aria-hidden": "true"
|
|
53864
53900
|
}, "\u26A0\uFE0F"), /*#__PURE__*/external_react_default().createElement("h3", {
|
|
53865
53901
|
style: {
|
|
53866
53902
|
margin: '0 0 12px',
|
|
53867
|
-
color: '#ff4d4f'
|
|
53903
|
+
color: 'var(--tv-error-color, #ff4d4f)',
|
|
53904
|
+
fontWeight: 700
|
|
53868
53905
|
}
|
|
53869
53906
|
}, "\u56FE\u8868\u6E32\u67D3\u5931\u8D25"), /*#__PURE__*/external_react_default().createElement("p", {
|
|
53870
53907
|
style: {
|
|
53871
53908
|
margin: '0 0 16px',
|
|
53872
|
-
color: '#666',
|
|
53873
|
-
textAlign: 'center'
|
|
53909
|
+
color: 'var(--tv-text-color-secondary, #666)',
|
|
53910
|
+
textAlign: 'center',
|
|
53911
|
+
maxWidth: '320px'
|
|
53874
53912
|
}
|
|
53875
53913
|
}, "\u56FE\u8868\u5728\u6E32\u67D3\u8FC7\u7A0B\u4E2D\u9047\u5230\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u6570\u636E\u914D\u7F6E\u662F\u5426\u6B63\u786E"), showDetails && (/*#__PURE__*/external_react_default().createElement("details", {
|
|
53876
53914
|
style: {
|
|
53877
53915
|
width: '100%',
|
|
53878
53916
|
padding: '12px',
|
|
53879
|
-
backgroundColor: '#f5f5f5',
|
|
53880
|
-
borderRadius: '4px',
|
|
53881
|
-
fontSize: '12px',
|
|
53882
|
-
fontFamily: 'monospace',
|
|
53917
|
+
backgroundColor: 'var(--tv-bg-color-secondary, #f5f5f5)',
|
|
53918
|
+
borderRadius: 'var(--tv-border-radius-small, 4px)',
|
|
53919
|
+
fontSize: 'var(--tv-font-size-small, 12px)',
|
|
53920
|
+
fontFamily: 'var(--tv-font-family, monospace)',
|
|
53883
53921
|
overflow: 'auto',
|
|
53884
53922
|
maxHeight: '150px'
|
|
53885
53923
|
}
|
|
53886
53924
|
}, /*#__PURE__*/external_react_default().createElement("summary", {
|
|
53887
53925
|
style: {
|
|
53888
53926
|
cursor: 'pointer',
|
|
53889
|
-
marginBottom: '8px'
|
|
53927
|
+
marginBottom: '8px',
|
|
53928
|
+
fontWeight: 600
|
|
53890
53929
|
}
|
|
53891
53930
|
}, "\u9519\u8BEF\u8BE6\u60C5"), /*#__PURE__*/external_react_default().createElement("pre", {
|
|
53892
53931
|
style: {
|
|
@@ -53899,12 +53938,20 @@ var ErrorBoundary = /** @class */function (_super) {
|
|
|
53899
53938
|
style: {
|
|
53900
53939
|
marginTop: '16px',
|
|
53901
53940
|
padding: '8px 24px',
|
|
53902
|
-
backgroundColor: '#1890ff',
|
|
53941
|
+
backgroundColor: 'var(--tv-primary-color, #1890ff)',
|
|
53903
53942
|
color: '#fff',
|
|
53904
53943
|
border: 'none',
|
|
53905
|
-
borderRadius: '4px',
|
|
53944
|
+
borderRadius: 'var(--tv-border-radius-small, 4px)',
|
|
53906
53945
|
cursor: 'pointer',
|
|
53907
|
-
fontSize: '14px'
|
|
53946
|
+
fontSize: 'var(--tv-font-size, 14px)',
|
|
53947
|
+
fontWeight: 600,
|
|
53948
|
+
transition: 'background-color var(--tv-transition-duration, 0.3s)'
|
|
53949
|
+
},
|
|
53950
|
+
onMouseEnter: function (e) {
|
|
53951
|
+
e.currentTarget.style.backgroundColor = 'var(--tv-primary-color-hover, #40a9ff)';
|
|
53952
|
+
},
|
|
53953
|
+
onMouseLeave: function (e) {
|
|
53954
|
+
e.currentTarget.style.backgroundColor = 'var(--tv-primary-color, #1890ff)';
|
|
53908
53955
|
}
|
|
53909
53956
|
}, "\u91CD\u8BD5"));
|
|
53910
53957
|
}
|
|
@@ -54023,12 +54070,14 @@ var LAZY_CHART_MODULES = {
|
|
|
54023
54070
|
};
|
|
54024
54071
|
var LAZY_CHART_TYPES = Object.keys(LAZY_CHART_MODULES);
|
|
54025
54072
|
/**
|
|
54026
|
-
*
|
|
54073
|
+
* 默认加载状态组件(使用 CSS 变量,与 ThemeManager 对齐)
|
|
54027
54074
|
*/
|
|
54028
54075
|
var DefaultLoadingFallback = function (_a) {
|
|
54029
54076
|
var _b = _a.text,
|
|
54030
54077
|
text = _b === void 0 ? '加载中...' : _b;
|
|
54031
54078
|
return /*#__PURE__*/external_react_default().createElement("div", {
|
|
54079
|
+
role: "status",
|
|
54080
|
+
"aria-label": text,
|
|
54032
54081
|
style: {
|
|
54033
54082
|
display: 'flex',
|
|
54034
54083
|
alignItems: 'center',
|
|
@@ -54036,8 +54085,8 @@ var DefaultLoadingFallback = function (_a) {
|
|
|
54036
54085
|
width: '100%',
|
|
54037
54086
|
height: '100%',
|
|
54038
54087
|
minHeight: '200px',
|
|
54039
|
-
backgroundColor: '#f5f5f5',
|
|
54040
|
-
borderRadius: '8px'
|
|
54088
|
+
backgroundColor: 'var(--tv-bg-color-secondary, #f5f5f5)',
|
|
54089
|
+
borderRadius: 'var(--tv-border-radius, 8px)'
|
|
54041
54090
|
}
|
|
54042
54091
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
54043
54092
|
style: {
|
|
@@ -54047,16 +54096,17 @@ var DefaultLoadingFallback = function (_a) {
|
|
|
54047
54096
|
style: {
|
|
54048
54097
|
width: '40px',
|
|
54049
54098
|
height: '40px',
|
|
54050
|
-
border: '3px solid #1890ff',
|
|
54099
|
+
border: '3px solid var(--tv-primary-color, #1890ff)',
|
|
54051
54100
|
borderTopColor: 'transparent',
|
|
54052
54101
|
borderRadius: '50%',
|
|
54053
54102
|
animation: 'taroviz-spin 1s linear infinite',
|
|
54054
54103
|
margin: '0 auto 12px'
|
|
54055
|
-
}
|
|
54104
|
+
},
|
|
54105
|
+
"aria-hidden": "true"
|
|
54056
54106
|
}), /*#__PURE__*/external_react_default().createElement("style", null, "\n @keyframes taroviz-spin {\n to { transform: rotate(360deg); }\n }\n "), /*#__PURE__*/external_react_default().createElement("span", {
|
|
54057
54107
|
style: {
|
|
54058
|
-
color: '#666',
|
|
54059
|
-
fontSize: '14px'
|
|
54108
|
+
color: 'var(--tv-text-color-secondary, #666)',
|
|
54109
|
+
fontSize: 'var(--tv-font-size, 14px)'
|
|
54060
54110
|
}
|
|
54061
54111
|
}, text)));
|
|
54062
54112
|
};
|
|
@@ -56149,6 +56199,491 @@ function useChartDownload(instance, options) {
|
|
|
56149
56199
|
// 导出
|
|
56150
56200
|
// ============================================================================
|
|
56151
56201
|
/* harmony default export */ const hooks_useChartDownload = ((/* unused pure expression or super */ null && (useChartDownload)));
|
|
56202
|
+
;// ./src/hooks/useChartHistory.ts
|
|
56203
|
+
var useChartHistory_spreadArray = undefined && undefined.__spreadArray || function (to, from, pack) {
|
|
56204
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
56205
|
+
if (ar || !(i in from)) {
|
|
56206
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
56207
|
+
ar[i] = from[i];
|
|
56208
|
+
}
|
|
56209
|
+
}
|
|
56210
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
56211
|
+
};
|
|
56212
|
+
/**
|
|
56213
|
+
* useChartHistory - 图表 Undo/Redo Hook
|
|
56214
|
+
* 追踪图表配置历史,支持撤销/重做操作和键盘快捷键
|
|
56215
|
+
*
|
|
56216
|
+
* 特性:
|
|
56217
|
+
* - 最多保存 50 条历史记录(可配置)
|
|
56218
|
+
* - 自动绑定 Ctrl+Z / Ctrl+Y 键盘快捷键
|
|
56219
|
+
* - 支持 ignoreKeys 忽略特定配置字段(如动画、时间戳)
|
|
56220
|
+
* - 暴露 canUndo / canRedo 状态
|
|
56221
|
+
*/
|
|
56222
|
+
|
|
56223
|
+
// ============================================================================
|
|
56224
|
+
// 工具函数
|
|
56225
|
+
// ============================================================================
|
|
56226
|
+
/** 深度省略指定键后比较两个配置是否相等 */
|
|
56227
|
+
function omitAndCompare(a, b, ignoreKeys) {
|
|
56228
|
+
if (a === b) return true;
|
|
56229
|
+
if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
|
|
56230
|
+
return a === b;
|
|
56231
|
+
}
|
|
56232
|
+
var aObj = a;
|
|
56233
|
+
var bObj = b;
|
|
56234
|
+
var aKeys = Object.keys(aObj).filter(function (k) {
|
|
56235
|
+
return !ignoreKeys.has(k);
|
|
56236
|
+
});
|
|
56237
|
+
var bKeys = Object.keys(bObj).filter(function (k) {
|
|
56238
|
+
return !ignoreKeys.has(k);
|
|
56239
|
+
});
|
|
56240
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
56241
|
+
for (var _i = 0, aKeys_1 = aKeys; _i < aKeys_1.length; _i++) {
|
|
56242
|
+
var key = aKeys_1[_i];
|
|
56243
|
+
if (!bObj.hasOwnProperty(key)) return false;
|
|
56244
|
+
if (!omitAndCompare(aObj[key], bObj[key], ignoreKeys)) return false;
|
|
56245
|
+
}
|
|
56246
|
+
return true;
|
|
56247
|
+
}
|
|
56248
|
+
// ============================================================================
|
|
56249
|
+
// Hook 实现
|
|
56250
|
+
// ============================================================================
|
|
56251
|
+
/**
|
|
56252
|
+
* 使用图表历史记录(Undo/Redo)
|
|
56253
|
+
* @param chartInstance 图表实例
|
|
56254
|
+
* @param options 配置选项
|
|
56255
|
+
* @returns 历史记录控制接口
|
|
56256
|
+
*/
|
|
56257
|
+
function useChartHistory(chartInstance, options) {
|
|
56258
|
+
if (options === void 0) {
|
|
56259
|
+
options = {};
|
|
56260
|
+
}
|
|
56261
|
+
var _a = options.maxHistorySize,
|
|
56262
|
+
maxHistorySize = _a === void 0 ? 50 : _a,
|
|
56263
|
+
_b = options.ignoreKeys,
|
|
56264
|
+
ignoreKeys = _b === void 0 ? ['animation', 'animationDuration', 'animationEasing', 'animationFrame'] : _b,
|
|
56265
|
+
_c = options.enableKeyboard,
|
|
56266
|
+
enableKeyboard = _c === void 0 ? true : _c,
|
|
56267
|
+
_d = options.clearOnUnmount,
|
|
56268
|
+
clearOnUnmount = _d === void 0 ? false : _d;
|
|
56269
|
+
// 忽略键集合
|
|
56270
|
+
var ignoreKeySet = (0,external_react_.useRef)(new Set(ignoreKeys));
|
|
56271
|
+
// 历史栈(每次 setOption 快照)
|
|
56272
|
+
var historyStack = (0,external_react_.useRef)([]);
|
|
56273
|
+
// 当前索引
|
|
56274
|
+
var _e = (0,external_react_.useState)(-1),
|
|
56275
|
+
currentIndex = _e[0],
|
|
56276
|
+
setCurrentIndex = _e[1];
|
|
56277
|
+
// Chart instance ref
|
|
56278
|
+
var chartRef = (0,external_react_.useRef)(null);
|
|
56279
|
+
chartRef.current = chartInstance;
|
|
56280
|
+
// 是否正在执行 undo/redo(避免 push 时重复记录)
|
|
56281
|
+
var isApplyingRef = (0,external_react_.useRef)(false);
|
|
56282
|
+
// 拦截 chart.setOption,记录历史
|
|
56283
|
+
(0,external_react_.useEffect)(function () {
|
|
56284
|
+
var chart = chartRef.current;
|
|
56285
|
+
if (!chart) return;
|
|
56286
|
+
var originalSetOption = chart.setOption.bind(chart);
|
|
56287
|
+
chart.setOption = function (option, notMerge, lazyUpdate) {
|
|
56288
|
+
// 如果正在执行 undo/redo,跳过历史记录
|
|
56289
|
+
if (isApplyingRef.current) {
|
|
56290
|
+
return originalSetOption(option, notMerge, lazyUpdate);
|
|
56291
|
+
}
|
|
56292
|
+
var stack = historyStack.current;
|
|
56293
|
+
var idx = currentIndex;
|
|
56294
|
+
// 如果当前索引不在栈顶,丢弃redo历史(类似 Git 行为)
|
|
56295
|
+
var newStack = idx < stack.length - 1 ? stack.slice(0, idx + 1) : useChartHistory_spreadArray([], stack, true);
|
|
56296
|
+
// 检查是否与上一次配置相同(忽略动画字段)
|
|
56297
|
+
var lastOption = newStack[newStack.length - 1];
|
|
56298
|
+
if (lastOption && omitAndCompare(lastOption, option, ignoreKeySet.current)) {
|
|
56299
|
+
// 配置没变,直接应用
|
|
56300
|
+
return originalSetOption(option, notMerge, lazyUpdate);
|
|
56301
|
+
}
|
|
56302
|
+
// 入栈
|
|
56303
|
+
newStack.push(option);
|
|
56304
|
+
// 裁剪超出 maxHistorySize
|
|
56305
|
+
if (newStack.length > maxHistorySize) {
|
|
56306
|
+
newStack.shift();
|
|
56307
|
+
} else {
|
|
56308
|
+
// 更新索引
|
|
56309
|
+
setCurrentIndex(newStack.length - 1);
|
|
56310
|
+
}
|
|
56311
|
+
historyStack.current = newStack;
|
|
56312
|
+
return originalSetOption(option, notMerge, lazyUpdate);
|
|
56313
|
+
};
|
|
56314
|
+
return function () {
|
|
56315
|
+
// 恢复原始 setOption
|
|
56316
|
+
chart.setOption = originalSetOption;
|
|
56317
|
+
};
|
|
56318
|
+
}, [chartInstance, currentIndex, maxHistorySize]);
|
|
56319
|
+
// 键盘快捷键:Ctrl+Z 撤销,Ctrl+Y / Ctrl+Shift+Z 重做
|
|
56320
|
+
(0,external_react_.useEffect)(function () {
|
|
56321
|
+
if (!enableKeyboard) return;
|
|
56322
|
+
var handleKeyDown = function (e) {
|
|
56323
|
+
var isMod = e.ctrlKey || e.metaKey;
|
|
56324
|
+
if (!isMod) return;
|
|
56325
|
+
if (e.key === 'z' && !e.shiftKey) {
|
|
56326
|
+
e.preventDefault();
|
|
56327
|
+
undo();
|
|
56328
|
+
} else if (e.key === 'y' || e.key === 'z' && e.shiftKey) {
|
|
56329
|
+
e.preventDefault();
|
|
56330
|
+
redo();
|
|
56331
|
+
}
|
|
56332
|
+
};
|
|
56333
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
56334
|
+
return function () {
|
|
56335
|
+
return window.removeEventListener('keydown', handleKeyDown);
|
|
56336
|
+
};
|
|
56337
|
+
}, [enableKeyboard]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
56338
|
+
// 组件卸载时清空
|
|
56339
|
+
(0,external_react_.useEffect)(function () {
|
|
56340
|
+
return function () {
|
|
56341
|
+
if (clearOnUnmount) {
|
|
56342
|
+
historyStack.current = [];
|
|
56343
|
+
setCurrentIndex(-1);
|
|
56344
|
+
}
|
|
56345
|
+
};
|
|
56346
|
+
}, [clearOnUnmount]);
|
|
56347
|
+
// ─── Public API ───────────────────────────────────────────────────────────
|
|
56348
|
+
var undo = (0,external_react_.useCallback)(function () {
|
|
56349
|
+
var chart = chartRef.current;
|
|
56350
|
+
if (!chart || currentIndex <= 0) return;
|
|
56351
|
+
var idx = currentIndex - 1;
|
|
56352
|
+
isApplyingRef.current = true;
|
|
56353
|
+
chart.setOption(historyStack.current[idx], true, true);
|
|
56354
|
+
isApplyingRef.current = false;
|
|
56355
|
+
setCurrentIndex(idx);
|
|
56356
|
+
}, [currentIndex]);
|
|
56357
|
+
var redo = (0,external_react_.useCallback)(function () {
|
|
56358
|
+
var chart = chartRef.current;
|
|
56359
|
+
if (!chart || currentIndex >= historyStack.current.length - 1) return;
|
|
56360
|
+
var idx = currentIndex + 1;
|
|
56361
|
+
isApplyingRef.current = true;
|
|
56362
|
+
chart.setOption(historyStack.current[idx], true, true);
|
|
56363
|
+
isApplyingRef.current = false;
|
|
56364
|
+
setCurrentIndex(idx);
|
|
56365
|
+
}, [currentIndex]);
|
|
56366
|
+
var goTo = (0,external_react_.useCallback)(function (index) {
|
|
56367
|
+
var chart = chartRef.current;
|
|
56368
|
+
if (!chart) return;
|
|
56369
|
+
if (index < 0 || index >= historyStack.current.length) return;
|
|
56370
|
+
if (index === currentIndex) return;
|
|
56371
|
+
isApplyingRef.current = true;
|
|
56372
|
+
chart.setOption(historyStack.current[index], true, true);
|
|
56373
|
+
isApplyingRef.current = false;
|
|
56374
|
+
setCurrentIndex(index);
|
|
56375
|
+
}, [currentIndex]);
|
|
56376
|
+
var push = (0,external_react_.useCallback)(function (option) {
|
|
56377
|
+
var stack = historyStack.current;
|
|
56378
|
+
var idx = currentIndex;
|
|
56379
|
+
var newStack = idx < stack.length - 1 ? stack.slice(0, idx + 1) : useChartHistory_spreadArray([], stack, true);
|
|
56380
|
+
newStack.push(option);
|
|
56381
|
+
if (newStack.length > maxHistorySize) newStack.shift();
|
|
56382
|
+
historyStack.current = newStack;
|
|
56383
|
+
setCurrentIndex(newStack.length - 1);
|
|
56384
|
+
}, [currentIndex, maxHistorySize]);
|
|
56385
|
+
var clear = (0,external_react_.useCallback)(function () {
|
|
56386
|
+
historyStack.current = [];
|
|
56387
|
+
setCurrentIndex(-1);
|
|
56388
|
+
}, []);
|
|
56389
|
+
return {
|
|
56390
|
+
canUndo: currentIndex > 0,
|
|
56391
|
+
canRedo: currentIndex < historyStack.current.length - 1,
|
|
56392
|
+
currentIndex: currentIndex,
|
|
56393
|
+
historyCount: historyStack.current.length,
|
|
56394
|
+
undo: undo,
|
|
56395
|
+
redo: redo,
|
|
56396
|
+
goTo: goTo,
|
|
56397
|
+
push: push,
|
|
56398
|
+
clear: clear
|
|
56399
|
+
};
|
|
56400
|
+
}
|
|
56401
|
+
/* harmony default export */ const hooks_useChartHistory = ((/* unused pure expression or super */ null && (useChartHistory)));
|
|
56402
|
+
;// ./src/hooks/useChartSelection.ts
|
|
56403
|
+
var useChartSelection_spreadArray = undefined && undefined.__spreadArray || function (to, from, pack) {
|
|
56404
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
56405
|
+
if (ar || !(i in from)) {
|
|
56406
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
56407
|
+
ar[i] = from[i];
|
|
56408
|
+
}
|
|
56409
|
+
}
|
|
56410
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
56411
|
+
};
|
|
56412
|
+
/**
|
|
56413
|
+
* useChartSelection - 图表数据点选择/高亮 Hook
|
|
56414
|
+
* 支持单个/批量选择、反选、清除选择,配合 ECharts select 事件
|
|
56415
|
+
*
|
|
56416
|
+
* 特性:
|
|
56417
|
+
* - 支持按 seriesIndex + dataIndex 选择
|
|
56418
|
+
* - 支持按 dataIndex 跨系列批量选择
|
|
56419
|
+
* - 支持反选(invertSelection)
|
|
56420
|
+
* - 支持多选模式(multi)
|
|
56421
|
+
* - 自动绑定图表 select/unselect 事件
|
|
56422
|
+
*/
|
|
56423
|
+
|
|
56424
|
+
// ============================================================================
|
|
56425
|
+
// 工具函数
|
|
56426
|
+
// ============================================================================
|
|
56427
|
+
/** 生成唯一键字符串 */
|
|
56428
|
+
function keyToString(key) {
|
|
56429
|
+
return "".concat(key.seriesIndex, ":").concat(key.dataIndex);
|
|
56430
|
+
}
|
|
56431
|
+
function stringToKey(str) {
|
|
56432
|
+
var _a = str.split(':').map(Number),
|
|
56433
|
+
seriesIndex = _a[0],
|
|
56434
|
+
dataIndex = _a[1];
|
|
56435
|
+
return {
|
|
56436
|
+
seriesIndex: seriesIndex,
|
|
56437
|
+
dataIndex: dataIndex
|
|
56438
|
+
};
|
|
56439
|
+
}
|
|
56440
|
+
// ============================================================================
|
|
56441
|
+
// Hook 实现
|
|
56442
|
+
// ============================================================================
|
|
56443
|
+
/**
|
|
56444
|
+
* 使用图表数据点选择功能
|
|
56445
|
+
* @param chartInstance 图表实例
|
|
56446
|
+
* @param options 配置选项
|
|
56447
|
+
* @returns 选择控制接口
|
|
56448
|
+
*/
|
|
56449
|
+
function useChartSelection(chartInstance, options) {
|
|
56450
|
+
if (options === void 0) {
|
|
56451
|
+
options = {};
|
|
56452
|
+
}
|
|
56453
|
+
var _a = options.mode,
|
|
56454
|
+
mode = _a === void 0 ? 'multiple' : _a,
|
|
56455
|
+
_b = options.clearOnUnmount,
|
|
56456
|
+
clearOnUnmount = _b === void 0 ? true : _b,
|
|
56457
|
+
_c = options.enableCtrlMultiSelect,
|
|
56458
|
+
enableCtrlMultiSelect = _c === void 0 ? true : _c,
|
|
56459
|
+
_d = options.enableShiftRangeSelect,
|
|
56460
|
+
enableShiftRangeSelect = _d === void 0 ? true : _d,
|
|
56461
|
+
onSelectionChange = options.onSelectionChange;
|
|
56462
|
+
// 选中点集合(字符串键)
|
|
56463
|
+
var _e = (0,external_react_.useState)([]),
|
|
56464
|
+
selectedPoints = _e[0],
|
|
56465
|
+
setSelectedPoints = _e[1];
|
|
56466
|
+
// Chart instance ref
|
|
56467
|
+
var chartRef = (0,external_react_.useRef)(null);
|
|
56468
|
+
chartRef.current = chartInstance;
|
|
56469
|
+
// 上一次 shift+click 的数据索引(用于范围选择)
|
|
56470
|
+
var lastShiftIndexRef = (0,external_react_.useRef)(null);
|
|
56471
|
+
// 当前模式 ref(用于事件处理)
|
|
56472
|
+
var modeRef = (0,external_react_.useRef)(mode);
|
|
56473
|
+
modeRef.current = mode;
|
|
56474
|
+
// 绑定图表 select/unselect 事件
|
|
56475
|
+
(0,external_react_.useEffect)(function () {
|
|
56476
|
+
var chart = chartRef.current;
|
|
56477
|
+
if (!chart || !chart.on) return;
|
|
56478
|
+
var handleSelect = function (params) {
|
|
56479
|
+
// ECharts 内置 select 会同步更新 legend
|
|
56480
|
+
// 这里我们用 dispatchAction 来实现纯数据点选择
|
|
56481
|
+
};
|
|
56482
|
+
// 单击 legend 时清除数据点选择(保持一致性)
|
|
56483
|
+
var handleLegendSelectChanged = function (params) {
|
|
56484
|
+
// 清除选择时的视觉反馈
|
|
56485
|
+
};
|
|
56486
|
+
chart.on('selectchanged', function (params) {
|
|
56487
|
+
// 当图表内部选择变化时同步状态
|
|
56488
|
+
var p = params;
|
|
56489
|
+
if (p.isFromClick) {
|
|
56490
|
+
// 用户点击了图例,清除所有数据点选择
|
|
56491
|
+
setSelectedPoints([]);
|
|
56492
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
|
|
56493
|
+
selected: [],
|
|
56494
|
+
unselected: []
|
|
56495
|
+
});
|
|
56496
|
+
}
|
|
56497
|
+
});
|
|
56498
|
+
return function () {
|
|
56499
|
+
if (chart.off) {
|
|
56500
|
+
chart.off('selectchanged');
|
|
56501
|
+
}
|
|
56502
|
+
};
|
|
56503
|
+
}, [onSelectionChange]);
|
|
56504
|
+
// 组件卸载时清除选择
|
|
56505
|
+
(0,external_react_.useEffect)(function () {
|
|
56506
|
+
return function () {
|
|
56507
|
+
if (clearOnUnmount) {
|
|
56508
|
+
var chart = chartRef.current;
|
|
56509
|
+
if (chart === null || chart === void 0 ? void 0 : chart.dispatchAction) {
|
|
56510
|
+
// 清除所有系列的选择状态
|
|
56511
|
+
chart.dispatchAction({
|
|
56512
|
+
type: 'unselect'
|
|
56513
|
+
});
|
|
56514
|
+
}
|
|
56515
|
+
}
|
|
56516
|
+
};
|
|
56517
|
+
}, [clearOnUnmount]);
|
|
56518
|
+
// ─── 私有方法 ───────────────────────────────────────────────────────────────
|
|
56519
|
+
/** 触发选择变化回调 */
|
|
56520
|
+
var notifyChange = (0,external_react_.useCallback)(function (selected, unselected) {
|
|
56521
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
|
|
56522
|
+
selected: selected,
|
|
56523
|
+
unselected: unselected
|
|
56524
|
+
});
|
|
56525
|
+
}, [onSelectionChange]);
|
|
56526
|
+
/** 执行 ECharts dispatchAction */
|
|
56527
|
+
var dispatchSelect = (0,external_react_.useCallback)(function (key, select) {
|
|
56528
|
+
var chart = chartRef.current;
|
|
56529
|
+
if (!(chart === null || chart === void 0 ? void 0 : chart.dispatchAction)) return;
|
|
56530
|
+
chart.dispatchAction({
|
|
56531
|
+
type: select ? 'select' : 'unselect',
|
|
56532
|
+
seriesIndex: key.seriesIndex,
|
|
56533
|
+
dataIndex: key.dataIndex
|
|
56534
|
+
});
|
|
56535
|
+
}, []);
|
|
56536
|
+
// ─── Public API ───────────────────────────────────────────────────────────
|
|
56537
|
+
var select = (0,external_react_.useCallback)(function (key) {
|
|
56538
|
+
setSelectedPoints(function (prev) {
|
|
56539
|
+
var str = keyToString(key);
|
|
56540
|
+
if (prev.some(function (p) {
|
|
56541
|
+
return keyToString(p) === str;
|
|
56542
|
+
})) return prev;
|
|
56543
|
+
var next = mode === 'single' ? [key] : useChartSelection_spreadArray(useChartSelection_spreadArray([], prev, true), [key], false);
|
|
56544
|
+
notifyChange(next, []);
|
|
56545
|
+
return next;
|
|
56546
|
+
});
|
|
56547
|
+
dispatchSelect(key, true);
|
|
56548
|
+
}, [mode, notifyChange, dispatchSelect]);
|
|
56549
|
+
var deselect = (0,external_react_.useCallback)(function (key) {
|
|
56550
|
+
setSelectedPoints(function (prev) {
|
|
56551
|
+
var str = keyToString(key);
|
|
56552
|
+
var removed = prev.filter(function (p) {
|
|
56553
|
+
return keyToString(p) !== str;
|
|
56554
|
+
});
|
|
56555
|
+
notifyChange([], removed);
|
|
56556
|
+
return removed;
|
|
56557
|
+
});
|
|
56558
|
+
dispatchSelect(key, false);
|
|
56559
|
+
}, [notifyChange, dispatchSelect]);
|
|
56560
|
+
var toggle = (0,external_react_.useCallback)(function (key) {
|
|
56561
|
+
var str = keyToString(key);
|
|
56562
|
+
if (selectedPoints.some(function (p) {
|
|
56563
|
+
return keyToString(p) === str;
|
|
56564
|
+
})) {
|
|
56565
|
+
deselect(key);
|
|
56566
|
+
} else {
|
|
56567
|
+
select(key);
|
|
56568
|
+
}
|
|
56569
|
+
}, [selectedPoints, select, deselect]);
|
|
56570
|
+
var selectMultiple = (0,external_react_.useCallback)(function (keys) {
|
|
56571
|
+
setSelectedPoints(function (prev) {
|
|
56572
|
+
var newPoints = mode === 'single' ? keys : useChartSelection_spreadArray(useChartSelection_spreadArray([], prev, true), keys.filter(function (k) {
|
|
56573
|
+
return !prev.some(function (p) {
|
|
56574
|
+
return keyToString(p) === keyToString(k);
|
|
56575
|
+
});
|
|
56576
|
+
}), true);
|
|
56577
|
+
notifyChange(newPoints, []);
|
|
56578
|
+
return newPoints;
|
|
56579
|
+
});
|
|
56580
|
+
keys.forEach(function (key) {
|
|
56581
|
+
return dispatchSelect(key, true);
|
|
56582
|
+
});
|
|
56583
|
+
}, [mode, notifyChange, dispatchSelect]);
|
|
56584
|
+
var deselectMultiple = (0,external_react_.useCallback)(function (keys) {
|
|
56585
|
+
setSelectedPoints(function (prev) {
|
|
56586
|
+
var keySet = new Set(keys.map(keyToString));
|
|
56587
|
+
var removed = prev.filter(function (p) {
|
|
56588
|
+
return keySet.has(keyToString(p));
|
|
56589
|
+
});
|
|
56590
|
+
var remaining = prev.filter(function (p) {
|
|
56591
|
+
return !keySet.has(keyToString(p));
|
|
56592
|
+
});
|
|
56593
|
+
notifyChange([], removed);
|
|
56594
|
+
return remaining;
|
|
56595
|
+
});
|
|
56596
|
+
keys.forEach(function (key) {
|
|
56597
|
+
return dispatchSelect(key, false);
|
|
56598
|
+
});
|
|
56599
|
+
}, [notifyChange, dispatchSelect]);
|
|
56600
|
+
var invertSelection = (0,external_react_.useCallback)(function (seriesIndex, dataIndices) {
|
|
56601
|
+
setSelectedPoints(function (prev) {
|
|
56602
|
+
var selectedSet = new Set(prev.filter(function (p) {
|
|
56603
|
+
return p.seriesIndex === seriesIndex;
|
|
56604
|
+
}).map(function (p) {
|
|
56605
|
+
return p.dataIndex;
|
|
56606
|
+
}));
|
|
56607
|
+
var toSelect = [];
|
|
56608
|
+
var toDeselect = [];
|
|
56609
|
+
dataIndices.forEach(function (dataIndex) {
|
|
56610
|
+
var key = {
|
|
56611
|
+
seriesIndex: seriesIndex,
|
|
56612
|
+
dataIndex: dataIndex
|
|
56613
|
+
};
|
|
56614
|
+
var str = keyToString(key);
|
|
56615
|
+
if (selectedSet.has(dataIndex)) {
|
|
56616
|
+
toDeselect.push(key);
|
|
56617
|
+
} else {
|
|
56618
|
+
toSelect.push(key);
|
|
56619
|
+
}
|
|
56620
|
+
});
|
|
56621
|
+
toDeselect.forEach(function (k) {
|
|
56622
|
+
return dispatchSelect(k, false);
|
|
56623
|
+
});
|
|
56624
|
+
toSelect.forEach(function (k) {
|
|
56625
|
+
return dispatchSelect(k, true);
|
|
56626
|
+
});
|
|
56627
|
+
var newSelected = prev.filter(function (p) {
|
|
56628
|
+
return !(p.seriesIndex === seriesIndex && selectedSet.has(p.dataIndex));
|
|
56629
|
+
}).concat(toSelect);
|
|
56630
|
+
notifyChange(toSelect, toDeselect);
|
|
56631
|
+
return newSelected;
|
|
56632
|
+
});
|
|
56633
|
+
}, [notifyChange, dispatchSelect]);
|
|
56634
|
+
var selectAll = (0,external_react_.useCallback)(function (seriesIndex, dataIndices) {
|
|
56635
|
+
var keys = dataIndices.map(function (dataIndex) {
|
|
56636
|
+
return {
|
|
56637
|
+
seriesIndex: seriesIndex,
|
|
56638
|
+
dataIndex: dataIndex
|
|
56639
|
+
};
|
|
56640
|
+
});
|
|
56641
|
+
setSelectedPoints(function (prev) {
|
|
56642
|
+
var newPoints = mode === 'single' ? keys : useChartSelection_spreadArray(useChartSelection_spreadArray([], prev, true), keys.filter(function (k) {
|
|
56643
|
+
return !prev.some(function (p) {
|
|
56644
|
+
return keyToString(p) === keyToString(k);
|
|
56645
|
+
});
|
|
56646
|
+
}), true);
|
|
56647
|
+
notifyChange(newPoints, []);
|
|
56648
|
+
return newPoints;
|
|
56649
|
+
});
|
|
56650
|
+
keys.forEach(function (key) {
|
|
56651
|
+
return dispatchSelect(key, true);
|
|
56652
|
+
});
|
|
56653
|
+
}, [mode, notifyChange, dispatchSelect]);
|
|
56654
|
+
var clearSelection = (0,external_react_.useCallback)(function () {
|
|
56655
|
+
var chart = chartRef.current;
|
|
56656
|
+
if (chart === null || chart === void 0 ? void 0 : chart.dispatchAction) {
|
|
56657
|
+
chart.dispatchAction({
|
|
56658
|
+
type: 'unselect'
|
|
56659
|
+
});
|
|
56660
|
+
}
|
|
56661
|
+
var prev = selectedPoints;
|
|
56662
|
+
setSelectedPoints([]);
|
|
56663
|
+
notifyChange([], prev);
|
|
56664
|
+
}, [selectedPoints, notifyChange]);
|
|
56665
|
+
var isSelected = (0,external_react_.useCallback)(function (key) {
|
|
56666
|
+
var str = keyToString(key);
|
|
56667
|
+
return selectedPoints.some(function (p) {
|
|
56668
|
+
return keyToString(p) === str;
|
|
56669
|
+
});
|
|
56670
|
+
}, [selectedPoints]);
|
|
56671
|
+
return {
|
|
56672
|
+
selectedPoints: selectedPoints,
|
|
56673
|
+
hasSelection: selectedPoints.length > 0,
|
|
56674
|
+
selectionCount: selectedPoints.length,
|
|
56675
|
+
select: select,
|
|
56676
|
+
deselect: deselect,
|
|
56677
|
+
selectMultiple: selectMultiple,
|
|
56678
|
+
deselectMultiple: deselectMultiple,
|
|
56679
|
+
toggle: toggle,
|
|
56680
|
+
invertSelection: invertSelection,
|
|
56681
|
+
selectAll: selectAll,
|
|
56682
|
+
clearSelection: clearSelection,
|
|
56683
|
+
isSelected: isSelected
|
|
56684
|
+
};
|
|
56685
|
+
}
|
|
56686
|
+
/* harmony default export */ const hooks_useChartSelection = ((/* unused pure expression or super */ null && (useChartSelection)));
|
|
56152
56687
|
;// ./src/hooks/useDataTransform.ts
|
|
56153
56688
|
var useDataTransform_assign = undefined && undefined.__assign || function () {
|
|
56154
56689
|
useDataTransform_assign = Object.assign || function (t) {
|
|
@@ -56740,6 +57275,8 @@ var hooks_spreadArray = undefined && undefined.__spreadArray || function (to, fr
|
|
|
56740
57275
|
|
|
56741
57276
|
|
|
56742
57277
|
|
|
57278
|
+
|
|
57279
|
+
|
|
56743
57280
|
// ============================================================================
|
|
56744
57281
|
// Hooks
|
|
56745
57282
|
// ============================================================================
|
|
@@ -57342,6 +57879,10 @@ function useChartTools(instance) {
|
|
|
57342
57879
|
|
|
57343
57880
|
// 图表下载 Hook
|
|
57344
57881
|
|
|
57882
|
+
// 图表历史记录 Hook (Undo/Redo)
|
|
57883
|
+
|
|
57884
|
+
// 图表选择 Hook
|
|
57885
|
+
|
|
57345
57886
|
// ============================================================================
|
|
57346
57887
|
// 导出
|
|
57347
57888
|
// ============================================================================
|
|
@@ -57365,7 +57906,9 @@ var hooks_version = '1.7.0';
|
|
|
57365
57906
|
// v1.7.0 新增
|
|
57366
57907
|
useDataZoom: useDataZoom,
|
|
57367
57908
|
useChartConnect: useChartConnect,
|
|
57368
|
-
useChartDownload: useChartDownload
|
|
57909
|
+
useChartDownload: useChartDownload,
|
|
57910
|
+
useChartHistory: useChartHistory,
|
|
57911
|
+
useChartSelection: useChartSelection
|
|
57369
57912
|
});
|
|
57370
57913
|
;// ./src/index.ts
|
|
57371
57914
|
/**
|