@agions/taroviz 1.11.5 → 2.0.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/CHANGELOG.md +245 -0
- package/README.md +31 -46
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/vendors.js +1 -1
- package/dist/cjs/vendors~echarts.js +1 -1
- package/dist/esm/index.js +1 -14270
- package/dist/esm/vendors.js +1 -16770
- package/dist/esm/vendors~echarts.js +1 -59417
- package/package.json +10 -15
- package/src/adapters/h5/index.ts +38 -38
- package/src/adapters/index.ts +32 -34
- package/src/adapters/types.ts +23 -55
- package/src/charts/boxplot/types.ts +2 -2
- package/src/charts/common/BaseChartWrapper.tsx +9 -7
- package/src/charts/createChartComponent.tsx +9 -21
- package/src/charts/createOptionChartComponent.tsx +32 -0
- package/src/charts/funnel/__tests__/index.test.tsx +99 -0
- package/src/charts/funnel/index.tsx +64 -0
- package/src/charts/funnel/types.ts +6 -0
- package/src/charts/graph/__tests__/index.test.tsx +116 -0
- package/src/charts/graph/index.tsx +70 -0
- package/src/charts/graph/types.ts +6 -0
- package/src/charts/heatmap/__tests__/index.test.tsx +139 -0
- package/src/charts/heatmap/index.tsx +107 -0
- package/src/charts/heatmap/types.ts +6 -0
- package/src/charts/index.ts +47 -57
- package/src/charts/liquid/__tests__/index.test.tsx +52 -0
- package/src/charts/liquid/index.tsx +7 -133
- package/src/charts/liquid/types.ts +6 -6
- package/src/charts/parallel/types.ts +3 -3
- package/src/charts/radar/__tests__/index.test.tsx +210 -0
- package/src/charts/radar/index.tsx +147 -0
- package/src/charts/radar/types.ts +13 -0
- package/src/charts/sankey/__tests__/index.test.tsx +124 -0
- package/src/charts/sankey/index.tsx +70 -0
- package/src/charts/sankey/types.ts +6 -0
- package/src/charts/tree/__tests__/index.test.tsx +71 -0
- package/src/charts/tree/index.tsx +1 -1
- package/src/charts/tree/types.ts +8 -8
- package/src/charts/types.ts +208 -106
- package/src/charts/wordcloud/__tests__/index.test.tsx +106 -0
- package/src/charts/wordcloud/index.tsx +79 -0
- package/src/charts/wordcloud/types.ts +6 -0
- package/src/components/DataFilter/index.tsx +7 -6
- package/src/core/animation/types.ts +6 -6
- package/src/core/components/Annotation.tsx +6 -6
- package/src/core/components/BaseChart.tsx +97 -133
- package/src/core/components/LazyChart.tsx +3 -8
- package/src/core/components/hooks/index.ts +6 -2
- package/src/core/components/hooks/usePerformance.ts +8 -2
- package/src/core/components/hooks/useVirtualScroll.ts +2 -1
- package/src/core/types/common.ts +2 -1
- package/src/core/types/platform.ts +1 -0
- package/src/core/utils/__tests__/deepClone.test.ts +317 -0
- package/src/core/utils/__tests__/index.test.ts +2 -1
- package/src/core/utils/chartInstances.ts +13 -0
- package/src/core/utils/common.ts +20 -36
- package/src/core/utils/deepClone.ts +114 -0
- package/src/core/utils/download.ts +22 -28
- package/src/core/utils/drillDown.ts +1 -0
- package/src/core/utils/events.ts +12 -0
- package/src/core/utils/export/ExportUtils.ts +2 -1
- package/src/core/utils/format.ts +44 -0
- package/src/core/utils/index.ts +18 -159
- package/src/core/utils/merge.ts +25 -0
- package/src/core/utils/performance/PerformanceAnalyzer.ts +3 -1
- package/src/core/utils/performance/hooks.ts +7 -0
- package/src/core/utils/performance/index.ts +2 -0
- package/src/{hooks → core/utils/performance}/useAnimation.ts +6 -5
- package/src/{hooks → core/utils/performance}/useDataZoom.ts +7 -2
- package/src/{hooks → core/utils/performance}/usePerformance.ts +39 -39
- package/src/{hooks → core/utils/performance}/usePerformanceHooks.ts +39 -39
- package/src/core/utils/runtime.ts +190 -0
- package/src/editor/components/ThemeSelector.tsx +3 -3
- package/src/hooks/chartConnectHelpers.ts +6 -0
- package/src/hooks/index.ts +54 -626
- package/src/hooks/types.ts +27 -0
- package/src/hooks/useChartAutoResize.ts +73 -0
- package/src/hooks/useChartConnect.ts +5 -1
- package/src/hooks/useChartDownload.ts +1 -1
- package/src/hooks/useChartHistory.ts +1 -3
- package/src/hooks/useChartInit.ts +59 -0
- package/src/hooks/useChartOptions.ts +259 -0
- package/src/hooks/useChartPerformance.ts +109 -0
- package/src/hooks/useChartSelection.ts +23 -12
- package/src/hooks/useChartTheme.ts +51 -0
- package/src/hooks/useDataTransform.ts +19 -4
- package/src/index.ts +5 -10
- package/src/react-dom.d.ts +3 -3
- package/src/themes/index.ts +30 -855
- package/src/themes/palettes/blue-green.ts +13 -0
- package/src/themes/palettes/chalk.ts +13 -0
- package/src/themes/palettes/cyber.ts +44 -0
- package/src/themes/palettes/dark.ts +52 -0
- package/src/themes/palettes/default.ts +52 -0
- package/src/themes/palettes/elegant.ts +34 -0
- package/src/themes/palettes/forest.ts +13 -0
- package/src/themes/palettes/glass.ts +49 -0
- package/src/themes/palettes/golden.ts +13 -0
- package/src/themes/palettes/neon.ts +43 -0
- package/src/themes/palettes/ocean.ts +39 -0
- package/src/themes/palettes/pastel.ts +37 -0
- package/src/themes/palettes/purple-passion.ts +13 -0
- package/src/themes/palettes/retro.ts +33 -0
- package/src/themes/palettes/sunset.ts +40 -0
- package/src/themes/palettes/walden.ts +13 -0
- package/src/themes/registry.ts +184 -0
- package/src/themes/types.ts +213 -0
- package/src/core/utils/codeGenerator/CodeGenerator.ts +0 -669
- package/src/core/utils/codeGenerator/index.ts +0 -13
- package/src/core/utils/codeGenerator/types.ts +0 -198
- package/src/core/utils/configGenerator/ConfigGenerator.ts +0 -583
- package/src/core/utils/configGenerator/index.ts +0 -13
- package/src/core/utils/configGenerator/types.ts +0 -449
- package/src/core/utils/debug/DebugPanel.tsx +0 -640
- package/src/core/utils/debug/debugger.ts +0 -322
- package/src/core/utils/debug/index.ts +0 -21
- package/src/core/utils/debug/types.ts +0 -142
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agions/taroviz",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "基于 Taro 和 ECharts 的多端图表组件库",
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "基于 Taro 和 ECharts 的多端图表组件库 - v2.0.0 大版本更新,新增 6 种图表类型",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
7
7
|
"module": "dist/esm/index.js",
|
|
@@ -42,10 +42,6 @@
|
|
|
42
42
|
"test:watch": "jest --watch",
|
|
43
43
|
"test:ci": "jest --ci --maxWorkers=50%",
|
|
44
44
|
"test:coverage": "jest --coverage",
|
|
45
|
-
"cypress:open": "cypress open",
|
|
46
|
-
"cypress:run": "cypress run",
|
|
47
|
-
"cypress:component": "cypress open --component",
|
|
48
|
-
"test:e2e": "cypress run --e2e",
|
|
49
45
|
"lint": "eslint src --ext .ts,.tsx",
|
|
50
46
|
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
51
47
|
"lint:prettier": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
|
|
@@ -86,24 +82,24 @@
|
|
|
86
82
|
"@commitlint/cli": "^19.0.0",
|
|
87
83
|
"@commitlint/config-conventional": "^19.0.0",
|
|
88
84
|
"@release-it/conventional-changelog": "^8.0.0",
|
|
89
|
-
"@testing-library/cypress": "^10.1.0",
|
|
90
85
|
"@testing-library/dom": "^10.4.1",
|
|
91
86
|
"@testing-library/jest-dom": "^6.9.1",
|
|
92
87
|
"@testing-library/react": "^16.3.0",
|
|
93
88
|
"@types/jest": "^29.5.12",
|
|
94
|
-
"@types/node": "^20.
|
|
89
|
+
"@types/node": "^20.19.39",
|
|
95
90
|
"@types/react": "^18.2.61",
|
|
96
91
|
"@types/react-dom": "^18.3.7",
|
|
97
92
|
"@types/testing-library__jest-dom": "^5.14.9",
|
|
98
93
|
"@typescript-eslint/eslint-plugin": "^8.59.1",
|
|
99
94
|
"@typescript-eslint/parser": "^8.59.1",
|
|
100
|
-
"ajv": "^8.
|
|
95
|
+
"ajv": "^8.20.0",
|
|
96
|
+
"ajv-formats": "^3.0.1",
|
|
101
97
|
"babel-loader": "^10.0.0",
|
|
102
98
|
"clean-webpack-plugin": "^4.0.0",
|
|
103
99
|
"commitizen": "^4.3.0",
|
|
104
100
|
"core-js": "3.41.0",
|
|
105
101
|
"css-loader": "^7.1.2",
|
|
106
|
-
"
|
|
102
|
+
"echarts": "^5.6.0",
|
|
107
103
|
"eslint": "^9.39.4",
|
|
108
104
|
"eslint-config-prettier": "^10.1.8",
|
|
109
105
|
"eslint-import-resolver-typescript": "^4.3.2",
|
|
@@ -120,6 +116,7 @@
|
|
|
120
116
|
"marked": "^12.0.2",
|
|
121
117
|
"mini-css-extract-plugin": "^2.9.2",
|
|
122
118
|
"prettier": "^3.2.5",
|
|
119
|
+
"react": "^18.2.0",
|
|
123
120
|
"react-dom": "^18.3.1",
|
|
124
121
|
"release-it": "^17.0.0",
|
|
125
122
|
"rimraf": "^5.0.5",
|
|
@@ -130,13 +127,14 @@
|
|
|
130
127
|
"ts-loader": "^9.5.2",
|
|
131
128
|
"typedoc": "^0.28.2",
|
|
132
129
|
"typedoc-plugin-markdown": "^3.17.1",
|
|
133
|
-
"typescript": "^5.
|
|
130
|
+
"typescript": "^5.9.3",
|
|
134
131
|
"vitepress": "^1.6.4",
|
|
135
132
|
"webpack": "^5.90.3",
|
|
136
133
|
"webpack-bundle-analyzer": "^4.10.2",
|
|
137
134
|
"webpack-cli": "^5.1.4",
|
|
138
135
|
"webpack-dev-server": "^5.0.4",
|
|
139
|
-
"whatwg-fetch": "^3.6.20"
|
|
136
|
+
"whatwg-fetch": "^3.6.20",
|
|
137
|
+
"zrender": "^5.6.1"
|
|
140
138
|
},
|
|
141
139
|
"dependencies": {
|
|
142
140
|
"@babel/runtime": "^7.28.4",
|
|
@@ -147,7 +145,6 @@
|
|
|
147
145
|
"@tarojs/runtime": "^3.6.0",
|
|
148
146
|
"@tarojs/taro": "^3.6.0",
|
|
149
147
|
"echarts": "^5.4.3",
|
|
150
|
-
"react": "^18.2.0",
|
|
151
148
|
"zrender": "^5.4.3"
|
|
152
149
|
},
|
|
153
150
|
"peerDependenciesMeta": {
|
|
@@ -179,8 +176,6 @@
|
|
|
179
176
|
"url": "https://github.com/agions/taroviz/issues"
|
|
180
177
|
},
|
|
181
178
|
"overrides": {
|
|
182
|
-
"ajv": "^8.18.0",
|
|
183
|
-
"ajv-formats": "^3.0.0",
|
|
184
179
|
"brace-expansion": "^3.0.1",
|
|
185
180
|
"esbuild": "^0.24.2",
|
|
186
181
|
"systeminformation": "^5.22.0",
|
package/src/adapters/h5/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ interface ExtendedH5AdapterOptions extends H5AdapterOptions {
|
|
|
23
23
|
height?: number | string;
|
|
24
24
|
theme?: string | object;
|
|
25
25
|
option?: EChartsOption;
|
|
26
|
-
onInit?: (
|
|
26
|
+
onInit?: (_instance: EChartsType) => void;
|
|
27
27
|
containerRef?: HTMLElement | { current: HTMLElement | null };
|
|
28
28
|
direction?: 'ltr' | 'rtl';
|
|
29
29
|
}
|
|
@@ -46,7 +46,7 @@ class H5Adapter implements Adapter {
|
|
|
46
46
|
/**
|
|
47
47
|
* 图表实例
|
|
48
48
|
*/
|
|
49
|
-
private
|
|
49
|
+
private _instance: EChartsType | null = null;
|
|
50
50
|
private options: ExtendedH5AdapterOptions;
|
|
51
51
|
private containerRef: ExtendedH5AdapterOptions['containerRef'] = undefined;
|
|
52
52
|
private canvasId: string;
|
|
@@ -70,8 +70,8 @@ class H5Adapter implements Adapter {
|
|
|
70
70
|
* 初始化图表
|
|
71
71
|
*/
|
|
72
72
|
init(_options?: EChartsOption): EChartsType {
|
|
73
|
-
if (this.
|
|
74
|
-
return this.
|
|
73
|
+
if (this._instance) {
|
|
74
|
+
return this._instance;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// 获取容器元素
|
|
@@ -85,16 +85,16 @@ class H5Adapter implements Adapter {
|
|
|
85
85
|
|
|
86
86
|
// 初始化图表
|
|
87
87
|
|
|
88
|
-
this.
|
|
88
|
+
this._instance = echarts.init(container as HTMLElement, this.options.theme, {
|
|
89
89
|
// 性能优化选项
|
|
90
90
|
useDirtyRect: true, // 使用脏矩形渲染,减少重绘区域
|
|
91
91
|
renderer: this.options.renderer || 'canvas',
|
|
92
92
|
}) as unknown as EChartsType;
|
|
93
93
|
|
|
94
94
|
// 设置性能优化相关的全局配置
|
|
95
|
-
if (this.
|
|
95
|
+
if (this._instance) {
|
|
96
96
|
// 渐进式渲染配置
|
|
97
|
-
this.
|
|
97
|
+
this._instance.setOption(
|
|
98
98
|
{
|
|
99
99
|
animation: this.options.option?.animation !== false,
|
|
100
100
|
animationDurationUpdate: 300,
|
|
@@ -107,31 +107,31 @@ class H5Adapter implements Adapter {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
// 设置初始化选项,使用lazyUpdate优化性能
|
|
110
|
-
if (this.options.option && this.
|
|
111
|
-
this.
|
|
110
|
+
if (this.options.option && this._instance) {
|
|
111
|
+
this._instance.setOption(this.options.option, false, true);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
// 执行初始化回调
|
|
115
|
-
if (this.options.onInit && this.
|
|
116
|
-
this.options.onInit(this.
|
|
115
|
+
if (this.options.onInit && this._instance) {
|
|
116
|
+
this.options.onInit(this._instance);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
return this.
|
|
119
|
+
return this._instance as EChartsType;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* 获取图表实例
|
|
124
124
|
*/
|
|
125
125
|
getInstance(): EChartsType | null {
|
|
126
|
-
return this.
|
|
126
|
+
return this._instance;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* 设置图表选项
|
|
131
131
|
*/
|
|
132
132
|
setOption(option: EChartsOption, notMerge?: boolean, lazyUpdate?: boolean): void {
|
|
133
|
-
if (this.
|
|
134
|
-
this.
|
|
133
|
+
if (this._instance) {
|
|
134
|
+
this._instance.setOption(option, notMerge, lazyUpdate);
|
|
135
135
|
} else {
|
|
136
136
|
this.options.option = option;
|
|
137
137
|
}
|
|
@@ -142,9 +142,9 @@ class H5Adapter implements Adapter {
|
|
|
142
142
|
*/
|
|
143
143
|
setTheme(theme: string | object): void {
|
|
144
144
|
this.options.theme = theme;
|
|
145
|
-
if (this.
|
|
145
|
+
if (this._instance) {
|
|
146
146
|
// 使用类型断言来访问私有方法
|
|
147
|
-
(this.
|
|
147
|
+
(this._instance as any).setTheme?.(theme);
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -152,14 +152,14 @@ class H5Adapter implements Adapter {
|
|
|
152
152
|
* 获取图表宽度
|
|
153
153
|
*/
|
|
154
154
|
getWidth(): number {
|
|
155
|
-
return this.
|
|
155
|
+
return this._instance?.getWidth() || 0;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
/**
|
|
159
159
|
* 获取图表高度
|
|
160
160
|
*/
|
|
161
161
|
getHeight(): number {
|
|
162
|
-
return this.
|
|
162
|
+
return this._instance?.getHeight() || 0;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
/**
|
|
@@ -178,15 +178,15 @@ class H5Adapter implements Adapter {
|
|
|
178
178
|
pixelRatio?: number;
|
|
179
179
|
backgroundColor?: string;
|
|
180
180
|
}): string | undefined {
|
|
181
|
-
return this.
|
|
181
|
+
return this._instance?.getDataURL(opts);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
185
|
* 清空图表
|
|
186
186
|
*/
|
|
187
187
|
clear(): void {
|
|
188
|
-
if (this.
|
|
189
|
-
this.
|
|
188
|
+
if (this._instance) {
|
|
189
|
+
this._instance.clear();
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
|
|
@@ -194,8 +194,8 @@ class H5Adapter implements Adapter {
|
|
|
194
194
|
* 绑定事件
|
|
195
195
|
*/
|
|
196
196
|
on(event: string, handler: EventHandler): void {
|
|
197
|
-
if (this.
|
|
198
|
-
this.
|
|
197
|
+
if (this._instance) {
|
|
198
|
+
this._instance.on(event, handler as any);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
@@ -203,8 +203,8 @@ class H5Adapter implements Adapter {
|
|
|
203
203
|
* 解绑事件
|
|
204
204
|
*/
|
|
205
205
|
off(event: string, handler?: EventHandler): void {
|
|
206
|
-
if (this.
|
|
207
|
-
this.
|
|
206
|
+
if (this._instance) {
|
|
207
|
+
this._instance.off(event, handler as any);
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
|
|
@@ -212,8 +212,8 @@ class H5Adapter implements Adapter {
|
|
|
212
212
|
* 显示加载动画
|
|
213
213
|
*/
|
|
214
214
|
showLoading(opts?: object): void {
|
|
215
|
-
if (this.
|
|
216
|
-
this.
|
|
215
|
+
if (this._instance) {
|
|
216
|
+
this._instance.showLoading(opts);
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
|
|
@@ -221,8 +221,8 @@ class H5Adapter implements Adapter {
|
|
|
221
221
|
* 隐藏加载动画
|
|
222
222
|
*/
|
|
223
223
|
hideLoading(): void {
|
|
224
|
-
if (this.
|
|
225
|
-
this.
|
|
224
|
+
if (this._instance) {
|
|
225
|
+
this._instance.hideLoading();
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
|
|
@@ -250,9 +250,9 @@ class H5Adapter implements Adapter {
|
|
|
250
250
|
* 销毁图表
|
|
251
251
|
*/
|
|
252
252
|
dispose(): void {
|
|
253
|
-
if (this.
|
|
254
|
-
this.
|
|
255
|
-
this.
|
|
253
|
+
if (this._instance) {
|
|
254
|
+
this._instance.dispose();
|
|
255
|
+
this._instance = null;
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
|
|
@@ -260,8 +260,8 @@ class H5Adapter implements Adapter {
|
|
|
260
260
|
* 触发图表行为
|
|
261
261
|
*/
|
|
262
262
|
dispatchAction(payload: { type: string; [key: string]: unknown }): void {
|
|
263
|
-
if (this.
|
|
264
|
-
this.
|
|
263
|
+
if (this._instance) {
|
|
264
|
+
this._instance.dispatchAction(payload);
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
|
|
@@ -269,15 +269,15 @@ class H5Adapter implements Adapter {
|
|
|
269
269
|
* 获取DataURL
|
|
270
270
|
*/
|
|
271
271
|
getDataURL(opts?: object): string | undefined {
|
|
272
|
-
return this.
|
|
272
|
+
return this._instance?.getDataURL(opts);
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
/**
|
|
276
276
|
* 处理图表大小变化
|
|
277
277
|
*/
|
|
278
278
|
resize(opts?: object): void {
|
|
279
|
-
if (this.
|
|
280
|
-
this.
|
|
279
|
+
if (this._instance) {
|
|
280
|
+
this._instance.resize(opts);
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
283
|
|
package/src/adapters/index.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { PlatformType } from '../core';
|
|
9
|
+
import { detectRuntime } from '../core/utils/runtime';
|
|
10
|
+
import type { RuntimeInfo } from '../core/utils/runtime';
|
|
9
11
|
import type { AdapterOptions, Adapter } from './types';
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -31,40 +33,37 @@ const PLATFORM_CONFIGS: Record<PlatformType, PlatformConfig> = {
|
|
|
31
33
|
[PlatformType.HARMONY]: { name: 'HarmonyOS', requireComponent: true },
|
|
32
34
|
};
|
|
33
35
|
|
|
36
|
+
/** Map RuntimeInfo miniAppType to PlatformType */
|
|
37
|
+
const MINI_APP_TO_PLATFORM: Record<string, PlatformType> = {
|
|
38
|
+
weapp: PlatformType.WEAPP,
|
|
39
|
+
alipay: PlatformType.ALIPAY,
|
|
40
|
+
swan: PlatformType.SWAN,
|
|
41
|
+
tt: PlatformType.TT,
|
|
42
|
+
qq: PlatformType.QQ,
|
|
43
|
+
jd: PlatformType.JD,
|
|
44
|
+
dd: PlatformType.DD,
|
|
45
|
+
qywx: PlatformType.QYWX,
|
|
46
|
+
lark: PlatformType.LARK,
|
|
47
|
+
kwai: PlatformType.KWAI,
|
|
48
|
+
};
|
|
49
|
+
|
|
34
50
|
/**
|
|
35
51
|
* 检测当前运行的平台环境
|
|
52
|
+
*
|
|
53
|
+
* Delegates to the unified detectRuntime() and maps the result to PlatformType.
|
|
54
|
+
* Also checks for HarmonyOS via userAgent, which is not a mini-app.
|
|
36
55
|
*/
|
|
37
56
|
export function detectPlatform(): PlatformType {
|
|
38
|
-
|
|
39
|
-
|
|
57
|
+
const runtime: RuntimeInfo = detectRuntime();
|
|
58
|
+
|
|
59
|
+
if (runtime.platform === 'miniapp' && runtime.miniAppType) {
|
|
60
|
+
return MINI_APP_TO_PLATFORM[runtime.miniAppType] ?? PlatformType.H5;
|
|
40
61
|
}
|
|
41
62
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
tt?: { getSystemInfoSync?: unknown; env?: { appName?: string } };
|
|
47
|
-
qq?: { getSystemInfoSync?: unknown };
|
|
48
|
-
jd?: { getSystemInfoSync?: unknown };
|
|
49
|
-
dd?: { getSystemInfoSync?: unknown };
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const checks: Array<{ test: () => boolean; platform: PlatformType }> = [
|
|
53
|
-
{ test: () => !!win.wx?.getSystemInfoSync && !win.wx?.qy, platform: PlatformType.WEAPP },
|
|
54
|
-
{ test: () => !!win.my?.getSystemInfoSync, platform: PlatformType.ALIPAY },
|
|
55
|
-
{ test: () => !!win.swan?.getSystemInfoSync, platform: PlatformType.SWAN },
|
|
56
|
-
{ test: () => !!win.tt?.getSystemInfoSync, platform: PlatformType.TT },
|
|
57
|
-
{ test: () => !!win.qq?.getSystemInfoSync, platform: PlatformType.QQ },
|
|
58
|
-
{ test: () => !!win.jd?.getSystemInfoSync, platform: PlatformType.JD },
|
|
59
|
-
{ test: () => !!win.dd?.getSystemInfoSync, platform: PlatformType.DD },
|
|
60
|
-
{ test: () => !!win.wx?.qy, platform: PlatformType.QYWX },
|
|
61
|
-
{ test: () => win.tt?.env?.appName === 'lark', platform: PlatformType.LARK },
|
|
62
|
-
{ test: () => navigator.userAgent.includes('HarmonyOS'), platform: PlatformType.HARMONY },
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
for (const check of checks) {
|
|
66
|
-
if (check.test()) {
|
|
67
|
-
return check.platform;
|
|
63
|
+
// HarmonyOS: detected via userAgent in browser context
|
|
64
|
+
if (runtime.platform === 'browser' && typeof navigator !== 'undefined') {
|
|
65
|
+
if (navigator.userAgent.includes('HarmonyOS')) {
|
|
66
|
+
return PlatformType.HARMONY;
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
|
|
@@ -75,13 +74,12 @@ export function detectPlatform(): PlatformType {
|
|
|
75
74
|
* 判断运行环境
|
|
76
75
|
*/
|
|
77
76
|
export function getEnv(): 'h5' | 'weapp' | 'unknown' {
|
|
78
|
-
|
|
77
|
+
const runtime = detectRuntime();
|
|
78
|
+
|
|
79
|
+
if (runtime.isBrowser) {
|
|
79
80
|
return 'h5';
|
|
80
81
|
}
|
|
81
|
-
if (
|
|
82
|
-
typeof global !== 'undefined' &&
|
|
83
|
-
(global as Global & { wx?: { getSystemInfoSync?: unknown } })?.wx?.getSystemInfoSync
|
|
84
|
-
) {
|
|
82
|
+
if (runtime.isMiniApp && runtime.miniAppType === 'weapp') {
|
|
85
83
|
return 'weapp';
|
|
86
84
|
}
|
|
87
85
|
return 'unknown';
|
|
@@ -131,7 +129,7 @@ export async function getAdapter(options: AdapterOptions): Promise<Adapter> {
|
|
|
131
129
|
}
|
|
132
130
|
case PlatformType.HARMONY: {
|
|
133
131
|
const { HarmonyAdapter } = (await import('./harmony')) as unknown as {
|
|
134
|
-
HarmonyAdapter: { create: (
|
|
132
|
+
HarmonyAdapter: { create: (_opts: object) => Adapter };
|
|
135
133
|
};
|
|
136
134
|
return HarmonyAdapter.create(options);
|
|
137
135
|
}
|
package/src/adapters/types.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface AdapterOptions {
|
|
|
22
22
|
theme?: string | object;
|
|
23
23
|
option?: unknown;
|
|
24
24
|
|
|
25
|
-
onInit?: (
|
|
25
|
+
onInit?: (_instance: EChartsType) => void;
|
|
26
26
|
style?: CSSProperties;
|
|
27
27
|
autoResize?: boolean;
|
|
28
28
|
devicePixelRatio?: number;
|
|
@@ -49,57 +49,25 @@ export interface WeappAdapterOptions extends AdapterOptions {
|
|
|
49
49
|
component?: object;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
*/
|
|
55
|
-
export
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
*/
|
|
65
|
-
export
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
*/
|
|
75
|
-
export interface TTAdapterOptions extends AdapterOptions {}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* QQ小程序适配器选项
|
|
79
|
-
*/
|
|
80
|
-
export interface QQAdapterOptions extends AdapterOptions {}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* 京东小程序适配器选项
|
|
84
|
-
*/
|
|
85
|
-
export interface JDAdapterOptions extends AdapterOptions {}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* 快手小程序适配器选项
|
|
89
|
-
*/
|
|
90
|
-
export interface KwaiAdapterOptions extends AdapterOptions {}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* 企业微信小程序适配器选项
|
|
94
|
-
*/
|
|
95
|
-
export interface QywxAdapterOptions extends AdapterOptions {}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* 飞书小程序适配器选项
|
|
99
|
-
*/
|
|
100
|
-
export interface LarkAdapterOptions extends AdapterOptions {}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* 小程序通用适配器选项
|
|
104
|
-
*/
|
|
105
|
-
export interface MiniAppAdapterOptions extends AdapterOptions {}
|
|
52
|
+
/** 支付宝小程序适配器选项 */
|
|
53
|
+
export type AlipayAdapterOptions = AdapterOptions;
|
|
54
|
+
/** 百度小程序适配器选项 */
|
|
55
|
+
export type SwanAdapterOptions = AdapterOptions;
|
|
56
|
+
/** 鸿蒙OS适配器选项 */
|
|
57
|
+
export type HarmonyAdapterOptions = AdapterOptions;
|
|
58
|
+
/** 钉钉小程序适配器选项 */
|
|
59
|
+
export type DDAdapterOptions = AdapterOptions;
|
|
60
|
+
/** 抖音小程序适配器选项 */
|
|
61
|
+
export type TTAdapterOptions = AdapterOptions;
|
|
62
|
+
/** QQ小程序适配器选项 */
|
|
63
|
+
export type QQAdapterOptions = AdapterOptions;
|
|
64
|
+
/** 京东小程序适配器选项 */
|
|
65
|
+
export type JDAdapterOptions = AdapterOptions;
|
|
66
|
+
/** 快手小程序适配器选项 */
|
|
67
|
+
export type KwaiAdapterOptions = AdapterOptions;
|
|
68
|
+
/** 企业微信小程序适配器选项 */
|
|
69
|
+
export type QywxAdapterOptions = AdapterOptions;
|
|
70
|
+
/** 飞书小程序适配器选项 */
|
|
71
|
+
export type LarkAdapterOptions = AdapterOptions;
|
|
72
|
+
/** 小程序通用适配器选项 */
|
|
73
|
+
export type MiniAppAdapterOptions = AdapterOptions;
|
|
@@ -10,11 +10,11 @@ export type BoxplotChartProps = {
|
|
|
10
10
|
height?: string | number;
|
|
11
11
|
className?: string;
|
|
12
12
|
style?: React.CSSProperties;
|
|
13
|
-
onEvents?: Record<string, (
|
|
13
|
+
onEvents?: Record<string, (_params: ECElementEvent) => void>;
|
|
14
14
|
loading?: boolean;
|
|
15
15
|
loadingOption?: LoadingOptions;
|
|
16
16
|
theme?: string;
|
|
17
|
-
onChartReady?: (
|
|
17
|
+
onChartReady?: (_chart: EChartsType) => void;
|
|
18
18
|
opts?: {
|
|
19
19
|
devicePixelRatio?: number;
|
|
20
20
|
renderer?: 'canvas' | 'svg';
|
|
@@ -64,7 +64,7 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
|
|
|
64
64
|
const seriesData = useMemo(() => extractSeriesData(option), [option]);
|
|
65
65
|
const ariaLabel = useMemo(() => buildAriaLabel(chartType, option), [chartType, option]);
|
|
66
66
|
|
|
67
|
-
// Keyboard
|
|
67
|
+
// Keyboard _handler for zoom/pan — attached to the chart container
|
|
68
68
|
const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
69
69
|
const instance = chartInstance.current;
|
|
70
70
|
if (!instance) return;
|
|
@@ -161,12 +161,12 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
|
|
|
161
161
|
chartInstance.current = instance;
|
|
162
162
|
|
|
163
163
|
if (onEvents) {
|
|
164
|
-
Object.entries(onEvents).forEach(([
|
|
164
|
+
Object.entries(onEvents).forEach(([_eventName, _handler]) => {
|
|
165
165
|
(
|
|
166
166
|
instance as unknown as {
|
|
167
|
-
on: (
|
|
167
|
+
on: (_event: string, _handler: (..._args: unknown[]) => void) => void;
|
|
168
168
|
}
|
|
169
|
-
).on(
|
|
169
|
+
).on(_eventName, _handler);
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -181,6 +181,7 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
|
|
|
181
181
|
});
|
|
182
182
|
|
|
183
183
|
const adapter = await getAdapter(initConfig);
|
|
184
|
+
const adapterRef = adapter; // store for cleanup
|
|
184
185
|
|
|
185
186
|
if (!isMountedRef.current) {
|
|
186
187
|
return;
|
|
@@ -189,11 +190,12 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
|
|
|
189
190
|
adapter.init();
|
|
190
191
|
|
|
191
192
|
cleanupRef.current = () => {
|
|
193
|
+
adapterRef.dispose?.();
|
|
192
194
|
const instance = chartInstance.current;
|
|
193
195
|
if (instance) {
|
|
194
196
|
if (onEvents) {
|
|
195
|
-
Object.entries(onEvents).forEach(([
|
|
196
|
-
(instance as unknown as { off: (
|
|
197
|
+
Object.entries(onEvents).forEach(([_eventName]) => {
|
|
198
|
+
(instance as unknown as { off: (_event: string) => void }).off(_eventName);
|
|
197
199
|
});
|
|
198
200
|
}
|
|
199
201
|
instance.dispose();
|
|
@@ -286,7 +288,7 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
|
|
|
286
288
|
|
|
287
289
|
{/*
|
|
288
290
|
Chart container with role="application" + keyboard navigation.
|
|
289
|
-
role="application" tells assistive tech to pass through keyboard
|
|
291
|
+
role="application" tells assistive tech to pass through keyboard _events.
|
|
290
292
|
aria-describedby links to the hidden data table above.
|
|
291
293
|
*/}
|
|
292
294
|
<div
|
|
@@ -9,37 +9,25 @@ import BaseChartWrapper from './common/BaseChartWrapper';
|
|
|
9
9
|
import type { BaseChartProps } from './types';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* 创建图表组件
|
|
13
13
|
* @param displayName 组件名称
|
|
14
14
|
* @param chartType ECharts 图表类型
|
|
15
|
+
* @param needOptionCast 是否需要 option 类型转换(用于 boxplot、parallel 等)
|
|
15
16
|
* @returns 带 displayName 的 memo 组件
|
|
16
17
|
*/
|
|
17
18
|
export function createChartComponent<P extends BaseChartProps = BaseChartProps>(
|
|
18
19
|
displayName: string,
|
|
19
|
-
chartType: string
|
|
20
|
-
|
|
21
|
-
const Chart: React.FC<P> = memo((props) => (
|
|
22
|
-
<BaseChartWrapper {...(props as unknown as BaseChartProps)} chartType={chartType} />
|
|
23
|
-
));
|
|
24
|
-
Chart.displayName = displayName;
|
|
25
|
-
return Chart;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 创建需要 EChartsOption 类型转换的图表组件
|
|
30
|
-
* 用于 boxplot、parallel 等使用自定义 Props 类型但需要转换 option 的图表
|
|
31
|
-
* @param displayName 组件名称
|
|
32
|
-
* @param chartType ECharts 图表类型
|
|
33
|
-
* @returns 带 displayName 的 memo 组件
|
|
34
|
-
*/
|
|
35
|
-
export function createChartComponentWithOptionCast<P extends Record<string, unknown>>(
|
|
36
|
-
displayName: string,
|
|
37
|
-
chartType: string
|
|
20
|
+
chartType: string,
|
|
21
|
+
needOptionCast = false
|
|
38
22
|
): React.FC<P> {
|
|
39
23
|
const Chart: React.FC<P> = memo((props) => (
|
|
40
24
|
<BaseChartWrapper
|
|
41
25
|
{...(props as unknown as BaseChartProps)}
|
|
42
|
-
option={
|
|
26
|
+
option={
|
|
27
|
+
needOptionCast
|
|
28
|
+
? ((props as { option?: EChartsOption }).option as EChartsOption)
|
|
29
|
+
: (props as unknown as BaseChartProps).option
|
|
30
|
+
}
|
|
43
31
|
chartType={chartType}
|
|
44
32
|
/>
|
|
45
33
|
));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory for charts that follow the buildXxxOption + render pattern.
|
|
3
|
+
* Eliminates the repeated null-check + BaseChart wrapper code.
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import BaseChart from '@/core/components/BaseChart';
|
|
7
|
+
import type { BaseChartProps } from './types';
|
|
8
|
+
|
|
9
|
+
interface OptionBuilderProps {
|
|
10
|
+
optionMerge?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates a chart component from a buildOption function.
|
|
15
|
+
* @param displayName Component display name
|
|
16
|
+
* @param buildOption Function that builds ECharts option from props, returns null if invalid
|
|
17
|
+
*/
|
|
18
|
+
export function createOptionChartComponent<Props extends OptionBuilderProps>(
|
|
19
|
+
displayName: string,
|
|
20
|
+
buildOption: (props: Props) => Record<string, unknown> | null
|
|
21
|
+
): React.FC<Props & Omit<BaseChartProps, 'option' | 'data'>> {
|
|
22
|
+
const Component: React.FC<Props & Omit<BaseChartProps, 'option' | 'data'>> = (props) => {
|
|
23
|
+
const { optionMerge, ...rest } = props;
|
|
24
|
+
const option = buildOption(props as Props);
|
|
25
|
+
if (!option) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return <BaseChart option={option as any} {...(rest as BaseChartProps)} />;
|
|
29
|
+
};
|
|
30
|
+
Component.displayName = displayName;
|
|
31
|
+
return Component;
|
|
32
|
+
}
|