@agions/taroviz 1.11.1 → 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.
Files changed (164) hide show
  1. package/CHANGELOG.md +245 -0
  2. package/README.md +104 -302
  3. package/dist/cjs/index.js +1 -1
  4. package/dist/cjs/vendors.js +1 -0
  5. package/dist/cjs/vendors~echarts.js +1 -0
  6. package/dist/esm/index.js +1 -58151
  7. package/dist/esm/vendors.js +1 -0
  8. package/dist/esm/vendors~echarts.js +1 -0
  9. package/package.json +19 -25
  10. package/src/adapters/MiniAppAdapter.ts +136 -0
  11. package/src/adapters/__tests__/index.test.ts +1 -1
  12. package/src/adapters/h5/__tests__/index.test.ts +4 -2
  13. package/src/adapters/h5/index.ts +63 -64
  14. package/src/adapters/harmony/index.ts +23 -245
  15. package/src/adapters/index.ts +49 -45
  16. package/src/adapters/swan/index.ts +6 -69
  17. package/src/adapters/tt/index.ts +7 -70
  18. package/src/adapters/types.ts +25 -58
  19. package/src/adapters/weapp/index.ts +6 -69
  20. package/src/charts/__tests__/testUtils.tsx +87 -0
  21. package/src/charts/boxplot/__tests__/index.test.tsx +49 -103
  22. package/src/charts/boxplot/index.tsx +2 -1
  23. package/src/charts/boxplot/types.ts +17 -16
  24. package/src/charts/common/BaseChartWrapper.tsx +90 -82
  25. package/src/charts/common/__mocks__/BaseChartWrapper.tsx +17 -0
  26. package/src/charts/createChartComponent.tsx +36 -0
  27. package/src/charts/createOptionChartComponent.tsx +32 -0
  28. package/src/charts/funnel/__tests__/index.test.tsx +99 -0
  29. package/src/charts/funnel/index.tsx +60 -10
  30. package/src/charts/funnel/types.ts +6 -0
  31. package/src/charts/graph/__tests__/index.test.tsx +102 -33
  32. package/src/charts/graph/index.tsx +66 -9
  33. package/src/charts/graph/types.ts +6 -0
  34. package/src/charts/heatmap/__tests__/index.test.tsx +139 -0
  35. package/src/charts/heatmap/index.tsx +103 -10
  36. package/src/charts/heatmap/types.ts +6 -0
  37. package/src/charts/index.ts +74 -26
  38. package/src/charts/liquid/__tests__/index.test.tsx +52 -0
  39. package/src/charts/liquid/index.tsx +239 -182
  40. package/src/charts/liquid/types.ts +11 -11
  41. package/src/charts/parallel/__tests__/index.test.tsx +40 -67
  42. package/src/charts/parallel/index.tsx +2 -1
  43. package/src/charts/parallel/types.ts +19 -18
  44. package/src/charts/radar/__tests__/index.test.tsx +210 -0
  45. package/src/charts/radar/index.tsx +143 -10
  46. package/src/charts/radar/types.ts +13 -0
  47. package/src/charts/sankey/__tests__/index.test.tsx +124 -0
  48. package/src/charts/sankey/index.tsx +62 -10
  49. package/src/charts/sankey/types.ts +6 -0
  50. package/src/charts/tree/__tests__/index.test.tsx +71 -0
  51. package/src/charts/tree/index.tsx +5 -2
  52. package/src/charts/tree/types.ts +9 -9
  53. package/src/charts/types.ts +208 -106
  54. package/src/charts/utils.ts +9 -7
  55. package/src/charts/wordcloud/__tests__/index.test.tsx +98 -31
  56. package/src/charts/wordcloud/index.tsx +75 -9
  57. package/src/charts/wordcloud/types.ts +6 -0
  58. package/src/components/DataFilter/index.tsx +32 -10
  59. package/src/core/animation/types.ts +6 -6
  60. package/src/core/components/Annotation.tsx +6 -7
  61. package/src/core/components/BaseChart.tsx +110 -168
  62. package/src/core/components/ErrorBoundary.tsx +17 -4
  63. package/src/core/components/LazyChart.tsx +54 -55
  64. package/src/core/components/hooks/index.ts +6 -2
  65. package/src/core/components/hooks/useChartInit.ts +6 -3
  66. package/src/core/components/hooks/usePerformance.ts +8 -2
  67. package/src/core/components/hooks/useVirtualScroll.ts +2 -1
  68. package/src/core/index.ts +1 -1
  69. package/src/core/themes/ThemeManager.ts +1 -1
  70. package/src/core/types/common.ts +2 -1
  71. package/src/core/types/index.ts +0 -12
  72. package/src/core/types/platform.ts +3 -5
  73. package/src/core/utils/__tests__/deepClone.test.ts +317 -0
  74. package/src/core/utils/__tests__/index.test.ts +2 -1
  75. package/src/core/utils/chartInstances.ts +13 -0
  76. package/src/core/utils/common.ts +20 -29
  77. package/src/core/utils/deepClone.ts +114 -0
  78. package/src/core/utils/download.ts +128 -0
  79. package/src/core/utils/drillDown.ts +34 -353
  80. package/src/core/utils/drillDownHelpers.ts +426 -0
  81. package/src/core/utils/events.ts +12 -0
  82. package/src/core/utils/export/ExportUtils.ts +36 -67
  83. package/src/core/utils/format.ts +44 -0
  84. package/src/core/utils/index.ts +21 -154
  85. package/src/core/utils/merge.ts +25 -0
  86. package/src/core/utils/performance/PerformanceAnalyzer.ts +38 -21
  87. package/src/core/utils/performance/hooks.ts +7 -0
  88. package/src/core/utils/performance/index.ts +2 -0
  89. package/src/{hooks → core/utils/performance}/useAnimation.ts +45 -41
  90. package/src/core/utils/performance/useDataZoom.ts +324 -0
  91. package/src/{hooks → core/utils/performance}/usePerformance.ts +49 -41
  92. package/src/core/utils/performance/usePerformanceHooks.ts +278 -0
  93. package/src/core/utils/performanceUtils.ts +310 -0
  94. package/src/core/utils/runtime.ts +190 -0
  95. package/src/core/utils/setOptionUtils.ts +59 -0
  96. package/src/core/version.ts +14 -0
  97. package/src/editor/EnhancedThemeEditor.tsx +362 -540
  98. package/src/editor/ThemeEditor.tsx +55 -321
  99. package/src/editor/components/ThemeBasicSettings.tsx +113 -0
  100. package/src/editor/components/ThemeColorEditor.tsx +105 -0
  101. package/src/editor/components/ThemeSelector.tsx +70 -0
  102. package/src/editor/hooks/useThemeEditorState.ts +201 -0
  103. package/src/editor/index.ts +10 -2
  104. package/src/hooks/__tests__/index.test.tsx +3 -1
  105. package/src/hooks/chartConnectHelpers.ts +341 -0
  106. package/src/hooks/index.ts +55 -660
  107. package/src/hooks/types.ts +189 -0
  108. package/src/hooks/useChartAutoResize.ts +73 -0
  109. package/src/hooks/useChartConnect.ts +92 -238
  110. package/src/hooks/useChartDownload.ts +25 -27
  111. package/src/hooks/useChartHistory.ts +34 -49
  112. package/src/hooks/useChartInit.ts +59 -0
  113. package/src/hooks/useChartOptions.ts +259 -0
  114. package/src/hooks/useChartPerformance.ts +109 -0
  115. package/src/hooks/useChartSelection.ts +52 -49
  116. package/src/hooks/useChartTheme.ts +51 -0
  117. package/src/hooks/useDataTransform.ts +19 -4
  118. package/src/hooks/utils/chartDownloadUtils.ts +40 -53
  119. package/src/hooks/utils/dataTransformUtils.ts +22 -0
  120. package/src/index.ts +48 -34
  121. package/src/main.tsx +4 -9
  122. package/src/react-dom.d.ts +3 -3
  123. package/src/themes/index.ts +30 -855
  124. package/src/themes/palettes/blue-green.ts +13 -0
  125. package/src/themes/palettes/chalk.ts +13 -0
  126. package/src/themes/palettes/cyber.ts +44 -0
  127. package/src/themes/palettes/dark.ts +52 -0
  128. package/src/themes/palettes/default.ts +52 -0
  129. package/src/themes/palettes/elegant.ts +34 -0
  130. package/src/themes/palettes/forest.ts +13 -0
  131. package/src/themes/palettes/glass.ts +49 -0
  132. package/src/themes/palettes/golden.ts +13 -0
  133. package/src/themes/palettes/neon.ts +43 -0
  134. package/src/themes/palettes/ocean.ts +39 -0
  135. package/src/themes/palettes/pastel.ts +37 -0
  136. package/src/themes/palettes/purple-passion.ts +13 -0
  137. package/src/themes/palettes/retro.ts +33 -0
  138. package/src/themes/palettes/sunset.ts +40 -0
  139. package/src/themes/palettes/walden.ts +13 -0
  140. package/src/themes/registry.ts +184 -0
  141. package/src/themes/types.ts +213 -0
  142. package/src/charts/bar/__tests__/index.test.tsx +0 -113
  143. package/src/charts/bar/index.tsx +0 -14
  144. package/src/charts/candlestick/__tests__/index.test.tsx +0 -40
  145. package/src/charts/candlestick/index.tsx +0 -13
  146. package/src/charts/gauge/index.tsx +0 -14
  147. package/src/charts/line/__tests__/index.test.tsx +0 -107
  148. package/src/charts/line/index.tsx +0 -15
  149. package/src/charts/pie/__tests__/index.test.tsx +0 -112
  150. package/src/charts/pie/index.tsx +0 -14
  151. package/src/charts/scatter/index.tsx +0 -14
  152. package/src/charts/sunburst/index.tsx +0 -18
  153. package/src/charts/treemap/index.tsx +0 -18
  154. package/src/core/utils/codeGenerator/CodeGenerator.ts +0 -669
  155. package/src/core/utils/codeGenerator/index.ts +0 -13
  156. package/src/core/utils/codeGenerator/types.ts +0 -198
  157. package/src/core/utils/configGenerator/ConfigGenerator.ts +0 -583
  158. package/src/core/utils/configGenerator/index.ts +0 -13
  159. package/src/core/utils/configGenerator/types.ts +0 -445
  160. package/src/core/utils/debug/DebugPanel.tsx +0 -637
  161. package/src/core/utils/debug/debugger.ts +0 -322
  162. package/src/core/utils/debug/index.ts +0 -21
  163. package/src/core/utils/debug/types.ts +0 -142
  164. package/src/hooks/useDataZoom.ts +0 -323
