@antv/gpt-vis 1.0.0 → 1.0.2

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 (98) hide show
  1. package/README.md +153 -34
  2. package/README.zh-CN.md +153 -34
  3. package/dist/cjs/types/index.d.ts +2 -1
  4. package/dist/cjs/util/animation.d.ts +2 -0
  5. package/dist/cjs/util/animation.js +38 -0
  6. package/dist/cjs/util/components.d.ts +15 -0
  7. package/dist/cjs/util/components.js +94 -0
  8. package/dist/cjs/util/crosshair-axis-labels.d.ts +15 -0
  9. package/dist/cjs/util/crosshair-axis-labels.js +401 -0
  10. package/dist/cjs/util/html.d.ts +1 -0
  11. package/dist/cjs/util/html.js +29 -0
  12. package/dist/cjs/util/index.d.ts +6 -0
  13. package/dist/cjs/util/index.js +33 -0
  14. package/dist/cjs/util/interaction.d.ts +14 -0
  15. package/dist/cjs/util/interaction.js +89 -0
  16. package/dist/cjs/util/theme.d.ts +18 -24
  17. package/dist/cjs/util/theme.js +303 -120
  18. package/dist/cjs/util/tokens.d.ts +31 -0
  19. package/dist/cjs/util/tokens.js +98 -0
  20. package/dist/cjs/vis/area/index.d.ts +2 -2
  21. package/dist/cjs/vis/area/index.js +76 -31
  22. package/dist/cjs/vis/bar/index.d.ts +2 -2
  23. package/dist/cjs/vis/bar/index.js +22 -19
  24. package/dist/cjs/vis/boxplot/index.js +1 -4
  25. package/dist/cjs/vis/column/index.d.ts +2 -2
  26. package/dist/cjs/vis/column/index.js +28 -18
  27. package/dist/cjs/vis/dual-axes/index.d.ts +2 -2
  28. package/dist/cjs/vis/dual-axes/index.js +107 -34
  29. package/dist/cjs/vis/funnel/index.d.ts +3 -2
  30. package/dist/cjs/vis/funnel/index.js +171 -94
  31. package/dist/cjs/vis/histogram/index.js +1 -4
  32. package/dist/cjs/vis/line/index.d.ts +2 -2
  33. package/dist/cjs/vis/line/index.js +71 -31
  34. package/dist/cjs/vis/liquid/index.d.ts +2 -2
  35. package/dist/cjs/vis/liquid/index.js +41 -16
  36. package/dist/cjs/vis/pie/index.d.ts +2 -2
  37. package/dist/cjs/vis/pie/index.js +26 -16
  38. package/dist/cjs/vis/radar/index.d.ts +2 -2
  39. package/dist/cjs/vis/radar/index.js +21 -29
  40. package/dist/cjs/vis/sankey/index.js +1 -4
  41. package/dist/cjs/vis/scatter/index.d.ts +2 -2
  42. package/dist/cjs/vis/scatter/index.js +40 -17
  43. package/dist/cjs/vis/table/index.js +13 -5
  44. package/dist/cjs/vis/treemap/index.js +1 -4
  45. package/dist/cjs/vis/venn/index.js +1 -4
  46. package/dist/cjs/vis/violin/index.js +1 -1
  47. package/dist/cjs/vis/waterfall/index.js +1 -1
  48. package/dist/cjs/vis/word-cloud/index.d.ts +3 -2
  49. package/dist/cjs/vis/word-cloud/index.js +125 -10
  50. package/dist/esm/types/index.d.ts +2 -1
  51. package/dist/esm/util/animation.d.ts +2 -0
  52. package/dist/esm/util/animation.js +17 -0
  53. package/dist/esm/util/components.d.ts +15 -0
  54. package/dist/esm/util/components.js +67 -0
  55. package/dist/esm/util/crosshair-axis-labels.d.ts +15 -0
  56. package/dist/esm/util/crosshair-axis-labels.js +431 -0
  57. package/dist/esm/util/html.d.ts +1 -0
  58. package/dist/esm/util/html.js +3 -0
  59. package/dist/esm/util/index.d.ts +6 -0
  60. package/dist/esm/util/index.js +6 -0
  61. package/dist/esm/util/interaction.d.ts +14 -0
  62. package/dist/esm/util/interaction.js +73 -0
  63. package/dist/esm/util/theme.d.ts +18 -24
  64. package/dist/esm/util/theme.js +302 -126
  65. package/dist/esm/util/tokens.d.ts +31 -0
  66. package/dist/esm/util/tokens.js +64 -0
  67. package/dist/esm/vis/area/index.d.ts +2 -2
  68. package/dist/esm/vis/area/index.js +91 -41
  69. package/dist/esm/vis/bar/index.d.ts +2 -2
  70. package/dist/esm/vis/bar/index.js +28 -29
  71. package/dist/esm/vis/boxplot/index.js +4 -5
  72. package/dist/esm/vis/column/index.d.ts +2 -2
  73. package/dist/esm/vis/column/index.js +36 -29
  74. package/dist/esm/vis/dual-axes/index.d.ts +2 -2
  75. package/dist/esm/vis/dual-axes/index.js +145 -42
  76. package/dist/esm/vis/funnel/index.d.ts +3 -2
  77. package/dist/esm/vis/funnel/index.js +159 -85
  78. package/dist/esm/vis/histogram/index.js +4 -5
  79. package/dist/esm/vis/line/index.d.ts +2 -2
  80. package/dist/esm/vis/line/index.js +80 -37
  81. package/dist/esm/vis/liquid/index.d.ts +2 -2
  82. package/dist/esm/vis/liquid/index.js +41 -14
  83. package/dist/esm/vis/pie/index.d.ts +2 -2
  84. package/dist/esm/vis/pie/index.js +36 -16
  85. package/dist/esm/vis/radar/index.d.ts +2 -2
  86. package/dist/esm/vis/radar/index.js +21 -34
  87. package/dist/esm/vis/sankey/index.js +4 -5
  88. package/dist/esm/vis/scatter/index.d.ts +2 -2
  89. package/dist/esm/vis/scatter/index.js +41 -25
  90. package/dist/esm/vis/table/index.js +9 -9
  91. package/dist/esm/vis/treemap/index.js +4 -5
  92. package/dist/esm/vis/venn/index.js +4 -5
  93. package/dist/esm/vis/violin/index.js +5 -13
  94. package/dist/esm/vis/waterfall/index.js +5 -7
  95. package/dist/esm/vis/word-cloud/index.d.ts +3 -2
  96. package/dist/esm/vis/word-cloud/index.js +158 -10
  97. package/dist/umd/index.min.js +1 -1
  98. package/package.json +18 -15
