@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.
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/infographic.min.js +110 -110
- package/dist/infographic.min.js.map +1 -1
- package/esm/constants/service.d.ts +1 -1
- package/esm/constants/service.js +1 -1
- package/esm/designs/structures/chart-line.js +5 -3
- package/esm/editor/interactions/dblclick-edit-text.js +3 -3
- package/esm/editor/managers/interaction.js +6 -4
- package/esm/editor/plugins/components/button.d.ts +2 -1
- package/esm/editor/plugins/components/button.js +4 -4
- package/esm/editor/plugins/components/color-picker.d.ts +1 -0
- package/esm/editor/plugins/components/color-picker.js +3 -3
- package/esm/editor/plugins/components/popover.d.ts +3 -1
- package/esm/editor/plugins/components/popover.js +29 -9
- package/esm/editor/plugins/edit-bar/edit-bar.d.ts +3 -1
- package/esm/editor/plugins/edit-bar/edit-bar.js +17 -7
- package/esm/editor/plugins/edit-bar/edit-items/align-elements.js +6 -4
- package/esm/editor/plugins/edit-bar/edit-items/font-align.js +8 -5
- package/esm/editor/plugins/edit-bar/edit-items/font-color.js +7 -4
- package/esm/editor/plugins/edit-bar/edit-items/font-family.js +11 -9
- package/esm/editor/plugins/edit-bar/edit-items/font-size.js +8 -5
- package/esm/editor/plugins/edit-bar/edit-items/icon-color.js +7 -4
- package/esm/editor/plugins/edit-bar/edit-items/types.d.ts +5 -1
- package/esm/editor/plugins/reset-viewbox.d.ts +4 -1
- package/esm/editor/plugins/reset-viewbox.js +12 -6
- package/esm/editor/utils/index.d.ts +1 -0
- package/esm/editor/utils/index.js +1 -0
- package/esm/editor/utils/root.d.ts +3 -0
- package/esm/editor/utils/root.js +18 -0
- package/esm/exporter/svg.js +192 -52
- package/esm/resource/loaders/search.js +0 -3
- package/esm/templates/utils.js +11 -6
- package/esm/utils/padding.js +1 -1
- package/esm/utils/style.d.ts +3 -1
- package/esm/utils/style.js +27 -4
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/lib/constants/service.d.ts +1 -1
- package/lib/constants/service.js +1 -1
- package/lib/designs/structures/chart-line.js +5 -3
- package/lib/editor/interactions/dblclick-edit-text.js +3 -3
- package/lib/editor/managers/interaction.js +7 -5
- package/lib/editor/plugins/components/button.d.ts +2 -1
- package/lib/editor/plugins/components/button.js +4 -4
- package/lib/editor/plugins/components/color-picker.d.ts +1 -0
- package/lib/editor/plugins/components/color-picker.js +3 -3
- package/lib/editor/plugins/components/popover.d.ts +3 -1
- package/lib/editor/plugins/components/popover.js +32 -12
- package/lib/editor/plugins/edit-bar/edit-bar.d.ts +3 -1
- package/lib/editor/plugins/edit-bar/edit-bar.js +17 -7
- package/lib/editor/plugins/edit-bar/edit-items/align-elements.js +6 -4
- package/lib/editor/plugins/edit-bar/edit-items/font-align.js +8 -5
- package/lib/editor/plugins/edit-bar/edit-items/font-color.js +7 -4
- package/lib/editor/plugins/edit-bar/edit-items/font-family.js +11 -9
- package/lib/editor/plugins/edit-bar/edit-items/font-size.js +8 -5
- package/lib/editor/plugins/edit-bar/edit-items/icon-color.js +7 -4
- package/lib/editor/plugins/edit-bar/edit-items/types.d.ts +5 -1
- package/lib/editor/plugins/reset-viewbox.d.ts +4 -1
- package/lib/editor/plugins/reset-viewbox.js +12 -6
- package/lib/editor/utils/index.d.ts +1 -0
- package/lib/editor/utils/index.js +1 -0
- package/lib/editor/utils/root.d.ts +3 -0
- package/lib/editor/utils/root.js +22 -0
- package/lib/exporter/svg.js +192 -52
- package/lib/resource/loaders/search.js +0 -3
- package/lib/templates/utils.js +11 -6
- package/lib/utils/padding.js +1 -1
- package/lib/utils/style.d.ts +3 -1
- package/lib/utils/style.js +27 -4
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/constants/service.ts +1 -1
- package/src/designs/structures/chart-line.tsx +5 -3
- package/src/editor/interactions/dblclick-edit-text.ts +3 -2
- package/src/editor/managers/interaction.ts +9 -7
- package/src/editor/plugins/components/button.ts +5 -2
- package/src/editor/plugins/components/color-picker.ts +4 -2
- package/src/editor/plugins/components/popover.ts +31 -12
- package/src/editor/plugins/edit-bar/edit-bar.ts +26 -11
- package/src/editor/plugins/edit-bar/edit-items/align-elements.ts +7 -2
- package/src/editor/plugins/edit-bar/edit-items/font-align.ts +8 -3
- package/src/editor/plugins/edit-bar/edit-items/font-color.ts +7 -2
- package/src/editor/plugins/edit-bar/edit-items/font-family.ts +11 -7
- package/src/editor/plugins/edit-bar/edit-items/font-size.ts +8 -3
- package/src/editor/plugins/edit-bar/edit-items/icon-color.ts +7 -2
- package/src/editor/plugins/edit-bar/edit-items/types.ts +6 -1
- package/src/editor/plugins/reset-viewbox.ts +17 -8
- package/src/editor/utils/index.ts +1 -0
- package/src/editor/utils/root.ts +26 -0
- package/src/exporter/svg.ts +267 -62
- package/src/resource/loaders/search.ts +0 -3
- package/src/templates/utils.ts +30 -6
- package/src/utils/padding.ts +1 -1
- package/src/utils/style.ts +31 -4
- 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
|
+
}
|
package/lib/exporter/svg.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
const contentHeightSVG = realScrollHeight > 0
|
|
94
|
-
? realScrollHeight * svgUnitsPerClientPxY
|
|
125
|
+
const contentHeightSVG = contentHeight > 0
|
|
126
|
+
? contentHeight * svgUnitsPerClientPxY
|
|
95
127
|
: foHeightSVG;
|
|
96
|
-
const
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
161
|
-
|
|
162
|
-
.forEach((fo) => {
|
|
163
|
-
const content = fo.firstElementChild;
|
|
164
|
-
if (!content)
|
|
232
|
+
adjustments.forEach((adjustment) => {
|
|
233
|
+
if (!adjustment)
|
|
165
234
|
return;
|
|
166
|
-
const
|
|
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
|
|
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
|
|
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);
|
package/lib/templates/utils.js
CHANGED
|
@@ -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 &&
|
|
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
|
|
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;
|
package/lib/utils/padding.js
CHANGED
package/lib/utils/style.d.ts
CHANGED
package/lib/utils/style.js
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.injectStyleOnce = injectStyleOnce;
|
|
4
|
-
function
|
|
5
|
-
if (
|
|
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
|
|
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
|
-
|
|
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.
|
|
1
|
+
export declare const VERSION = "0.2.19";
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
package/src/constants/service.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ICON_SERVICE_URL = 'https://
|
|
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:
|
|
59
|
-
positionV:
|
|
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
|
|
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
|
}
|