@antv/gpt-vis 1.0.0-beta.1 → 1.0.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.
- package/README.md +223 -47
- package/README.zh-CN.md +227 -51
- package/dist/cjs/gpt-vis/index.d.ts +8 -1
- package/dist/cjs/gpt-vis/index.js +43 -20
- package/dist/cjs/index.d.ts +15 -2
- package/dist/cjs/index.js +22 -2
- package/dist/cjs/syntax/parser.d.ts +17 -2
- package/dist/cjs/syntax/parser.js +151 -38
- package/dist/cjs/util/container.d.ts +5 -0
- package/dist/cjs/util/container.js +43 -0
- package/dist/cjs/util/theme.d.ts +5 -0
- package/dist/cjs/util/theme.js +9 -2
- package/dist/cjs/vis/area/index.js +2 -1
- package/dist/cjs/vis/bar/index.js +5 -4
- package/dist/cjs/vis/boxplot/index.js +7 -2
- package/dist/cjs/vis/column/index.js +5 -4
- package/dist/cjs/vis/dual-axes/index.js +3 -3
- package/dist/cjs/vis/fishbone-diagram/index.d.ts +35 -0
- package/dist/cjs/vis/fishbone-diagram/index.js +191 -0
- package/dist/cjs/vis/flow-diagram/index.d.ts +27 -0
- package/dist/cjs/vis/flow-diagram/index.js +287 -0
- package/dist/cjs/vis/funnel/index.js +2 -1
- package/dist/cjs/vis/histogram/index.js +3 -7
- package/dist/cjs/vis/indented-tree/index.d.ts +40 -0
- package/dist/cjs/vis/indented-tree/index.js +385 -0
- package/dist/cjs/vis/line/index.js +2 -1
- package/dist/cjs/vis/liquid/index.js +2 -1
- package/dist/cjs/vis/mindmap/index.d.ts +32 -0
- package/dist/cjs/vis/mindmap/index.js +222 -0
- package/dist/cjs/vis/network-graph/index.d.ts +59 -0
- package/dist/cjs/vis/network-graph/index.js +175 -0
- package/dist/cjs/vis/organization-chart/index.d.ts +64 -0
- package/dist/cjs/vis/organization-chart/index.js +200 -0
- package/dist/cjs/vis/pie/index.js +3 -3
- package/dist/cjs/vis/radar/index.d.ts +1 -0
- package/dist/cjs/vis/radar/index.js +10 -9
- package/dist/cjs/vis/sankey/index.js +2 -1
- package/dist/cjs/vis/scatter/index.d.ts +2 -0
- package/dist/cjs/vis/scatter/index.js +9 -4
- package/dist/cjs/vis/summary/index.js +17 -3
- package/dist/cjs/vis/table/index.d.ts +1 -0
- package/dist/cjs/vis/table/index.js +37 -1
- package/dist/cjs/vis/treemap/index.js +2 -1
- package/dist/cjs/vis/venn/index.d.ts +2 -1
- package/dist/cjs/vis/venn/index.js +18 -3
- package/dist/cjs/vis/violin/index.js +2 -1
- package/dist/cjs/vis/waterfall/index.d.ts +6 -9
- package/dist/cjs/vis/waterfall/index.js +29 -6
- package/dist/cjs/vis/word-cloud/index.js +2 -1
- package/dist/cjs/vis-wrapper/icons.js +2 -2
- package/dist/cjs/vis-wrapper/index.d.ts +1 -0
- package/dist/cjs/vis-wrapper/index.js +27 -16
- package/dist/cjs/vis-wrapper/styles.d.ts +1 -1
- package/dist/cjs/vis-wrapper/styles.js +8 -1
- package/dist/esm/gpt-vis/index.d.ts +8 -1
- package/dist/esm/gpt-vis/index.js +47 -26
- package/dist/esm/index.d.ts +15 -2
- package/dist/esm/index.js +7 -1
- package/dist/esm/syntax/parser.d.ts +17 -2
- package/dist/esm/syntax/parser.js +248 -90
- package/dist/esm/util/container.d.ts +5 -0
- package/dist/esm/util/container.js +20 -0
- package/dist/esm/util/theme.d.ts +5 -0
- package/dist/esm/util/theme.js +9 -0
- package/dist/esm/vis/area/index.js +3 -2
- package/dist/esm/vis/bar/index.js +7 -6
- package/dist/esm/vis/boxplot/index.js +17 -4
- package/dist/esm/vis/column/index.js +7 -6
- package/dist/esm/vis/dual-axes/index.js +13 -5
- package/dist/esm/vis/fishbone-diagram/index.d.ts +35 -0
- package/dist/esm/vis/fishbone-diagram/index.js +219 -0
- package/dist/esm/vis/flow-diagram/index.d.ts +27 -0
- package/dist/esm/vis/flow-diagram/index.js +349 -0
- package/dist/esm/vis/funnel/index.js +3 -2
- package/dist/esm/vis/histogram/index.js +6 -7
- package/dist/esm/vis/indented-tree/index.d.ts +40 -0
- package/dist/esm/vis/indented-tree/index.js +569 -0
- package/dist/esm/vis/line/index.js +3 -2
- package/dist/esm/vis/liquid/index.js +3 -2
- package/dist/esm/vis/mindmap/index.d.ts +32 -0
- package/dist/esm/vis/mindmap/index.js +316 -0
- package/dist/esm/vis/network-graph/index.d.ts +59 -0
- package/dist/esm/vis/network-graph/index.js +242 -0
- package/dist/esm/vis/organization-chart/index.d.ts +64 -0
- package/dist/esm/vis/organization-chart/index.js +271 -0
- package/dist/esm/vis/pie/index.js +4 -8
- package/dist/esm/vis/radar/index.d.ts +1 -0
- package/dist/esm/vis/radar/index.js +20 -4
- package/dist/esm/vis/sankey/index.js +3 -2
- package/dist/esm/vis/scatter/index.d.ts +2 -0
- package/dist/esm/vis/scatter/index.js +15 -4
- package/dist/esm/vis/summary/index.js +25 -4
- package/dist/esm/vis/table/index.d.ts +1 -0
- package/dist/esm/vis/table/index.js +9 -2
- package/dist/esm/vis/treemap/index.js +3 -2
- package/dist/esm/vis/venn/index.d.ts +2 -1
- package/dist/esm/vis/venn/index.js +29 -4
- package/dist/esm/vis/violin/index.js +3 -2
- package/dist/esm/vis/waterfall/index.d.ts +6 -9
- package/dist/esm/vis/waterfall/index.js +33 -13
- package/dist/esm/vis/word-cloud/index.js +3 -2
- package/dist/esm/vis-wrapper/icons.js +2 -2
- package/dist/esm/vis-wrapper/index.d.ts +1 -0
- package/dist/esm/vis-wrapper/index.js +15 -10
- package/dist/esm/vis-wrapper/styles.d.ts +1 -1
- package/dist/esm/vis-wrapper/styles.js +1 -1
- package/dist/umd/index.min.js +1 -1
- package/package.json +17 -21
- package/src/gpt-vis/index.ts +0 -283
- package/src/index.ts +0 -44
- package/src/readme.md +0 -37
- package/src/syntax/index.ts +0 -2
- package/src/syntax/parser.ts +0 -411
- package/src/types/index.ts +0 -29
- package/src/util/theme.ts +0 -167
- package/src/vis/area/README.md +0 -143
- package/src/vis/area/index.ts +0 -212
- package/src/vis/bar/README.md +0 -158
- package/src/vis/bar/index.ts +0 -186
- package/src/vis/boxplot/README.md +0 -168
- package/src/vis/boxplot/index.ts +0 -162
- package/src/vis/column/README.md +0 -158
- package/src/vis/column/index.ts +0 -185
- package/src/vis/dual-axes/README.md +0 -191
- package/src/vis/dual-axes/index.ts +0 -218
- package/src/vis/funnel/README.md +0 -143
- package/src/vis/funnel/index.ts +0 -238
- package/src/vis/histogram/README.md +0 -130
- package/src/vis/histogram/index.ts +0 -153
- package/src/vis/line/README.md +0 -138
- package/src/vis/line/index.ts +0 -159
- package/src/vis/liquid/README.md +0 -150
- package/src/vis/liquid/index.ts +0 -130
- package/src/vis/pie/README.md +0 -127
- package/src/vis/pie/index.ts +0 -163
- package/src/vis/radar/README.md +0 -184
- package/src/vis/radar/index.ts +0 -214
- package/src/vis/sankey/README.md +0 -144
- package/src/vis/sankey/index.ts +0 -144
- package/src/vis/scatter/README.md +0 -145
- package/src/vis/scatter/index.ts +0 -147
- package/src/vis/summary/README.md +0 -272
- package/src/vis/summary/index.ts +0 -91
- package/src/vis/table/README.md +0 -174
- package/src/vis/table/index.ts +0 -241
- package/src/vis/treemap/README.md +0 -199
- package/src/vis/treemap/index.ts +0 -167
- package/src/vis/venn/README.md +0 -153
- package/src/vis/venn/index.ts +0 -149
- package/src/vis/violin/README.md +0 -168
- package/src/vis/violin/index.ts +0 -216
- package/src/vis/waterfall/README.md +0 -178
- package/src/vis/waterfall/index.ts +0 -258
- package/src/vis/word-cloud/README.md +0 -137
- package/src/vis/word-cloud/index.ts +0 -137
- package/src/vis-wrapper/README.md +0 -159
- package/src/vis-wrapper/icons.ts +0 -35
- package/src/vis-wrapper/index.ts +0 -276
- package/src/vis-wrapper/styles.ts +0 -195
package/src/vis/violin/index.ts
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { Chart } from '@antv/g2';
|
|
2
|
-
import type { VisualizationOptions } from '../../types';
|
|
3
|
-
import { getBackgroundColor, getThemeColors, getThemeObject } from '../../util/theme';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* ViolinDataItem is the type for each data item in the violin chart.
|
|
7
|
-
*/
|
|
8
|
-
export type ViolinDataItem = {
|
|
9
|
-
category: string;
|
|
10
|
-
value: number;
|
|
11
|
-
group?: string;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* ViolinConfig defines the configuration for rendering the violin chart.
|
|
16
|
-
*/
|
|
17
|
-
export interface ViolinConfig {
|
|
18
|
-
type?: 'violin';
|
|
19
|
-
data: ViolinDataItem[];
|
|
20
|
-
theme?: 'default' | 'academy' | 'dark';
|
|
21
|
-
title?: string;
|
|
22
|
-
axisXTitle?: string;
|
|
23
|
-
axisYTitle?: string;
|
|
24
|
-
style?: {
|
|
25
|
-
backgroundColor?: string;
|
|
26
|
-
palette?: string[];
|
|
27
|
-
startAtZero?: boolean;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* ViolinInstance represents a violin chart instance with render and destroy.
|
|
33
|
-
*/
|
|
34
|
-
export interface ViolinInstance {
|
|
35
|
-
render: (config: ViolinConfig) => void;
|
|
36
|
-
destroy: () => void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Violin chart component using G2 5.0.
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* const violin = Violin({
|
|
45
|
-
* container: '#container',
|
|
46
|
-
* width: 600,
|
|
47
|
-
* height: 400,
|
|
48
|
-
* });
|
|
49
|
-
*
|
|
50
|
-
* violin.render({
|
|
51
|
-
* type: 'violin',
|
|
52
|
-
* data: [
|
|
53
|
-
* { category: '班级A', value: 15 },
|
|
54
|
-
* { category: '班级A', value: 18 },
|
|
55
|
-
* { category: '班级A', value: 22 },
|
|
56
|
-
* { category: '班级A', value: 27 },
|
|
57
|
-
* { category: '班级A', value: 35 },
|
|
58
|
-
* ],
|
|
59
|
-
* theme: 'academy'
|
|
60
|
-
* });
|
|
61
|
-
*
|
|
62
|
-
* violin.destroy();
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
|
-
export const Violin = (options: VisualizationOptions): ViolinInstance => {
|
|
66
|
-
const { container, width, height, theme: chartTheme = 'default' } = options;
|
|
67
|
-
let chart: Chart | null = null;
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Render the violin chart with the given configuration.
|
|
71
|
-
*/
|
|
72
|
-
const render = (config: ViolinConfig): void => {
|
|
73
|
-
const { data = [], theme = chartTheme, title, axisXTitle, axisYTitle, style = {} } = config;
|
|
74
|
-
|
|
75
|
-
// Clean up previous chart if exists
|
|
76
|
-
if (chart) {
|
|
77
|
-
chart.destroy();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Get colors from style.palette or theme defaults
|
|
81
|
-
const colors = style.palette || getThemeColors(theme);
|
|
82
|
-
const backgroundColor = style.backgroundColor || getBackgroundColor(theme);
|
|
83
|
-
const startAtZero = style.startAtZero || false;
|
|
84
|
-
|
|
85
|
-
// Determine if data has group field for grouped violin plot
|
|
86
|
-
const hasGroupField = (data || [])[0]?.group !== undefined;
|
|
87
|
-
|
|
88
|
-
// Create chart
|
|
89
|
-
chart = new Chart({
|
|
90
|
-
container,
|
|
91
|
-
width,
|
|
92
|
-
height,
|
|
93
|
-
autoFit: true,
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Configure chart children for violin plot
|
|
97
|
-
// Violin plot is composed of density plot + boxplot overlay
|
|
98
|
-
let children = [];
|
|
99
|
-
|
|
100
|
-
if (hasGroupField) {
|
|
101
|
-
// Grouped violin plot: density by category and group
|
|
102
|
-
children = [
|
|
103
|
-
{
|
|
104
|
-
type: 'density',
|
|
105
|
-
data: {
|
|
106
|
-
transform: [{ type: 'kde', field: 'value', groupBy: ['category', 'group'] }],
|
|
107
|
-
},
|
|
108
|
-
encode: {
|
|
109
|
-
x: 'category',
|
|
110
|
-
y: 'y',
|
|
111
|
-
color: 'group',
|
|
112
|
-
series: 'group',
|
|
113
|
-
size: 'size',
|
|
114
|
-
},
|
|
115
|
-
scale: {
|
|
116
|
-
y: { nice: true },
|
|
117
|
-
color: { range: colors },
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
type: 'boxplot',
|
|
122
|
-
encode: {
|
|
123
|
-
x: 'category',
|
|
124
|
-
y: 'value',
|
|
125
|
-
series: 'group',
|
|
126
|
-
color: 'group',
|
|
127
|
-
shape: 'violin',
|
|
128
|
-
},
|
|
129
|
-
style: { opacity: 0.5, strokeOpacity: 0.5, point: false },
|
|
130
|
-
scale: {
|
|
131
|
-
y: { nice: true },
|
|
132
|
-
color: { range: colors },
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
];
|
|
136
|
-
} else {
|
|
137
|
-
// Simple violin plot: density by category only
|
|
138
|
-
children = [
|
|
139
|
-
{
|
|
140
|
-
type: 'density',
|
|
141
|
-
data: {
|
|
142
|
-
transform: [{ type: 'kde', field: 'value', groupBy: ['category'], size: 20 }],
|
|
143
|
-
},
|
|
144
|
-
encode: {
|
|
145
|
-
x: 'category',
|
|
146
|
-
y: 'y',
|
|
147
|
-
color: 'category',
|
|
148
|
-
size: 'size',
|
|
149
|
-
},
|
|
150
|
-
scale: {
|
|
151
|
-
y: { nice: true },
|
|
152
|
-
color: { range: colors },
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
type: 'boxplot',
|
|
157
|
-
encode: {
|
|
158
|
-
x: 'category',
|
|
159
|
-
y: 'value',
|
|
160
|
-
color: 'category',
|
|
161
|
-
shape: 'violin',
|
|
162
|
-
},
|
|
163
|
-
style: { opacity: 0.5, strokeOpacity: 0.5, point: false },
|
|
164
|
-
scale: {
|
|
165
|
-
y: { nice: true },
|
|
166
|
-
color: { range: colors },
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Configure chart options
|
|
173
|
-
// Note: Using 'any' type due to G2's complex type system with transformations
|
|
174
|
-
// This is consistent with how G2 5.0 is used elsewhere in the codebase
|
|
175
|
-
const chartOptions: any = {
|
|
176
|
-
type: 'view',
|
|
177
|
-
data,
|
|
178
|
-
title: title ?? '',
|
|
179
|
-
axis: {
|
|
180
|
-
x: {
|
|
181
|
-
title: axisXTitle || false,
|
|
182
|
-
},
|
|
183
|
-
y: {
|
|
184
|
-
title: axisYTitle || false,
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
scale: {
|
|
188
|
-
y: { nice: true, zero: startAtZero },
|
|
189
|
-
},
|
|
190
|
-
children: children,
|
|
191
|
-
legend: {
|
|
192
|
-
color: hasGroupField ? { position: 'top' } : false,
|
|
193
|
-
},
|
|
194
|
-
...(backgroundColor ? { viewStyle: { viewFill: backgroundColor } } : {}),
|
|
195
|
-
theme: getThemeObject(theme),
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
chart.options(chartOptions);
|
|
199
|
-
chart.render();
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Destroy the chart instance and clean up resources.
|
|
204
|
-
*/
|
|
205
|
-
const destroy = (): void => {
|
|
206
|
-
if (chart) {
|
|
207
|
-
chart.destroy();
|
|
208
|
-
chart = null;
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
render,
|
|
214
|
-
destroy,
|
|
215
|
-
};
|
|
216
|
-
};
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
# Waterfall
|
|
2
|
-
|
|
3
|
-
A waterfall chart component for displaying cumulative effects of sequential values, built with G2 5.0.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { Waterfall } from '@antv/gpt-vis/ai';
|
|
9
|
-
|
|
10
|
-
const waterfall = Waterfall({
|
|
11
|
-
container: '#container',
|
|
12
|
-
width: 600,
|
|
13
|
-
height: 400,
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
waterfall.render({
|
|
17
|
-
data: [
|
|
18
|
-
{ category: '期初利润', value: 100 },
|
|
19
|
-
{ category: '销售收入', value: 80 },
|
|
20
|
-
{ category: '运营成本', value: -50 },
|
|
21
|
-
{ category: '税费', value: -20 },
|
|
22
|
-
{ category: '总计', isTotal: true },
|
|
23
|
-
],
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
waterfall.destroy();
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Configuration
|
|
30
|
-
|
|
31
|
-
### Constructor Options (WaterfallOptions)
|
|
32
|
-
|
|
33
|
-
| Property | Type | Default | Description |
|
|
34
|
-
| --------- | --------------------- | ------- | ----------------------------- |
|
|
35
|
-
| container | string \| HTMLElement | - | Container element or selector |
|
|
36
|
-
| width | number | 640 | Chart width in pixels |
|
|
37
|
-
| height | number | 480 | Chart height in pixels |
|
|
38
|
-
|
|
39
|
-
### Render Config (WaterfallConfig)
|
|
40
|
-
|
|
41
|
-
| Property | Type | Default | Description |
|
|
42
|
-
| ---------- | ------ | --------- | ------------------------- |
|
|
43
|
-
| data | Array | - | Chart data array |
|
|
44
|
-
| theme | string | 'default' | Color theme |
|
|
45
|
-
| title | string | - | Chart title |
|
|
46
|
-
| axisXTitle | string | - | X-axis title |
|
|
47
|
-
| axisYTitle | string | - | Y-axis title |
|
|
48
|
-
| style | object | - | Chart style configuration |
|
|
49
|
-
|
|
50
|
-
### Data Structure
|
|
51
|
-
|
|
52
|
-
```ts
|
|
53
|
-
type WaterfallDataItem = {
|
|
54
|
-
category: string; // Step or category name (required)
|
|
55
|
-
value?: number; // Increment or decrement value (optional)
|
|
56
|
-
isIntermediateTotal?: boolean; // Whether it's an intermediate total (optional)
|
|
57
|
-
isTotal?: boolean; // Whether it's the final total (optional)
|
|
58
|
-
};
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Style Options
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
style?: {
|
|
65
|
-
backgroundColor?: string; // Background color
|
|
66
|
-
palette?: {
|
|
67
|
-
positiveColor?: string; // Color for positive values (default: '#FF4D4F')
|
|
68
|
-
negativeColor?: string; // Color for negative values (default: '#2EBB59')
|
|
69
|
-
totalColor?: string; // Color for total bars (default: '#1783FF')
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Examples
|
|
75
|
-
|
|
76
|
-
### Basic Example
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
waterfall.render({
|
|
80
|
-
data: [
|
|
81
|
-
{ category: '期初利润', value: 100 },
|
|
82
|
-
{ category: '销售收入', value: 80 },
|
|
83
|
-
{ category: '运营成本', value: -50 },
|
|
84
|
-
{ category: '税费', value: -20 },
|
|
85
|
-
{ category: '总计', isTotal: true },
|
|
86
|
-
],
|
|
87
|
-
});
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### With Theme
|
|
91
|
-
|
|
92
|
-
```ts
|
|
93
|
-
waterfall.render({
|
|
94
|
-
data: [
|
|
95
|
-
{ category: '基础预算', value: 500 },
|
|
96
|
-
{ category: '市场投入', value: 120 },
|
|
97
|
-
{ category: '采购优化', value: -60 },
|
|
98
|
-
{ category: '运营效率', value: -30 },
|
|
99
|
-
{ category: '总利润', isTotal: true },
|
|
100
|
-
],
|
|
101
|
-
theme: 'dark',
|
|
102
|
-
title: '预算执行情况',
|
|
103
|
-
});
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### With Custom Colors
|
|
107
|
-
|
|
108
|
-
```ts
|
|
109
|
-
waterfall.render({
|
|
110
|
-
data: [
|
|
111
|
-
{ category: 'Q1 收入', value: 1000 },
|
|
112
|
-
{ category: 'Q2 收入', value: 1200 },
|
|
113
|
-
{ category: '成本', value: -800 },
|
|
114
|
-
{ category: '净利润', isTotal: true },
|
|
115
|
-
],
|
|
116
|
-
title: '季度财务报告',
|
|
117
|
-
style: {
|
|
118
|
-
palette: {
|
|
119
|
-
positiveColor: '#52c41a',
|
|
120
|
-
negativeColor: '#f5222d',
|
|
121
|
-
totalColor: '#1890ff',
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### With Intermediate Total
|
|
128
|
-
|
|
129
|
-
```ts
|
|
130
|
-
waterfall.render({
|
|
131
|
-
data: [
|
|
132
|
-
{ category: '基础预算', value: 500 },
|
|
133
|
-
{ category: '市场投入', value: 120 },
|
|
134
|
-
{ category: '总投入', isIntermediateTotal: true },
|
|
135
|
-
{ category: '采购优化', value: -60 },
|
|
136
|
-
{ category: '运营效率', value: -30 },
|
|
137
|
-
{ category: '总利润', isTotal: true },
|
|
138
|
-
],
|
|
139
|
-
title: '预算分析',
|
|
140
|
-
});
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### With Axis Titles
|
|
144
|
-
|
|
145
|
-
```ts
|
|
146
|
-
waterfall.render({
|
|
147
|
-
data: [
|
|
148
|
-
{ category: '期初', value: 100 },
|
|
149
|
-
{ category: '收入', value: 80 },
|
|
150
|
-
{ category: '支出', value: -50 },
|
|
151
|
-
{ category: '期末', isTotal: true },
|
|
152
|
-
],
|
|
153
|
-
axisXTitle: '项目',
|
|
154
|
-
axisYTitle: '金额(万元)',
|
|
155
|
-
title: '财务流水',
|
|
156
|
-
});
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### With Background Color
|
|
160
|
-
|
|
161
|
-
```ts
|
|
162
|
-
waterfall.render({
|
|
163
|
-
data: [
|
|
164
|
-
{ category: '初始', value: 50 },
|
|
165
|
-
{ category: '增长', value: 30 },
|
|
166
|
-
{ category: '减少', value: -10 },
|
|
167
|
-
{ category: '最终', isTotal: true },
|
|
168
|
-
],
|
|
169
|
-
style: {
|
|
170
|
-
backgroundColor: '#f0f2f5',
|
|
171
|
-
},
|
|
172
|
-
});
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
## Methods
|
|
176
|
-
|
|
177
|
-
- `render(config: WaterfallConfig): void` - Render or update the chart
|
|
178
|
-
- `destroy(): void` - Destroy the chart instance and clean up resources
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import { Chart } from '@antv/g2';
|
|
2
|
-
import type { VisualizationOptions } from '../../types';
|
|
3
|
-
import { getBackgroundColor, getThemeObject } from '../../util/theme';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* WaterfallDataItem is the type for each data item in the waterfall chart.
|
|
7
|
-
*/
|
|
8
|
-
export type WaterfallDataItem = {
|
|
9
|
-
category: string;
|
|
10
|
-
value?: number;
|
|
11
|
-
isIntermediateTotal?: boolean;
|
|
12
|
-
isTotal?: boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* WaterfallPalette defines custom colors for positive, negative, total bars.
|
|
17
|
-
*/
|
|
18
|
-
export interface WaterfallPalette {
|
|
19
|
-
positiveColor?: string;
|
|
20
|
-
negativeColor?: string;
|
|
21
|
-
totalColor?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* WaterfallConfig defines the configuration for rendering the waterfall chart.
|
|
26
|
-
*/
|
|
27
|
-
export interface WaterfallConfig {
|
|
28
|
-
type?: 'waterfall';
|
|
29
|
-
data: WaterfallDataItem[];
|
|
30
|
-
theme?: 'default' | 'academy' | 'dark';
|
|
31
|
-
title?: string;
|
|
32
|
-
axisXTitle?: string;
|
|
33
|
-
axisYTitle?: string;
|
|
34
|
-
style?: {
|
|
35
|
-
backgroundColor?: string;
|
|
36
|
-
palette?: WaterfallPalette;
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* WaterfallInstance represents a waterfall chart instance with render/destroy.
|
|
42
|
-
*/
|
|
43
|
-
export interface WaterfallInstance {
|
|
44
|
-
render: (config: WaterfallConfig) => void;
|
|
45
|
-
destroy: () => void;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Default colors for waterfall chart
|
|
49
|
-
const DEFAULT_POSITIVE_COLOR = '#FF4D4F';
|
|
50
|
-
const DEFAULT_NEGATIVE_COLOR = '#2EBB59';
|
|
51
|
-
const DEFAULT_TOTAL_COLOR = '#1783FF';
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Transform waterfall data to add __start__ and __end__ fields
|
|
55
|
-
* for proper rendering of stacked intervals
|
|
56
|
-
*/
|
|
57
|
-
function transformWaterfallData(data: WaterfallDataItem[]) {
|
|
58
|
-
let cumulative = 0;
|
|
59
|
-
let lastIntermediateTotalEnd = 0;
|
|
60
|
-
let totalSum = 0;
|
|
61
|
-
|
|
62
|
-
return data.map((item) => {
|
|
63
|
-
const value = item.value || 0;
|
|
64
|
-
let start: number;
|
|
65
|
-
let end: number;
|
|
66
|
-
|
|
67
|
-
if (item.isTotal) {
|
|
68
|
-
start = 0;
|
|
69
|
-
end = totalSum;
|
|
70
|
-
} else if (item.isIntermediateTotal) {
|
|
71
|
-
start = lastIntermediateTotalEnd;
|
|
72
|
-
end = cumulative;
|
|
73
|
-
lastIntermediateTotalEnd = end;
|
|
74
|
-
} else {
|
|
75
|
-
start = cumulative;
|
|
76
|
-
end = cumulative + value;
|
|
77
|
-
cumulative = end;
|
|
78
|
-
totalSum += value;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
...item,
|
|
83
|
-
__start__: start,
|
|
84
|
-
__end__: end,
|
|
85
|
-
__value__: item.isTotal ? totalSum : item.isIntermediateTotal ? end - start : value,
|
|
86
|
-
};
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Generate link data for connecting waterfall bars
|
|
92
|
-
* Each link connects the end of the previous bar to the start of the current bar
|
|
93
|
-
*/
|
|
94
|
-
function generateLinkData(data: any[]) {
|
|
95
|
-
return data.reduce((result: any[], current: any, index: number) => {
|
|
96
|
-
if (index > 0) {
|
|
97
|
-
const previous = data[index - 1];
|
|
98
|
-
result.push({
|
|
99
|
-
x: [previous.category, current.category],
|
|
100
|
-
y: current.isTotal || current.isIntermediateTotal ? current.__end__ : current.__start__,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
return result;
|
|
104
|
-
}, []);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Waterfall chart component using G2 5.0.
|
|
109
|
-
*
|
|
110
|
-
* @example
|
|
111
|
-
* ```ts
|
|
112
|
-
* const waterfall = Waterfall({
|
|
113
|
-
* container: '#container',
|
|
114
|
-
* width: 600,
|
|
115
|
-
* height: 400,
|
|
116
|
-
* });
|
|
117
|
-
*
|
|
118
|
-
* waterfall.render({
|
|
119
|
-
* type: 'waterfall',
|
|
120
|
-
* data: [
|
|
121
|
-
* { category: '期初利润', value: 100 },
|
|
122
|
-
* { category: '销售收入', value: 80 },
|
|
123
|
-
* { category: '运营成本', value: -50 },
|
|
124
|
-
* { category: '税费', value: -20 },
|
|
125
|
-
* { category: '总计', isTotal: true },
|
|
126
|
-
* ],
|
|
127
|
-
* theme: 'academy'
|
|
128
|
-
* });
|
|
129
|
-
*
|
|
130
|
-
* waterfall.destroy();
|
|
131
|
-
* ```
|
|
132
|
-
*/
|
|
133
|
-
export const Waterfall = (options: VisualizationOptions): WaterfallInstance => {
|
|
134
|
-
const { container, width, height, theme: chartTheme = 'default' } = options;
|
|
135
|
-
let chart: Chart | null = null;
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Render the waterfall chart with the given configuration.
|
|
139
|
-
*/
|
|
140
|
-
const render = (config: WaterfallConfig): void => {
|
|
141
|
-
const { data = [], theme = chartTheme, title, axisXTitle, axisYTitle, style = {} } = config;
|
|
142
|
-
|
|
143
|
-
// Clean up previous chart if exists
|
|
144
|
-
if (chart) {
|
|
145
|
-
chart.destroy();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Get colors from style.palette or defaults
|
|
149
|
-
const backgroundColor = style.backgroundColor || getBackgroundColor(theme);
|
|
150
|
-
const palette = style.palette || {};
|
|
151
|
-
const positiveColor = palette.positiveColor || DEFAULT_POSITIVE_COLOR;
|
|
152
|
-
const negativeColor = palette.negativeColor || DEFAULT_NEGATIVE_COLOR;
|
|
153
|
-
const totalColor = palette.totalColor || DEFAULT_TOTAL_COLOR;
|
|
154
|
-
|
|
155
|
-
// Transform data to include __start__ and __end__ fields
|
|
156
|
-
const transformedData = transformWaterfallData(data);
|
|
157
|
-
|
|
158
|
-
// Generate link data for connecting lines
|
|
159
|
-
const linkData = generateLinkData(transformedData);
|
|
160
|
-
|
|
161
|
-
// Create chart
|
|
162
|
-
chart = new Chart({
|
|
163
|
-
container,
|
|
164
|
-
width,
|
|
165
|
-
height,
|
|
166
|
-
autoFit: true,
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Configure chart options
|
|
170
|
-
// Note: Using 'any' type due to G2's complex type system with transformations
|
|
171
|
-
// This is consistent with how G2 5.0 is used elsewhere in the codebase
|
|
172
|
-
const chartOptions: any = {
|
|
173
|
-
type: 'view',
|
|
174
|
-
data: transformedData,
|
|
175
|
-
title: title ?? '',
|
|
176
|
-
marginRight: 28,
|
|
177
|
-
axis: {
|
|
178
|
-
x: {
|
|
179
|
-
title: axisXTitle || false,
|
|
180
|
-
},
|
|
181
|
-
y: {
|
|
182
|
-
title: axisYTitle || false,
|
|
183
|
-
labelFormatter: '~s',
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
scale: {
|
|
187
|
-
y: { nice: true },
|
|
188
|
-
},
|
|
189
|
-
children: [
|
|
190
|
-
{
|
|
191
|
-
type: 'interval',
|
|
192
|
-
data: transformedData,
|
|
193
|
-
encode: { x: 'category', y: ['__start__', '__end__'], color: 'category' },
|
|
194
|
-
style: {
|
|
195
|
-
maxWidth: 60,
|
|
196
|
-
stroke: '#666',
|
|
197
|
-
radius: 4,
|
|
198
|
-
fill: (d: any) => {
|
|
199
|
-
return d.isTotal || d.isIntermediateTotal
|
|
200
|
-
? totalColor
|
|
201
|
-
: d.__value__ > 0
|
|
202
|
-
? positiveColor
|
|
203
|
-
: negativeColor;
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
labels: [
|
|
207
|
-
{
|
|
208
|
-
text: '__value__',
|
|
209
|
-
position: 'inside',
|
|
210
|
-
fontSize: 10,
|
|
211
|
-
transform: [{ type: 'overflowHide' }],
|
|
212
|
-
formatter: '~s',
|
|
213
|
-
fill: '#000',
|
|
214
|
-
fontWeight: 600,
|
|
215
|
-
stroke: '#fff',
|
|
216
|
-
},
|
|
217
|
-
],
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
type: 'link',
|
|
221
|
-
data: linkData,
|
|
222
|
-
encode: {
|
|
223
|
-
x: 'x',
|
|
224
|
-
y: 'y',
|
|
225
|
-
},
|
|
226
|
-
zIndex: -1,
|
|
227
|
-
style: {
|
|
228
|
-
stroke: '#ccc',
|
|
229
|
-
lineDash: [4, 2],
|
|
230
|
-
lineWidth: 1,
|
|
231
|
-
},
|
|
232
|
-
tooltip: false,
|
|
233
|
-
},
|
|
234
|
-
],
|
|
235
|
-
legend: false,
|
|
236
|
-
...(backgroundColor ? { viewStyle: { viewFill: backgroundColor } } : {}),
|
|
237
|
-
theme: getThemeObject(theme),
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
chart.options(chartOptions);
|
|
241
|
-
chart.render();
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Destroy the chart instance and clean up resources.
|
|
246
|
-
*/
|
|
247
|
-
const destroy = (): void => {
|
|
248
|
-
if (chart) {
|
|
249
|
-
chart.destroy();
|
|
250
|
-
chart = null;
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
return {
|
|
255
|
-
render,
|
|
256
|
-
destroy,
|
|
257
|
-
};
|
|
258
|
-
};
|