@antv/gpt-vis 1.0.0-beta.2 → 1.0.1

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 (106) hide show
  1. package/README.md +282 -43
  2. package/README.zh-CN.md +286 -47
  3. package/dist/cjs/gpt-vis/index.js +1 -1
  4. package/dist/cjs/types/index.d.ts +2 -1
  5. package/dist/cjs/util/animation.d.ts +2 -0
  6. package/dist/cjs/util/animation.js +38 -0
  7. package/dist/cjs/util/components.d.ts +15 -0
  8. package/dist/cjs/util/components.js +94 -0
  9. package/dist/cjs/util/crosshair-axis-labels.d.ts +9 -0
  10. package/dist/cjs/util/crosshair-axis-labels.js +304 -0
  11. package/dist/cjs/util/index.d.ts +6 -0
  12. package/dist/cjs/util/index.js +33 -0
  13. package/dist/cjs/util/interaction.d.ts +14 -0
  14. package/dist/cjs/util/interaction.js +89 -0
  15. package/dist/cjs/util/theme.d.ts +18 -24
  16. package/dist/cjs/util/theme.js +303 -120
  17. package/dist/cjs/util/tokens.d.ts +31 -0
  18. package/dist/cjs/util/tokens.js +98 -0
  19. package/dist/cjs/vis/area/index.d.ts +2 -2
  20. package/dist/cjs/vis/area/index.js +76 -31
  21. package/dist/cjs/vis/bar/index.d.ts +2 -2
  22. package/dist/cjs/vis/bar/index.js +22 -19
  23. package/dist/cjs/vis/boxplot/index.js +1 -4
  24. package/dist/cjs/vis/column/index.d.ts +2 -2
  25. package/dist/cjs/vis/column/index.js +28 -18
  26. package/dist/cjs/vis/dual-axes/index.d.ts +2 -2
  27. package/dist/cjs/vis/dual-axes/index.js +90 -36
  28. package/dist/cjs/vis/fishbone-diagram/index.js +12 -4
  29. package/dist/cjs/vis/flow-diagram/index.js +27 -11
  30. package/dist/cjs/vis/funnel/index.d.ts +4 -2
  31. package/dist/cjs/vis/funnel/index.js +171 -92
  32. package/dist/cjs/vis/histogram/index.js +1 -4
  33. package/dist/cjs/vis/indented-tree/index.js +13 -3
  34. package/dist/cjs/vis/line/index.d.ts +2 -2
  35. package/dist/cjs/vis/line/index.js +71 -31
  36. package/dist/cjs/vis/liquid/index.d.ts +2 -2
  37. package/dist/cjs/vis/liquid/index.js +41 -16
  38. package/dist/cjs/vis/mindmap/index.js +12 -4
  39. package/dist/cjs/vis/network-graph/index.js +11 -2
  40. package/dist/cjs/vis/organization-chart/index.js +12 -3
  41. package/dist/cjs/vis/pie/index.d.ts +2 -2
  42. package/dist/cjs/vis/pie/index.js +26 -16
  43. package/dist/cjs/vis/radar/index.d.ts +2 -2
  44. package/dist/cjs/vis/radar/index.js +21 -29
  45. package/dist/cjs/vis/sankey/index.js +1 -4
  46. package/dist/cjs/vis/scatter/index.d.ts +4 -2
  47. package/dist/cjs/vis/scatter/index.js +43 -16
  48. package/dist/cjs/vis/treemap/index.js +1 -4
  49. package/dist/cjs/vis/venn/index.js +1 -4
  50. package/dist/cjs/vis/violin/index.js +1 -1
  51. package/dist/cjs/vis/waterfall/index.js +2 -2
  52. package/dist/cjs/vis/word-cloud/index.d.ts +3 -2
  53. package/dist/cjs/vis/word-cloud/index.js +125 -10
  54. package/dist/esm/gpt-vis/index.js +1 -1
  55. package/dist/esm/types/index.d.ts +2 -1
  56. package/dist/esm/util/animation.d.ts +2 -0
  57. package/dist/esm/util/animation.js +17 -0
  58. package/dist/esm/util/components.d.ts +15 -0
  59. package/dist/esm/util/components.js +67 -0
  60. package/dist/esm/util/crosshair-axis-labels.d.ts +9 -0
  61. package/dist/esm/util/crosshair-axis-labels.js +328 -0
  62. package/dist/esm/util/index.d.ts +6 -0
  63. package/dist/esm/util/index.js +6 -0
  64. package/dist/esm/util/interaction.d.ts +14 -0
  65. package/dist/esm/util/interaction.js +73 -0
  66. package/dist/esm/util/theme.d.ts +18 -24
  67. package/dist/esm/util/theme.js +302 -126
  68. package/dist/esm/util/tokens.d.ts +31 -0
  69. package/dist/esm/util/tokens.js +64 -0
  70. package/dist/esm/vis/area/index.d.ts +2 -2
  71. package/dist/esm/vis/area/index.js +91 -41
  72. package/dist/esm/vis/bar/index.d.ts +2 -2
  73. package/dist/esm/vis/bar/index.js +28 -29
  74. package/dist/esm/vis/boxplot/index.js +4 -5
  75. package/dist/esm/vis/column/index.d.ts +2 -2
  76. package/dist/esm/vis/column/index.js +36 -29
  77. package/dist/esm/vis/dual-axes/index.d.ts +2 -2
  78. package/dist/esm/vis/dual-axes/index.js +123 -43
  79. package/dist/esm/vis/fishbone-diagram/index.js +6 -5
  80. package/dist/esm/vis/flow-diagram/index.js +17 -10
  81. package/dist/esm/vis/funnel/index.d.ts +4 -2
  82. package/dist/esm/vis/funnel/index.js +156 -83
  83. package/dist/esm/vis/histogram/index.js +4 -5
  84. package/dist/esm/vis/indented-tree/index.js +9 -4
  85. package/dist/esm/vis/line/index.d.ts +2 -2
  86. package/dist/esm/vis/line/index.js +80 -37
  87. package/dist/esm/vis/liquid/index.d.ts +2 -2
  88. package/dist/esm/vis/liquid/index.js +41 -14
  89. package/dist/esm/vis/mindmap/index.js +6 -5
  90. package/dist/esm/vis/network-graph/index.js +5 -3
  91. package/dist/esm/vis/organization-chart/index.js +6 -4
  92. package/dist/esm/vis/pie/index.d.ts +2 -2
  93. package/dist/esm/vis/pie/index.js +36 -16
  94. package/dist/esm/vis/radar/index.d.ts +2 -2
  95. package/dist/esm/vis/radar/index.js +21 -34
  96. package/dist/esm/vis/sankey/index.js +4 -5
  97. package/dist/esm/vis/scatter/index.d.ts +4 -2
  98. package/dist/esm/vis/scatter/index.js +45 -19
  99. package/dist/esm/vis/treemap/index.js +4 -5
  100. package/dist/esm/vis/venn/index.js +4 -5
  101. package/dist/esm/vis/violin/index.js +5 -13
  102. package/dist/esm/vis/waterfall/index.js +11 -11
  103. package/dist/esm/vis/word-cloud/index.d.ts +3 -2
  104. package/dist/esm/vis/word-cloud/index.js +158 -10
  105. package/dist/umd/index.min.js +1 -1
  106. package/package.json +18 -19