@@ -1,649 +1,49 @@
1
1
  /**
2
- * TaroViz React Hooks - 增强版
3
- * 提供与图表相关的 React Hooks
2
+ * TaroViz React Hooks
3
+ * 此文件为纯 re-export 入口,各 Hook 实现在独立文件中。
4
4
  */
5
- import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
6
- import { getAdapter } from '../adapters';
7
- import { getThemeByName } from '../themes';
8
- import type { EChartsOption } from 'echarts';
9
- import { useDataZoom } from './useDataZoom';
10
- import { useChartConnect } from './useChartConnect';
11
- import { useChartDownload } from './useChartDownload';
12
- import { useChartHistory } from './useChartHistory';
13
- import { useChartSelection } from './useChartSelection';
14
-
15
- // ============================================================================
16
- // 类型定义
17
- // ============================================================================
18
-
19
- /** 图表实例类型 */
20
- export interface ChartInstance {
21
- setOption: (option: EChartsOption, notMerge?: boolean, lazyUpdate?: boolean) => void;
22
- getOption: () => EChartsOption;
23
- resize: (option?: { width?: number | string; height?: number | string }) => void;
24
- on: (event: string, handler: EventHandler) => void;
25
- off: (event: string, handler?: EventHandler) => void;
26
- showLoading: (opts?: LoadingOptions) => void;
27
- hideLoading: () => void;
28
- dispose: () => void;
29
- isDisposed: () => boolean;
30
- getWidth: () => number;
31
- getHeight: () => number;
32
- getDom: () => HTMLElement;
33
- getDataURL?: (options?: {
34
- type?: string;
35
- pixelRatio?: number;
36
- backgroundColor?: string;
37
- }) => string;
38
- getSvgData?: () => string;
39
- getCompressedDataURL?: (options?: { seriesIndex?: number; dimension?: number }) => string;
40
- clear?: () => void;
41
- dispatchAction?: (action: { type: string; [key: string]: unknown }) => void;
42
- [key: string]: any;
43
- }
44
-
45
- /** 事件处理器 */
46
- export type EventHandler = (params?: unknown) => void;
47
-
48
- /** 加载选项 */
49
- export interface LoadingOptions {
50
- text?: string;
51
- color?: string;
52
- textColor?: string;
53
- maskColor?: string;
54
- zlevel?: number;
55
- }
56
-
57
- /** 图表配置 */
58
- export interface ChartConfig {
59
- width?: number | string;
60
- height?: number | string;
61
- renderer?: 'canvas' | 'svg';
62
- theme?: string | Record<string, unknown>;
63
- [key: string]: unknown;
64
- }
65
-
66
- /** 数据转换器 */
67
- export type DataTransformer<T = unknown> = (data: T) => EChartsOption;
68
-
69
- /** 响应式断点 */
70
- export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
71
-
72
- /** 断点配置 */
73
- export interface BreakpointConfig {
74
- width: number;
75
- }
76
-
77
- /** 主题切换回调 */
78
- export type ThemeChangeCallback = (theme: string | Record<string, unknown>) => void;
79
-
80
- // ============================================================================
81
- // Hooks
82
- // ============================================================================
83
-
84
- /**
85
- * 使用图表 Hook
86
- * @param chartRef 图表容器的引用
87
- * @param config 图表配置
88
- * @returns [图表实例, 设置实例函数, 是否已初始化]
89
- */
90
- export function useChart(
91
- chartRef: React.RefObject<HTMLElement>,
92
- config?: ChartConfig
93
- ): [ChartInstance | null, React.Dispatch<React.SetStateAction<ChartInstance | null>>, boolean] {
94
- const [instance, setInstance] = useState<ChartInstance | null>(null);
95
- const [initialized, setInitialized] = useState(false);
96
- const configRef = useRef(config);
97
- configRef.current = config;
98
-
99
- useEffect(() => {
100
- if (!chartRef.current || instance) {
101
- return;
102
- }
103
-
104
- const initAdapter = async () => {
105
- try {
106
- const adapter = await getAdapter(configRef.current || {});
107
- const chartInstance = adapter as unknown as ChartInstance;
108
- setInstance(chartInstance);
109
- setInitialized(true);
110
- } catch (error) {
111
- console.error('Failed to initialize chart:', error);
112
- }
113
- };
114
-
115
- initAdapter();
116
-
117
- return () => {
118
- if (instance) {
119
- try {
120
- const inst = instance as any;
121
- if (!inst.isDisposed?.()) {
122
- inst.dispose();
123
- }
124
- } catch (e) {
125
- console.warn('Failed to dispose chart instance:', e);
126
- }
127
- setInstance(null);
128
- setInitialized(false);
129
- }
130
- };
131
- }, [chartRef]);
132
-
133
- return [instance, setInstance, initialized];
134
- }
135
-
136
- /**
137
- * 设置图表选项 Hook
138
- * @param instance 图表实例
139
- * @param option 图表选项
140
- * @param options 配置选项
141
- */
142
- export function useOption(
143
- instance: ChartInstance | null,
144
- option: EChartsOption | null,
145
- options?: {
146
- /** 是否不合并 */
147
- notMerge?: boolean;
148
- /** 是否延迟更新 */
149
- lazyUpdate?: boolean;
150
- /** 是否在数据变化时替换 */
151
- replaceMerge?: string[];
152
- /** 依赖数组 */
153
- deps?: unknown[];
154
- }
155
- ) {
156
- const { notMerge = false, lazyUpdate = false, replaceMerge, deps = [] } = options || {};
157
-
158
- useEffect(() => {
159
- if (instance && option) {
160
- try {
161
- instance.setOption(option, notMerge, lazyUpdate);
162
- } catch (e) {
163
- console.warn('Failed to set chart option:', e);
164
- }
165
- }
166
- }, [instance, option, notMerge, lazyUpdate, replaceMerge, ...deps]);
167
- }
168
-
169
- /**
170
- * 图表自适应 Hook
171
- * @param instance 图表实例
172
- * @param options 配置选项
173
- */
174
- export function useResize(
175
- instance: ChartInstance | null,
176
- options?: {
177
- /** 延迟时间 (ms) */
178
- delay?: number;
179
- /** 最小宽度 */
180
- minWidth?: number;
181
- /** 最小高度 */
182
- minHeight?: number;
183
- /** 是否启用 */
184
- enabled?: boolean;
185
- }
186
- ) {
187
- const { delay = 300, minWidth, minHeight, enabled = true } = options || {};
188
- const timeoutRef = useRef<NodeJS.Timeout>();
189
-
190
- useEffect(() => {
191
- if (!instance || !enabled) {
192
- return;
193
- }
194
-
195
- const handleResize = () => {
196
- if (timeoutRef.current) {
197
- clearTimeout(timeoutRef.current);
198
- }
199
-
200
- timeoutRef.current = setTimeout(() => {
201
- try {
202
- const dom = instance.getDom?.();
203
- if (dom) {
204
- const { clientWidth, clientHeight } = dom;
205
- if (minWidth && clientWidth < minWidth) return;
206
- if (minHeight && clientHeight < minHeight) return;
207
- }
208
- instance.resize?.();
209
- } catch (e) {
210
- console.warn('Failed to resize chart:', e);
211
- }
212
- }, delay);
213
- };
214
-
215
- window.addEventListener('resize', handleResize);
216
-
217
- // 创建一个 ResizeObserver 来监听容器大小变化
218
- const dom = instance.getDom?.();
219
- if (dom && typeof ResizeObserver !== 'undefined') {
220
- const observer = new ResizeObserver(handleResize);
221
- observer.observe(dom);
222
- return () => {
223
- observer.disconnect();
224
- window.removeEventListener('resize', handleResize);
225
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
226
- };
227
- }
228
-
229
- return () => {
230
- window.removeEventListener('resize', handleResize);
231
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
232
- };
233
- }, [instance, delay, minWidth, minHeight, enabled]);
234
- }
235
-
236
- /**
237
- * 图表事件 Hook
238
- * @param instance 图表实例
239
- * @param events 事件对象
240
- */
241
- export function useEvents(instance: ChartInstance | null, events: Record<string, EventHandler>) {
242
- useEffect(() => {
243
- if (!instance || !events) {
244
- return;
245
- }
246
-
247
- const eventEntries = Object.entries(events);
248
-
249
- // 绑定事件
250
- eventEntries.forEach(([eventName, handler]) => {
251
- try {
252
- instance.on(eventName, handler);
253
- } catch (e) {
254
- console.warn(`Failed to bind event ${eventName}:`, e);
255
- }
256
- });
257
-
258
- // 清理事件
259
- return () => {
260
- eventEntries.forEach(([eventName, handler]) => {
261
- try {
262
- instance.off(eventName, handler);
263
- } catch (e) {
264
- console.warn(`Failed to unbind event ${eventName}:`, e);
265
- }
266
- });
267
- };
268
- }, [instance, events]);
269
- }
270
-
271
- /**
272
- * 图表加载状态 Hook
273
- * @param instance 图表实例
274
- * @param loading 是否加载中
275
- * @param options 加载选项
276
- */
277
- export function useLoading(
278
- instance: ChartInstance | null,
279
- loading: boolean,
280
- options?: LoadingOptions
281
- ) {
282
- useEffect(() => {
283
- if (!instance) {
284
- return;
285
- }
286
-
287
- try {
288
- if (loading) {
289
- instance.showLoading(options);
290
- } else {
291
- instance.hideLoading();
292
- }
293
- } catch (e) {
294
- console.warn('Failed to set chart loading state:', e);
295
- }
296
- }, [instance, loading, options]);
297
- }
298
-
299
- /**
300
- * 使用图表主题
301
- * @param theme 主题名称或配置
302
- * @param darkMode 是否为暗色模式
303
- * @returns 处理后的主题
304
- */
305
- export function useChartTheme(theme: string | Record<string, unknown>, darkMode = false) {
306
- return useMemo(() => {
307
- if (typeof theme === 'string') {
308
- // 如果是字符串,尝试获取内置主题配置
309
- try {
310
- const builtinTheme = getThemeByName(theme);
311
- return builtinTheme || (darkMode ? 'dark' : theme);
312
- } catch {
313
- return darkMode ? 'dark' : theme;
314
- }
315
- }
316
- return theme;
317
- }, [theme, darkMode]);
318
- }
319
-
320
- /**
321
- * 使用图表数据变更
322
- * @param data 数据源
323
- * @param transformer 数据转换函数
324
- * @returns 转换后的图表选项
325
- */
326
- export function useChartData<T = unknown>(data: T | null, transformer: DataTransformer<T>) {
327
- return useMemo(() => {
328
- if (!data || (Array.isArray(data) && data.length === 0)) {
329
- return {};
330
- }
331
- return transformer(data);
332
- }, [data, transformer]);
333
- }
334
-
335
- /**
336
- * 使用响应式图表配置
337
- * @param config 响应式配置
338
- * @returns 当前断点和配置
339
- */
340
- export function useResponsive(config?: {
341
- /** 断点配置 */
342
- breakpoints?: Record<Breakpoint, number>;
343
- /** 默认断点 */
344
- defaultBreakpoint?: Breakpoint;
345
- }) {
346
- const { breakpoints = { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200 }, defaultBreakpoint = 'md' } =
347
- config || {};
348
-
349
- const [breakpoint, setBreakpoint] = useState<Breakpoint>(defaultBreakpoint);
350
- const [windowSize, setWindowSize] = useState({ width: 0, height: 0 });
351
-
352
- useEffect(() => {
353
- const handleResize = () => {
354
- const width = window.innerWidth;
355
- setWindowSize({ width, height: window.innerHeight });
356
-
357
- // 确定当前断点
358
- let current: Breakpoint = 'xs';
359
- if (width >= breakpoints.xl) current = 'xl';
360
- else if (width >= breakpoints.lg) current = 'lg';
361
- else if (width >= breakpoints.md) current = 'md';
362
- else if (width >= breakpoints.sm) current = 'sm';
363
-
364
- setBreakpoint(current);
365
- };
366
-
367
- handleResize();
368
- window.addEventListener('resize', handleResize);
369
-
370
- return () => window.removeEventListener('resize', handleResize);
371
- }, [breakpoints]);
372
-
373
- return { breakpoint, windowSize };
374
- }
375
-
376
- /**
377
- * 使用主题切换
378
- * @param initialTheme 初始主题
379
- * @returns [当前主题, 切换主题函数]
380
- */
381
- export function useThemeSwitcher(initialTheme = 'default') {
382
- const [theme, setTheme] = useState<string | Record<string, unknown>>(initialTheme);
383
- const [isDark, setIsDark] = useState(false);
384
-
385
- const switchTheme = useCallback((newTheme: string | Record<string, unknown>) => {
386
- setTheme(newTheme);
387
- if (typeof newTheme === 'string') {
388
- setIsDark(newTheme === 'dark' || newTheme.includes('dark'));
389
- }
390
- }, []);
391
-
392
- const toggleDark = useCallback(() => {
393
- setIsDark((prev) => !prev);
394
- setTheme((prev) => (prev === 'dark' ? 'default' : 'dark'));
395
- }, []);
396
-
397
- return { theme, isDark, switchTheme, toggleDark, setTheme };
398
- }
399
-
400
- /**
401
- * 使用数据轮询
402
- * @param fetchFn 数据获取函数
403
- * @param options 配置选项
404
- * @returns [数据, 加载状态, 错误, 刷新函数]
405
- */
406
- export function useDataPolling<T>(
407
- fetchFn: () => Promise<T>,
408
- options?: {
409
- /** 轮询间隔 (ms) */
410
- interval?: number;
411
- /** 是否自动开始 */
412
- autoStart?: boolean;
413
- /** 错误重试次数 */
414
- retryCount?: number;
415
- /** 重试延迟 (ms) */
416
- retryDelay?: number;
417
- }
418
- ) {
419
- const { interval = 5000, autoStart = false, retryCount = 3, retryDelay = 1000 } = options || {};
420
-
421
- const [data, setData] = useState<T | null>(null);
422
- const [loading, setLoading] = useState(autoStart);
423
- const [error, setError] = useState<Error | null>(null);
424
-
425
- // 用于取消进行中的请求
426
- const abortRef = useRef<{ cancelled: boolean }>({ cancelled: false });
427
-
428
- const fetchData = useCallback(async () => {
429
- // 取消之前的请求
430
- abortRef.current.cancelled = true;
431
- // 创建新的取消标记
432
- abortRef.current = { cancelled: false };
433
- const currentAbort = abortRef.current;
434
-
435
- let retries = retryCount;
436
- setLoading(true);
437
- setError(null);
438
5
 
439
- while (retries > 0 && !currentAbort.cancelled) {
440
- try {
441
- const result = await fetchFn();
442
- if (!currentAbort.cancelled) {
443
- setData(result);
444
- setLoading(false);
445
- }
446
- return;
447
- } catch (e) {
448
- retries--;
449
- if (retries <= 0 || currentAbort.cancelled) {
450
- if (!currentAbort.cancelled) {
451
- setError(e as Error);
452
- }
453
- setLoading(false);
454
- return;
455
- } else {
456
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
457
- }
458
- }
459
- }
460
-
461
- // No retries configured — if fetch fails immediately, that's an error
462
- if (retryCount <= 0 && !currentAbort.cancelled) {
463
- try {
464
- const result = await fetchFn();
465
- if (!currentAbort.cancelled) {
466
- setData(result);
467
- setLoading(false);
468
- }
469
- } catch (e) {
470
- if (!currentAbort.cancelled) {
471
- setError(e as Error);
472
- setLoading(false);
473
- }
474
- }
475
- return;
476
- }
477
-
478
- // All retries exhausted without success (caught in loop already handled above)
479
- if (!currentAbort.cancelled) {
480
- setError(new Error('All retries failed'));
481
- setLoading(false);
482
- }
483
- }, [fetchFn, retryCount, retryDelay]);
484
-
485
- useEffect(() => {
486
- if (autoStart) {
487
- fetchData();
488
- }
489
-
490
- if (interval > 0) {
491
- const timer = setInterval(fetchData, interval);
492
- return () => {
493
- clearInterval(timer);
494
- abortRef.current.cancelled = true;
495
- };
496
- }
497
-
498
- return () => {
499
- abortRef.current.cancelled = true;
500
- };
501
- }, [interval, autoStart, fetchData]);
502
-
503
- const refresh = useCallback(() => {
504
- fetchData();
505
- }, [fetchData]);
506
-
507
- return { data, loading, error, refresh };
508
- }
509
-
510
- /**
511
- * 使用图表全屏
512
- * @param chartRef 图表容器引用
513
- * @returns [是否全屏, 进入/退出全屏函数]
514
- */
515
- export function useFullscreen(chartRef: React.RefObject<HTMLElement>) {
516
- const [isFullscreen, setIsFullscreen] = useState(false);
517
-
518
- const toggle = useCallback(() => {
519
- if (!chartRef.current) return;
520
-
521
- if (!isFullscreen) {
522
- if (chartRef.current.requestFullscreen) {
523
- chartRef.current.requestFullscreen();
524
- }
525
- } else {
526
- if (document.exitFullscreen) {
527
- document.exitFullscreen();
528
- }
529
- }
530
- }, [chartRef, isFullscreen]);
531
-
532
- useEffect(() => {
533
- const handleChange = () => {
534
- setIsFullscreen(!!document.fullscreenElement);
535
- };
536
-
537
- document.addEventListener('fullscreenchange', handleChange);
538
- return () => document.removeEventListener('fullscreenchange', handleChange);
539
- }, []);
540
-
541
- return { isFullscreen, toggle };
542
- }
543
-
544
- /**
545
- * 使用图表导出
546
- * @param instance 图表实例
547
- * @returns 导出函数
548
- */
549
- export function useExport(instance: ChartInstance | null) {
550
- const inst = instance as any;
551
- const exportImage = useCallback(
552
- (options?: { type?: 'png' | 'jpeg'; pixelRatio?: number; backgroundColor?: string }) => {
553
- if (!inst) return null;
554
- const { type = 'png', pixelRatio = 2, backgroundColor } = options || {};
555
- return inst.getDataURL?.({ type, pixelRatio, backgroundColor });
556
- },
557
- [inst]
558
- );
559
-
560
- const exportSVG = useCallback(() => {
561
- if (!inst) return null;
562
- return inst.getSvgData?.();
563
- }, [inst]);
564
-
565
- const exportCSV = useCallback(
566
- (options?: { seriesIndex?: number; dimension?: number }) => {
567
- if (!inst) return null;
568
- return inst.getCompressedDataURL?.(options);
569
- },
570
- [inst]
571
- );
572
-
573
- return { exportImage, exportSVG, exportCSV };
574
- }
575
-
576
- /**
577
- * 使用图表工具
578
- * @param instance 图表实例
579
- * @returns 工具函数
580
- */
581
- export function useChartTools(instance: ChartInstance | null) {
582
- const inst = instance as any;
583
- const getInstance = useCallback(() => instance, [instance]);
584
-
585
- const clear = useCallback(() => {
586
- inst?.clear?.();
587
- }, [inst]);
588
-
589
- const repaint = useCallback(() => {
590
- inst?.resize?.();
591
- }, [inst]);
592
-
593
- const dispatchAction = useCallback(
594
- (action: { type: string; [key: string]: unknown }) => {
595
- inst?.dispatchAction?.(action);
596
- },
597
- [inst]
598
- );
599
-
600
- const showTip = useCallback(
601
- (seriesIndex?: number, dataIndex?: number) => {
602
- inst?.dispatchAction?.({ type: 'showTip', seriesIndex, dataIndex });
603
- },
604
- [inst]
605
- );
606
-
607
- const hideTip = useCallback(() => {
608
- inst?.dispatchAction?.({ type: 'hideTip' });
609
- }, [inst]);
610
-
611
- const zoom = useCallback(
612
- (start?: number, end?: number) => {
613
- inst?.dispatchAction?.({
614
- type: 'dataZoom',
615
- start: start ?? 0,
616
- end: end ?? 100,
617
- });
618
- },
619
- [inst]
620
- );
621
-
622
- return { getInstance, clear, repaint, dispatchAction, showTip, hideTip, zoom };
623
- }
624
-
625
- // ============================================================================
626
- // v1.7.0 新增 Hooks
627
- // ============================================================================
628
-
629
- // 数据缩放 Hook
6
+ // Types
7
+ export type {
8
+ ChartConfig,
9
+ DataTransformer,
10
+ Breakpoint,
11
+ BreakpointConfig,
12
+ ThemeChangeCallback,
13
+ ChartInstance,
14
+ EventHandler,
15
+ LoadingOptions,
16
+ } from './types';
17
+
18
+ // Core hooks
19
+ export { useChart } from './useChartInit';
630
20
  export {
631
- useDataZoom,
632
- type UseDataZoomOptions,
633
- type UseDataZoomReturn,
634
- type DataZoomType,
635
- type ZoomRange,
636
- } from './useDataZoom';
21
+ useOption,
22
+ useEvents,
23
+ useLoading,
24
+ useResponsive,
25
+ useFullscreen,
26
+ useExport,
27
+ useChartTools,
28
+ } from './useChartOptions';
29
+ export { useResize } from './useChartAutoResize';
30
+ export { useChartTheme, useThemeSwitcher } from './useChartTheme';
31
+ export { useDataPolling } from './useChartPerformance';
32
+ export {
33
+ useChartData,
34
+ useDataTransform,
35
+ useTableTransform,
36
+ useTimeSeriesTransform,
37
+ useTransform,
38
+ } from './useDataTransform';
637
39
 