@@ -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,9 @@ 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
+ conversionRateLabel?: string;
17
18
  style?: {
18
19
  backgroundColor?: string;
19
20
  palette?: string[];
@@ -23,32 +23,97 @@ __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 { data = [], theme = chartTheme, title, conversionRateLabel, style = {} } = config;
56
+ const chartLocale = (0, import_util.resolveChartLocale)(locale);
57
+ const labels = FUNNEL_LABELS[chartLocale];
58
+ const numberFormatter = new Intl.NumberFormat(chartLocale);
59
+ const stageConversionRateLabel = conversionRateLabel ?? labels.conversionRate;
60
+ const overallConversionRateLabel = conversionRateLabel ?? labels.overallConversionRate;
33
61
  if (chart) {
34
62
  chart.destroy();
35
63
  }
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)} %`;
64
+ const colors = (0, import_util.normalizePalette)(style.palette, theme);
65
+ const backgroundColor = style.backgroundColor || (0, import_util.getBackgroundColor)(theme);
66
+ const tokens = (0, import_util.getChartVisualTokens)(theme);
67
+ const formatValue = (value) => Number.isFinite(value) ? numberFormatter.format(value) : "—";
68
+ const isInverted = data.length > 1 && data[0].value < data[data.length - 1].value;
69
+ const metricsByCategory = new Map(
70
+ data.map((item, index) => {
71
+ const previous = data[index - 1];
72
+ return [
73
+ item.category,
74
+ {
75
+ conversion: previous ? formatConversionRate(previous.value, item.value) : labels.baseline,
76
+ dropOff: previous ? Math.max(0, previous.value - item.value) : null
77
+ }
78
+ ];
79
+ })
80
+ );
81
+ const funnelTooltip = {
82
+ title: "category",
83
+ items: [
84
+ (d) => ({
85
+ name: labels.currentValue,
86
+ value: formatValue(d.value)
87
+ }),
88
+ (d) => {
89
+ var _a;
90
+ return {
91
+ name: labels.stageConversion,
92
+ value: ((_a = metricsByCategory.get(d.category)) == null ? void 0 : _a.conversion) ?? "—"
93
+ };
94
+ },
95
+ (d) => {
96
+ var _a, _b;
97
+ return {
98
+ name: labels.dropOff,
99
+ 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)
100
+ };
101
+ }
102
+ ]
103
+ };
39
104
  chart = new import_g2.Chart({
40
105
  container,
41
106
  width,
42
107
  height,
43
108
  autoFit: true,
44
- paddingLeft: 40,
45
- paddingRight: 68
109
+ paddingLeft: 56,
110
+ paddingRight: 118
46
111
  });
47
112
  const chartOptions = {
48
113
  animate: false,
49
114
  type: "view",
50
115
  data,
51
- title: title ?? "",
116
+ title: title || "",
52
117
  children: [
53
118
  {
54
119
  type: "interval",
@@ -66,109 +131,121 @@ var Funnel = (options) => {
66
131
  x: { padding: 0 },
67
132
  color: { range: colors }
68
133
  },
69
- legend: {
70
- color: {
71
- position: "top",
72
- layout: {
73
- justifyContent: "center"
74
- }
75
- }
76
- },
134
+ legend: false,
135
+ tooltip: funnelTooltip,
77
136
  labels: [
78
- // Inside label showing category and value
79
137
  {
80
138
  text: (d) => `${d.category}
