@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
@@ -11,7 +11,7 @@ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symb
11
11
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
12
12
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
13
13
  import { Chart } from '@antv/g2';
14
- import { getBackgroundColor, getThemeObject, normalizePalette } from "../../util/theme";
14
+ import { CHART_STYLE_DEFAULTS, bindCrosshairAxisLabels, getCartesianAxis, getCartesianLayout, getChartAnimation, getLineHighlightState, getSeriesHighlightByColorInteraction, getSharedTooltipInteraction, getThemeObject, normalizePalette } from "../../util";
15
15
 
16
16
  /**
17
17
  * DualAxesSeriesItem defines a single series in the dual-axes chart.
@@ -29,14 +29,16 @@ import { getBackgroundColor, getThemeObject, normalizePalette } from "../../util
29
29
  * Transform series data to G2 format.
30
30
  * Combines multiple series into a single data array with categories.
31
31
  */
32
+ var getSeriesField = function getSeriesField(index) {
33
+ return "value_".concat(index + 1);
34
+ };
32
35
  function transformData(series, categories) {
33
36
  return categories.map(function (category, index) {
34
37
  var dataPoint = {
35
38
  category: category
36
39
  };
37
- series.forEach(function (s, i) {
38
- var yField = s.axisYTitle || "value_".concat(i + 1);
39
- dataPoint[yField] = s.data[index];
40
+ series.forEach(function (item, seriesIndex) {
41
+ dataPoint[getSeriesField(seriesIndex)] = item.data[index];
40
42
  });
41
43
  return dataPoint;
42
44
  });
@@ -80,6 +82,8 @@ export var DualAxes = function DualAxes(options) {
80
82
  _options$theme = options.theme,
81
83
  chartTheme = _options$theme === void 0 ? 'default' : _options$theme;
82
84
  var chart = null;
85
+ var hasRendered = false;
86
+ var cleanupCrosshairAxisLabels = null;
83
87
 
84
88
  /**
85
89
  * Render the dual-axes chart with the given configuration.
@@ -96,12 +100,18 @@ export var DualAxes = function DualAxes(options) {
96
100
 
97
101
  // Clean up previous chart if exists
98
102
  if (chart) {
103
+ var _cleanupCrosshairAxis;
104
+ (_cleanupCrosshairAxis = cleanupCrosshairAxisLabels) === null || _cleanupCrosshairAxis === void 0 || _cleanupCrosshairAxis();
105
+ cleanupCrosshairAxisLabels = null;
99
106
  chart.destroy();
100
107
  }
101
108
  var _style$startAtZero = style.startAtZero,
102
109
  startAtZero = _style$startAtZero === void 0 ? false : _style$startAtZero;
103
- var colors = normalizePalette(style.palette, theme);
104
- var backgroundColor = style.backgroundColor || getBackgroundColor(theme);
110
+ var requestedColors = style.palette ? normalizePalette(style.palette, theme) : [];
111
+ var defaultColors = normalizePalette(undefined, theme);
112
+ var colors = [].concat(_toConsumableArray(requestedColors), _toConsumableArray(defaultColors.filter(function (color) {
113
+ return !requestedColors.includes(color);
114
+ })));
105
115
 
106
116
  // Transform data
107
117
  var data = transformData(series, categories);
@@ -115,15 +125,55 @@ export var DualAxes = function DualAxes(options) {
115
125
  });
116
126
 
117
127
  // Sort series: column first, then line (line rendered last appears on top)
118
- var sortedSeries = _toConsumableArray(series).sort(function (a, b) {
128
+ var sortedSeries = series.map(function (item, originalIndex) {
129
+ return {
130
+ item: item,
131
+ originalIndex: originalIndex
132
+ };
133
+ }).sort(function (a, b) {
119
134
  var order = ['column', 'line'];
120
- return order.indexOf(a.type) - order.indexOf(b.type);
135
+ return order.indexOf(a.item.type) - order.indexOf(b.item.type);
121
136
  });
137
+ var seriesMeta = sortedSeries.map(function (_ref, index) {
138
+ var item = _ref.item,
139
+ originalIndex = _ref.originalIndex;
140
+ return {
141
+ item: item,
142
+ yField: getSeriesField(originalIndex),
143
+ displayName: item.axisYTitle || getSeriesField(originalIndex),
144
+ color: colors[index % colors.length]
145
+ };
146
+ });
147
+ var seriesByField = new Map(seriesMeta.map(function (_ref2) {
148
+ var item = _ref2.item,
149
+ yField = _ref2.yField,
150
+ displayName = _ref2.displayName;
151
+ return [yField, {
152
+ type: item.type,
153
+ displayName: displayName
154
+ }];
155
+ }));
156
+ var cartesianAxisOptions = {
157
+ axisXTitle: axisXTitle,
158
+ xLabels: categories,
159
+ chartWidth: width
160
+ };
161
+ var cartesianAxis = getCartesianAxis(cartesianAxisOptions);
122
162
 
123
163
  // Create children configurations for each series
124
- var children = sortedSeries.map(function (item, index) {
125
- var yField = item.axisYTitle || "value_".concat(index + 1);
126
- var color = colors[index % colors.length];
164
+ var children = seriesMeta.map(function (_ref3) {
165
+ var item = _ref3.item,
166
+ yField = _ref3.yField,
167
+ displayName = _ref3.displayName,
168
+ color = _ref3.color;
169
+ var tooltip = {
170
+ items: [function (datum) {
171
+ return {
172
+ name: displayName,
173
+ value: datum[yField]
174
+ };
175
+ }]
176
+ };
127
177
  if (item.type === 'column') {
128
178
  return {
129
179
  type: 'interval',
@@ -138,22 +188,25 @@ export var DualAxes = function DualAxes(options) {
138
188
  y: {
139
189
  nice: true,
140
190
  zero: startAtZero
141
- },
142
- color: {
143
- range: [color]
144
191
  }
145
192
  },
193
+ tooltip: tooltip,
146
194
  axis: {
147
- y: {
148
- title: item.axisYTitle || ''
149
- }
195
+ y: _objectSpread(_objectSpread({}, cartesianAxis.y), {}, {
196
+ title: item.axisYTitle || '',
197
+ titleFill: color,
198
+ titleFontWeight: 500
199
+ })
150
200
  },
151
201
  style: _objectSpread({
152
- columnWidthRatio: 0.8
202
+ fill: color,
203
+ fillOpacity: 0.86,
204
+ columnWidthRatio: CHART_STYLE_DEFAULTS.intervalWidthRatio
153
205
  }, theme !== 'academy' ? {
154
206
  radiusTopLeft: 4,
155
207
  radiusTopRight: 4
156
- } : {})
208
+ } : {}),
209
+ animate: getChartAnimation(hasRendered, 'growInY')
157
210
  };
158
211
  } else {
159
212
  // line type
@@ -171,20 +224,26 @@ export var DualAxes = function DualAxes(options) {
171
224
  y: {
172
225
  independent: true,
173
226
  zero: startAtZero
174
- },
175
- color: {
176
- range: [color]
177
227
  }
178
228
  },
229
+ tooltip: tooltip,
179
230
  axis: {
180
- y: {
231
+ y: _objectSpread(_objectSpread({}, cartesianAxis.y), {}, {
181
232
  position: 'right',
182
- title: item.axisYTitle || ''
183
- }
233
+ title: item.axisYTitle || '',
234
+ titleFill: color,
235
+ titleFontWeight: 500,
236
+ grid: false
237
+ })
184
238
  },
185
239
  style: {
186
- lineWidth: 2
187
- }
240
+ stroke: color,
241
+ lineWidth: CHART_STYLE_DEFAULTS.lineWidth,
242
+ lineCap: 'round',
243
+ lineJoin: 'round'
244
+ },
245
+ state: getLineHighlightState(CHART_STYLE_DEFAULTS.lineWidth),
246
+ animate: getChartAnimation(hasRendered, 'pathIn')
188
247
  };
189
248
  }
190
249
  });
@@ -192,38 +251,78 @@ export var DualAxes = function DualAxes(options) {
192
251
  // Configure chart options
193
252
  // Note: Using 'any' type due to G2's complex type system with transformations
194
253
  // This is consistent with how G2 5.0 is used elsewhere in the codebase
195
- var chartOptions = {
196
- animate: false,
254
+ var chartOptions = _objectSpread(_objectSpread({
197
255
  type: 'view',
198
256
  data: data,
199
- title: title !== null && title !== void 0 ? title : '',
200
- children: children,
257
+ title: title || '',
258
+ children: children
259
+ }, getCartesianLayout(cartesianAxisOptions)), {}, {
201
260
  axis: {
202
- x: {
203
- title: axisXTitle || false
204
- }
261
+ x: cartesianAxis.x
205
262
  },
206
263
  scale: {
207
264
  y: {
208
265
  nice: true
266
+ },
267
+ color: {
268
+ domain: seriesMeta.map(function (_ref4) {
269
+ var yField = _ref4.yField;
270
+ return yField;
271
+ }),
272
+ range: seriesMeta.map(function (_ref5) {
273
+ var color = _ref5.color;
274
+ return color;
275
+ })
209
276
  }
210
277
  },
211
278
  legend: {
212
279
  color: {
213
- position: 'top',
214
- itemMarker: function itemMarker(v, index) {
215
- var seriesItem = series[index];
216
- return (seriesItem === null || seriesItem === void 0 ? void 0 : seriesItem.type) === 'line' ? 'smooth' : 'rect';
280
+ labelFormatter: function labelFormatter(value) {
281
+ var _seriesByField$get;
282
+ return ((_seriesByField$get = seriesByField.get(value)) === null || _seriesByField$get === void 0 ? void 0 : _seriesByField$get.displayName) || value;
283
+ },
284
+ itemMarker: function itemMarker(value) {
285
+ var _seriesByField$get2;
286
+ return ((_seriesByField$get2 = seriesByField.get(value)) === null || _seriesByField$get2 === void 0 ? void 0 : _seriesByField$get2.type) === 'line' ? 'smooth' : 'rect';
217
287
  }
218
288
  }
219
289
  },
220
- viewStyle: {
221
- viewFill: backgroundColor
222
- },
290
+ interaction: _objectSpread({
291
+ tooltip: getSharedTooltipInteraction({
292
+ crosshairs: true
293
+ })
294
+ }, getSeriesHighlightByColorInteraction()),
295
+ viewStyle: style.backgroundColor ? {
296
+ viewFill: style.backgroundColor
297
+ } : undefined,
223
298
  theme: getThemeObject(theme)
224
- };
299
+ });
225
300
  chart.options(chartOptions);
301
+ var lineYFields = seriesMeta.filter(function (_ref6) {
302
+ var item = _ref6.item;
303
+ return item.type === 'line';
304
+ }).map(function (_ref7) {
305
+ var yField = _ref7.yField;
306
+ return yField;
307
+ });
308
+ if (lineYFields.length) {
309
+ var currentChart = chart;
310
+ var cleanups = lineYFields.map(function (yField, index) {
311
+ return bindCrosshairAxisLabels(currentChart, theme, {
312
+ showXLabel: index === 0,
313
+ useStandaloneYLabel: true,
314
+ yAxisPosition: 'right',
315
+ yField: yField
316
+ });
317
+ });
318
+ cleanupCrosshairAxisLabels = function cleanupCrosshairAxisLabels() {
319
+ return cleanups.forEach(function (cleanup) {
320
+ return cleanup();
321
+ });
322
+ };
323
+ }
226
324
  chart.render();
325
+ hasRendered = true;
227
326
  };
228
327
 
229
328
  /**
@@ -231,9 +330,13 @@ export var DualAxes = function DualAxes(options) {
231
330
  */
232
331
  var destroy = function destroy() {
233
332
  if (chart) {
333
+ var _cleanupCrosshairAxis2;
334
+ (_cleanupCrosshairAxis2 = cleanupCrosshairAxisLabels) === null || _cleanupCrosshairAxis2 === void 0 || _cleanupCrosshairAxis2();
335
+ cleanupCrosshairAxisLabels = null;
234
336
  chart.destroy();
235
337
  chart = null;
236
338
  }
339
+ hasRendered = false;
237
340
  };
238
341
  return {
239
342
  render: render,
@@ -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[];
@@ -1,5 +1,17 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
8
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
9
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
10
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
11
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
12
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
1
13
  import { Chart } from '@antv/g2';
2
- import { getBackgroundColor, getThemeObject, normalizePalette } from "../../util/theme";
14
+ import { CHART_FONT_FAMILY, getBackgroundColor, getChartVisualTokens, getThemeObject, normalizePalette, resolveChartLocale } from "../../util";
3
15
 
4
16
  /**
5
17
  * FunnelDataItem is the type for each data item in the funnel chart.
@@ -13,6 +25,32 @@ import { getBackgroundColor, getThemeObject, normalizePalette } from "../../util
13
25
  * FunnelInstance represents a funnel chart instance with render and destroy methods.
14
26
  */
15
27
 
28
+ var FUNNEL_LABELS = {
29
+ 'en-US': {
30
+ baseline: 'Baseline',
31
+ conversionRate: 'Conversion Rate',
32
+ currentValue: 'Current value',
33
+ dropOff: 'Drop-off from previous',
34
+ overallConversionRate: 'Overall conversion',
35
+ stageConversion: 'Stage conversion'
36
+ },
37
+ 'zh-CN': {
38
+ baseline: '基准',
39
+ conversionRate: '转化率',
40
+ currentValue: '当前值',
41
+ dropOff: '较上一步流失',
42
+ overallConversionRate: '整体转化率',
43
+ stageConversion: '阶段转化率'
44
+ }
45
+ };
46
+ var formatConversionRate = function formatConversionRate(start, end) {
47
+ if (!Number.isFinite(start) || !Number.isFinite(end) || start === 0) return '—';
48
+ return "".concat((end / start * 100).toFixed(1), "%");
49
+ };
50
+ var formatMetricLabel = function formatMetricLabel(label, value, locale) {
51
+ return locale === 'zh-CN' ? "".concat(label, "\uFF1A").concat(value) : "".concat(label, ": ").concat(value);
52
+ };
53
+
16
54
  /**
17
55
  * Funnel chart component using G2 5.0.
18
56
  *
@@ -42,6 +80,7 @@ export var Funnel = function Funnel(options) {
42
80
  var container = options.container,
43
81
  width = options.width,
44
82
  height = options.height,
83
+ locale = options.locale,
45
84
  _options$theme = options.theme,
46
85
  chartTheme = _options$theme === void 0 ? 'default' : _options$theme;
47
86
  var chart = null;
@@ -50,14 +89,19 @@ export var Funnel = function Funnel(options) {
50
89
  * Render the funnel chart with the given configuration.
51
90
  */
52
91
  var render = function render(config) {
53
- var _data$, _data, _data$2, _data2, _data$3, _data3;
54
92
  var _config$data = config.data,
55
93
  data = _config$data === void 0 ? [] : _config$data,
56
94
  _config$theme = config.theme,
57
95
  theme = _config$theme === void 0 ? chartTheme : _config$theme,
58
96
  title = config.title,
97
+ conversionRateLabel = config.conversionRateLabel,
59
98
  _config$style = config.style,
60
99
  style = _config$style === void 0 ? {} : _config$style;
100
+ var chartLocale = resolveChartLocale(locale);
101
+ var labels = FUNNEL_LABELS[chartLocale];
102
+ var numberFormatter = new Intl.NumberFormat(chartLocale);
103
+ var stageConversionRateLabel = conversionRateLabel !== null && conversionRateLabel !== void 0 ? conversionRateLabel : labels.conversionRate;
104
+ var overallConversionRateLabel = conversionRateLabel !== null && conversionRateLabel !== void 0 ? conversionRateLabel : labels.overallConversionRate;
61
105
 
62
106
  // Clean up previous chart if exists
63
107
  if (chart) {
@@ -67,10 +111,38 @@ export var Funnel = function Funnel(options) {
67
111
  // Get colors from style.palette or theme defaults
68
112
  var colors = normalizePalette(style.palette, theme);
69
113
  var backgroundColor = style.backgroundColor || getBackgroundColor(theme);
70
-
71
- // Helper function to calculate conversion rate
72
- var conversionRate = function conversionRate(start, end) {
73
- return "".concat((end / start * 100).toFixed(2), " %");
114
+ var tokens = getChartVisualTokens(theme);
115
+ var formatValue = function formatValue(value) {
116
+ return Number.isFinite(value) ? numberFormatter.format(value) : '—';
117
+ };
118
+ var isInverted = data.length > 1 && data[0].value < data[data.length - 1].value;
119
+ var metricsByCategory = new Map(data.map(function (item, index) {
120
+ var previous = data[index - 1];
121
+ return [item.category, {
122
+ conversion: previous ? formatConversionRate(previous.value, item.value) : labels.baseline,
123
+ dropOff: previous ? Math.max(0, previous.value - item.value) : null
124
+ }];
125
+ }));
126
+ var funnelTooltip = {
127
+ title: 'category',
128
+ items: [function (d) {
129
+ return {
130
+ name: labels.currentValue,
131
+ value: formatValue(d.value)
132
+ };
133
+ }, function (d) {
134
+ var _metricsByCategory$ge, _metricsByCategory$ge2;
135
+ return {
136
+ name: labels.stageConversion,
137
+ value: (_metricsByCategory$ge = (_metricsByCategory$ge2 = metricsByCategory.get(d.category)) === null || _metricsByCategory$ge2 === void 0 ? void 0 : _metricsByCategory$ge2.conversion) !== null && _metricsByCategory$ge !== void 0 ? _metricsByCategory$ge : '—'
138
+ };
139
+ }, function (d) {
140
+ var _metricsByCategory$ge3, _metricsByCategory$ge4, _metricsByCategory$ge5;
141
+ return {
142
+ name: labels.dropOff,
143
+ value: ((_metricsByCategory$ge3 = metricsByCategory.get(d.category)) === null || _metricsByCategory$ge3 === void 0 ? void 0 : _metricsByCategory$ge3.dropOff) === null ? '—' : formatValue((_metricsByCategory$ge4 = (_metricsByCategory$ge5 = metricsByCategory.get(d.category)) === null || _metricsByCategory$ge5 === void 0 ? void 0 : _metricsByCategory$ge5.dropOff) !== null && _metricsByCategory$ge4 !== void 0 ? _metricsByCategory$ge4 : Number.NaN)
144
+ };
145
+ }]
74
146
  };
75
147
 
76
148
  // Create chart
@@ -79,8 +151,8 @@ export var Funnel = function Funnel(options) {
79
151
  width: width,
80
152
  height: height,
81
153
  autoFit: true,
82
- paddingLeft: 40,
83
- paddingRight: 68
154
+ paddingLeft: 56,
155
+ paddingRight: 118
84
156
  });
85
157
 
86
158
  // Configure chart options
@@ -90,7 +162,7 @@ export var Funnel = function Funnel(options) {
90
162
  animate: false,
91
163
  type: 'view',
92
164
  data: data,
93
- title: title !== null && title !== void 0 ? title : '',
165
+ title: title || '',
94
166
  children: [{
95
167
  type: 'interval',
96
168
  data: data,
@@ -116,73 +188,80 @@ export var Funnel = function Funnel(options) {
116
188
  range: colors
117
189
  }
118
190
  },
119
- legend: {
120
- color: {
121
- position: 'top',
122
- layout: {
123
- justifyContent: 'center'
124
- }
125
- }
126
- },
127
- labels: [
128
- // Inside label showing category and value
129
- {
191
+ legend: false,
192
+ tooltip: funnelTooltip,
193
+ labels: [{
130
194
  text: function text(d) {
131
- return "".concat(d.category, "\n").concat(d.value);
195
+ return "".concat(d.category, "\n").concat(formatValue(d.value));
132
196
  },
133
197
  position: 'inside',
134
198
  transform: [{
135
199
  type: 'contrastReverse'
136
- }]
137
- },
138
- // Connecting line for conversion rate
139
- {
140
- text: function text(d, i) {
141
- return i !== 0 ? '———' : '';
142
- },
200
+ }, {
201
+ type: 'overflowStroke'
202
+ }],
143
203
  style: {
144
- 'font-size': '1px',
145
- color: '#666',
146
- 'letter-spacing': '0px'
147
- },
148
- position: 'top-right',
149
- fill: '#666',
150
- dx: 35,
151
- dy: -8
152
- },
153
- // Conversion rate label text
154
- {
155
- text: function text(d, i) {
156
- return i !== 0 ? '转化率' : '';
204
+ fontFamily: CHART_FONT_FAMILY,
205
+ fontSize: 12,
206
+ fontWeight: 500,
207
+ lineHeight: 17
208
+ }
209
+ }, {
210
+ text: function text(_d, index, items) {
211
+ return (isInverted ? index < items.length - 1 : index > 0) ? '———' : '';
157
212
  },
158
- position: 'top-right',
159
- textAlign: 'left',
160
- textBaseline: 'middle',
161
- fill: '#666',
162
- dx: 40
163
- },
164
- // Conversion rate percentage
165
- {
166
- text: function text(d, i, dataArray) {
167
- return i !== 0 ? conversionRate(dataArray[i - 1].value, dataArray[i].value) : '';
213
+ position: isInverted ? 'bottom-right' : 'top-right',
214
+ fill: tokens.textSecondary,
215
+ fillOpacity: 0.72,
216
+ dx: 8,
217
+ dy: isInverted ? 6 : -6,
218
+ style: {
219
+ fontFamily: CHART_FONT_FAMILY,
220
+ fontSize: 8,
221
+ fontWeight: 400,
222
+ letterSpacing: -2
223
+ }
224
+ }, {
225
+ text: function text(_d, index, items) {
226
+ var from = isInverted ? items[index] : items[index - 1];
227
+ var to = isInverted ? items[index + 1] : items[index];
228
+ return from && to ? formatMetricLabel(stageConversionRateLabel, formatConversionRate(from.value, to.value), chartLocale) : '';
168
229
  },
169
- position: 'top-right',
230
+ position: isInverted ? 'bottom-right' : 'top-right',
170
231
  textAlign: 'left',
171
232
  textBaseline: 'middle',
172
- dx: 80
233
+ fill: tokens.textPrimary,
234
+ dx: 26,
235
+ style: {
236
+ fontFamily: CHART_FONT_FAMILY,
237
+ fontSize: 11,
238
+ fontWeight: 500
239
+ }
173
240
  }],
174
- viewStyle: {
241
+ style: _objectSpread({
242
+ fillOpacity: 0.94,
243
+ stroke: tokens.separator,
244
+ lineWidth: 2
245
+ }, theme === 'academy' ? {} : {
246
+ radius: 4
247
+ }),
248
+ state: {
249
+ active: {
250
+ fillOpacity: 1,
251
+ stroke: tokens.separator,
252
+ lineWidth: 3
253
+ }
254
+ },
255
+ viewStyle: style.backgroundColor ? {
175
256
  viewFill: backgroundColor
176
- }
177
- },
178
- // Overall conversion rate connector
179
- {
257
+ } : undefined
258
+ }].concat(_toConsumableArray(data.length > 1 ? [{
180
259
  type: 'connector',
181
260
  data: [{
182
- startX: (_data$ = data[0]) === null || _data$ === void 0 ? void 0 : _data$.category,
183
- startY: (_data = data[data.length - 1]) === null || _data === void 0 ? void 0 : _data.category,
261
+ startX: isInverted ? data[data.length - 1].category : data[0].category,
262
+ startY: isInverted ? data[0].category : data[data.length - 1].category,
184
263
  endX: 0,
185
- endY: (((_data$2 = data[0]) === null || _data$2 === void 0 ? void 0 : _data$2.value) - ((_data2 = data[data.length - 1]) === null || _data2 === void 0 ? void 0 : _data2.value)) / 2
264
+ endY: Math.abs(data[0].value - data[data.length - 1].value) / 2
186
265
  }],
187
266
  encode: {
188
267
  x: 'startX',
@@ -190,41 +269,36 @@ export var Funnel = function Funnel(options) {
190
269
  y: 'endX',
191
270
  y1: 'endY'
192
271
  },
272
+ tooltip: false,
193
273
  style: {
194
- stroke: '#666',
274
+ stroke: tokens.axisLine,
275
+ strokeOpacity: theme === 'academy' ? 1 : 0.82,
276
+ lineWidth: theme === 'academy' ? 1 : 0.75,
195
277
  markerEnd: false,
196
- connectLength1: -12,
197
- offset2: -20,
198
- connectorStroke: '#0649f2',
199
- lineDash: [12, 2]
278
+ connectLength1: -12
200
279
  },
201
280
  labels: [{
202
- text: '转化率',
281
+ text: formatMetricLabel(overallConversionRateLabel, formatConversionRate(data[0].value, data[data.length - 1].value), chartLocale),
203
282
  position: 'left',
204
283
  textAlign: 'start',
205
284
  textBaseline: 'middle',
206
- fill: '#666',
207
- dx: 10
208
- }, {
209
- text: conversionRate((_data$3 = data[0]) === null || _data$3 === void 0 ? void 0 : _data$3.value, (_data3 = data[data.length - 1]) === null || _data3 === void 0 ? void 0 : _data3.value),
210
- position: 'left',
211
- textAlign: 'start',
212
- dx: 50,
213
- fill: '#000'
285
+ fill: tokens.textPrimary,
286
+ dx: 8,
287
+ style: {
288
+ fontFamily: CHART_FONT_FAMILY,
289
+ fontSize: 11,
290
+ fontWeight: 500
291
+ }
214
292
  }]
215
- }],
293
+ }] : [])),
216
294
  axis: false,
217
- tooltip: {
218
- items: [function (d) {
219
- return {
220
- name: d.category,
221
- value: d.value
222
- };
223
- }]
295
+ interaction: {
296
+ tooltip: true,
297
+ elementHighlight: true
224
298
  },
225
- viewStyle: {
299
+ viewStyle: style.backgroundColor ? {
226
300
  viewFill: backgroundColor
227
- },
301
+ } : undefined,
228
302
  theme: getThemeObject(theme)
229
303
  };
230
304
  chart.options(chartOptions);
@@ -1,5 +1,5 @@
1
1
  import { Chart } from '@antv/g2';
2
- import { getBackgroundColor, getThemeObject, normalizePalette } from "../../util/theme";
2
+ import { getThemeObject, normalizePalette } from "../../util/theme";
3
3
 
4
4
  /**
5
5
  * HistogramConfig defines the configuration for rendering the histogram chart.
@@ -61,7 +61,6 @@ export var Histogram = function Histogram(options) {
61
61
 
62
62
  // Get colors from style.palette or theme defaults
63
63
  var colors = normalizePalette(style.palette, theme);
64
- var backgroundColor = style.backgroundColor || getBackgroundColor(theme);
65
64
 
66
65
  // Create chart
67
66
  chart = new Chart({
@@ -122,9 +121,9 @@ export var Histogram = function Histogram(options) {
122
121
  name: '频数'
123
122
  }]
124
123
  },
125
- viewStyle: {
126
- viewFill: backgroundColor
127
- },
124
+ viewStyle: style.backgroundColor ? {
125
+ viewFill: style.backgroundColor
126
+ } : undefined,
128
127
  theme: getThemeObject(theme)
129
128
  };
130
129
  chart.options(chartOptions);