@@ -53,12 +53,13 @@ function ensureBehaviorRegistered() {
53
53
  function escapeHtml(str = "") {
54
54
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
55
55
  }
56
- function createNodeHTML(d, color, selectedBorderColor = "#000") {
56
+ function createNodeHTML(d, color, selectedBorderColor = "#000", theme = "default") {
57
57
  var _a, _b, _c;
58
58
  const text = escapeHtml(((_a = d.data) == null ? void 0 : _a.text) || "");
59
59
  const isHovered = (_b = d.states) == null ? void 0 : _b.includes("active");
60
60
  const isSelected = (_c = d.states) == null ? void 0 : _c.includes("selected");
61
61
  const nodeColor = isHovered ? ACTIVE_COLOR : color;
62
+ const borderRadius = theme === "academy" ? "0px" : "8px";
62
63
  return `
63
64
  <div
64
65
  data-node-key="${escapeHtml(String(d.id))}"
@@ -69,7 +70,7 @@ function createNodeHTML(d, color, selectedBorderColor = "#000") {
69
70
  padding: 16px;
70
71
  background: ${nodeColor};
71
72
  border: 3px solid ${isSelected ? selectedBorderColor : nodeColor};
72
- border-radius: 16px;
73
+ border-radius: ${borderRadius};
73
74
  color: #fff;
74
75
  font-size: 16px;
75
76
  font-weight: 600;
@@ -90,7 +91,7 @@ function createNodeHTML(d, color, selectedBorderColor = "#000") {
90
91
  </div>
91
92
  `;
92
93
  }
93
- function measureAndUpdateNodeSizes(graph, container, nodeColorMap, selectedBorderColor) {
94
+ function measureAndUpdateNodeSizes(graph, container, nodeColorMap, selectedBorderColor, theme = "default") {
94
95
  const nodes = graph.getNodeData();
95
96
  const updatedNodes = nodes.map((node) => {
96
97
  const dom = container.querySelector(`[data-node-key="${CSS.escape(String(node.id))}"]`);
@@ -107,7 +108,8 @@ function measureAndUpdateNodeSizes(graph, container, nodeColorMap, selectedBorde
107
108
  innerHTML: createNodeHTML(
108
109
  node,
109
110
  nodeColorMap.get(String(node.id)) || "#1783FF",
110
- selectedBorderColor
111
+ selectedBorderColor,
112
+ theme
111
113
  )
112
114
  }
113
115
  };
@@ -187,21 +189,35 @@ var FlowDiagram = (options) => {
187
189
  container: containerEl,
188
190
  width,
189
191
  height,
190
- theme,
192
+ theme: (0, import_theme.getTheme)(theme),
191
193
  data: { nodes: g6Nodes, edges: g6Edges },
192
194
  autoFit: "view",
193
195
  autoResize: true,
194
- padding: 20,
195
- plugins: title ? [{ key: "title", type: "title", title, titleFill: isDark ? "#e0e6ed" : "#1a1a2e" }] : [],
196
+ padding: title ? [46, 20, 20, 20] : 20,
197
+ plugins: title ? [
198
+ {
199
+ key: "title",
200
+ type: "title",
201
+ title,
202
+ titleFill: isDark ? "#e0e6ed" : "#000",
203
+ titleFontFamily: "sans-serif"
204
+ }
205
+ ] : [],
196
206
  node: {
197
207
  type: "html",
198
208
  style: (d) => {
209
+ var _a;
199
210
  const color = nodeColorMap.get(String(d.id)) || colors[0];
211
+ const size = ((_a = d.style) == null ? void 0 : _a.size) || [
212
+ DEFAULT_NODE_WIDTH,
213
+ DEFAULT_NODE_HEIGHT
214
+ ];
215
+ const height2 = size[1];
200
216
  return {
201
- size: [DEFAULT_NODE_WIDTH, DEFAULT_NODE_HEIGHT],
217
+ size,
202
218
  dx: -DEFAULT_NODE_WIDTH / 2,
203
- dy: -DEFAULT_NODE_HEIGHT / 2,
204
- innerHTML: createNodeHTML(d, color, selectedBorder),
219
+ dy: -height2 / 2,
220
+ innerHTML: createNodeHTML(d, color, selectedBorder, theme),
205
221
  ports: [{ placement: "top" }, { placement: "bottom" }]
206
222
  };
207
223
  },
@@ -248,7 +264,7 @@ var FlowDiagram = (options) => {
248
264
  graph.render();
249
265
  graph.once("afterrender", () => {
250
266
  if (graph) {
251
- measureAndUpdateNodeSizes(graph, containerEl, nodeColorMap, selectedBorder);
267
+ measureAndUpdateNodeSizes(graph, containerEl, nodeColorMap, selectedBorder, theme);
252
268
  }
253
269
  });
254
270
  };
@@ -1,4 +1,4 @@
1
- import type { VisualizationOptions } from '../../types';
1
+ import type { VisualizationOptions, VisualizationTheme } from '../../types';
2
2
  /**
3
3
  * FunnelDataItem is the type for each data item in the funnel chart.
4
4
  */
@@ -12,8 +12,10 @@ export type FunnelDataItem = {
12
12
  export interface FunnelConfig {
13
13
  type?: 'funnel';
14
14
  data: FunnelDataItem[];
15
- theme?: 'default' | 'academy' | 'dark';
15
+ theme?: VisualizationTheme;
16
16
  title?: string;
17
+ locale?: string;
18
+ conversionRateLabel?: string;
17
19
  style?: {
18
20
  backgroundColor?: string;
19
21
  palette?: string[];
@@ -23,32 +23,103 @@ __export(funnel_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(funnel_exports);
25
25
  var import_g2 = require("@antv/g2");
26
- var import_theme = require("../../util/theme");
26
+ var import_util = require("../../util");
27
+ var FUNNEL_LABELS = {
28
+ "en-US": {
29
+ baseline: "Baseline",
30
+ conversionRate: "Conversion Rate",
31
+ currentValue: "Current value",
32
+ dropOff: "Drop-off from previous",
33
+ overallConversionRate: "Overall conversion",
34
+ stageConversion: "Stage conversion"
35
+ },
36
+ "zh-CN": {
37
+ baseline: "基准",
38
+ conversionRate: "转化率",
39
+ currentValue: "当前值",
40
+ dropOff: "较上一步流失",
41
+ overallConversionRate: "整体转化率",
42
+ stageConversion: "阶段转化率"
43
+ }
44
+ };
45
+ var formatConversionRate = (start, end) => {
46
+ if (!Number.isFinite(start) || !Number.isFinite(end) || start === 0)
47
+ return "—";
48
+ return `${(end / start * 100).toFixed(1)}%`;
49
+ };
50
+ var formatMetricLabel = (label, value, locale) => locale === "zh-CN" ? `${label}:${value}` : `${label}: ${value}`;
27
51
  var Funnel = (options) => {
28
- const { container, width, height, theme: chartTheme = "default" } = options;
52
+ const { container, width, height, locale, theme: chartTheme = "default" } = options;
29
53
  let chart = null;
30
54
  const render = (config) => {
31
- var _a, _b, _c, _d, _e, _f;
32
- const { data = [], theme = chartTheme, title, style = {} } = config;
55
+ const {
56
+ data = [],
57
+ theme = chartTheme,
58
+ title,
59
+ locale: renderLocale = locale,
60
+ conversionRateLabel,
61
+ style = {}
62
+ } = config;
63
+ const chartLocale = (0, import_util.resolveChartLocale)(renderLocale);
64
+ const labels = FUNNEL_LABELS[chartLocale];
65
+ const numberFormatter = new Intl.NumberFormat(chartLocale);
66
+ const stageConversionRateLabel = conversionRateLabel ?? labels.conversionRate;
67
+ const overallConversionRateLabel = conversionRateLabel ?? labels.overallConversionRate;
33
68
  if (chart) {
34
69
  chart.destroy();
35
70
  }
36
- const colors = (0, import_theme.normalizePalette)(style.palette, theme);
37
- const backgroundColor = style.backgroundColor || (0, import_theme.getBackgroundColor)(theme);
38
- const conversionRate = (start, end) => `${(end / start * 100).toFixed(2)} %`;
71
+ const colors = (0, import_util.normalizePalette)(style.palette, theme);
72
+ const backgroundColor = style.backgroundColor || (0, import_util.getBackgroundColor)(theme);
73
+ const tokens = (0, import_util.getChartVisualTokens)(theme);
74
+ const formatValue = (value) => Number.isFinite(value) ? numberFormatter.format(value) : "—";
75
+ const metricsByCategory = new Map(
76
+ data.map((item, index) => {
77
+ const previous = data[index - 1];
78
+ return [
79
+ item.category,
80
+ {
81
+ conversion: previous ? formatConversionRate(previous.value, item.value) : labels.baseline,
82
+ dropOff: previous ? Math.max(0, previous.value - item.value) : null
83
+ }
84
+ ];
85
+ })
86
+ );
87
+ const funnelTooltip = {
88
+ title: "category",
89
+ items: [
90
+ (d) => ({
91
+ name: labels.currentValue,
92
+ value: formatValue(d.value)
93
+ }),
94
+ (d) => {
95
+ var _a;
96
+ return {
97
+ name: labels.stageConversion,
98
+ value: ((_a = metricsByCategory.get(d.category)) == null ? void 0 : _a.conversion) ?? "—"
99
+ };
100
+ },
101
+ (d) => {
102
+ var _a, _b;
103
+ return {
104
+ name: labels.dropOff,
105
+ value: ((_a = metricsByCategory.get(d.category)) == null ? void 0 : _a.dropOff) === null ? "—" : formatValue(((_b = metricsByCategory.get(d.category)) == null ? void 0 : _b.dropOff) ?? Number.NaN)
106
+ };
107
+ }
108
+ ]
109
+ };
39
110
  chart = new import_g2.Chart({
40
111
  container,
41
112
  width,
42
113
  height,
43
114
  autoFit: true,
44
- paddingLeft: 40,
45
- paddingRight: 68
115
+ paddingLeft: 56,
116
+ paddingRight: 118
46
117
  });
47
118
  const chartOptions = {
48
119
  animate: false,
49
120
  type: "view",
50
121
  data,
51
- title: title ?? "",
122
+ title: title || "",
52
123
  children: [
53
124
  {
54
125
  type: "interval",
@@ -66,109 +137,117 @@ var Funnel = (options) => {
66
137
  x: { padding: 0 },
67
138
  color: { range: colors }
68
139
  },
69
- legend: {
70
- color: {
71
- position: "top",
72
- layout: {
73
- justifyContent: "center"
74
- }
75
- }
76
- },
140
+ legend: false,
141
+ tooltip: funnelTooltip,
77
142
  labels: [
78
- // Inside label showing category and value
79
143
  {
80
144
  text: (d) => `${d.category}
81
- ${d.value}`,
145
+ ${formatValue(d.value)}`,
82
146
  position: "inside",
83
- transform: [{ type: "contrastReverse" }]
84
- },
85
- // Connecting line for conversion rate
86
- {
87
- text: (d, i) => i !== 0 ? "———" : "",
147
+ transform: [{ type: "contrastReverse" }, { type: "overflowStroke" }],
88
148
  style: {
89
- "font-size": "1px",
90
- color: "#666",
91
- "letter-spacing": "0px"
92
- },
93
- position: "top-right",
94
- fill: "#666",
95
- dx: 35,
96
- dy: -8
149
+ fontFamily: import_util.CHART_FONT_FAMILY,
150
+ fontSize: 12,
151
+ fontWeight: 500,
152
+ lineHeight: 17
153
+ }
97
154
  },
98
- // Conversion rate label text
99
155
  {
100
- text: (d, i) => i !== 0 ? "转化率" : "",
156
+ text: (_d, index) => index === 0 ? "" : "———",
101
157
  position: "top-right",
102
- textAlign: "left",
103
- textBaseline: "middle",
104
- fill: "#666",
105
- dx: 40
158
+ fill: tokens.textSecondary,
159
+ fillOpacity: 0.72,
160
+ dx: 18,
161
+ dy: -6,
162
+ style: {
163
+ fontFamily: import_util.CHART_FONT_FAMILY,
164
+ fontSize: 8,
165
+ fontWeight: 400,
166
+ letterSpacing: -2
167
+ }
106
168
  },
107
- // Conversion rate percentage
108
169
  {
109
- text: (d, i, dataArray) => i !== 0 ? conversionRate(dataArray[i - 1].value, dataArray[i].value) : "",
170
+ text: (_d, index, items) => index === 0 ? "" : formatMetricLabel(
171
+ stageConversionRateLabel,
172
+ formatConversionRate(items[index - 1].value, items[index].value),
173
+ chartLocale
174
+ ),
110
175
  position: "top-right",
111
176
  textAlign: "left",
112
177
  textBaseline: "middle",
113
- dx: 80
114
- }
115
- ],
116
- viewStyle: {
117
- viewFill: backgroundColor
118
- }
119
- },
120
- // Overall conversion rate connector
121
- {
122
- type: "connector",
123
- data: [
124
- {
125
- startX: (_a = data[0]) == null ? void 0 : _a.category,
126
- startY: (_b = data[data.length - 1]) == null ? void 0 : _b.category,
127
- endX: 0,
128
- endY: (((_c = data[0]) == null ? void 0 : _c.value) - ((_d = data[data.length - 1]) == null ? void 0 : _d.value)) / 2
178
+ fill: tokens.textPrimary,
179
+ dx: 44,
180
+ style: {
181
+ fontFamily: import_util.CHART_FONT_FAMILY,
182
+ fontSize: 11,
183
+ fontWeight: 500
184
+ }
129
185
  }
130
186
  ],
131
- encode: { x: "startX", x1: "startY", y: "endX", y1: "endY" },
132
187
  style: {
133
- stroke: "#666",
134
- markerEnd: false,
135
- connectLength1: -12,
136
- offset2: -20,
137
- connectorStroke: "#0649f2",
138
- lineDash: [12, 2]
188
+ fillOpacity: 0.94,
189
+ stroke: tokens.separator,
190
+ lineWidth: 2,
191
+ ...theme === "academy" ? {} : { radius: 4 }
139
192
  },
140
- labels: [
141
- {
142
- text: "转化率",
143
- position: "left",
144
- textAlign: "start",
145
- textBaseline: "middle",
146
- fill: "#666",
147
- dx: 10
148
- },
149
- {
150
- text: conversionRate((_e = data[0]) == null ? void 0 : _e.value, (_f = data[data.length - 1]) == null ? void 0 : _f.value),
151
- position: "left",
152
- textAlign: "start",
153
- dx: 50,
154
- fill: "#000"
193
+ state: {
194
+ active: {
195
+ fillOpacity: 1,
196
+ stroke: tokens.separator,
197
+ lineWidth: 3
155
198
  }
156
- ]
157
- }
199
+ },
200
+ viewStyle: style.backgroundColor ? { viewFill: backgroundColor } : void 0
201
+ },
202
+ ...data.length > 1 ? [
203
+ {
204
+ type: "connector",
205
+ data: [
206
+ {
207
+ startX: data[0].category,
208
+ startY: data[data.length - 1].category,
209
+ endX: 0,
210
+ endY: (data[0].value - data[data.length - 1].value) / 2
211
+ }
212
+ ],
213
+ encode: { x: "startX", x1: "startY", y: "endX", y1: "endY" },
214
+ tooltip: false,
215
+ style: {
216
+ stroke: tokens.axisLine,
217
+ strokeOpacity: theme === "academy" ? 1 : 0.82,
218
+ lineWidth: theme === "academy" ? 1 : 0.75,
219
+ markerEnd: false,
220
+ connectLength1: -12
221
+ },
222
+ labels: [
223
+ {
224
+ text: formatMetricLabel(
225
+ overallConversionRateLabel,
226
+ formatConversionRate(data[0].value, data[data.length - 1].value),
227
+ chartLocale
228
+ ),
229
+ position: "left",
230
+ textAlign: "start",
231
+ textBaseline: "middle",
232
+ fill: tokens.textPrimary,
233
+ dx: 8,
234
+ style: {
235
+ fontFamily: import_util.CHART_FONT_FAMILY,
236
+ fontSize: 11,
237
+ fontWeight: 500
238
+ }
239
+ }
240
+ ]
241
+ }
242
+ ] : []
158
243
  ],
159
244
  axis: false,
160
- tooltip: {
161
- items: [
162
- (d) => ({
163
- name: d.category,
164
- value: d.value
165
- })
166
- ]
167
- },
168
- viewStyle: {
169
- viewFill: backgroundColor
245
+ interaction: {
246
+ tooltip: true,
247
+ elementHighlight: true
170
248
  },
171
- theme: (0, import_theme.getThemeObject)(theme)
249
+ viewStyle: style.backgroundColor ? { viewFill: backgroundColor } : void 0,
250
+ theme: (0, import_util.getThemeObject)(theme)
172
251
  };
173
252
  chart.options(chartOptions);
174
253
  chart.render();
@@ -41,7 +41,6 @@ var Histogram = (options) => {
41
41
  chart.destroy();
42
42
  }
43
43
  const colors = (0, import_theme.normalizePalette)(style.palette, theme);
44
- const backgroundColor = style.backgroundColor || (0, import_theme.getBackgroundColor)(theme);
45
44
  chart = new import_g2.Chart({
46
45
  container,
47
46
  width,
@@ -83,9 +82,7 @@ var Histogram = (options) => {
83
82
  tooltip: {
84
83
  items: [{ channel: "y", name: "频数" }]
85
84
  },
86
- viewStyle: {
87
- viewFill: backgroundColor
88
- },
85
+ viewStyle: style.backgroundColor ? { viewFill: style.backgroundColor } : void 0,
89
86
  theme: (0, import_theme.getThemeObject)(theme)
90
87
  };
91
88
  chart.options(chartOptions);
@@ -281,15 +281,17 @@ var IndentedTree = (options) => {
281
281
  height,
282
282
  autoFit: "view",
283
283
  autoResize: true,
284
- padding: 20,
284
+ theme: (0, import_theme.getTheme)(theme),
285
+ padding: title ? [46, 20, 20, 20] : 20,
285
286
  data: graphData,
286
287
  node: {
287
288
  type: GPT_VIS_INDENTED_NODE,
288
289
  style: {
289
290
  size: (d) => [measureTextWidth(String(d.id ?? ""), 12) + 6, NODE_HEIGHT],
290
291
  labelBackground: (datum) => datum.id === rootId,
291
- labelBackgroundRadius: 0,
292
+ labelBackgroundRadius: theme === "academy" ? 0 : 4,
292
293
  labelBackgroundFill: palette[0] ?? "#1783FF",
294
+ labelPadding: (datum) => datum.id === rootId ? [2, 8] : 0,
293
295
  labelFill: (datum) => datum.id === rootId ? "#fff" : isDark ? "#d0d0d0" : "#666",
294
296
  labelText: (d) => {
295
297
  var _a;
@@ -352,7 +354,15 @@ var IndentedTree = (options) => {
352
354
  enable: (event) => event.targetType === "node" && event.target.id !== rootId
353
355
  }
354
356
  ],
355
- plugins: title ? [{ key: "title", type: "title", title, titleFill: isDark ? "#e0e6ed" : "#1a1a2e" }] : []
357
+ plugins: title ? [
358
+ {
359
+ key: "title",
360
+ type: "title",
361
+ title,
362
+ titleFill: isDark ? "#e0e6ed" : "#000",
363
+ titleFontFamily: "sans-serif"
364
+ }
365
+ ] : []
356
366
  });
357
367
  graph.render();
358
368
  };
@@ -1,4 +1,4 @@
1
- import type { VisualizationOptions } from '../../types';
1
+ import type { VisualizationOptions, VisualizationTheme } from '../../types';
2
2
  /**
3
3
  * LineDataItem is the type for each data item in the line chart.
4
4
  */
@@ -16,7 +16,7 @@ export interface LineConfig {
16
16
  title?: string;
17
17
  axisXTitle?: string;
18
18
  axisYTitle?: string;
19
- theme?: 'default' | 'academy' | 'dark';
19
+ theme?: VisualizationTheme;
20
20
  style?: {
21
21
  backgroundColor?: string;
22
22
  palette?: string[];
@@ -23,20 +23,40 @@ __export(line_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(line_exports);
25
25
  var import_g2 = require("@antv/g2");
26
- var import_theme = require("../../util/theme");
26
+ var import_util = require("../../util");
27
27
  var Line = (options) => {
28
28
  const { container, width, height, theme: chartTheme = "default" } = options;
29
29
  let chart = null;
30
+ let hasRendered = false;
31
+ let cleanupCrosshairAxisLabels = null;
30
32
  const render = (config) => {
31
33
  var _a;
32
34
  const { data = [], theme = chartTheme, title, axisXTitle, axisYTitle, style = {} } = config;
33
35
  if (chart) {
36
+ cleanupCrosshairAxisLabels == null ? void 0 : cleanupCrosshairAxisLabels();
37
+ cleanupCrosshairAxisLabels = null;
34
38
  chart.destroy();
35
39
  }
36
- const { lineWidth = 2 } = style;
40
+ const { lineWidth = import_util.CHART_STYLE_DEFAULTS.lineWidth } = style;
37
41
  const hasGroupField = data.length > 0 && ((_a = data[0]) == null ? void 0 : _a.group) !== void 0;
38
- const colors = (0, import_theme.normalizePalette)(style.palette, theme);
39
- const backgroundColor = style.backgroundColor || (0, import_theme.getBackgroundColor)(theme);
42
+ const colors = (0, import_util.normalizePalette)(style.palette, theme);
43
+ const backgroundColor = style.backgroundColor || (0, import_util.getBackgroundColor)(theme);
44
+ const tooltip = {
45
+ items: [
46
+ (d) => ({
47
+ name: hasGroupField ? d.group : axisYTitle || d.time,
48
+ value: d.value
49
+ })
50
+ ]
51
+ };
52
+ const lineAnimation = (0, import_util.getChartAnimation)(hasRendered, "pathIn");
53
+ const pointAnimation = (0, import_util.getChartAnimation)(hasRendered, "fadeIn");
54
+ const cartesianAxisOptions = {
55
+ axisXTitle,
56
+ axisYTitle,
57
+ xLabels: data.map(({ time }) => time),
58
+ chartWidth: width
59
+ };
40
60
  chart = new import_g2.Chart({
41
61
  container,
42
62
  width,
@@ -51,48 +71,68 @@ var Line = (options) => {
51
71
  } else {
52
72
  encode = { x: "time", y: "value" };
53
73
  }
74
+ const children = [
75
+ {
76
+ type: "line",
77
+ tooltip,
78
+ style: {
79
+ lineWidth,
80
+ lineCap: "round",
81
+ lineJoin: "round",
82
+ ...!hasGroupField ? { stroke: colors[0] } : {}
83
+ },
84
+ animate: lineAnimation
85
+ }
86
+ ];
87
+ const showPoints = data.length <= (hasGroupField ? 36 : 24);
88
+ if (showPoints) {
89
+ children.push({
90
+ type: "point",
91
+ encode: {
92
+ x: "time",
93
+ y: "value",
94
+ shape: "point",
95
+ size: import_util.CHART_STYLE_DEFAULTS.pointSize,
96
+ ...hasGroupField ? { color: "group" } : {}
97
+ },
98
+ animate: pointAnimation,
99
+ tooltip: false,
100
+ style: {
101
+ lineWidth: import_util.CHART_STYLE_DEFAULTS.pointLineWidth,
102
+ stroke: backgroundColor,
103
+ ...!hasGroupField ? { fill: colors[0] } : {}
104
+ }
105
+ });
106
+ }
54
107
  const chartOptions = {
55
- animate: false,
56
108
  type: "view",
57
109
  data,
58
- title: title ?? "",
110
+ title: title || "",
59
111
  encode,
60
- children: [
61
- {
62
- type: "line",
63
- style: {
64
- lineWidth,
65
- ...!hasGroupField && style.palette ? { stroke: colors[0] } : {}
66
- }
67
- }
68
- ],
112
+ children,
69
113
  scale: scaleConfig,
70
- axis: {
71
- x: { title: axisXTitle || false },
72
- y: { title: axisYTitle || false }
73
- },
74
- legend: hasGroupField ? { color: { position: "top" } } : false,
75
- tooltip: {
76
- items: [
77
- (d) => ({
78
- name: axisYTitle || d.time,
79
- value: d.value
80
- })
81
- ]
82
- },
83
- viewStyle: {
84
- viewFill: backgroundColor
114
+ ...(0, import_util.getCartesianLayout)(cartesianAxisOptions),
115
+ axis: (0, import_util.getCartesianAxis)(cartesianAxisOptions),
116
+ legend: (0, import_util.getColorLegend)(hasGroupField),
117
+ interaction: {
118
+ tooltip: (0, import_util.getSharedTooltipInteraction)({ crosshairs: true })
85
119
  },
86
- theme: (0, import_theme.getThemeObject)(theme)
120
+ viewStyle: style.backgroundColor ? { viewFill: backgroundColor } : void 0,
121
+ theme: (0, import_util.getThemeObject)(theme)
87
122
  };
88
123
  chart.options(chartOptions);
124
+ cleanupCrosshairAxisLabels = (0, import_util.bindCrosshairAxisLabels)(chart, theme);
89
125
  chart.render();
126
+ hasRendered = true;
90
127
  };
91
128
  const destroy = () => {
92
129
  if (chart) {
130
+ cleanupCrosshairAxisLabels == null ? void 0 : cleanupCrosshairAxisLabels();
131
+ cleanupCrosshairAxisLabels = null;
93
132
  chart.destroy();
94
133
  chart = null;
95
134
  }
135
+ hasRendered = false;
96
136
  };
97
137
  return {
98
138
  render,
@@ -1,4 +1,4 @@
1
- import type { VisualizationOptions } from '../../types';
1
+ import type { VisualizationOptions, VisualizationTheme } from '../../types';
2
2
  /**
3
3
  * LiquidConfig defines the configuration for rendering the liquid chart.
4
4
  */
@@ -6,7 +6,7 @@ export interface LiquidConfig {
6
6
  type?: 'liquid';
7
7
  percent: number;
8
8
  shape?: 'rect' | 'circle' | 'pin' | 'triangle';
9
- theme?: 'default' | 'academy' | 'dark';
9
+ theme?: VisualizationTheme;
10
10
  title?: string;
11
11
  style?: {
12
12
  backgroundColor?: string;