@agions/taroviz 1.1.0 → 1.2.0

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 (73) hide show
  1. package/README.md +318 -53
  2. package/dist/index.esm.js +67955 -3318
  3. package/package.json +102 -20
  4. package/src/__tests__/integration.test.tsx +168 -0
  5. package/src/adapters/__tests__/index.test.ts +91 -0
  6. package/src/adapters/h5/__tests__/index.test.ts +156 -0
  7. package/src/adapters/h5/index.ts +301 -0
  8. package/src/adapters/harmony/index.ts +274 -0
  9. package/src/adapters/index.ts +234 -0
  10. package/src/adapters/swan/index.ts +274 -0
  11. package/src/adapters/tt/index.ts +274 -0
  12. package/src/adapters/types.ts +162 -0
  13. package/src/adapters/weapp/index.ts +237 -0
  14. package/src/charts/bar/__tests__/index.test.tsx +113 -0
  15. package/src/charts/bar/index.tsx +27 -0
  16. package/src/charts/common/BaseChartWrapper.tsx +136 -0
  17. package/src/charts/funnel/index.tsx +33 -0
  18. package/src/charts/gauge/index.tsx +33 -0
  19. package/src/charts/heatmap/index.tsx +33 -0
  20. package/src/charts/index.ts +21 -0
  21. package/src/charts/line/__tests__/index.test.tsx +107 -0
  22. package/src/charts/line/index.tsx +27 -0
  23. package/src/charts/pie/__tests__/index.test.tsx +112 -0
  24. package/src/charts/pie/index.tsx +22 -0
  25. package/src/charts/radar/index.tsx +33 -0
  26. package/src/charts/scatter/index.tsx +33 -0
  27. package/src/charts/types.ts +146 -0
  28. package/src/charts/utils.ts +56 -0
  29. package/src/core/__tests__/platform.test.ts +48 -0
  30. package/src/core/animation/AnimationManager.ts +391 -0
  31. package/src/core/animation/index.ts +20 -0
  32. package/src/core/animation/types.ts +248 -0
  33. package/src/core/components/BaseChart.tsx +1319 -0
  34. package/src/core/index.ts +19 -0
  35. package/src/core/types/chart.ts +66 -0
  36. package/src/core/types/common.ts +224 -0
  37. package/src/core/types/index.ts +281 -0
  38. package/src/core/types/platform.ts +325 -0
  39. package/src/core/utils/__tests__/common.test.ts +52 -0
  40. package/src/core/utils/__tests__/environment.test.ts +94 -0
  41. package/src/core/utils/__tests__/i18n.test.ts +247 -0
  42. package/src/core/utils/__tests__/index.test.ts +219 -0
  43. package/src/core/utils/__tests__/uuid.test.ts +78 -0
  44. package/src/core/utils/chartInstances.ts +69 -0
  45. package/src/core/utils/codeGenerator/CodeGenerator.ts +655 -0
  46. package/src/core/utils/codeGenerator/index.ts +13 -0
  47. package/src/core/utils/codeGenerator/types.ts +200 -0
  48. package/src/core/utils/common.ts +58 -0
  49. package/src/core/utils/configGenerator/ConfigGenerator.ts +583 -0
  50. package/src/core/utils/configGenerator/index.ts +13 -0
  51. package/src/core/utils/configGenerator/types.ts +445 -0
  52. package/src/core/utils/debug/DebugPanel.tsx +637 -0
  53. package/src/core/utils/debug/debugger.ts +322 -0
  54. package/src/core/utils/debug/index.ts +21 -0
  55. package/src/core/utils/debug/types.ts +142 -0
  56. package/src/core/utils/i18n.ts +452 -0
  57. package/src/core/utils/index.ts +162 -0
  58. package/src/core/utils/performance/PerformanceAnalyzer.ts +586 -0
  59. package/src/core/utils/performance/index.ts +13 -0
  60. package/src/core/utils/performance/types.ts +180 -0
  61. package/src/core/utils/uuid.ts +30 -0
  62. package/src/editor/ThemeEditor.tsx +449 -0
  63. package/src/editor/index.ts +10 -0
  64. package/src/hooks/__tests__/index.test.tsx +333 -0
  65. package/src/hooks/index.ts +214 -0
  66. package/src/index.ts +75 -0
  67. package/src/main.tsx +247 -0
  68. package/src/react-dom.d.ts +7 -0
  69. package/src/themes/__tests__/index.test.ts +91 -0
  70. package/src/themes/index.ts +465 -0
  71. package/dist/index.esm.js.map +0 -1
  72. package/dist/index.js +0 -4012
  73. package/dist/index.js.map +0 -1