81
- ${d.value}`,
139
+ ${formatValue(d.value)}`,
82
140
  position: "inside",
83
- transform: [{ type: "contrastReverse" }]
84
- },
85
- // Connecting line for conversion rate
86
- {
87
- text: (d, i) => i !== 0 ? "———" : "",
141
+ transform: [{ type: "contrastReverse" }, { type: "overflowStroke" }],
88
142
  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
143
+ fontFamily: import_util.CHART_FONT_FAMILY,
144
+ fontSize: 12,
145
+ fontWeight: 500,
146
+ lineHeight: 17
147
+ }
97
148
  },
98
- // Conversion rate label text
99
149
  {
100
- text: (d, i) => i !== 0 ? "转化率" : "",
101
- position: "top-right",
102
- textAlign: "left",
103
- textBaseline: "middle",
104
- fill: "#666",
105
- dx: 40
150
+ text: (_d, index, items) => (isInverted ? index < items.length - 1 : index > 0) ? "———" : "",
151
+ position: isInverted ? "bottom-right" : "top-right",
152
+ fill: tokens.textSecondary,
153
+ fillOpacity: 0.72,
154
+ dx: 8,
155
+ dy: isInverted ? 6 : -6,
156
+ style: {
157
+ fontFamily: import_util.CHART_FONT_FAMILY,
158
+ fontSize: 8,
159
+ fontWeight: 400,
160
+ letterSpacing: -2
161
+ }
106
162
  },
107
- // Conversion rate percentage
108
163
  {
109
- text: (d, i, dataArray) => i !== 0 ? conversionRate(dataArray[i - 1].value, dataArray[i].value) : "",
110
- position: "top-right",
164
+ text: (_d, index, items) => {
165
+ const from = isInverted ? items[index] : items[index - 1];
166
+ const to = isInverted ? items[index + 1] : items[index];
167
+ return from && to ? formatMetricLabel(
168
+ stageConversionRateLabel,
169
+ formatConversionRate(from.value, to.value),
170
+ chartLocale
171
+ ) : "";
172
+ },
173
+ position: isInverted ? "bottom-right" : "top-right",
111
174
  textAlign: "left",
112
175
  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
176
+ fill: tokens.textPrimary,
177
+ dx: 26,
178
+ style: {
179
+ fontFamily: import_util.CHART_FONT_FAMILY,
180
+ fontSize: 11,
181
+ fontWeight: 500
182
+ }
129
183
  }
