@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
@@ -20,10 +20,9 @@ export interface AdapterOptions {
20
20
  width?: number | string;
21
21
  height?: number | string;
22
22
  theme?: string | object;
23
- /** 初始化完成回调 */
24
- onInit?: (instance: EChartsType) => void;
25
- /** 图表配置 */
26
- option?: EChartsOption;
23
+ option?: unknown;
24
+
25
+ onInit?: (_instance: EChartsType) => void;
27
26
  style?: CSSProperties;
28
27
  autoResize?: boolean;
29
28
  devicePixelRatio?: number;
@@ -50,57 +49,25 @@ export interface WeappAdapterOptions extends AdapterOptions {
50
49
  component?: object;
51
50
  }
52
51
 
53
- /**
54
- * 支付宝小程序适配器选项
55
- */
56
- export interface AlipayAdapterOptions extends AdapterOptions {}
57
-
58
- /**
59
- * 百度小程序适配器选项
60
- */
61
- export interface SwanAdapterOptions extends AdapterOptions {}
62
-
63
- /**
64
- * 鸿蒙OS适配器选项
65
- */
66
- export interface HarmonyAdapterOptions extends AdapterOptions {}
67
-
68
- /**
69
- * 钉钉小程序适配器选项
70
- */
71
- export interface DDAdapterOptions extends AdapterOptions {}
72
-
73
- /**
74
- * 抖音小程序适配器选项
75
- */
76
- export interface TTAdapterOptions extends AdapterOptions {}
77
-
78
- /**
79
- * QQ小程序适配器选项
80
- */
81
- export interface QQAdapterOptions extends AdapterOptions {}
82
-
83
- /**
84
- * 京东小程序适配器选项
85
- */
86
- export interface JDAdapterOptions extends AdapterOptions {}
87
-
88
- /**
89
- * 快手小程序适配器选项
90
- */
91
- export interface KwaiAdapterOptions extends AdapterOptions {}
92
-
93
- /**
94
- * 企业微信小程序适配器选项
95
- */
96
- export interface QywxAdapterOptions extends AdapterOptions {}
97
-
98
- /**
99
- * 飞书小程序适配器选项
100
- */
101
- export interface LarkAdapterOptions extends AdapterOptions {}
102
-
103
- /**
104
- * 小程序通用适配器选项
105
- */
106
- 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;
@@ -1,77 +1,14 @@
1
1
  /**
2
2
  * TaroViz 微信小程序适配器
3
- * 基于微信小程序canvas组件实现图表渲染
4
3
  */
4
+ import { MiniAppAdapter, createMiniAppAdapter } from '../MiniAppAdapter';
5
+ import type { WeappAdapterOptions } from '../types';
5
6
 
6
- import { BaseAdapter } from '../BaseAdapter';
7
- import type { Adapter, WeappAdapterOptions } from '../types';
8
-
9
- export class WeappAdapter extends BaseAdapter {
10
- private component: unknown = null;
11
-
12
- constructor(config: WeappAdapterOptions) {
13
- super(config);
14
- this.component = config.component;
15
- }
16
-
17
- static create(options: WeappAdapterOptions): Adapter {
18
- return new WeappAdapter(options) as unknown as Adapter;
19
- }
20
-
21
- init(): unknown {
22
- const config = this.config as WeappAdapterOptions & { canvasId?: string };
23
- const { canvasId, width, height, theme, option } = config;
24
-
25
- if (!this.component) {
26
- console.error('[TaroViz] WeappAdapter: component is required');
27
- return null;
28
- }
29
-
30
- if (!canvasId) {
31
- console.error('[TaroViz] WeappAdapter: canvasId is required');
32
- return null;
33
- }
34
-
35
- const chart = (this.component as { createChart: (config: unknown) => unknown }).createChart({
36
- id: canvasId,
37
- width,
38
- height,
39
- theme,
40
- });
41
-
42
- if (option) {
43
- (chart as { setOption: (o: unknown) => void }).setOption(option);
44
- }
45
-
46
- this.chartInstance = chart;
47
-
48
- const onInit = this.config['onInit'] as ((instance: unknown) => void) | undefined;
49
- if (onInit) {
50
- onInit(chart);
51
- }
52
-
53
- return chart;
54
- }
55
-
56
- getWidth(): number {
57
- return this.parseSize((this.config as WeappAdapterOptions).width, 300);
58
- }
59
-
60
- getHeight(): number {
61
- return this.parseSize((this.config as WeappAdapterOptions).height, 300);
62
- }
63
-
64
- setComponent(component: unknown): void {
65
- this.component = component;
66
- }
67
-
68
- dispatchAction(action: unknown): void {
69
- (this.chartInstance as { dispatchAction?: (a: unknown) => void })?.dispatchAction?.(action);
70
- }
71
-
72
- getDataURL(opts?: unknown): string | undefined {
73
- return (this.chartInstance as { getDataURL?: (o?: unknown) => string })?.getDataURL?.(opts);
7
+ export class WeappAdapter extends MiniAppAdapter {
8
+ protected get platformName(): string {
9
+ return 'Weapp';
74
10
  }
75
11
  }
76
12
 
13
+ export const createWeappAdapter = createMiniAppAdapter(WeappAdapter);
77
14
  export default WeappAdapter;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * TaroViz 图表测试工具函数
3
+ * 消除各图表组件测试文件中的重复测试逻辑
4
+ *
5
+ * 使用方式:
6
+ * 1. 测试文件顶层写:jest.mock('../common/BaseChartWrapper');
7
+ * Jest 会自动使用 src/charts/common/__mocks__/BaseChartWrapper.tsx
8
+ * 2. 图表特定 mock:jest.mock('echarts/charts', () => ({ XxxChart: jest.fn() }));
9
+ * 3. import { runStandardChartTests } from '../../__tests__/testUtils';
10
+ */
11
+
12
+ import { render } from '@testing-library/react';
13
+ import React from 'react';
14
+
15
+ /**
16
+ * 标准图表测试用例
17
+ * 所有基础图表共享的测试逻辑
18
+ */
19
+ export function runStandardChartTests(
20
+ ChartComponent: React.ComponentType<any>,
21
+ chartType: string,
22
+ mockOption: Record<string, unknown>
23
+ ): void {
24
+ describe(`${chartType} Component`, () => {
25
+ it('should render correctly with default props', () => {
26
+ const { getByTestId } = render(
27
+ React.createElement(ChartComponent, { option: mockOption } as any)
28
+ );
29
+
30
+ const chartWrapper = getByTestId('base-chart-wrapper');
31
+ expect(chartWrapper).toBeInTheDocument();
32
+ expect(chartWrapper).toHaveClass(`taroviz-${chartType}`);
33
+ });
34
+
35
+ it('should pass the correct option to BaseChartWrapper', () => {
36
+ const { getByTestId } = render(
37
+ React.createElement(ChartComponent, { option: mockOption } as any)
38
+ );
39
+
40
+ const chartOption = getByTestId('chart-option');
41
+ expect(JSON.parse(chartOption.textContent || '')).toEqual(mockOption);
42
+ });
43
+
44
+ it('should render with custom width and height', () => {
45
+ const customWidth = '500px';
46
+ const customHeight = '400px';
47
+
48
+ const { getByTestId } = render(
49
+ React.createElement(ChartComponent, {
50
+ option: mockOption,
51
+ width: customWidth,
52
+ height: customHeight,
53
+ } as any)
54
+ );
55
+
56
+ const chartWrapper = getByTestId('base-chart-wrapper');
57
+ expect(chartWrapper).toHaveStyle(`width: ${customWidth}`);
58
+ expect(chartWrapper).toHaveStyle(`height: ${customHeight}`);
59
+ });
60
+
61
+ it('should render with custom className', () => {
62
+ const customClass = `custom-${chartType}`;
63
+
64
+ const { getByTestId } = render(
65
+ React.createElement(ChartComponent, {
66
+ option: mockOption,
67
+ className: customClass,
68
+ } as any)
69
+ );
70
+
71
+ const chartWrapper = getByTestId('base-chart-wrapper');
72
+ expect(chartWrapper).toHaveClass(customClass);
73
+ });
74
+
75
+ it('should render with loading state', () => {
76
+ const { getByTestId } = render(
77
+ React.createElement(ChartComponent, {
78
+ option: mockOption,
79
+ loading: true,
80
+ } as any)
81
+ );
82
+
83
+ const chartWrapper = getByTestId('base-chart-wrapper');
84
+ expect(chartWrapper).toBeInTheDocument();
85
+ });
86
+ });
87
+ }
@@ -1,130 +1,76 @@
1
1
  /**
2
- * @jest-environment jsdom
2
+ * BoxplotChart 组件测试
3
3
  */
4
4
  import React from 'react';
5
5
  import { render } from '@testing-library/react';
6
6
  import '@testing-library/jest-dom';
7
- import BoxplotChart from '../index';
8
-
9
- // Mock ECharts and adapters
10
- jest.mock('echarts/core', () => ({
11
- use: jest.fn(),
12
- init: jest.fn(() => ({
13
- setOption: jest.fn(),
14
- showLoading: jest.fn(),
15
- hideLoading: jest.fn(),
16
- on: jest.fn(),
17
- off: jest.fn(),
18
- dispose: jest.fn(),
19
- resize: jest.fn(),
20
- })),
21
- getInstanceByDom: jest.fn(),
22
- }));
23
7
 
24
- // Mock ECharts components
25
- jest.mock('echarts/components', () => ({
26
- GridComponent: jest.fn(),
27
- TooltipComponent: jest.fn(),
28
- TitleComponent: jest.fn(),
29
- LegendComponent: jest.fn(),
30
- }));
8
+ import BoxplotChart from '../index';
31
9
 
32
- // Mock BaseChartWrapper
33
- jest.mock('../../common/BaseChartWrapper', () => ({
34
- __esModule: true,
35
- default: (props: any) => (
36
- <div
37
- data-testid="boxplot-chart"
38
- className={`taroviz-boxplot ${props.className || ''}`}
39
- style={{ width: props.width || '100%', height: props.height || 300, ...props.style }}
40
- >
41
- <div data-testid="chart-option">{JSON.stringify(props.option)}</div>
42
- </div>
43
- ),
44
- }));
10
+ // 自动使用 src/charts/common/__mocks__/BaseChartWrapper.tsx
11
+ jest.mock('../../common/BaseChartWrapper');
12
+ jest.mock('echarts/charts', () => ({ BoxplotChart: jest.fn() }));
45
13
 
46
- describe('BoxplotChart', () => {
47
- const basicOption = {
48
- title: { text: '箱线图测试' },
49
- xAxis: { type: 'category' as const, data: ['A', 'B', 'C'] },
50
- yAxis: { type: 'value' as const },
51
- series: [{
14
+ const basicOption = {
15
+ title: { text: '箱线图测试' },
16
+ xAxis: { type: 'category' as const, data: ['A', 'B', 'C'] },
17
+ yAxis: { type: 'value' as const },
18
+ series: [
19
+ {
52
20
  type: 'boxplot' as const,
53
21
  data: [
54
22
  [850, 940, 980, 1050, 1130],
55
23
  [920, 1000, 1050, 1150, 1200],
56
24
  [780, 850, 920, 1050, 1150],
57
25
  ],
58
- }],
59
- };
60
-
61
- describe('Basic Rendering', () => {
62
- it('should render without crashing', () => {
63
- const { getByTestId } = render(<BoxplotChart option={basicOption} />);
64
- expect(getByTestId('boxplot-chart')).toBeInTheDocument();
65
- });
66
-
67
- it('should render with custom width and height', () => {
68
- const { getByTestId } = render(<BoxplotChart option={basicOption} width={600} height={500} />);
69
- expect(getByTestId('boxplot-chart')).toBeInTheDocument();
70
- });
71
-
72
- it('should have correct display name', () => {
73
- expect(BoxplotChart.displayName).toBe('BoxplotChart');
74
- });
26
+ },
27
+ ],
28
+ };
75
29
 
76
- it('should pass option to wrapper', () => {
77
- const { getByTestId } = render(<BoxplotChart option={basicOption} />);
78
- expect(getByTestId('chart-option')).toHaveTextContent('箱线图测试');
79
- });
30
+ describe('BoxplotChart', () => {
31
+ it('should render without crashing', () => {
32
+ const { getByTestId } = render(<BoxplotChart option={basicOption} />);
33
+ expect(getByTestId('base-chart-wrapper')).toBeInTheDocument();
80
34
  });
81
35
 
82
- describe('Props', () => {
83
- it('should accept className prop', () => {
84
- const { getByTestId } = render(<BoxplotChart option={basicOption} className="test-class" />);
85
- expect(getByTestId('boxplot-chart')).toHaveClass('test-class');
86
- });
87
-
88
- it('should accept style prop', () => {
89
- const { getByTestId } = render(<BoxplotChart option={basicOption} style={{ padding: '10px' }} />);
90
- expect(getByTestId('boxplot-chart')).toBeInTheDocument();
91
- });
36
+ it('should have correct display name', () => {
37
+ expect(BoxplotChart.displayName).toBe('BoxplotChart');
38
+ });
92
39
 
93
- it('should accept loading prop', () => {
94
- const { getByTestId } = render(<BoxplotChart option={basicOption} loading={true} />);
95
- expect(getByTestId('boxplot-chart')).toBeInTheDocument();
96
- });
40
+ it('should accept className prop', () => {
41
+ const { getByTestId } = render(<BoxplotChart option={basicOption} className="test-class" />);
42
+ expect(getByTestId('base-chart-wrapper')).toHaveClass('test-class');
43
+ });
97
44
 
98
- it('should accept theme prop', () => {
99
- const { getByTestId } = render(<BoxplotChart option={basicOption} theme="dark" />);
100
- expect(getByTestId('boxplot-chart')).toBeInTheDocument();
101
- });
45
+ it('should accept loading prop', () => {
46
+ const { getByTestId } = render(<BoxplotChart option={basicOption} loading={true} />);
47
+ expect(getByTestId('base-chart-wrapper')).toBeInTheDocument();
102
48
  });
103
49
 
104
- describe('Chart Options', () => {
105
- it('should render with multiple data series', () => {
106
- const multiOption = {
107
- ...basicOption,
108
- series: [
109
- { type: 'boxplot' as const, name: '2024', data: [[850, 940, 980, 1050, 1130]] },
110
- { type: 'boxplot' as const, name: '2025', data: [[920, 1000, 1050, 1150, 1200]] },
111
- ],
112
- };
113
- const { getByTestId } = render(<BoxplotChart option={multiOption} />);
114
- expect(getByTestId('boxplot-chart')).toBeInTheDocument();
115
- });
50
+ it('should render with multiple data series', () => {
51
+ const multiOption = {
52
+ ...basicOption,
53
+ series: [
54
+ { type: 'boxplot' as const, name: '2024', data: [[850, 940, 980, 1050, 1130]] },
55
+ { type: 'boxplot' as const, name: '2025', data: [[920, 1000, 1050, 1150, 1200]] },
56
+ ],
57
+ };
58
+ const { getByTestId } = render(<BoxplotChart option={multiOption} />);
59
+ expect(getByTestId('base-chart-wrapper')).toBeInTheDocument();
60
+ });
116
61
 
117
- it('should render with custom itemStyle', () => {
118
- const optionWithStyle = {
119
- ...basicOption,
120
- series: [{
62
+ it('should render with custom itemStyle', () => {
63
+ const optionWithStyle = {
64
+ ...basicOption,
65
+ series: [
66
+ {
121
67
  type: 'boxplot' as const,
122
68
  data: [[850, 940, 980, 1050, 1130]],
123
69
  itemStyle: { color: '#1890ff', borderColor: '#000' },
124
- }],
125
- };
126
- const { getByTestId } = render(<BoxplotChart option={optionWithStyle} />);
127
- expect(getByTestId('boxplot-chart')).toBeInTheDocument();
128
- });
70
+ },
71
+ ],
72
+ };
73
+ const { getByTestId } = render(<BoxplotChart option={optionWithStyle} />);
74
+ expect(getByTestId('base-chart-wrapper')).toBeInTheDocument();
129
75
  });
130
76
  });
@@ -3,11 +3,12 @@
3
3
  * 用于展示数据的分布情况,包括最小值、Q1、中位数、Q3、最大值
4
4
  */
5
5
  import React, { memo } from 'react';
6
+ import type { EChartsOption } from 'echarts';
6
7
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
8
  import { BoxplotChartProps } from './types';
8
9
 
9
10
  const BoxplotChart: React.FC<BoxplotChartProps> = memo((props) => (
10
- <BaseChartWrapper {...props} chartType="boxplot" />
11
+ <BaseChartWrapper {...props} option={props.option as EChartsOption} chartType="boxplot" />
11
12
  ));
12
13
 
13
14
  BoxplotChart.displayName = 'BoxplotChart';
@@ -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, (params: ECElementEvent) => void>;
13
+ onEvents?: Record<string, (_params: ECElementEvent) => void>;
14
14
  loading?: boolean;
15
15
  loadingOption?: LoadingOptions;
16
16
  theme?: string;
17
- onChartReady?: (chart: EChartsType) => void;
17
+ onChartReady?: (_chart: EChartsType) => void;
18
18
  opts?: {
19
19
  devicePixelRatio?: number;
20
20
  renderer?: 'canvas' | 'svg';
@@ -23,26 +23,27 @@ export type BoxplotChartProps = {
23
23
  };
24
24
 
25
25
  export interface BoxplotOption {
26
- title?: any;
27
- legend?: any;
28
- grid?: any;
29
- xAxis?: any;
30
- yAxis?: any;
31
- tooltip?: any;
26
+ title?: unknown;
27
+ legend?: unknown;
28
+ grid?: unknown;
29
+ xAxis?: unknown;
30
+ yAxis?: unknown;
31
+ tooltip?: unknown;
32
32
  series: BoxplotSeriesItem[];
33
- dataset?: any;
33
+ dataset?: unknown;
34
34
  color?: string[];
35
- backgroundColor?: any;
36
- textStyle?: any;
37
- [key: string]: any;
35
+ backgroundColor?: unknown;
36
+ textStyle?: unknown;
37
+ [key: string]: unknown;
38
38
  }
39
39
 
40
40
  export interface BoxplotSeriesItem {
41
41
  type: 'boxplot';
42
42
  name?: string;
43
- data?: any[];
44
- itemStyle?: any;
45
- emphasis?: any;
43
+ data?: unknown[];
44
+ itemStyle?: unknown;
45
+ emphasis?: unknown;
46
46
  dimensions?: string[];
47
- encode?: any;
47
+ encode?: Record<string, number | string>;
48
+ [key: string]: unknown;
48
49
  }