@antv/infographic 0.2.17 → 0.2.19

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 (97) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/infographic.min.js +110 -110
  4. package/dist/infographic.min.js.map +1 -1
  5. package/esm/constants/service.d.ts +1 -1
  6. package/esm/constants/service.js +1 -1
  7. package/esm/designs/structures/chart-line.js +5 -3
  8. package/esm/editor/interactions/dblclick-edit-text.js +3 -3
  9. package/esm/editor/managers/interaction.js +6 -4
  10. package/esm/editor/plugins/components/button.d.ts +2 -1
  11. package/esm/editor/plugins/components/button.js +4 -4
  12. package/esm/editor/plugins/components/color-picker.d.ts +1 -0
  13. package/esm/editor/plugins/components/color-picker.js +3 -3
  14. package/esm/editor/plugins/components/popover.d.ts +3 -1
  15. package/esm/editor/plugins/components/popover.js +29 -9
  16. package/esm/editor/plugins/edit-bar/edit-bar.d.ts +3 -1
  17. package/esm/editor/plugins/edit-bar/edit-bar.js +17 -7
  18. package/esm/editor/plugins/edit-bar/edit-items/align-elements.js +6 -4
  19. package/esm/editor/plugins/edit-bar/edit-items/font-align.js +8 -5
  20. package/esm/editor/plugins/edit-bar/edit-items/font-color.js +7 -4
  21. package/esm/editor/plugins/edit-bar/edit-items/font-family.js +11 -9
  22. package/esm/editor/plugins/edit-bar/edit-items/font-size.js +8 -5
  23. package/esm/editor/plugins/edit-bar/edit-items/icon-color.js +7 -4
  24. package/esm/editor/plugins/edit-bar/edit-items/types.d.ts +5 -1
  25. package/esm/editor/plugins/reset-viewbox.d.ts +4 -1
  26. package/esm/editor/plugins/reset-viewbox.js +12 -6
  27. package/esm/editor/utils/index.d.ts +1 -0
  28. package/esm/editor/utils/index.js +1 -0
  29. package/esm/editor/utils/root.d.ts +3 -0
  30. package/esm/editor/utils/root.js +18 -0
  31. package/esm/exporter/svg.js +192 -52
  32. package/esm/resource/loaders/search.js +0 -3
  33. package/esm/templates/utils.js +11 -6
  34. package/esm/utils/padding.js +1 -1
  35. package/esm/utils/style.d.ts +3 -1
  36. package/esm/utils/style.js +27 -4
  37. package/esm/version.d.ts +1 -1
  38. package/esm/version.js +1 -1
  39. package/lib/constants/service.d.ts +1 -1
  40. package/lib/constants/service.js +1 -1
  41. package/lib/designs/structures/chart-line.js +5 -3
  42. package/lib/editor/interactions/dblclick-edit-text.js +3 -3
  43. package/lib/editor/managers/interaction.js +7 -5
  44. package/lib/editor/plugins/components/button.d.ts +2 -1
  45. package/lib/editor/plugins/components/button.js +4 -4
  46. package/lib/editor/plugins/components/color-picker.d.ts +1 -0
  47. package/lib/editor/plugins/components/color-picker.js +3 -3
  48. package/lib/editor/plugins/components/popover.d.ts +3 -1
  49. package/lib/editor/plugins/components/popover.js +32 -12
  50. package/lib/editor/plugins/edit-bar/edit-bar.d.ts +3 -1
  51. package/lib/editor/plugins/edit-bar/edit-bar.js +17 -7
  52. package/lib/editor/plugins/edit-bar/edit-items/align-elements.js +6 -4
  53. package/lib/editor/plugins/edit-bar/edit-items/font-align.js +8 -5
  54. package/lib/editor/plugins/edit-bar/edit-items/font-color.js +7 -4
  55. package/lib/editor/plugins/edit-bar/edit-items/font-family.js +11 -9
  56. package/lib/editor/plugins/edit-bar/edit-items/font-size.js +8 -5
  57. package/lib/editor/plugins/edit-bar/edit-items/icon-color.js +7 -4
  58. package/lib/editor/plugins/edit-bar/edit-items/types.d.ts +5 -1
  59. package/lib/editor/plugins/reset-viewbox.d.ts +4 -1
  60. package/lib/editor/plugins/reset-viewbox.js +12 -6
  61. package/lib/editor/utils/index.d.ts +1 -0
  62. package/lib/editor/utils/index.js +1 -0
  63. package/lib/editor/utils/root.d.ts +3 -0
  64. package/lib/editor/utils/root.js +22 -0
  65. package/lib/exporter/svg.js +192 -52
  66. package/lib/resource/loaders/search.js +0 -3
  67. package/lib/templates/utils.js +11 -6
  68. package/lib/utils/padding.js +1 -1
  69. package/lib/utils/style.d.ts +3 -1
  70. package/lib/utils/style.js +27 -4
  71. package/lib/version.d.ts +1 -1
  72. package/lib/version.js +1 -1
  73. package/package.json +1 -1
  74. package/src/constants/service.ts +1 -1
  75. package/src/designs/structures/chart-line.tsx +5 -3
  76. package/src/editor/interactions/dblclick-edit-text.ts +3 -2
  77. package/src/editor/managers/interaction.ts +9 -7
  78. package/src/editor/plugins/components/button.ts +5 -2
  79. package/src/editor/plugins/components/color-picker.ts +4 -2
  80. package/src/editor/plugins/components/popover.ts +31 -12
  81. package/src/editor/plugins/edit-bar/edit-bar.ts +26 -11
  82. package/src/editor/plugins/edit-bar/edit-items/align-elements.ts +7 -2
  83. package/src/editor/plugins/edit-bar/edit-items/font-align.ts +8 -3
  84. package/src/editor/plugins/edit-bar/edit-items/font-color.ts +7 -2
  85. package/src/editor/plugins/edit-bar/edit-items/font-family.ts +11 -7
  86. package/src/editor/plugins/edit-bar/edit-items/font-size.ts +8 -3
  87. package/src/editor/plugins/edit-bar/edit-items/icon-color.ts +7 -2
  88. package/src/editor/plugins/edit-bar/edit-items/types.ts +6 -1
  89. package/src/editor/plugins/reset-viewbox.ts +17 -8
  90. package/src/editor/utils/index.ts +1 -0
  91. package/src/editor/utils/root.ts +26 -0
  92. package/src/exporter/svg.ts +267 -62
  93. package/src/resource/loaders/search.ts +0 -3
  94. package/src/templates/utils.ts +30 -6
  95. package/src/utils/padding.ts +1 -1
  96. package/src/utils/style.ts +31 -4
  97. package/src/version.ts +1 -1
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOverlayContainer = getOverlayContainer;
4
+ exports.eventPathContains = eventPathContains;
5
+ function getConnectedRoot(node) {
6
+ if (!(node === null || node === void 0 ? void 0 : node.isConnected))
7
+ return document;
8
+ const root = node.getRootNode();
9
+ return root instanceof ShadowRoot ? root : document;
10
+ }
11
+ function getOverlayContainer(node) {
12
+ const root = getConnectedRoot(node);
13
+ return root instanceof ShadowRoot ? root : document.body;
14
+ }
15
+ function eventPathContains(event, node) {
16
+ const path = typeof event.composedPath === 'function' ? event.composedPath() : [];
17
+ if (path.length > 0) {
18
+ return path.some((current) => current === node || (current instanceof Node && node.contains(current)));
19
+ }
20
+ const target = event.target;
21
+ return target instanceof Node && (target === node || node.contains(target));
22
+ }
@@ -26,7 +26,10 @@ function getExportViewBox(svg) {
26
26
  return (0, utils_1.getViewBox)(svg);
27
27
  const width = parseAbsoluteLength(svg.getAttribute('width'));
28
28
  const height = parseAbsoluteLength(svg.getAttribute('height'));
29
- if (width > 0 && height > 0) {
29
+ if (!Number.isNaN(width) &&
30
+ width > 0 &&
31
+ !Number.isNaN(height) &&
32
+ height > 0) {
30
33
  return { x: 0, y: 0, width, height };
31
34
  }
32
35
  const rect = svg.getBoundingClientRect();
@@ -45,38 +48,69 @@ function parseAbsoluteLength(value) {
45
48
  return Number.NaN;
46
49
  return Number.parseFloat(trimmed);
47
50
  }
48
- function measureSpanContentHeight(span) {
51
+ function parseCoordinate(value) {
52
+ const parsed = parseAbsoluteLength(value);
53
+ return Number.isNaN(parsed) ? 0 : parsed;
54
+ }
55
+ function measureSpanContentDimensions(span, measureWidth) {
49
56
  const prevHeight = span.style.height;
57
+ const prevWidth = span.style.width;
50
58
  const prevOverflow = span.style.overflow;
51
59
  try {
52
60
  span.style.height = 'max-content';
53
61
  span.style.overflow = 'hidden';
54
62
  void span.offsetHeight; // force reflow
55
- return span.scrollHeight;
63
+ const scrollHeight = span.scrollHeight;
64
+ const rectHeight = span.getBoundingClientRect().height;
65
+ let width = span.scrollWidth;
66
+ if (measureWidth) {
67
+ span.style.width = 'max-content';
68
+ void span.offsetWidth; // force reflow
69
+ width = span.scrollWidth;
70
+ }
71
+ return {
72
+ height: Math.max(scrollHeight, rectHeight),
73
+ width,
74
+ };
56
75
  }
57
76
  finally {
58
77
  span.style.height = prevHeight;
59
- span.style.overflow = prevOverflow;
60
- }
61
- }
62
- function measureSpanContentWidth(span) {
63
- const prevWidth = span.style.width;
64
- const prevOverflow = span.style.overflow;
65
- try {
66
- span.style.width = 'max-content';
67
- span.style.overflow = 'hidden';
68
- void span.offsetWidth; // force reflow
69
- return span.scrollWidth;
70
- }
71
- finally {
72
78
  span.style.width = prevWidth;
73
79
  span.style.overflow = prevOverflow;
74
80
  }
75
81
  }
76
- // Returns [left, top, right, bottom] in SVG coordinates for a foreignObject,
82
+ function shouldKeepForeignObjectWidth(style) {
83
+ const whiteSpace = style.whiteSpace;
84
+ const flexWrap = style.flexWrap;
85
+ const wordBreak = style.wordBreak;
86
+ const overflowWrap = style.overflowWrap;
87
+ return (flexWrap === 'wrap' ||
88
+ flexWrap === 'wrap-reverse' ||
89
+ whiteSpace === 'pre-wrap' ||
90
+ whiteSpace === 'pre-line' ||
91
+ whiteSpace === 'normal' ||
92
+ overflowWrap === 'break-word' ||
93
+ wordBreak === 'break-word' ||
94
+ wordBreak === 'break-all');
95
+ }
96
+ function createCoordConverter(svg, element) {
97
+ if (typeof element.getScreenCTM !== 'function')
98
+ return null;
99
+ const screenCTM = element.getScreenCTM();
100
+ if (!screenCTM)
101
+ return null;
102
+ const inverseCTM = screenCTM.inverse();
103
+ return (clientX, clientY) => {
104
+ const pt = svg.createSVGPoint();
105
+ pt.x = clientX;
106
+ pt.y = clientY;
107
+ return pt.matrixTransform(inverseCTM);
108
+ };
109
+ }
110
+ // Returns [left, top, right, bottom] in target coordinates for a foreignObject,
77
111
  // accounting for flex alignment: bottom/center-aligned content can overflow,
78
112
  // and horizontally aligned content can overflow as well.
79
- function getFOContentBoundsInSVG(fo, content, toSVGCoord) {
113
+ function getFOContentBoundsInSVG(fo, toSVGCoord, { contentHeight, contentWidth, keepForeignObjectWidth, }) {
80
114
  const foRect = fo.getBoundingClientRect();
81
115
  const foTopLeft = toSVGCoord(foRect.left, foRect.top);
82
116
  const foBottomRight = toSVGCoord(foRect.right, foRect.bottom);
@@ -88,16 +122,15 @@ function getFOContentBoundsInSVG(fo, content, toSVGCoord) {
88
122
  const foHeightSVG = foBottomSVG - foTopSVG;
89
123
  const svgUnitsPerClientPxY = foRect.height > 0 ? foHeightSVG / foRect.height : 1;
90
124
  const svgUnitsPerClientPxX = foRect.width > 0 ? foWidthSVG / foRect.width : 1;
91
- // Measure actual content dimensions
92
- const realScrollHeight = measureSpanContentHeight(content);
93
- const contentHeightSVG = realScrollHeight > 0
94
- ? realScrollHeight * svgUnitsPerClientPxY
125
+ const contentHeightSVG = contentHeight > 0
126
+ ? contentHeight * svgUnitsPerClientPxY
95
127
  : foHeightSVG;
96
- const realScrollWidth = measureSpanContentWidth(content);
97
- const contentWidthSVG = realScrollWidth > 0 ? realScrollWidth * svgUnitsPerClientPxX : foWidthSVG;
98
- const computedStyle = window.getComputedStyle(content);
128
+ const computedStyle = window.getComputedStyle(fo.firstElementChild);
99
129
  const alignItems = computedStyle.alignItems;
100
130
  const justifyContent = computedStyle.justifyContent;
131
+ const contentWidthSVG = keepForeignObjectWidth
132
+ ? foWidthSVG
133
+ : Math.max(foWidthSVG, contentWidth * svgUnitsPerClientPxX);
101
134
  // Calculate vertical bounds
102
135
  let top, bottom;
103
136
  if (alignItems === 'flex-end' || alignItems === 'end') {
@@ -132,38 +165,75 @@ function getFOContentBoundsInSVG(fo, content, toSVGCoord) {
132
165
  }
133
166
  return [left, top, right, bottom];
134
167
  }
135
- /**
136
- * Computes a viewBox that fully covers all foreignObject text content,
137
- * accounting for overflow caused by flex alignment (bottom/center align
138
- * can push content outside the foreignObject bounds).
139
- */
140
- function computeFullViewBox(svg) {
168
+ function collectForeignObjectExportAdjustments(svg) {
169
+ const toSVGCoord = createCoordConverter(svg, svg);
170
+ if (!toSVGCoord)
171
+ return [];
172
+ return Array.from(svg.querySelectorAll('foreignObject')).map((fo) => {
173
+ const content = fo.firstElementChild;
174
+ if (!content)
175
+ return null;
176
+ const computedStyle = window.getComputedStyle(content);
177
+ const keepForeignObjectWidth = shouldKeepForeignObjectWidth(computedStyle);
178
+ const measuredContent = measureSpanContentDimensions(content, !keepForeignObjectWidth);
179
+ const parent = fo.parentElement instanceof SVGGraphicsElement ? fo.parentElement : svg;
180
+ const toParentCoord = createCoordConverter(svg, parent);
181
+ const toLocalCoord = createCoordConverter(svg, fo);
182
+ if (!toParentCoord)
183
+ return null;
184
+ const parentBounds = getFOContentBoundsInSVG(fo, toParentCoord, {
185
+ contentHeight: measuredContent.height,
186
+ contentWidth: measuredContent.width,
187
+ keepForeignObjectWidth,
188
+ });
189
+ const originalX = parseCoordinate(fo.getAttribute('x'));
190
+ const originalY = parseCoordinate(fo.getAttribute('y'));
191
+ const localBounds = toLocalCoord
192
+ ? getFOContentBoundsInSVG(fo, toLocalCoord, {
193
+ contentHeight: measuredContent.height,
194
+ contentWidth: measuredContent.width,
195
+ keepForeignObjectWidth,
196
+ })
197
+ : null;
198
+ const hasTransform = fo.hasAttribute('transform');
199
+ if (hasTransform && !localBounds)
200
+ return null;
201
+ const exportBounds = localBounds
202
+ ? {
203
+ x: originalX + localBounds[0],
204
+ y: originalY + localBounds[1],
205
+ width: localBounds[2] - localBounds[0],
206
+ height: localBounds[3] - localBounds[1],
207
+ }
208
+ : {
209
+ x: parentBounds[0],
210
+ y: parentBounds[1],
211
+ width: parentBounds[2] - parentBounds[0],
212
+ height: parentBounds[3] - parentBounds[1],
213
+ };
214
+ return {
215
+ rootBounds: getFOContentBoundsInSVG(fo, toSVGCoord, {
216
+ contentHeight: measuredContent.height,
217
+ contentWidth: measuredContent.width,
218
+ keepForeignObjectWidth,
219
+ }),
220
+ exportBounds,
221
+ };
222
+ });
223
+ }
224
+ function computeFullViewBox(svg, adjustments) {
141
225
  const viewBox = getExportViewBox(svg);
142
226
  if (!viewBox)
143
227
  return null;
144
- if (typeof svg.getScreenCTM !== 'function')
145
- return null;
146
- const screenCTM = svg.getScreenCTM();
147
- if (!screenCTM)
148
- return null;
149
- const inverseCTM = screenCTM.inverse();
150
- const toSVGCoord = (clientX, clientY) => {
151
- const pt = svg.createSVGPoint();
152
- pt.x = clientX;
153
- pt.y = clientY;
154
- return pt.matrixTransform(inverseCTM);
155
- };
156
228
  let minX = viewBox.x;
157
229
  let minY = viewBox.y;
158
230
  let maxX = viewBox.x + viewBox.width;
159
231
  let maxY = viewBox.y + viewBox.height;
160
- svg
161
- .querySelectorAll('foreignObject')
162
- .forEach((fo) => {
163
- const content = fo.firstElementChild;
164
- if (!content)
232
+ adjustments.forEach((adjustment) => {
233
+ if (!adjustment)
165
234
  return;
166
- const [left, top, right, bottom] = getFOContentBoundsInSVG(fo, content, toSVGCoord);
235
+ const { rootBounds } = adjustment;
236
+ const [left, top, right, bottom] = rootBounds;
167
237
  minX = Math.min(minX, left);
168
238
  minY = Math.min(minY, top);
169
239
  maxX = Math.max(maxX, right);
@@ -180,12 +250,25 @@ function computeFullViewBox(svg) {
180
250
  return null;
181
251
  return `${newX} ${newY} ${newWidth} ${newHeight}`;
182
252
  }
253
+ function applyForeignObjectExportAdjustments(svg, adjustments) {
254
+ const clonedForeignObjects = Array.from(svg.querySelectorAll('foreignObject'));
255
+ adjustments.forEach((adjustment, index) => {
256
+ if (!adjustment)
257
+ return;
258
+ const clonedForeignObject = clonedForeignObjects[index];
259
+ if (!clonedForeignObject)
260
+ return;
261
+ (0, utils_1.setAttributes)(clonedForeignObject, adjustment.exportBounds);
262
+ });
263
+ }
183
264
  function exportToSVG(svg_1) {
184
265
  return __awaiter(this, arguments, void 0, function* (svg, options = {}) {
185
266
  const { removeBackground = false, embedResources = true, removeIds = false, } = options;
186
267
  const clonedSVG = svg.cloneNode(true);
187
268
  if (typeof document !== 'undefined') {
188
- const fullViewBox = computeFullViewBox(svg);
269
+ const adjustments = collectForeignObjectExportAdjustments(svg);
270
+ applyForeignObjectExportAdjustments(clonedSVG, adjustments);
271
+ const fullViewBox = computeFullViewBox(svg, adjustments);
189
272
  if (fullViewBox) {
190
273
  clonedSVG.setAttribute('viewBox', fullViewBox);
191
274
  }
@@ -218,8 +301,9 @@ function embedIcons(svg) {
218
301
  const existsSymbol = svg.querySelector(href);
219
302
  if (!existsSymbol) {
220
303
  const symbolElement = document.querySelector(href);
221
- if (symbolElement)
304
+ if (symbolElement) {
222
305
  defs.appendChild(symbolElement.cloneNode(true));
306
+ }
223
307
  }
224
308
  });
225
309
  });
@@ -427,6 +511,8 @@ function collectDefElements(svg, ids) {
427
511
  };
428
512
  while (queue.length) {
429
513
  const id = queue.shift();
514
+ if (!id)
515
+ continue;
430
516
  if (visited.has(id))
431
517
  continue;
432
518
  visited.add(id);
@@ -441,11 +527,65 @@ function collectDefElements(svg, ids) {
441
527
  }
442
528
  return collected;
443
529
  }
530
+ // Fallback implementation based on the CSS.escape algorithm
531
+ function cssEscape(value) {
532
+ const string = String(value);
533
+ const length = string.length;
534
+ let result = '';
535
+ if (length === 0) {
536
+ return '';
537
+ }
538
+ for (let i = 0; i < length; i++) {
539
+ const codeUnit = string.charCodeAt(i);
540
+ // Null character
541
+ if (codeUnit === 0x0000) {
542
+ result += '\uFFFD';
543
+ continue;
544
+ }
545
+ // Control characters or DEL
546
+ if ((codeUnit >= 0x0001 && codeUnit <= 0x001f) || codeUnit === 0x007f) {
547
+ result += '\\' + codeUnit.toString(16) + ' ';
548
+ continue;
549
+ }
550
+ // Escape if first character is a digit
551
+ if (i === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) {
552
+ result += '\\' + codeUnit.toString(16) + ' ';
553
+ continue;
554
+ }
555
+ // Escape if second character is a digit and first is a hyphen
556
+ if (i === 1 &&
557
+ codeUnit >= 0x0030 &&
558
+ codeUnit <= 0x0039 &&
559
+ string.charCodeAt(0) === 0x002d) {
560
+ result += '\\' + codeUnit.toString(16) + ' ';
561
+ continue;
562
+ }
563
+ // If the character is the first and is a hyphen followed by end of string, escape it
564
+ if (i === 0 && length === 1 && codeUnit === 0x002d) {
565
+ result += '\\' + string.charAt(i);
566
+ continue;
567
+ }
568
+ // Characters that are safe to use unescaped
569
+ if (codeUnit >= 0x0080 ||
570
+ (codeUnit >= 0x0030 && codeUnit <= 0x0039) || // 0-9
571
+ (codeUnit >= 0x0041 && codeUnit <= 0x005a) || // A-Z
572
+ (codeUnit >= 0x0061 && codeUnit <= 0x007a) || // a-z
573
+ codeUnit === 0x002d || // -
574
+ codeUnit === 0x005f // _
575
+ ) {
576
+ result += string.charAt(i);
577
+ continue;
578
+ }
579
+ // All other characters
580
+ result += '\\' + string.charAt(i);
581
+ }
582
+ return result;
583
+ }
444
584
  function escapeCssId(id) {
445
585
  if (globalThis.CSS && typeof globalThis.CSS.escape === 'function') {
446
586
  return globalThis.CSS.escape(id);
447
587
  }
448
- return id.replace(/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g, '\\$1');
588
+ return cssEscape(id);
449
589
  }
450
590
  function removeDefs(svg) {
451
591
  const defsList = Array.from(svg.querySelectorAll('defs'));
@@ -57,9 +57,6 @@ function loadSearchResource(query, format) {
57
57
  const svgText = commaIndex >= 0 ? result.slice(commaIndex + 1) : result;
58
58
  return (0, svg_1.loadSVGResource)(svgText);
59
59
  }
60
- if (mimeType === 'image/svg+xml' && format === 'svg' && isBase64) {
61
- return (0, image_1.loadImageBase64Resource)(result);
62
- }
63
60
  return (0, image_1.loadImageBase64Resource)(result);
64
61
  }
65
62
  return (0, remote_1.loadRemoteResource)(result, format);
@@ -33,11 +33,20 @@ function getLevenshteinDistance(source, target) {
33
33
  function getCommonPrefixLength(source, target) {
34
34
  const limit = Math.min(source.length, target.length);
35
35
  let index = 0;
36
- while (index < limit && source[index] === target[index]) {
36
+ while (index < limit &&
37
+ source.charCodeAt(index) === target.charCodeAt(index)) {
37
38
  index += 1;
38
39
  }
39
40
  return index;
40
41
  }
42
+ function isBetterMatch(bestMatch, bestDistance, bestPrefixLength, candidateKey, candidateDistance, candidatePrefixLength) {
43
+ return (candidateDistance < bestDistance ||
44
+ (candidateDistance === bestDistance &&
45
+ candidatePrefixLength > bestPrefixLength) ||
46
+ (candidateDistance === bestDistance &&
47
+ candidatePrefixLength === bestPrefixLength &&
48
+ (!bestMatch || candidateKey < bestMatch)));
49
+ }
41
50
  function findClosestTemplateKey(type, keys) {
42
51
  const normalizedType = normalizeTemplateKey(type);
43
52
  if (!normalizedType)
@@ -52,11 +61,7 @@ function findClosestTemplateKey(type, keys) {
52
61
  }
53
62
  const distance = getLevenshteinDistance(normalizedType, normalizedKey);
54
63
  const prefixLength = getCommonPrefixLength(normalizedType, normalizedKey);
55
- if (distance < bestDistance ||
56
- (distance === bestDistance && prefixLength > bestPrefixLength) ||
57
- (distance === bestDistance &&
58
- prefixLength === bestPrefixLength &&
59
- (!bestMatch || key < bestMatch))) {
64
+ if (isBetterMatch(bestMatch, bestDistance, bestPrefixLength, key, distance, prefixLength)) {
60
65
  bestMatch = key;
61
66
  bestDistance = distance;
62
67
  bestPrefixLength = prefixLength;
@@ -31,7 +31,7 @@ function setSVGPadding(svg, padding) {
31
31
  setSVGPaddingInNode(svg, padding);
32
32
  }
33
33
  else {
34
- if (document.contains(svg)) {
34
+ if (svg.isConnected) {
35
35
  setSVGPaddingInBrowser(svg, padding);
36
36
  }
37
37
  else {
@@ -1 +1,3 @@
1
- export declare function injectStyleOnce(id: string, styles: string): void;
1
+ type StyleTarget = Document | ShadowRoot | Node | null | undefined;
2
+ export declare function injectStyleOnce(id: string, styles: string, target?: StyleTarget): void;
3
+ export {};
@@ -1,11 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.injectStyleOnce = injectStyleOnce;
4
- function injectStyleOnce(id, styles) {
5
- if (document.getElementById(id))
4
+ function resolveStyleRoot(target) {
5
+ if (!target)
6
+ return document;
7
+ if (target instanceof Document || target instanceof ShadowRoot)
8
+ return target;
9
+ if (!target.isConnected)
10
+ return document;
11
+ const root = target.getRootNode();
12
+ return root instanceof ShadowRoot ? root : document;
13
+ }
14
+ function hasStyle(root, id) {
15
+ if (root instanceof Document)
16
+ return Boolean(root.getElementById(id));
17
+ return Boolean(root.querySelector(`#${id}`));
18
+ }
19
+ function injectStyleOnce(id, styles, target) {
20
+ var _a;
21
+ const root = resolveStyleRoot(target);
22
+ if (hasStyle(root, id))
6
23
  return;
7
- const style = document.createElement('style');
24
+ const doc = root instanceof Document ? root : ((_a = root.ownerDocument) !== null && _a !== void 0 ? _a : document);
25
+ const style = doc.createElement('style');
8
26
  style.id = id;
9
27
  style.textContent = styles;
10
- document.head.appendChild(style);
28
+ if (root instanceof Document) {
29
+ root.head.appendChild(style);
30
+ }
31
+ else {
32
+ root.appendChild(style);
33
+ }
11
34
  }
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.2.17";
1
+ export declare const VERSION = "0.2.19";
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.2.17';
4
+ exports.VERSION = '0.2.19';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antv/infographic",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "An Infographic Generation and Rendering Framework, bring words to life!",
5
5
  "keywords": [
6
6
  "antv",
@@ -1 +1 @@
1
- export const ICON_SERVICE_URL = 'https://lab.weavefox.cn/api/v1/infographic/icon';
1
+ export const ICON_SERVICE_URL = 'https://www.weavefox.cn/api/v1/infographic/icon';
@@ -18,6 +18,9 @@ export interface ChartLineProps extends BaseStructureProps {
18
18
  valueFormatter?: (value: number, datum: ItemDatum) => string;
19
19
  }
20
20
 
21
+ const ITEM_POSITION_H = 'center' as const;
22
+ const ITEM_POSITION_V = 'normal' as const;
23
+
21
24
  export const ChartLine: ComponentType<ChartLineProps> = (props) => {
22
25
  const {
23
26
  Title,
@@ -55,8 +58,8 @@ export const ChartLine: ComponentType<ChartLineProps> = (props) => {
55
58
  indexes: [0],
56
59
  datum: items[0],
57
60
  data,
58
- positionH: 'center',
59
- positionV: 'normal',
61
+ positionH: ITEM_POSITION_H,
62
+ positionV: ITEM_POSITION_V,
60
63
  };
61
64
  const sampleBounds = getElementBounds(<Item {...itemProps} />);
62
65
  const labelWidth = sampleBounds.width;
@@ -396,7 +399,6 @@ export const ChartLine: ComponentType<ChartLineProps> = (props) => {
396
399
  </linearGradient>
397
400
  <linearGradient id={gradientAreaId} x1="0%" y1="0%" x2="100%" y2="0%">
398
401
  {areaStops}
399
- <stop offset="100%" stopColor={colorPrimary} stopOpacity="0.04" />
400
402
  </linearGradient>
401
403
  </Defs>
402
404
  <Group>{gridElements}</Group>
@@ -92,7 +92,7 @@ function editText(text: TextElement, options?: EditTextOptions) {
92
92
  const entity = getTextEntity(text);
93
93
  if (!entity) return;
94
94
 
95
- ensureEditorStyles();
95
+ ensureEditorStyles(entity);
96
96
  new InlineTextEditor(entity, options).start();
97
97
  }
98
98
 
@@ -240,7 +240,7 @@ class InlineTextEditor {
240
240
  }
241
241
  }
242
242
 
243
- function ensureEditorStyles() {
243
+ function ensureEditorStyles(target?: Node) {
244
244
  injectStyleOnce(
245
245
  EDITOR_STYLE_ID,
246
246
  `
@@ -256,5 +256,6 @@ function ensureEditorStyles() {
256
256
  background-color: #b3d4fc;
257
257
  }
258
258
  `,
259
+ target,
259
260
  );
260
261
  }
@@ -16,6 +16,7 @@ import type {
16
16
  SelectionChangePayload,
17
17
  SelectMode,
18
18
  } from '../types';
19
+ import { eventPathContains } from '../utils';
19
20
  import { Extension } from '../utils';
20
21
 
21
22
  export class InteractionManager implements IInteractionManager {
@@ -129,18 +130,19 @@ export class InteractionManager implements IInteractionManager {
129
130
 
130
131
  private handleClick = (event: MouseEvent) => {
131
132
  const doc = this.editor.getDocument();
132
- const target = event.target;
133
+ const path = typeof event.composedPath === 'function' ? event.composedPath() : [];
134
+ const insideInfographic =
135
+ eventPathContains(event, doc) ||
136
+ path.some(
137
+ (node) => node instanceof HTMLElement && isInfographicComponent(node),
138
+ );
133
139
 
134
- if (!target) {
140
+ if (!event.target) {
135
141
  this.deactivate();
136
142
  return;
137
143
  }
138
144
  // 点击画布 SVG 或者标记为组件的元素
139
- if (
140
- doc.contains(target as Node) ||
141
- isInfographicComponent(target as HTMLElement)
142
- )
143
- this.activate();
145
+ if (insideInfographic) this.activate();
144
146
  else this.deactivate();
145
147
  };
146
148
 
@@ -7,6 +7,7 @@ export interface IconButtonProps {
7
7
  icon: Icon;
8
8
  onClick?: () => void;
9
9
  activate?: boolean;
10
+ root?: Node;
10
11
  }
11
12
 
12
13
  export interface IconButtonHandle {
@@ -18,8 +19,9 @@ export const IconButton = ({
18
19
  icon,
19
20
  onClick,
20
21
  activate = false,
22
+ root,
21
23
  }: IconButtonProps): Button => {
22
- ensureIconButtonStyle();
24
+ ensureIconButtonStyle(root);
23
25
 
24
26
  const button = document.createElement('button');
25
27
  button.type = 'button';
@@ -44,7 +46,7 @@ export const IconButton = ({
44
46
  const ICON_BUTTON_CLASS = 'infographic-edit-bar-icon-btn';
45
47
  const ICON_BUTTON_STYLE_ID = 'infographic-edit-bar-icon-btn-style';
46
48
 
47
- function ensureIconButtonStyle() {
49
+ function ensureIconButtonStyle(target?: Node) {
48
50
  injectStyleOnce(
49
51
  ICON_BUTTON_STYLE_ID,
50
52
  `
@@ -73,5 +75,6 @@ function ensureIconButtonStyle() {
73
75
  background-color: #d9d9d9;
74
76
  }
75
77
  `,
78
+ target,
76
79
  );
77
80
  }
@@ -6,6 +6,7 @@ export type ColorPickerProps = {
6
6
  value?: string;
7
7
  swatches?: string[];
8
8
  onChange?: (value: string) => void;
9
+ root?: Node;
9
10
  };
10
11
 
11
12
  export type ColorPickerHandle = {
@@ -66,7 +67,7 @@ export function ColorPicker(
66
67
  throw new Error('ColorPicker can only be used in the browser.');
67
68
  }
68
69
 
69
- ensureColorPickerStyles();
70
+ ensureColorPickerStyles(props.root);
70
71
 
71
72
  const container = document.createElement('div');
72
73
  container.classList.add(COLOR_PICKER_CLASS);
@@ -279,7 +280,7 @@ function createSwitchLabel(text: string): HTMLSpanElement {
279
280
  return span;
280
281
  }
281
282
 
282
- function ensureColorPickerStyles() {
283
+ function ensureColorPickerStyles(target?: Node) {
283
284
  injectStyleOnce(
284
285
  COLOR_PICKER_STYLE_ID,
285
286
  `
@@ -393,5 +394,6 @@ function ensureColorPickerStyles() {
393
394
  color: #ffffff;
394
395
  }
395
396
  `,
397
+ target,
396
398
  );
397
399
  }