130
184
  ],
131
- encode: { x: "startX", x1: "startY", y: "endX", y1: "endY" },
132
185
  style: {
133
- stroke: "#666",
134
- markerEnd: false,
135
- connectLength1: -12,
136
- offset2: -20,
137
- connectorStroke: "#0649f2",
138
- lineDash: [12, 2]
186
+ fillOpacity: 0.94,
187
+ stroke: tokens.separator,
188
+ lineWidth: 2,
189
+ ...theme === "academy" ? {} : { radius: 4 }
139
190
  },
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"
191
+ state: {
192
+ active: {
193
+ fillOpacity: 1,
194
+ stroke: tokens.separator,
195
+ lineWidth: 3
155
196
  }
156
- ]
157
- }
197
+ },
198
+ viewStyle: style.backgroundColor ? { viewFill: backgroundColor } : void 0
199
+ },
200
+ ...data.length > 1 ? [
201
+ {
202
+ type: "connector",
203
+ data: [
204
+ {
205
+ startX: isInverted ? data[data.length - 1].category : data[0].category,
206
+ startY: isInverted ? data[0].category : data[data.length - 1].category,
207
+ endX: 0,
208
+ endY: Math.abs(data[0].value - data[data.length - 1].value) / 2
209
+ }
210
+ ],
211
+ encode: { x: "startX", x1: "startY", y: "endX", y1: "endY" },
212
+ tooltip: false,
213
+ style: {
214
+ stroke: tokens.axisLine,
215
+ strokeOpacity: theme === "academy" ? 1 : 0.82,
216
+ lineWidth: theme === "academy" ? 1 : 0.75,
217
+ markerEnd: false,
218
+ connectLength1: -12
219
+ },
220
+ labels: [
221
+ {
222
+ text: formatMetricLabel(
223
+ overallConversionRateLabel,
224
+ formatConversionRate(data[0].value, data[data.length - 1].value),
225
+ chartLocale
226
+ ),
227
+ position: "left",
228
+ textAlign: "start",
229
+ textBaseline: "middle",
230
+ fill: tokens.textPrimary,
231
+ dx: 8,
232
+ style: {
233
+ fontFamily: import_util.CHART_FONT_FAMILY,
234
+ fontSize: 11,
235
+ fontWeight: 500
236
+ }
237
+ }
238
+ ]
239
+ }
240
+ ] : []
158
241
  ],
159
242
  axis: false,
160
- tooltip: {
161
- items: [
162
- (d) => ({
163
- name: d.category,
164
- value: d.value
165
- })
166
- ]
167
- },
168
- viewStyle: {
169
- viewFill: backgroundColor
243
+ interaction: {
244
+ tooltip: true,
245
+ elementHighlight: true
170
246
  },
171
- theme: (0, import_theme.getThemeObject)(theme)
247
+ viewStyle: style.backgroundColor ? { viewFill: backgroundColor } : void 0,
248
+ theme: (0, import_util.getThemeObject)(theme)
172
249
  };
173
250
  chart.options(chartOptions);
174
251
  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);