638
- // 图表联动 Hook
40
+ // v1.7.0 hooks
639
41
  export {
640
42
  useChartConnect,
641
43
  type UseChartConnectOptions,
642
44
  type UseChartConnectReturn,
643
45
  type ConnectEventType,
644
46
  } from './useChartConnect';
645
-
646
- // 图表下载 Hook
647
47
  export {
648
48
  useChartDownload,
649
49
  type UseChartDownloadOptions,
@@ -652,8 +52,6 @@ export {
652
52
  type DownloadImageOptions,
653
53
  type DownloadDataOptions,
654
54
  } from './useChartDownload';
655
-
656
- // 图表下载工具函数
657
55
  export {
658
56
  generateFilename,
659
57
  downloadBlob,
@@ -664,8 +62,6 @@ export {
664
62
  convertToJSON,
665
63
  createPdfFromImage,
666
64
  } from './utils/chartDownloadUtils';
667
-
668
- // 数据转换工具函数(类型导出)
669
65
  export type {
670
66
  DataItem,
671
67
  DataSource,
@@ -673,8 +69,6 @@ export type {
673
69
  TimePeriod,
674
70
  TransformMapping,
675
71
  } from './utils/dataTransformUtils';
676
-
677
- // 数据转换工具函数(值导出)
678
72
  export {
679
73
  transformLineOrBar,
680
74
  transformPie,
@@ -684,15 +78,11 @@ export {
684
78
  groupByTime,
685
79
  aggregateValues,
686
80
  } from './utils/dataTransformUtils';
687
-
688
- // 图表历史记录 Hook (Undo/Redo)
689
81
  export {
690
82
  useChartHistory,
691
83
  type UseChartHistoryOptions,
692
84
  type UseChartHistoryReturn,
693
85
  } from './useChartHistory';
694
-
695
- // 图表选择 Hook
696
86
  export {
697
87
  useChartSelection,
698
88
  type UseChartSelectionOptions,
@@ -702,19 +92,27 @@ export {
702
92
  type SelectionEvent,
703
93
  } from './useChartSelection';
704
94
 
705
- // ============================================================================
706
- // 导出
707
- // ============================================================================
708
-
709
- export const version = '1.7.0';
95
+ // Version
96
+ export { VERSION as version } from '../core/version';
710
97
 
711
- // 新增数据转换 hooks
712
- export {
713
- useDataTransform,
714
- useTableTransform,
715
- useTimeSeriesTransform,
716
- useTransform,
717
- } from './useDataTransform';
98
+ // Default export for backward compatibility
99
+ import { useChart } from './useChartInit';
100
+ import {
101
+ useOption,
102
+ useEvents,
103
+ useLoading,
104
+ useResponsive,
105
+ useFullscreen,
106
+ useExport,
107
+ useChartTools,
108
+ } from './useChartOptions';
109
+ import { useResize } from './useChartAutoResize';
110
+ import { useChartTheme, useThemeSwitcher } from './useChartTheme';
111
+ import { useDataPolling } from './useChartPerformance';
112
+ import { useChartConnect } from './useChartConnect';
113
+ import { useChartDownload } from './useChartDownload';
114
+ import { useChartHistory } from './useChartHistory';
115
+ import { useChartSelection } from './useChartSelection';
718
116
 
719
117
  export default {
720
118
  useChart,
@@ -723,15 +121,12 @@ export default {
723
121
  useEvents,
724
122
  useLoading,
725
123
  useChartTheme,
726
- useChartData,
727
124
  useResponsive,
728
125
  useThemeSwitcher,
729
126
  useDataPolling,
730
127
  useFullscreen,
731
128
  useExport,
732
129
  useChartTools,
733
- // v1.7.0 新增
734
- useDataZoom,
735
130
  useChartConnect,
736
131
  useChartDownload,
737
132
  useChartHistory,