@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.
- package/CHANGELOG.md +245 -0
- package/README.md +104 -302
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/vendors.js +1 -0
- package/dist/cjs/vendors~echarts.js +1 -0
- package/dist/esm/index.js +1 -58151
- package/dist/esm/vendors.js +1 -0
- package/dist/esm/vendors~echarts.js +1 -0
- package/package.json +19 -25
- package/src/adapters/MiniAppAdapter.ts +136 -0
- package/src/adapters/__tests__/index.test.ts +1 -1
- package/src/adapters/h5/__tests__/index.test.ts +4 -2
- package/src/adapters/h5/index.ts +63 -64
- package/src/adapters/harmony/index.ts +23 -245
- package/src/adapters/index.ts +49 -45
- package/src/adapters/swan/index.ts +6 -69
- package/src/adapters/tt/index.ts +7 -70
- package/src/adapters/types.ts +25 -58
- package/src/adapters/weapp/index.ts +6 -69
- package/src/charts/__tests__/testUtils.tsx +87 -0
- package/src/charts/boxplot/__tests__/index.test.tsx +49 -103
- package/src/charts/boxplot/index.tsx +2 -1
- package/src/charts/boxplot/types.ts +17 -16
- package/src/charts/common/BaseChartWrapper.tsx +90 -82
- package/src/charts/common/__mocks__/BaseChartWrapper.tsx +17 -0
- package/src/charts/createChartComponent.tsx +36 -0
- package/src/charts/createOptionChartComponent.tsx +32 -0
- package/src/charts/funnel/__tests__/index.test.tsx +99 -0
- package/src/charts/funnel/index.tsx +60 -10
- package/src/charts/funnel/types.ts +6 -0
- package/src/charts/graph/__tests__/index.test.tsx +102 -33
- package/src/charts/graph/index.tsx +66 -9
- package/src/charts/graph/types.ts +6 -0
- package/src/charts/heatmap/__tests__/index.test.tsx +139 -0
- package/src/charts/heatmap/index.tsx +103 -10
- package/src/charts/heatmap/types.ts +6 -0
- package/src/charts/index.ts +74 -26
- package/src/charts/liquid/__tests__/index.test.tsx +52 -0
- package/src/charts/liquid/index.tsx +239 -182
- package/src/charts/liquid/types.ts +11 -11
- package/src/charts/parallel/__tests__/index.test.tsx +40 -67
- package/src/charts/parallel/index.tsx +2 -1
- package/src/charts/parallel/types.ts +19 -18
- package/src/charts/radar/__tests__/index.test.tsx +210 -0
- package/src/charts/radar/index.tsx +143 -10
- package/src/charts/radar/types.ts +13 -0
- package/src/charts/sankey/__tests__/index.test.tsx +124 -0
- package/src/charts/sankey/index.tsx +62 -10
- package/src/charts/sankey/types.ts +6 -0
- package/src/charts/tree/__tests__/index.test.tsx +71 -0
- package/src/charts/tree/index.tsx +5 -2
- package/src/charts/tree/types.ts +9 -9
- package/src/charts/types.ts +208 -106
- package/src/charts/utils.ts +9 -7
- package/src/charts/wordcloud/__tests__/index.test.tsx +98 -31
- package/src/charts/wordcloud/index.tsx +75 -9
- package/src/charts/wordcloud/types.ts +6 -0
- package/src/components/DataFilter/index.tsx +32 -10
- package/src/core/animation/types.ts +6 -6
- package/src/core/components/Annotation.tsx +6 -7
- package/src/core/components/BaseChart.tsx +110 -168
- package/src/core/components/ErrorBoundary.tsx +17 -4
- package/src/core/components/LazyChart.tsx +54 -55
- package/src/core/components/hooks/index.ts +6 -2
- package/src/core/components/hooks/useChartInit.ts +6 -3
- package/src/core/components/hooks/usePerformance.ts +8 -2
- package/src/core/components/hooks/useVirtualScroll.ts +2 -1
- package/src/core/index.ts +1 -1
- package/src/core/themes/ThemeManager.ts +1 -1
- package/src/core/types/common.ts +2 -1
- package/src/core/types/index.ts +0 -12
- package/src/core/types/platform.ts +3 -5
- 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 -29
- package/src/core/utils/deepClone.ts +114 -0
- package/src/core/utils/download.ts +128 -0
- package/src/core/utils/drillDown.ts +34 -353
- package/src/core/utils/drillDownHelpers.ts +426 -0
- package/src/core/utils/events.ts +12 -0
- package/src/core/utils/export/ExportUtils.ts +36 -67
- package/src/core/utils/format.ts +44 -0
- package/src/core/utils/index.ts +21 -154
- package/src/core/utils/merge.ts +25 -0
- package/src/core/utils/performance/PerformanceAnalyzer.ts +38 -21
- 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 +45 -41
- package/src/core/utils/performance/useDataZoom.ts +324 -0
- package/src/{hooks → core/utils/performance}/usePerformance.ts +49 -41
- package/src/core/utils/performance/usePerformanceHooks.ts +278 -0
- package/src/core/utils/performanceUtils.ts +310 -0
- package/src/core/utils/runtime.ts +190 -0
- package/src/core/utils/setOptionUtils.ts +59 -0
- package/src/core/version.ts +14 -0
- package/src/editor/EnhancedThemeEditor.tsx +362 -540
- package/src/editor/ThemeEditor.tsx +55 -321
- package/src/editor/components/ThemeBasicSettings.tsx +113 -0
- package/src/editor/components/ThemeColorEditor.tsx +105 -0
- package/src/editor/components/ThemeSelector.tsx +70 -0
- package/src/editor/hooks/useThemeEditorState.ts +201 -0
- package/src/editor/index.ts +10 -2
- package/src/hooks/__tests__/index.test.tsx +3 -1
- package/src/hooks/chartConnectHelpers.ts +341 -0
- package/src/hooks/index.ts +55 -660
- package/src/hooks/types.ts +189 -0
- package/src/hooks/useChartAutoResize.ts +73 -0
- package/src/hooks/useChartConnect.ts +92 -238
- package/src/hooks/useChartDownload.ts +25 -27
- package/src/hooks/useChartHistory.ts +34 -49
- 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 +52 -49
- package/src/hooks/useChartTheme.ts +51 -0
- package/src/hooks/useDataTransform.ts +19 -4
- package/src/hooks/utils/chartDownloadUtils.ts +40 -53
- package/src/hooks/utils/dataTransformUtils.ts +22 -0
- package/src/index.ts +48 -34
- package/src/main.tsx +4 -9
- 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/charts/bar/__tests__/index.test.tsx +0 -113
- package/src/charts/bar/index.tsx +0 -14
- package/src/charts/candlestick/__tests__/index.test.tsx +0 -40
- package/src/charts/candlestick/index.tsx +0 -13
- package/src/charts/gauge/index.tsx +0 -14
- package/src/charts/line/__tests__/index.test.tsx +0 -107
- package/src/charts/line/index.tsx +0 -15
- package/src/charts/pie/__tests__/index.test.tsx +0 -112
- package/src/charts/pie/index.tsx +0 -14
- package/src/charts/scatter/index.tsx +0 -14
- package/src/charts/sunburst/index.tsx +0 -18
- package/src/charts/treemap/index.tsx +0 -18
- 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 -445
- package/src/core/utils/debug/DebugPanel.tsx +0 -637
- 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/src/hooks/useDataZoom.ts +0 -323
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaroViz 主题注册表 - 管理主题注册、查询和切换
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ThemeOptions } from './types';
|
|
6
|
+
import { defaultTheme } from './palettes/default';
|
|
7
|
+
import { darkTheme } from './palettes/dark';
|
|
8
|
+
import { neonTheme } from './palettes/neon';
|
|
9
|
+
import { glassTheme } from './palettes/glass';
|
|
10
|
+
import { pastelTheme } from './palettes/pastel';
|
|
11
|
+
import { sunsetTheme } from './palettes/sunset';
|
|
12
|
+
import { oceanTheme } from './palettes/ocean';
|
|
13
|
+
import { cyberTheme } from './palettes/cyber';
|
|
14
|
+
import { retroTheme } from './palettes/retro';
|
|
15
|
+
import { elegantTheme } from './palettes/elegant';
|
|
16
|
+
import { waldenTheme } from './palettes/walden';
|
|
17
|
+
import { chalkTheme } from './palettes/chalk';
|
|
18
|
+
import { purplePassionTheme } from './palettes/purple-passion';
|
|
19
|
+
import { blueGreenTheme } from './palettes/blue-green';
|
|
20
|
+
import { goldenTheme } from './palettes/golden';
|
|
21
|
+
import { forestTheme } from './palettes/forest';
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// 主题注册表
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
const themeRegistry = new Map<string, ThemeOptions>();
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// 内置主题集合
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
const builtinThemes: Record<string, ThemeOptions> = {
|
|
34
|
+
default: defaultTheme,
|
|
35
|
+
dark: darkTheme,
|
|
36
|
+
walden: waldenTheme,
|
|
37
|
+
chalk: chalkTheme,
|
|
38
|
+
'purple-passion': purplePassionTheme,
|
|
39
|
+
'blue-green': blueGreenTheme,
|
|
40
|
+
golden: goldenTheme,
|
|
41
|
+
forest: forestTheme,
|
|
42
|
+
neon: neonTheme,
|
|
43
|
+
glass: glassTheme,
|
|
44
|
+
pastel: pastelTheme,
|
|
45
|
+
sunset: sunsetTheme,
|
|
46
|
+
ocean: oceanTheme,
|
|
47
|
+
cyber: cyberTheme,
|
|
48
|
+
retro: retroTheme,
|
|
49
|
+
elegant: elegantTheme,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// 注册所有内置主题
|
|
53
|
+
Object.entries(builtinThemes).forEach(([name, theme]) => {
|
|
54
|
+
themeRegistry.set(name, theme as ThemeOptions);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// 主题管理函数
|
|
59
|
+
// ============================================================================
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 获取主题配置
|
|
63
|
+
* @param options 自定义选项
|
|
64
|
+
* @returns 合并后的主题配置
|
|
65
|
+
*/
|
|
66
|
+
export function getTheme(options?: Partial<ThemeOptions>): ThemeOptions {
|
|
67
|
+
if (!options) {
|
|
68
|
+
return defaultTheme;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let baseTheme: ThemeOptions;
|
|
72
|
+
if (options.theme && typeof options.theme === 'string') {
|
|
73
|
+
const registeredTheme = themeRegistry.get(options.theme);
|
|
74
|
+
if (registeredTheme) {
|
|
75
|
+
baseTheme = registeredTheme;
|
|
76
|
+
} else {
|
|
77
|
+
baseTheme = options.darkMode ? darkTheme : defaultTheme;
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
baseTheme = options.darkMode ? darkTheme : defaultTheme;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { ...baseTheme, ...options };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 注册主题
|
|
88
|
+
* @param name 主题名称
|
|
89
|
+
* @param theme 主题配置
|
|
90
|
+
*/
|
|
91
|
+
export function registerTheme(name: string, theme: ThemeOptions): void {
|
|
92
|
+
themeRegistry.set(name, { ...theme, name });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 获取已注册的主题列表
|
|
97
|
+
* @returns 主题列表
|
|
98
|
+
*/
|
|
99
|
+
export function getRegisteredThemes(): ThemeOptions[] {
|
|
100
|
+
return Array.from(themeRegistry.values());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 获取指定主题
|
|
105
|
+
* @param name 主题名称
|
|
106
|
+
* @returns 主题配置
|
|
107
|
+
*/
|
|
108
|
+
export function getThemeByName(name: string): ThemeOptions | undefined {
|
|
109
|
+
return themeRegistry.get(name);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 删除主题
|
|
114
|
+
* @param name 主题名称
|
|
115
|
+
*/
|
|
116
|
+
export function unregisterTheme(name: string): void {
|
|
117
|
+
themeRegistry.delete(name);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 重置主题注册表(清除所有已注册的主题,恢复内置主题)
|
|
122
|
+
* 主要用于测试环境
|
|
123
|
+
*/
|
|
124
|
+
export function resetThemeRegistry(): void {
|
|
125
|
+
themeRegistry.clear();
|
|
126
|
+
// 重新注册所有内置主题
|
|
127
|
+
Object.entries(builtinThemes).forEach(([name, theme]) => {
|
|
128
|
+
themeRegistry.set(name, theme as ThemeOptions);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 动态切换主题
|
|
134
|
+
* @param theme 主题名称或主题配置
|
|
135
|
+
* @param callback 切换完成后的回调函数
|
|
136
|
+
* @returns 主题配置
|
|
137
|
+
*/
|
|
138
|
+
export function switchTheme(theme: string | ThemeOptions, callback?: () => void): ThemeOptions {
|
|
139
|
+
let themeConfig: ThemeOptions;
|
|
140
|
+
|
|
141
|
+
if (typeof theme === 'string') {
|
|
142
|
+
const registeredTheme = themeRegistry.get(theme);
|
|
143
|
+
themeConfig = registeredTheme || defaultTheme;
|
|
144
|
+
} else {
|
|
145
|
+
themeConfig = theme;
|
|
146
|
+
if (theme.name) {
|
|
147
|
+
registerTheme(theme.name, theme);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 触发主题切换事件
|
|
152
|
+
if (typeof window !== 'undefined') {
|
|
153
|
+
window.dispatchEvent(new CustomEvent('themeChange', { detail: themeConfig }));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
callback?.();
|
|
157
|
+
|
|
158
|
+
return themeConfig;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* 根据标签获取主题
|
|
163
|
+
* @param tag 标签
|
|
164
|
+
* @returns 主题列表
|
|
165
|
+
*/
|
|
166
|
+
export function getThemesByTag(tag: string): ThemeOptions[] {
|
|
167
|
+
return getRegisteredThemes().filter((t) => t.tags?.includes(tag));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 获取浅色主题
|
|
172
|
+
* @returns 浅色主题列表
|
|
173
|
+
*/
|
|
174
|
+
export function getLightThemes(): ThemeOptions[] {
|
|
175
|
+
return getRegisteredThemes().filter((t) => !t.darkMode);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 获取深色主题
|
|
180
|
+
* @returns 深色主题列表
|
|
181
|
+
*/
|
|
182
|
+
export function getDarkThemes(): ThemeOptions[] {
|
|
183
|
+
return getRegisteredThemes().filter((t) => t.darkMode);
|
|
184
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaroViz 主题系统 - 类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 内置主题类型
|
|
7
|
+
*/
|
|
8
|
+
export type BuiltinTheme =
|
|
9
|
+
| 'default'
|
|
10
|
+
| 'light'
|
|
11
|
+
| 'dark'
|
|
12
|
+
| 'vintage'
|
|
13
|
+
| 'macarons'
|
|
14
|
+
| 'roma'
|
|
15
|
+
| 'shine'
|
|
16
|
+
| 'infographic'
|
|
17
|
+
| 'westeros'
|
|
18
|
+
| 'walden'
|
|
19
|
+
| 'chalk'
|
|
20
|
+
| 'purple-passion'
|
|
21
|
+
| 'blue-green'
|
|
22
|
+
| 'golden'
|
|
23
|
+
| 'forest'
|
|
24
|
+
// 新增主题
|
|
25
|
+
| 'neon'
|
|
26
|
+
| 'glass'
|
|
27
|
+
| 'pastel'
|
|
28
|
+
| 'sunset'
|
|
29
|
+
| 'ocean'
|
|
30
|
+
| 'cyber'
|
|
31
|
+
| 'retro'
|
|
32
|
+
| 'elegant';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 主题模式
|
|
36
|
+
*/
|
|
37
|
+
export type ThemeMode = 'light' | 'dark' | 'auto';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 主题渐变类型
|
|
41
|
+
*/
|
|
42
|
+
export interface ThemeGradient {
|
|
43
|
+
/** 渐变起始色 */
|
|
44
|
+
start: string;
|
|
45
|
+
/** 渐变结束色 */
|
|
46
|
+
end: string;
|
|
47
|
+
/** 渐变角度 */
|
|
48
|
+
angle?: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 主题效果配置
|
|
53
|
+
*/
|
|
54
|
+
export interface ThemeEffects {
|
|
55
|
+
/** 是否启用阴影 */
|
|
56
|
+
shadows?: boolean;
|
|
57
|
+
/** 阴影颜色 */
|
|
58
|
+
shadowColor?: string;
|
|
59
|
+
/** 是否启用渐变 */
|
|
60
|
+
gradients?: boolean;
|
|
61
|
+
/** 自定义渐变 */
|
|
62
|
+
customGradients?: ThemeGradient[];
|
|
63
|
+
/** 是否启用玻璃态 */
|
|
64
|
+
glassmorphism?: boolean;
|
|
65
|
+
/** 玻璃态模糊度 */
|
|
66
|
+
blur?: number;
|
|
67
|
+
/** 圆角风格 */
|
|
68
|
+
borderRadius?: 'none' | 'small' | 'medium' | 'large' | 'pill';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 主题配置选项
|
|
73
|
+
*/
|
|
74
|
+
export interface ThemeOptions {
|
|
75
|
+
/** 主题名称/键名 */
|
|
76
|
+
theme?: BuiltinTheme | Record<string, unknown>;
|
|
77
|
+
|
|
78
|
+
/** 是否启用深色模式 */
|
|
79
|
+
darkMode?: boolean;
|
|
80
|
+
|
|
81
|
+
/** 主题模式 */
|
|
82
|
+
mode?: ThemeMode;
|
|
83
|
+
|
|
84
|
+
/** 颜色列表 */
|
|
85
|
+
colors?: string[];
|
|
86
|
+
|
|
87
|
+
/** 背景色 */
|
|
88
|
+
backgroundColor?: string;
|
|
89
|
+
|
|
90
|
+
/** 背景渐变 */
|
|
91
|
+
backgroundGradient?: ThemeGradient;
|
|
92
|
+
|
|
93
|
+
/** 文本颜色 */
|
|
94
|
+
textColor?: string;
|
|
95
|
+
|
|
96
|
+
/** 次要文本颜色 */
|
|
97
|
+
textColorSecondary?: string;
|
|
98
|
+
|
|
99
|
+
/** 边框颜色 */
|
|
100
|
+
borderColor?: string;
|
|
101
|
+
|
|
102
|
+
/** 分割线颜色 */
|
|
103
|
+
dividerColor?: string;
|
|
104
|
+
|
|
105
|
+
/** 字体 */
|
|
106
|
+
fontFamily?: string;
|
|
107
|
+
|
|
108
|
+
/** 标题字体 */
|
|
109
|
+
fontFamilyTitle?: string;
|
|
110
|
+
|
|
111
|
+
/** 正文字体 */
|
|
112
|
+
fontFamilyBody?: string;
|
|
113
|
+
|
|
114
|
+
/** 主题名称(显示用) */
|
|
115
|
+
name?: string;
|
|
116
|
+
|
|
117
|
+
/** 主题描述 */
|
|
118
|
+
description?: string;
|
|
119
|
+
|
|
120
|
+
/** 主题作者 */
|
|
121
|
+
author?: string;
|
|
122
|
+
|
|
123
|
+
/** 主题版本 */
|
|
124
|
+
version?: string;
|
|
125
|
+
|
|
126
|
+
/** 主题类型 */
|
|
127
|
+
type?: ThemeMode;
|
|
128
|
+
|
|
129
|
+
/** 主题标签 */
|
|
130
|
+
tags?: string[];
|
|
131
|
+
|
|
132
|
+
/** 效果配置 */
|
|
133
|
+
effects?: ThemeEffects;
|
|
134
|
+
|
|
135
|
+
/** 图表特定配置 */
|
|
136
|
+
chart?: ChartThemeConfig;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 图表主题配置
|
|
141
|
+
*/
|
|
142
|
+
export interface ChartThemeConfig {
|
|
143
|
+
/** 图例配置 */
|
|
144
|
+
legend?: LegendThemeConfig;
|
|
145
|
+
/** 坐标轴配置 */
|
|
146
|
+
axis?: AxisThemeConfig;
|
|
147
|
+
/** 提示框配置 */
|
|
148
|
+
tooltip?: TooltipThemeConfig;
|
|
149
|
+
/** 标题配置 */
|
|
150
|
+
title?: TitleThemeConfig;
|
|
151
|
+
/** 网格配置 */
|
|
152
|
+
grid?: GridThemeConfig;
|
|
153
|
+
/** 数据区域缩放配置 */
|
|
154
|
+
dataZoom?: DataZoomThemeConfig;
|
|
155
|
+
/** 时间线配置 */
|
|
156
|
+
timeline?: TimelineThemeConfig;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** 图例主题配置 */
|
|
160
|
+
export interface LegendThemeConfig {
|
|
161
|
+
textColor?: string;
|
|
162
|
+
backgroundColor?: string;
|
|
163
|
+
borderColor?: string;
|
|
164
|
+
borderRadius?: number | number[];
|
|
165
|
+
padding?: number | number[];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** 坐标轴主题配置 */
|
|
169
|
+
export interface AxisThemeConfig {
|
|
170
|
+
textColor?: string;
|
|
171
|
+
lineColor?: string;
|
|
172
|
+
tickColor?: string;
|
|
173
|
+
splitLineColor?: string;
|
|
174
|
+
splitAreaColor?: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** 提示框主题配置 */
|
|
178
|
+
export interface TooltipThemeConfig {
|
|
179
|
+
textColor?: string;
|
|
180
|
+
backgroundColor?: string;
|
|
181
|
+
borderColor?: string;
|
|
182
|
+
borderRadius?: number;
|
|
183
|
+
shadowColor?: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** 标题主题配置 */
|
|
187
|
+
export interface TitleThemeConfig {
|
|
188
|
+
textColor?: string;
|
|
189
|
+
subTextColor?: string;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** 网格主题配置 */
|
|
193
|
+
export interface GridThemeConfig {
|
|
194
|
+
backgroundColor?: string;
|
|
195
|
+
borderColor?: string;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** 数据区域缩放主题配置 */
|
|
199
|
+
export interface DataZoomThemeConfig {
|
|
200
|
+
backgroundColor?: string;
|
|
201
|
+
fillerColor?: string;
|
|
202
|
+
borderColor?: string;
|
|
203
|
+
textColor?: string;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** 时间线主题配置 */
|
|
207
|
+
export interface TimelineThemeConfig {
|
|
208
|
+
backgroundColor?: string;
|
|
209
|
+
borderColor?: string;
|
|
210
|
+
textColor?: string;
|
|
211
|
+
lineColor?: string;
|
|
212
|
+
controlColor?: string;
|
|
213
|
+
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { render } from '@testing-library/react';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
import BarChart from '../index';
|
|
5
|
-
|
|
6
|
-
// Mock ECharts and adapters
|
|
7
|
-
jest.mock('echarts/core', () => ({
|
|
8
|
-
use: jest.fn(),
|
|
9
|
-
init: jest.fn(() => ({
|
|
10
|
-
setOption: jest.fn(),
|
|
11
|
-
showLoading: jest.fn(),
|
|
12
|
-
hideLoading: jest.fn(),
|
|
13
|
-
on: jest.fn(),
|
|
14
|
-
off: jest.fn(),
|
|
15
|
-
dispose: jest.fn(),
|
|
16
|
-
resize: jest.fn(),
|
|
17
|
-
})),
|
|
18
|
-
getInstanceByDom: jest.fn(),
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
// Mock specific ECharts chart imports
|
|
22
|
-
jest.mock('echarts/charts', () => ({
|
|
23
|
-
BarChart: jest.fn(),
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
jest.mock('echarts/components', () => ({
|
|
27
|
-
GridComponent: jest.fn(),
|
|
28
|
-
TooltipComponent: jest.fn(),
|
|
29
|
-
TitleComponent: jest.fn(),
|
|
30
|
-
LegendComponent: jest.fn(),
|
|
31
|
-
}));
|
|
32
|
-
|
|
33
|
-
jest.mock('../../common/BaseChartWrapper', () => ({
|
|
34
|
-
__esModule: true,
|
|
35
|
-
default: (props: any) => (
|
|
36
|
-
<div
|
|
37
|
-
data-testid="base-chart-wrapper"
|
|
38
|
-
className={`taroviz-${props.chartType} ${props.className || ''}`}
|
|
39
|
-
style={{ width: props.width, height: props.height }}
|
|
40
|
-
>
|
|
41
|
-
<div data-testid="chart-option">{JSON.stringify(props.option)}</div>
|
|
42
|
-
</div>
|
|
43
|
-
),
|
|
44
|
-
}));
|
|
45
|
-
|
|
46
|
-
describe('BarChart Component', () => {
|
|
47
|
-
const mockOption = {
|
|
48
|
-
xAxis: {
|
|
49
|
-
type: 'category' as const,
|
|
50
|
-
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
|
51
|
-
},
|
|
52
|
-
yAxis: {
|
|
53
|
-
type: 'value' as const,
|
|
54
|
-
},
|
|
55
|
-
series: [
|
|
56
|
-
{
|
|
57
|
-
data: [150, 230, 224, 218, 135, 147, 260],
|
|
58
|
-
type: 'bar' as const,
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
it('should render correctly with default props', () => {
|
|
64
|
-
const { getByTestId } = render(<BarChart option={mockOption} />);
|
|
65
|
-
|
|
66
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
67
|
-
expect(chartWrapper).toBeInTheDocument();
|
|
68
|
-
expect(chartWrapper).toHaveClass('taroviz-bar-chart');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should pass the correct option to BaseChartWrapper', () => {
|
|
72
|
-
const { getByTestId } = render(<BarChart option={mockOption} />);
|
|
73
|
-
|
|
74
|
-
const chartOption = getByTestId('chart-option');
|
|
75
|
-
expect(JSON.parse(chartOption.textContent || '')).toEqual(mockOption);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should render with custom width and height', () => {
|
|
79
|
-
const customWidth = '600px';
|
|
80
|
-
const customHeight = '450px';
|
|
81
|
-
|
|
82
|
-
const { getByTestId } = render(
|
|
83
|
-
<BarChart option={mockOption} width={customWidth} height={customHeight} />
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
87
|
-
expect(chartWrapper).toHaveStyle(`width: ${customWidth}`);
|
|
88
|
-
expect(chartWrapper).toHaveStyle(`height: ${customHeight}`);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should render with custom className', () => {
|
|
92
|
-
const customClass = 'custom-bar-chart';
|
|
93
|
-
|
|
94
|
-
const { getByTestId } = render(<BarChart option={mockOption} className={customClass} />);
|
|
95
|
-
|
|
96
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
97
|
-
expect(chartWrapper).toHaveClass(customClass);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should render with loading state', () => {
|
|
101
|
-
const { getByTestId } = render(<BarChart option={mockOption} loading={true} />);
|
|
102
|
-
|
|
103
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
104
|
-
expect(chartWrapper).toBeInTheDocument();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('should render with svg renderer', () => {
|
|
108
|
-
const { getByTestId } = render(<BarChart option={mockOption} renderer="svg" />);
|
|
109
|
-
|
|
110
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
111
|
-
expect(chartWrapper).toBeInTheDocument();
|
|
112
|
-
});
|
|
113
|
-
});
|
package/src/charts/bar/index.tsx
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BarChart组件
|
|
3
|
-
*/
|
|
4
|
-
import React, { memo } from 'react';
|
|
5
|
-
import BaseChartWrapper from '../common/BaseChartWrapper';
|
|
6
|
-
import { BarChartProps } from '../types';
|
|
7
|
-
import '@/core/echarts';
|
|
8
|
-
|
|
9
|
-
const BarChart: React.FC<BarChartProps> = memo((props) => (
|
|
10
|
-
<BaseChartWrapper {...props} chartType="bar-chart" />
|
|
11
|
-
));
|
|
12
|
-
BarChart.displayName = 'BarChart';
|
|
13
|
-
|
|
14
|
-
export default BarChart;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @version v1.5.0
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import { render } from '@testing-library/react';
|
|
7
|
-
import CandlestickChart from '../index';
|
|
8
|
-
|
|
9
|
-
describe('CandlestickChart', () => {
|
|
10
|
-
it('renders without crashing', () => {
|
|
11
|
-
const { container } = render(<CandlestickChart />);
|
|
12
|
-
expect(container).toBeTruthy();
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('renders with custom width and height', () => {
|
|
16
|
-
const { container } = render(<CandlestickChart width={500} 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: '500px', height: '400px' });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('renders with stock data', () => {
|
|
24
|
-
const option = {
|
|
25
|
-
xAxis: { data: ['2024-01', '2024-02', '2024-03'] },
|
|
26
|
-
series: [
|
|
27
|
-
{
|
|
28
|
-
type: 'candlestick' as const,
|
|
29
|
-
data: [
|
|
30
|
-
[20, 30, 15, 35], // [open, close, lowest, highest]
|
|
31
|
-
[25, 35, 20, 40],
|
|
32
|
-
[30, 25, 20, 35],
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
};
|
|
37
|
-
const { container } = render(<CandlestickChart option={option} />);
|
|
38
|
-
expect(container).toBeTruthy();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CandlestickChart组件
|
|
3
|
-
*/
|
|
4
|
-
import React, { memo } from 'react';
|
|
5
|
-
import BaseChartWrapper from '../common/BaseChartWrapper';
|
|
6
|
-
import { CandlestickChartProps } from '../types';
|
|
7
|
-
|
|
8
|
-
const CandlestickChart: React.FC<CandlestickChartProps> = memo((props) => (
|
|
9
|
-
<BaseChartWrapper {...props} chartType="candlestick-chart" />
|
|
10
|
-
));
|
|
11
|
-
CandlestickChart.displayName = 'CandlestickChart';
|
|
12
|
-
|
|
13
|
-
export default CandlestickChart;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GaugeChart组件
|
|
3
|
-
*/
|
|
4
|
-
import React, { memo } from 'react';
|
|
5
|
-
import BaseChartWrapper from '../common/BaseChartWrapper';
|
|
6
|
-
import { GaugeChartProps } from '../types';
|
|
7
|
-
import '@/core/echarts';
|
|
8
|
-
|
|
9
|
-
const GaugeChart: React.FC<GaugeChartProps> = memo((props) => (
|
|
10
|
-
<BaseChartWrapper {...props} chartType="gauge-chart" />
|
|
11
|
-
));
|
|
12
|
-
GaugeChart.displayName = 'GaugeChart';
|
|
13
|
-
|
|
14
|
-
export default GaugeChart;
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { render } from '@testing-library/react';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
import LineChart from '../index';
|
|
5
|
-
|
|
6
|
-
// Mock ECharts and adapters
|
|
7
|
-
jest.mock('echarts/core', () => ({
|
|
8
|
-
use: jest.fn(),
|
|
9
|
-
init: jest.fn(() => ({
|
|
10
|
-
setOption: jest.fn(),
|
|
11
|
-
showLoading: jest.fn(),
|
|
12
|
-
hideLoading: jest.fn(),
|
|
13
|
-
on: jest.fn(),
|
|
14
|
-
off: jest.fn(),
|
|
15
|
-
dispose: jest.fn(),
|
|
16
|
-
resize: jest.fn(),
|
|
17
|
-
})),
|
|
18
|
-
getInstanceByDom: jest.fn(),
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
// Mock specific ECharts chart imports
|
|
22
|
-
jest.mock('echarts/charts', () => ({
|
|
23
|
-
LineChart: jest.fn(),
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
jest.mock('echarts/components', () => ({
|
|
27
|
-
GridComponent: jest.fn(),
|
|
28
|
-
TooltipComponent: jest.fn(),
|
|
29
|
-
TitleComponent: jest.fn(),
|
|
30
|
-
LegendComponent: jest.fn(),
|
|
31
|
-
}));
|
|
32
|
-
|
|
33
|
-
jest.mock('../../common/BaseChartWrapper', () => ({
|
|
34
|
-
__esModule: true,
|
|
35
|
-
default: (props: any) => (
|
|
36
|
-
<div
|
|
37
|
-
data-testid="base-chart-wrapper"
|
|
38
|
-
className={`taroviz-${props.chartType} ${props.className || ''}`}
|
|
39
|
-
style={{ width: props.width, height: props.height }}
|
|
40
|
-
>
|
|
41
|
-
<div data-testid="chart-option">{JSON.stringify(props.option)}</div>
|
|
42
|
-
</div>
|
|
43
|
-
),
|
|
44
|
-
}));
|
|
45
|
-
|
|
46
|
-
describe('LineChart Component', () => {
|
|
47
|
-
const mockOption = {
|
|
48
|
-
xAxis: {
|
|
49
|
-
type: 'category' as const,
|
|
50
|
-
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
|
51
|
-
},
|
|
52
|
-
yAxis: {
|
|
53
|
-
type: 'value' as const,
|
|
54
|
-
},
|
|
55
|
-
series: [
|
|
56
|
-
{
|
|
57
|
-
data: [150, 230, 224, 218, 135, 147, 260],
|
|
58
|
-
type: 'line' as const,
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
it('should render correctly with default props', () => {
|
|
64
|
-
const { getByTestId } = render(<LineChart option={mockOption} />);
|
|
65
|
-
|
|
66
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
67
|
-
expect(chartWrapper).toBeInTheDocument();
|
|
68
|
-
expect(chartWrapper).toHaveClass('taroviz-line-chart');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should pass the correct option to BaseChartWrapper', () => {
|
|
72
|
-
const { getByTestId } = render(<LineChart option={mockOption} />);
|
|
73
|
-
|
|
74
|
-
const chartOption = getByTestId('chart-option');
|
|
75
|
-
expect(JSON.parse(chartOption.textContent || '')).toEqual(mockOption);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should render with custom width and height', () => {
|
|
79
|
-
const customWidth = '500px';
|
|
80
|
-
const customHeight = '400px';
|
|
81
|
-
|
|
82
|
-
const { getByTestId } = render(
|
|
83
|
-
<LineChart option={mockOption} width={customWidth} height={customHeight} />
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
87
|
-
expect(chartWrapper).toHaveStyle(`width: ${customWidth}`);
|
|
88
|
-
expect(chartWrapper).toHaveStyle(`height: ${customHeight}`);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should render with custom className', () => {
|
|
92
|
-
const customClass = 'custom-line-chart';
|
|
93
|
-
|
|
94
|
-
const { getByTestId } = render(<LineChart option={mockOption} className={customClass} />);
|
|
95
|
-
|
|
96
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
97
|
-
expect(chartWrapper).toHaveClass(customClass);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should render with loading state', () => {
|
|
101
|
-
const { getByTestId } = render(<LineChart option={mockOption} loading={true} />);
|
|
102
|
-
|
|
103
|
-
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
104
|
-
expect(chartWrapper).toBeInTheDocument();
|
|
105
|
-
// The loading state is handled by BaseChartWrapper, which we've mocked
|
|
106
|
-
});
|
|
107
|
-
});
|