@@ -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;
@@ -23,7 +23,7 @@ __export(liquid_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(liquid_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 DEFAULT_WIDTH = 640;
28
28
  var DEFAULT_HEIGHT = 480;
29
29
  var Liquid = (options) => {
@@ -34,10 +34,18 @@ var Liquid = (options) => {
34
34
  if (chart) {
35
35
  chart.destroy();
36
36
  }
37
- const colors = (0, import_theme.normalizePalette)(style.palette, theme);
38
- const backgroundColor = style.backgroundColor || (0, import_theme.getBackgroundColor)(theme);
37
+ const colors = (0, import_util.normalizePalette)(style.palette, theme);
38
+ const backgroundColor = style.backgroundColor || (0, import_util.getBackgroundColor)(theme);
39
+ const tokens = (0, import_util.getChartVisualTokens)(theme);
40
+ const normalizedPercent = Number.isFinite(percent) ? Math.max(0, Math.min(1, percent)) : 0;
39
41
  const inferFontSize = Math.min(width ?? DEFAULT_WIDTH, height ?? DEFAULT_HEIGHT) / 10;
40
42
  const fontSize = Math.min(Math.max(inferFontSize, 24), 64);
43
+ const chartSize = Math.min(width ?? DEFAULT_WIDTH, height ?? DEFAULT_HEIGHT);
44
+ const waveLength = Math.min(Math.max(chartSize * 0.4, 96), 192);
45
+ const formattedPercent = `${Number((normalizedPercent * 100).toFixed(1))}%`;
46
+ const liquidColor = colors[0];
47
+ const isAcademy = theme === "academy";
48
+ const outlineShadowColor = theme === "dark" ? "rgba(0, 0, 0, 0.32)" : "rgba(15, 23, 42, 0.10)";
41
49
  chart = new import_g2.Chart({
42
50
  container,
43
51
  width,
@@ -47,25 +55,42 @@ var Liquid = (options) => {
47
55
  const chartOptions = {
48
56
  animate: false,
49
57
  type: "liquid",
50
- data: percent,
51
- title: title ?? "",
58
+ data: normalizedPercent,
59
+ title: title || "",
60
+ inset: 20,
52
61
  style: {
53
62
  shape,
63
+ contentText: formattedPercent,
54
64
  contentFontSize: fontSize,
55
- contentFill: "#000",
56
- contentStroke: "#fff",
57
- contentLineWidth: 2,
58
- outlineBorder: 4,
59
- outlineDistance: 4,
60
- waveLength: 128,
65
+ contentFill: tokens.textPrimary,
66
+ contentStroke: backgroundColor,
67
+ contentStrokeOpacity: 0.92,
68
+ contentLineWidth: theme === "dark" ? 3 : 2.5,
69
+ contentFontFamily: import_util.CHART_FONT_FAMILY,
70
+ contentFontWeight: 600,
71
+ contentLetterSpacing: -0.8,
72
+ contentFontVariantNumeric: "tabular-nums",
73
+ contentPaintOrder: "stroke",
74
+ backgroundFill: liquidColor,
75
+ backgroundFillOpacity: theme === "dark" ? 0.14 : isAcademy ? 0.06 : 0.08,
76
+ backgroundStroke: liquidColor,
77
+ backgroundStrokeOpacity: theme === "dark" ? 0.3 : 0.22,
78
+ backgroundLineWidth: 1,
79
+ outlineBorder: isAcademy ? 1.5 : 2,
80
+ outlineDistance: 0,
81
+ outlineStrokeOpacity: isAcademy ? 0.9 : 0.72,
82
+ outlineShadowColor: isAcademy ? "transparent" : outlineShadowColor,
83
+ outlineShadowBlur: isAcademy ? 0 : 6,
84
+ outlineShadowOffsetY: isAcademy ? 0 : 2,
85
+ waveLength,
86
+ waveCount: 2,
87
+ fillOpacity: isAcademy ? 0.9 : 0.88,
61
88
  contentPointerEvents: "none",
62
89
  // Use palette color if provided
63
- ...colors[0] ? { fill: colors[0], outlineStroke: colors[0] } : {}
90
+ ...liquidColor ? { fill: liquidColor, outlineStroke: liquidColor } : {}
64
91
  },
65
- viewStyle: {
66
- viewFill: backgroundColor
67
- },
68
- theme: (0, import_theme.getThemeObject)(theme),
92
+ viewStyle: style.backgroundColor ? { viewFill: backgroundColor } : void 0,
93
+ theme: (0, import_util.getThemeObject)(theme),
69
94
  tooltip: false
70
95
  };
71
96
  chart.options(chartOptions);
@@ -1,4 +1,4 @@
1
- import type { VisualizationOptions } from '../../types';
1
+ import type { VisualizationOptions, VisualizationTheme } from '../../types';
2
2
  /**
3
3
  * PieDataItem is the type for each data item in the pie chart.
4
4
  */
@@ -13,7 +13,7 @@ export interface PieConfig {
13
13
  type?: 'pie';
14
14
  data: PieDataItem[];
15
15
  innerRadius?: number;
16
- theme?: 'default' | 'academy' | 'dark';
16
+ theme?: VisualizationTheme;
17
17
  title?: string;
18
18
  style?: {
19
19
  backgroundColor?: string;