@@ -0,0 +1,219 @@
1
+ import {
2
+ deepMerge,
3
+ debounce,
4
+ throttle,
5
+ getEnvironment,
6
+ formatNumber,
7
+ getContrastColor,
8
+ uuid,
9
+ shortId,
10
+ prefixedId,
11
+ } from '../index';
12
+
13
+ describe('Data Processing Utilities', () => {
14
+ describe('deepMerge', () => {
15
+ it('should merge two objects', () => {
16
+ const target = { a: 1, b: { c: 2 } };
17
+ const source = { b: { d: 3 }, e: 4 };
18
+ const result = deepMerge(target, source);
19
+
20
+ expect(result).toEqual({ a: 1, b: { c: 2, d: 3 }, e: 4 });
21
+ });
22
+
23
+ it('should overwrite primitive values', () => {
24
+ const target = { a: 1, b: 'original' };
25
+ const source = { a: 2, b: 'updated' };
26
+ const result = deepMerge(target, source);
27
+
28
+ expect(result).toEqual({ a: 2, b: 'updated' });
29
+ });
30
+
31
+ it('should preserve nested objects when source has no matching key', () => {
32
+ const target = { a: { b: { c: 1 } } };
33
+ const source = { d: 2 };
34
+ const result = deepMerge(target, source);
35
+
36
+ expect(result).toEqual({ a: { b: { c: 1 } }, d: 2 });
37
+ });
38
+
39
+ it('should return target when source is empty', () => {
40
+ const target = { a: 1, b: 2 };
41
+ const source = {};
42
+ const result = deepMerge(target, source);
43
+
44
+ expect(result).toEqual(target);
45
+ });
46
+ });
47
+
48
+ describe('debounce', () => {
49
+ jest.useFakeTimers();
50
+
51
+ it('should delay execution', () => {
52
+ const mockFn = jest.fn();
53
+ const debouncedFn = debounce(mockFn, 100);
54
+
55
+ debouncedFn();
56
+ expect(mockFn).not.toHaveBeenCalled();
57
+
58
+ jest.advanceTimersByTime(50);
59
+ expect(mockFn).not.toHaveBeenCalled();
60
+
61
+ jest.advanceTimersByTime(50);
62
+ expect(mockFn).toHaveBeenCalledTimes(1);
63
+ });
64
+
65
+ it('should reset timer when called again before delay', () => {
66
+ const mockFn = jest.fn();
67
+ const debouncedFn = debounce(mockFn, 100);
68
+
69
+ debouncedFn();
70
+ jest.advanceTimersByTime(50);
71
+ debouncedFn();
72
+ jest.advanceTimersByTime(50);
73
+ expect(mockFn).not.toHaveBeenCalled();
74
+
75
+ jest.advanceTimersByTime(50);
76
+ expect(mockFn).toHaveBeenCalledTimes(1);
77
+ });
78
+
79
+ it('should pass arguments correctly', () => {
80
+ const mockFn = jest.fn();
81
+ const debouncedFn = debounce(mockFn, 100);
82
+
83
+ debouncedFn('arg1', 2, { key: 'value' });
84
+ jest.advanceTimersByTime(100);
85
+
86
+ expect(mockFn).toHaveBeenCalledWith('arg1', 2, { key: 'value' });
87
+ });
88
+ });
89
+
90
+ describe('throttle', () => {
91
+ jest.useFakeTimers();
92
+
93
+ it('should limit execution to once per interval', () => {
94
+ const mockFn = jest.fn();
95
+ const throttledFn = throttle(mockFn, 100);
96
+
97
+ throttledFn();
98
+ expect(mockFn).toHaveBeenCalledTimes(1);
99
+
100
+ throttledFn();
101
+ expect(mockFn).toHaveBeenCalledTimes(1);
102
+
103
+ jest.advanceTimersByTime(100);
104
+ throttledFn();
105
+ expect(mockFn).toHaveBeenCalledTimes(2);
106
+ });
107
+
108
+ it('should pass arguments correctly', () => {
109
+ const mockFn = jest.fn();
110
+ const throttledFn = throttle(mockFn, 100);
111
+
112
+ throttledFn('arg1', 2);
113
+ expect(mockFn).toHaveBeenCalledWith('arg1', 2);
114
+ });
115
+
116
+ it('should execute immediately on first call', () => {
117
+ const mockFn = jest.fn();
118
+ const throttledFn = throttle(mockFn, 100);
119
+
120
+ throttledFn();
121
+ expect(mockFn).toHaveBeenCalledTimes(1);
122
+ });
123
+ });
124
+
125
+ describe('getEnvironment', () => {
126
+ it('should detect environment correctly', () => {
127
+ const env = getEnvironment();
128
+
129
+ // In Jest test environment, it should be server-side
130
+ expect(env).toHaveProperty('isServer');
131
+ expect(env).toHaveProperty('isClient');
132
+ expect(env).toHaveProperty('isWeapp');
133
+ expect(env).toHaveProperty('isAlipay');
134
+ expect(env).toHaveProperty('isWeb');
135
+ });
136
+ });
137
+
138
+ describe('formatNumber', () => {
139
+ it('should format numbers with default options', () => {
140
+ expect(formatNumber(1234.5678)).toBe('1,234.57');
141
+ });
142
+
143
+ it('should format numbers with custom decimal digits', () => {
144
+ expect(formatNumber(1234.5678, 0)).toBe('1,235');
145
+ expect(formatNumber(1234.5678, 4)).toBe('1,234.5678');
146
+ });
147
+
148
+ it('should format numbers without grouping', () => {
149
+ expect(formatNumber(1234.5678, 2, { useGrouping: false })).toBe('1234.57');
150
+ });
151
+
152
+ it('should format numbers with different locales', () => {
153
+ // US locale uses commas for thousands and dots for decimals
154
+ expect(formatNumber(1234.5678, 2, { locale: 'en-US' })).toBe('1,234.57');
155
+
156
+ // German locale uses dots for thousands and commas for decimals
157
+ expect(formatNumber(1234.5678, 2, { locale: 'de-DE' })).toBe('1.234,57');
158
+ });
159
+
160
+ it('should handle zero correctly', () => {
161
+ expect(formatNumber(0)).toBe('0.00');
162
+ expect(formatNumber(0, 0)).toBe('0');
163
+ });
164
+
165
+ it('should handle negative numbers correctly', () => {
166
+ expect(formatNumber(-1234.5678)).toBe('-1,234.57');
167
+ });
168
+ });
169
+
170
+ describe('getContrastColor', () => {
171
+ it('should return white for dark colors', () => {
172
+ expect(getContrastColor('#000000')).toBe('#FFFFFF');
173
+ expect(getContrastColor('#333333')).toBe('#FFFFFF');
174
+ expect(getContrastColor('#1a1a1a')).toBe('#FFFFFF');
175
+ });
176
+
177
+ it('should return black for light colors', () => {
178
+ expect(getContrastColor('#FFFFFF')).toBe('#000000');
179
+ expect(getContrastColor('#EEEEEE')).toBe('#000000');
180
+ expect(getContrastColor('#f0f0f0')).toBe('#000000');
181
+ });
182
+
183
+ it('should handle hex colors without # prefix', () => {
184
+ expect(getContrastColor('000000')).toBe('#FFFFFF');
185
+ expect(getContrastColor('FFFFFF')).toBe('#000000');
186
+ });
187
+
188
+ it('should handle medium colors', () => {
189
+ // Test a color right at the threshold (128 brightness returns white)
190
+ expect(getContrastColor('#808080')).toBe('#FFFFFF');
191
+ // Test a slightly brighter color that should return black
192
+ expect(getContrastColor('#818181')).toBe('#000000');
193
+ });
194
+ });
195
+
196
+ describe('UUID Generation', () => {
197
+ it('should generate unique UUIDs', () => {
198
+ const id1 = uuid();
199
+ const id2 = uuid();
200
+ expect(id1).not.toBe(id2);
201
+ expect(id1).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
202
+ });
203
+
204
+ it('should generate short IDs', () => {
205
+ const id1 = shortId();
206
+ const id2 = shortId();
207
+ expect(id1).not.toBe(id2);
208
+ expect(id1.length).toBe(8);
209
+ expect(id1).toMatch(/^[0-9a-z]{8}$/);
210
+ });
211
+
212
+ it('should generate prefixed IDs', () => {
213
+ const prefix = 'chart';
214
+ const id = prefixedId(prefix);
215
+ expect(id).toMatch(new RegExp(`^${prefix}-`));
216
+ expect(id).toMatch(/^chart-[0-9a-z]{8}$/);
217
+ });
218
+ });
219
+ });
@@ -0,0 +1,78 @@
1
+ import { uuid, shortId, prefixedId } from '../uuid';
2
+
3
+ describe('UUID Utils', () => {
4
+ describe('uuid', () => {
5
+ it('should generate a valid UUID v4', () => {
6
+ const generatedUuid = uuid();
7
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8
+
9
+ expect(uuidRegex.test(generatedUuid)).toBe(true);
10
+ });
11
+
12
+ it('should generate unique UUIDs', () => {
13
+ const uuid1 = uuid();
14
+ const uuid2 = uuid();
15
+ const uuid3 = uuid();
16
+
17
+ expect(uuid1).not.toBe(uuid2);
18
+ expect(uuid2).not.toBe(uuid3);
19
+ expect(uuid1).not.toBe(uuid3);
20
+ });
21
+ });
22
+
23
+ describe('shortId', () => {
24
+ it('should generate a short string', () => {
25
+ const generatedShortId = shortId();
26
+
27
+ expect(typeof generatedShortId).toBe('string');
28
+ expect(generatedShortId.length).toBe(8);
29
+ });
30
+
31
+ it('should generate unique short IDs', () => {
32
+ const shortId1 = shortId();
33
+ const shortId2 = shortId();
34
+ const shortId3 = shortId();
35
+
36
+ expect(shortId1).not.toBe(shortId2);
37
+ expect(shortId2).not.toBe(shortId3);
38
+ expect(shortId1).not.toBe(shortId3);
39
+ });
40
+
41
+ it('should generate alphanumeric strings', () => {
42
+ const generatedShortId = shortId();
43
+ const alphanumericRegex = /^[a-zA-Z0-9]+$/;
44
+
45
+ expect(alphanumericRegex.test(generatedShortId)).toBe(true);
46
+ });
47
+ });
48
+
49
+ describe('prefixedId', () => {
50
+ it('should generate a prefixed ID', () => {
51
+ const prefix = 'test';
52
+ const generatedPrefixedId = prefixedId(prefix);
53
+
54
+ expect(generatedPrefixedId.startsWith(`${prefix}-`)).toBe(true);
55
+ });
56
+
57
+ it('should generate unique prefixed IDs with the same prefix', () => {
58
+ const prefix = 'test';
59
+ const prefixedId1 = prefixedId(prefix);
60
+ const prefixedId2 = prefixedId(prefix);
61
+ const prefixedId3 = prefixedId(prefix);
62
+
63
+ expect(prefixedId1).not.toBe(prefixedId2);
64
+ expect(prefixedId2).not.toBe(prefixedId3);
65
+ expect(prefixedId1).not.toBe(prefixedId3);
66
+ });
67
+
68
+ it('should handle different prefixes correctly', () => {
69
+ const prefix1 = 'test1';
70
+ const prefix2 = 'test2';
71
+ const prefixedId1 = prefixedId(prefix1);
72
+ const prefixedId2 = prefixedId(prefix2);
73
+
74
+ expect(prefixedId1.startsWith(`${prefix1}-`)).toBe(true);
75
+ expect(prefixedId2.startsWith(`${prefix2}-`)).toBe(true);
76
+ });
77
+ });
78
+ });
@@ -0,0 +1,69 @@
1
+ import type { EChartsType } from 'echarts';
2
+
3
+ /**
4
+ * 全局图表实例存储
5
+ */
6
+ export const CHART_INSTANCES: Record<string, EChartsType> = {};
7
+
8
+ /**
9
+ * 注册图表实例
10
+ * @param id 图表ID
11
+ * @param instance 图表实例
12
+ */
13
+ export function registerChart(id: string, instance: EChartsType): void {
14
+ CHART_INSTANCES[id] = instance;
15
+ }
16
+
17
+ /**
18
+ * 获取图表实例
19
+ * @param id 图表ID
20
+ * @returns 图表实例
21
+ */
22
+ export function getChart(id: string): EChartsType | undefined {
23
+ return CHART_INSTANCES[id];
24
+ }
25
+
26
+ /**
27
+ * 移除图表实例
28
+ * @param id 图表ID
29
+ */
30
+ export function removeChart(id: string): void {
31
+ if (CHART_INSTANCES[id]) {
32
+ delete CHART_INSTANCES[id];
33
+ }
34
+ }
35
+
36
+ /**
37
+ * 获取所有图表实例
38
+ * @returns 所有图表实例
39
+ */
40
+ export function getAllCharts(): Record<string, EChartsType> {
41
+ return CHART_INSTANCES;
42
+ }
43
+
44
+ /**
45
+ * 清空所有图表实例
46
+ */
47
+ export function clearAllCharts(): void {
48
+ Object.keys(CHART_INSTANCES).forEach(id => {
49
+ try {
50
+ CHART_INSTANCES[id].dispose();
51
+ } catch (e) {
52
+ console.warn(`Failed to dispose chart: ${id}`, e);
53
+ }
54
+ delete CHART_INSTANCES[id];
55
+ });
56
+ }
57
+
58
+ /**
59
+ * 调整所有图表实例大小
60
+ */
61
+ export function resizeAllCharts(): void {
62
+ Object.keys(CHART_INSTANCES).forEach(id => {
63
+ try {
64
+ CHART_INSTANCES[id].resize();
65
+ } catch (e) {
66
+ console.warn(`Failed to resize chart: ${id}`, e);
67
+ }
68
+ });
69
+ }