@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
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import type { CSSProperties, ReactNode } from 'react';
5
5
  import type { EChartsOption, ECharts } from 'echarts';
6
+ import type { AnimationConfig } from '../core/animation/types';
6
7
 
7
8
  // ============================================================================
8
9
  // 基础类型定义
@@ -163,24 +164,8 @@ export interface ChartData {
163
164
  // 动画配置
164
165
  // ============================================================================
165
166
 
166
- /** 动画配置 */
167
- export interface AnimationConfig {
168
- /** 是否启用动画 */
169
- enabled?: boolean;
170
- /** 动画时长 (ms) */
171
- duration?: number;
172
- /** 动画缓动函数 */
173
- easing?: string;
174
- /** 动画延迟 (ms) */
175
- delay?: number;
176
- /** 是否在渲染时使用动画 */
177
- animate?: boolean;
178
- /** 是否在数据更新时使用动画 */
179
- animateUpdate?: boolean;
180
- }
181
-
182
167
  // ============================================================================
183
- // 基础图表属性
168
+ // 事件回调类型
184
169
  // ============================================================================
185
170
 
186
171
  /**
@@ -472,81 +457,145 @@ export interface ScatterChartProps extends BaseChartProps {
472
457
  /**
473
458
  * 雷达图属性
474
459
  */
475
- export interface RadarChartProps extends BaseChartProps {
476
- /** 雷达图指示器 */
477
- indicators?: Array<{ name: string; max?: number; color?: string }>;
460
+ export interface RadarIndicator {
461
+ /** 指标名称 */
462
+ name: string;
463
+ /** 最大值 */
464
+ max: number;
465
+ /** 最小值(可选,默认 0) */
466
+ min?: number;
467
+ }
478
468
 
479
- /** 雷达图形状 */
480
- shape?: 'polygon' | 'circle';
469
+ /** 雷达图数据系列项 */
470
+ export interface RadarDataItem {
471
+ /** 数据值数组,对应每个 indicator 的值 */
472
+ value: number[];
473
+ /** 系列名称 */
474
+ name?: string;
475
+ }
481
476
 
482
- /** 中心点 */
483
- center?: [number | string, number | string];
477
+ /** 雷达图面积样式配置 */
478
+ export interface RadarAreaStyle {
479
+ /** 是否显示面积填充 */
480
+ show?: boolean;
481
+ /** 填充颜色 */
482
+ color?: string;
483
+ /** 透明度 */
484
+ opacity?: number;
485
+ }
484
486
 
485
- /** 半径 */
486
- radius?: number | string;
487
+ /** 雷达图线样式配置 */
488
+ export interface RadarLineStyle {
489
+ /** 线宽 */
490
+ width?: number;
491
+ /** 线型 */
492
+ type?: 'solid' | 'dashed' | 'dotted';
493
+ /** 颜色 */
494
+ color?: string;
495
+ }
496
+
497
+ /** 雷达图标签配置 */
498
+ export interface RadarLabel {
499
+ /** 是否显示标签 */
500
+ show?: boolean;
501
+ /** 标签位置 */
502
+ position?: 'inside' | 'outside' | 'center';
503
+ /** 标签格式化 */
504
+ formatter?: string | ((value: number, indicator: RadarIndicator) => string);
505
+ }
506
+
507
+ /**
508
+ * 雷达图属性
509
+ */
510
+ export interface RadarChartProps extends Omit<BaseChartProps, 'data'> {
511
+ /** 雷达图指示器 */
512
+ indicators: RadarIndicator[];
513
+ /** 雷达图数据系列 */
514
+ data: RadarDataItem[];
515
+ /** 起始角度(0-360,默认 90) */
516
+ startAngle?: number;
517
+ /** 是否显示中心圆环 */
518
+ centerCircle?: boolean;
519
+ /** 中心圆环半径(0-1,默认 0) */
520
+ centerCircleSize?: number;
521
+ /** 面积样式 */
522
+ areaStyle?: RadarAreaStyle;
523
+ /** 线样式 */
524
+ lineStyle?: RadarLineStyle;
525
+ /** 标签配置 */
526
+ label?: RadarLabel;
527
+ /** 是否平滑曲线 */
528
+ smooth?: boolean;
529
+ /** 自定义 ECharts option 合并 */
530
+ optionMerge?: Partial<EChartsOption>;
531
+ }
532
+
533
+ /**
534
+ * 漏斗图数据项
535
+ */
536
+ export interface FunnelDataItem {
537
+ /** 数值 */
538
+ value: number;
539
+ /** 名称 */
540
+ name: string;
487
541
  }
488
542
 
489
543
  /**
490
544
  * 漏斗图属性
491
545
  */
492
- export interface FunnelChartProps extends BaseChartProps {
546
+ export interface FunnelChartProps extends Omit<BaseChartProps, 'data'> {
547
+ /** 漏斗数据 */
548
+ data?: FunnelDataItem[];
493
549
  /** 漏斗排序方式 */
494
550
  sort?: 'ascending' | 'descending' | 'none';
495
-
496
551
  /** 漏斗对齐方式 */
497
552
  align?: 'left' | 'center' | 'right';
498
-
499
553
  /** 间隙 */
500
554
  gap?: number;
501
-
502
555
  /** 最小高度 */
503
556
  min?: number;
504
-
505
557
  /** 最大高度 */
506
558
  max?: number;
559
+ /** 自定义 ECharts option 合并 */
560
+ optionMerge?: Partial<EChartsOption>;
507
561
  }
508
562
 
509
563
  /**
510
- * 仪表盘属性
564
+ * 热力图数据项
511
565
  */
512
- export interface GaugeChartProps extends BaseChartProps {
513
- /** 最小值 */
514
- min?: number;
515
-
516
- /** 最大值 */
517
- max?: number;
518
-
519
- /** 当前值 */
520
- value?: number;
521
-
522
- /** 刻度分段数 */
523
- splitNumber?: number;
524
-
525
- /** 半径 */
526
- radius?: number | string;
527
-
528
- /** 起始角度 */
529
- startAngle?: number;
530
-
531
- /** 结束角度 */
532
- endAngle?: number;
566
+ export interface HeatmapDataItem {
567
+ /** X 轴索引或值 */
568
+ x: number | string;
569
+ /** Y 轴索引或值 */
570
+ y: number | string;
571
+ /** 热力值 */
572
+ value: number;
573
+ }
533
574
 
534
- /** 进度显示 */
535
- showProgress?: boolean;
575
+ /**
576
+ * 热力图 X/Y 轴配置
577
+ */
578
+ export interface HeatmapAxis {
579
+ /** 轴标签 */
580
+ name?: string;
581
+ /** 轴数据 */
582
+ data?: (string | number)[];
536
583
  }
537
584
 
538
585
  /**
539
586
  * 热力图属性
540
587
  */
541
- export interface HeatmapChartProps extends BaseChartProps {
588
+ export interface HeatmapChartProps extends Omit<BaseChartProps, 'data'> {
542
589
  /** X 轴数据 */
543
- xAxisData?: (string | number)[];
544
-
590
+ xData?: (string | number)[];
545
591
  /** Y 轴数据 */
546
- yAxisData?: (string | number)[];
547
-
592
+ yData?: (string | number)[];
593
+ /** 热力图数据 */
594
+ data?: HeatmapDataItem[];
548
595
  /** 视觉映射配置 */
549
596
  visualMap?: Record<string, unknown>;
597
+ /** 自定义 ECharts option 合并 */
598
+ optionMerge?: Partial<EChartsOption>;
550
599
  }
551
600
 
552
601
  /**
@@ -707,6 +756,8 @@ export interface SankeyChartProps extends BaseChartProps {
707
756
  itemStyle?: Record<string, unknown>;
708
757
  lineStyle?: Record<string, unknown>;
709
758
  };
759
+ /** 自定义 ECharts option 合并 */
760
+ optionMerge?: Partial<EChartsOption>;
710
761
  }
711
762
 
712
763
  /**
@@ -739,48 +790,6 @@ export interface BoxplotChartProps extends Omit<BaseChartProps, 'data'> {
739
790
  smooth?: boolean;
740
791
  }
741
792
 
742
- /**
743
- * K线图/股票图属性
744
- * 用于展示股票、外汇等金融数据
745
- */
746
- export interface CandlestickChartProps extends Omit<BaseChartProps, 'data'> {
747
- /** K线数据数组,每项为 [open, close, lowest, highest] */
748
- candlestickData?: number[][];
749
-
750
- /** X轴数据 */
751
- xAxisData?: (string | number)[];
752
-
753
- /** 数据对应的维度名 */
754
- dimensions?: string[];
755
-
756
- /** 批量数据 */
757
- batchData?: Array<{
758
- name: string;
759
- data: number[][];
760
- }>;
761
-
762
- /** K线柱条样式 */
763
- itemStyle?: Record<string, unknown>;
764
-
765
- /** 强调状态 */
766
- emphasis?: Record<string, unknown>;
767
-
768
- /** 是否平滑曲线 */
769
- smooth?: boolean;
770
-
771
- /** 是否显示MA线 */
772
- ma?: Array<{
773
- period: number;
774
- color?: string;
775
- }>;
776
-
777
- /** 是否显示成交量 */
778
- showVolume?: boolean;
779
-
780
- /** 成交量柱子样式 */
781
- volumeBar?: Record<string, unknown>;
782
- }
783
-
784
793
  /**
785
794
  * 关系图属性
786
795
  * 用于展示节点之间的关系
@@ -839,6 +848,8 @@ export interface GraphChartProps extends BaseChartProps {
839
848
  itemStyle?: Record<string, unknown>;
840
849
  lineStyle?: Record<string, unknown>;
841
850
  };
851
+ /** 自定义 ECharts option 合并 */
852
+ optionMerge?: Partial<EChartsOption>;
842
853
  }
843
854
 
844
855
  // ============================================================================
@@ -880,9 +891,98 @@ export type { EChartsOption, ECharts } from 'echarts';
880
891
  export type { ECBasicOption as EChartsCoreOption } from 'echarts/types/dist/shared';
881
892
 
882
893
  /**
883
- * 词云图属性
884
- * 用于展示文本数据的词频分布
894
+ * 漏斗图标签配置
885
895
  */
896
+ export interface FunnelLabel {
897
+ /** 是否显示标签 */
898
+ show?: boolean;
899
+ /** 标签位置 */
900
+ position?: 'inside' | 'outside' | 'left' | 'right';
901
+ /** 标签格式化 */
902
+ formatter?: string | ((_value: number, _name: string) => string);
903
+ }
904
+
905
+ /**
906
+ * 关系图节点数据
907
+ */
908
+ export interface GraphNode {
909
+ /** 节点 ID */
910
+ id?: string | number;
911
+ /** 节点名称 */
912
+ name: string;
913
+ /** 节点值 */
914
+ value?: number | number[];
915
+ /** 节点类别 */
916
+ category?: number;
917
+ /** 节点符号 */
918
+ symbol?: string;
919
+ /** 节点符号大小 */
920
+ symbolSize?: number | number[];
921
+ /** 是否固定位置 */
922
+ fixed?: boolean;
923
+ /** X 坐标 */
924
+ x?: number;
925
+ /** Y 坐标 */
926
+ y?: number;
927
+ /** 其他自定义属性 */
928
+ [key: string]: unknown;
929
+ }
930
+
931
+ /**
932
+ * 关系图链接/边数据
933
+ */
934
+ export interface GraphLink {
935
+ /** 源节点 */
936
+ source: string | number;
937
+ /** 目标节点 */
938
+ target: string | number;
939
+ /** 链接值 */
940
+ value?: number;
941
+ /** 线条样式 */
942
+ lineStyle?: Record<string, unknown>;
943
+ /** 其他自定义属性 */
944
+ [key: string]: unknown;
945
+ }
946
+
947
+ /**
948
+ * 桑基图节点数据
949
+ */
950
+ export interface SankeyNode {
951
+ /** 节点名称 */
952
+ name: string;
953
+ /** 节点值 */
954
+ value?: number;
955
+ /** 其他自定义属性 */
956
+ [key: string]: unknown;
957
+ }
958
+
959
+ /**
960
+ * 桑基图链接/边数据
961
+ */
962
+ export interface SankeyLink {
963
+ /** 源节点 */
964
+ source: string | number;
965
+ /** 目标节点 */
966
+ target: string | number;
967
+ /** 链接值 */
968
+ value: number;
969
+ /** 其他自定义属性 */
970
+ [key: string]: unknown;
971
+ }
972
+
973
+ /**
974
+ * 词云图数据项
975
+ */
976
+ export interface WordCloudDataItem {
977
+ /** 词名 */
978
+ name: string;
979
+ /** 词频值 */
980
+ value: number;
981
+ /** 文本样式 */
982
+ textStyle?: Record<string, unknown>;
983
+ /** emphasis 状态 */
984
+ emphasis?: Record<string, unknown>;
985
+ }
886
986
  export interface WordCloudChartProps extends BaseChartProps {
887
987
  /** 词云数据 - 也可以通过 option.series[0].data 传入 */
888
988
  wordCloudData?: Array<{
@@ -915,7 +1015,9 @@ export interface WordCloudChartProps extends BaseChartProps {
915
1015
 
916
1016
  /** 强调状态 */
917
1017
  emphasis?: {
918
- focus?: 'self' | 'adjacency';
919
- textStyle?: Record<string, unknown>;
1018
+ itemStyle?: Record<string, unknown>;
1019
+ lineStyle?: Record<string, unknown>;
920
1020
  };
1021
+ /** 自定义 ECharts option 合并 */
1022
+ optionMerge?: Partial<EChartsOption>;
921
1023
  }
@@ -12,13 +12,13 @@ export function processAdapterConfig(config: {
12
12
  theme?: string | object;
13
13
  autoResize?: boolean;
14
14
  canvasId?: string;
15
- containerRef?: any;
16
- option?: any;
15
+ containerRef?: unknown;
16
+ option?: unknown;
17
17
  renderer?: 'canvas' | 'svg';
18
- [key: string]: any;
19
- }): any {
18
+ [key: string]: unknown;
19
+ }): Record<string, unknown> {
20
20
  // 将复杂类型转换为简单类型
21
- const processedConfig = {
21
+ const processedConfig: Record<string, unknown> = {
22
22
  width: typeof config.width === 'number' ? config.width : undefined,
23
23
  height: typeof config.height === 'number' ? config.height : undefined,
24
24
  theme: typeof config.theme === 'string' ? config.theme : undefined,
@@ -30,7 +30,7 @@ export function processAdapterConfig(config: {
30
30
  };
31
31
 
32
32
  // 复制其他可能存在的属性
33
- const result: Record<string, any> = { ...processedConfig };
33
+ const result: Record<string, unknown> = { ...processedConfig };
34
34
  Object.keys(config).forEach((key) => {
35
35
  if (!(key in processedConfig)) {
36
36
  result[key] = config[key];
@@ -44,7 +44,9 @@ export function processAdapterConfig(config: {
44
44
  * 安全地调用适配器渲染方法
45
45
  * 解决 render 方法可能不存在的问题
46
46
  */
47
- export function safeRenderAdapter(adapter: any): JSX.Element | null {
47
+ export function safeRenderAdapter(
48
+ adapter: { render?: () => JSX.Element | null } | null
49
+ ): JSX.Element | null {
48
50
  if (adapter && typeof adapter.render === 'function') {
49
51
  try {
50
52
  return adapter.render();
@@ -1,39 +1,106 @@
1
1
  /**
2
- * @version v1.5.0
2
+ * WordCloudChart 组件测试
3
3
  */
4
-
5
4
  import React from 'react';
6
- import { render } from '@testing-library/react';
5
+ import { render, screen } from '@testing-library/react';
6
+ import '@testing-library/jest-dom';
7
7
  import WordCloudChart from '../index';
8
8
 
9
+ // 使用正确的 mock 方式,参考 parallel 图表的测试
10
+ jest.mock('../../common/BaseChartWrapper');
11
+ jest.mock('echarts/charts', () => ({ WordCloudChart: jest.fn() }));
12
+
9
13
  describe('WordCloudChart', () => {
10
- it('renders without crashing', () => {
11
- const { container } = render(<WordCloudChart />);
12
- expect(container).toBeTruthy();
13
- });
14
-
15
- it('renders with custom width and height', () => {
16
- const { container } = render(<WordCloudChart width={600} height={400} />);
17
- // BaseChartWrapper renders a fragment with a hidden accessibility table (first child)
18
- // and the actual chart div (last child), so we query the last child for styles
19
- const chartDiv = container.lastChild;
20
- expect(chartDiv).toHaveStyle({ width: '600px', height: '400px' });
21
- });
22
-
23
- it('renders with word data', () => {
24
- const option = {
25
- series: [
26
- {
27
- type: 'wordCloud' as const,
28
- data: [
29
- { name: 'JavaScript', value: 10000 },
30
- { name: 'TypeScript', value: 8000 },
31
- { name: 'React', value: 6000 },
32
- ],
33
- },
34
- ],
35
- } as any;
36
- const { container } = render(<WordCloudChart option={option} />);
37
- expect(container).toBeTruthy();
14
+ const mockData = [
15
+ { name: 'JavaScript', value: 100 },
16
+ { name: 'TypeScript', value: 80 },
17
+ { name: 'React', value: 60 },
18
+ { name: 'Vue', value: 50 },
19
+ { name: 'Node.js', value: 40 },
20
+ { name: 'Python', value: 30 },
21
+ { name: 'Go', value: 20 },
22
+ ];
23
+
24
+ it('应该渲染词云图组件', () => {
25
+ render(<WordCloudChart wordCloudData={mockData} width={800} height={400} />);
26
+
27
+ expect(screen.getByTestId('base-chart-wrapper')).toBeInTheDocument();
28
+ });
29
+
30
+ it('应该传递正确的 option 到 BaseChart', () => {
31
+ render(<WordCloudChart wordCloudData={mockData} width={800} height={400} />);
32
+
33
+ const baseChartWrapper = screen.getByTestId('base-chart-wrapper');
34
+ const optionElement = baseChartWrapper.querySelector('[data-testid="chart-option"]');
35
+ const option = JSON.parse(optionElement?.textContent || '{}');
36
+
37
+ expect(option.series).toBeDefined();
38
+ expect(option.series.type).toBe('wordCloud');
39
+ expect(option.series.data).toEqual(mockData);
40
+ expect(option.series.shape).toBe('circle');
41
+ });
42
+
43
+ it('当 wordCloudData 为空时应该返回 null', () => {
44
+ const { container } = render(<WordCloudChart wordCloudData={[]} width={800} height={400} />);
45
+
46
+ expect(container.firstChild).toBeNull();
47
+ });
48
+
49
+ it('应该支持自定义 shape', () => {
50
+ render(<WordCloudChart wordCloudData={mockData} shape="star" width={800} height={400} />);
51
+
52
+ const baseChartWrapper = screen.getByTestId('base-chart-wrapper');
53
+ const optionElement = baseChartWrapper.querySelector('[data-testid="chart-option"]');
54
+ const option = JSON.parse(optionElement?.textContent || '{}');
55
+
56
+ expect(option.series.shape).toBe('star');
57
+ });
58
+
59
+ it('应该支持自定义 sizeRange', () => {
60
+ render(
61
+ <WordCloudChart wordCloudData={mockData} sizeRange={[15, 80]} width={800} height={400} />
62
+ );
63
+
64
+ const baseChartWrapper = screen.getByTestId('base-chart-wrapper');
65
+ const optionElement = baseChartWrapper.querySelector('[data-testid="chart-option"]');
66
+ const option = JSON.parse(optionElement?.textContent || '{}');
67
+
68
+ expect(option.series.sizeRange).toEqual([15, 80]);
69
+ });
70
+
71
+ it('应该支持自定义 rotationRange', () => {
72
+ render(
73
+ <WordCloudChart wordCloudData={mockData} rotationRange={[-45, 45]} width={800} height={400} />
74
+ );
75
+
76
+ const baseChartWrapper = screen.getByTestId('base-chart-wrapper');
77
+ const optionElement = baseChartWrapper.querySelector('[data-testid="chart-option"]');
78
+ const option = JSON.parse(optionElement?.textContent || '{}');
79
+
80
+ expect(option.series.rotationRange).toEqual([-45, 45]);
81
+ });
82
+
83
+ it('应该支持自定义 gridSize', () => {
84
+ render(<WordCloudChart wordCloudData={mockData} gridSize={10} width={800} height={400} />);
85
+
86
+ const baseChartWrapper = screen.getByTestId('base-chart-wrapper');
87
+ const optionElement = baseChartWrapper.querySelector('[data-testid="chart-option"]');
88
+ const option = JSON.parse(optionElement?.textContent || '{}');
89
+
90
+ expect(option.series.gridSize).toBe(10);
91
+ });
92
+
93
+ it('应该支持 optionMerge 自定义配置', () => {
94
+ const customTitle = { title: { text: '词云图标题', left: 'center' } };
95
+
96
+ render(
97
+ <WordCloudChart wordCloudData={mockData} optionMerge={customTitle} width={800} height={400} />
98
+ );
99
+
100
+ const baseChartWrapper = screen.getByTestId('base-chart-wrapper');
101
+ const optionElement = baseChartWrapper.querySelector('[data-testid="chart-option"]');
102
+ const option = JSON.parse(optionElement?.textContent || '{}');
103
+
104
+ expect(option.title).toEqual(customTitle.title);
38
105
  });
39
106
  });
@@ -1,13 +1,79 @@
1
1
  /**
2
- * WordCloudChart组件
2
+ * TaroViz 词云图组件
3
+ *
4
+ * 基于 ECharts wordCloud 系列实现词云可视化
3
5
  */
4
- import React, { memo } from 'react';
5
- import BaseChartWrapper from '../common/BaseChartWrapper';
6
- import { WordCloudChartProps } from '../types';
7
-
8
- const WordCloudChart: React.FC<WordCloudChartProps> = memo((props) => (
9
- <BaseChartWrapper {...props} chartType="wordcloud-chart" />
10
- ));
11
- WordCloudChart.displayName = 'WordCloudChart';
6
+ import { createOptionChartComponent } from '@/charts/createOptionChartComponent';
7
+ import type { WordCloudChartProps } from './types';
8
+ // 类型 WordCloudDataItem 通过下方 export type 导出供外部使用
9
+
10
+ /**
11
+ * 构建词云图 ECharts option
12
+ */
13
+ function buildWordCloudOption(props: WordCloudChartProps) {
14
+ const {
15
+ wordCloudData,
16
+ shape,
17
+ sizeRange,
18
+ rotationRange,
19
+ rotationStep,
20
+ gridSize,
21
+ drawOutOfBound,
22
+ textStyle,
23
+ optionMerge,
24
+ } = props;
25
+
26
+ // 验证数据
27
+ if (!wordCloudData || wordCloudData.length === 0) {
28
+ console.warn('[TaroViz] WordCloudChart: wordCloudData is required');
29
+ return null;
30
+ }
31
+
32
+ // 构建词云图 series
33
+ const series = {
34
+ type: 'wordCloud' as const,
35
+ shape: shape || 'circle',
36
+ data: wordCloudData,
37
+ sizeRange: sizeRange || [12, 60],
38
+ rotationRange: rotationRange || [-90, 90],
39
+ rotationStep: rotationStep || 45,
40
+ gridSize: gridSize || 8,
41
+ drawOutOfBound: drawOutOfBound !== false,
42
+ textStyle: {
43
+ fontFamily: 'sans-serif',
44
+ fontWeight: 'bold',
45
+ ...textStyle,
46
+ },
47
+ emphasis: {
48
+ itemStyle: {
49
+ shadowBlur: 10,
50
+ shadowColor: 'rgba(0, 0, 0, 0.5)',
51
+ },
52
+ },
53
+ };
54
+
55
+ const option: any = {
56
+ tooltip: {
57
+ trigger: 'item',
58
+ formatter: (params: any) => {
59
+ if (!params || !params.data) return '';
60
+ return `<b>${params.data.name}</b><br/>词频: ${params.data.value}`;
61
+ },
62
+ },
63
+ series,
64
+ };
65
+
66
+ // 合并自定义配置
67
+ if (optionMerge) {
68
+ Object.assign(option, optionMerge);
69
+ }
70
+
71
+ return option;
72
+ }
73
+
74
+ const WordCloudChart = createOptionChartComponent<WordCloudChartProps>(
75
+ 'WordCloudChart',
76
+ buildWordCloudOption
77
+ );
12
78
 
13
79
  export default WordCloudChart;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * TaroViz 词云图类型定义
3
+ *
4
+ * 从主 types 文件导入基础类型,只导出组件特有的类型
5
+ */
6
+ export type { WordCloudChartProps, WordCloudDataItem } from '../types';