@antv/infographic 0.2.17 → 0.2.18
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 +99 -99
- 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 +63 -3
- 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 +63 -3
- 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 +80 -3
- 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
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.18";
|
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
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { eventPathContains, getOverlayContainer } from '../../utils';
|
|
1
2
|
import { COMPONENT_ROLE } from '../../../constants';
|
|
2
3
|
import { injectStyleOnce, setElementRole } from '../../../utils';
|
|
3
4
|
|
|
@@ -7,7 +8,7 @@ export type PopoverPlacementPreference = PopoverPlacement | PopoverPlacement[];
|
|
|
7
8
|
export interface PopoverProps {
|
|
8
9
|
content: HTMLElement | string | (() => HTMLElement | string);
|
|
9
10
|
target?: HTMLElement;
|
|
10
|
-
getContainer?:
|
|
11
|
+
getContainer?: OverlayRoot | (() => OverlayRoot);
|
|
11
12
|
placement?: PopoverPlacementPreference;
|
|
12
13
|
padding?: number | string;
|
|
13
14
|
open?: boolean;
|
|
@@ -18,6 +19,8 @@ export interface PopoverProps {
|
|
|
18
19
|
offset?: number;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
type OverlayRoot = HTMLElement | ShadowRoot;
|
|
23
|
+
|
|
21
24
|
export interface PopoverHandle {
|
|
22
25
|
setOpen: (open: boolean) => void;
|
|
23
26
|
toggle: () => void;
|
|
@@ -32,8 +35,6 @@ const POPOVER_ARROW_CLASS = `${POPOVER_CLASS}__arrow`;
|
|
|
32
35
|
const POPOVER_STYLE_ID = 'infographic-edit-popover-style';
|
|
33
36
|
|
|
34
37
|
export function Popover(props: PopoverProps): HTMLDivElement & PopoverHandle {
|
|
35
|
-
ensurePopoverStyle();
|
|
36
|
-
|
|
37
38
|
const placement = props.placement ?? 'top';
|
|
38
39
|
const closeOnOutsideClick = props.closeOnOutsideClick ?? true;
|
|
39
40
|
const triggerActions = Array.isArray(props.trigger)
|
|
@@ -60,7 +61,7 @@ export function Popover(props: PopoverProps): HTMLDivElement & PopoverHandle {
|
|
|
60
61
|
typeof props.getContainer === 'function'
|
|
61
62
|
? props.getContainer()
|
|
62
63
|
: props.getContainer;
|
|
63
|
-
return next ??
|
|
64
|
+
return next ?? getOverlayContainer(trigger);
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
const content = document.createElement('div');
|
|
@@ -78,8 +79,17 @@ export function Popover(props: PopoverProps): HTMLDivElement & PopoverHandle {
|
|
|
78
79
|
);
|
|
79
80
|
|
|
80
81
|
const contentContainer = getContentContainer();
|
|
82
|
+
ensurePopoverStyle(contentContainer);
|
|
81
83
|
const isPortal = contentContainer !== container;
|
|
82
84
|
|
|
85
|
+
const getPortalOffsetParent = () => {
|
|
86
|
+
const offsetParent = content.offsetParent as HTMLElement | null;
|
|
87
|
+
if (offsetParent) return offsetParent;
|
|
88
|
+
if (contentContainer instanceof ShadowRoot) return contentContainer.host;
|
|
89
|
+
if (contentContainer instanceof HTMLElement) return contentContainer;
|
|
90
|
+
return document.documentElement as HTMLElement;
|
|
91
|
+
};
|
|
92
|
+
|
|
83
93
|
const arrow = document.createElement('div');
|
|
84
94
|
arrow.classList.add(POPOVER_ARROW_CLASS);
|
|
85
95
|
content.appendChild(arrow);
|
|
@@ -170,8 +180,18 @@ export function Popover(props: PopoverProps): HTMLDivElement & PopoverHandle {
|
|
|
170
180
|
if (!isPortal) return;
|
|
171
181
|
|
|
172
182
|
({ left, top } = position);
|
|
173
|
-
|
|
174
|
-
|
|
183
|
+
const offsetParent = getPortalOffsetParent();
|
|
184
|
+
if (
|
|
185
|
+
offsetParent === document.body ||
|
|
186
|
+
offsetParent === document.documentElement
|
|
187
|
+
) {
|
|
188
|
+
content.style.left = `${left}px`;
|
|
189
|
+
content.style.top = `${top}px`;
|
|
190
|
+
} else {
|
|
191
|
+
const parentRect = offsetParent.getBoundingClientRect();
|
|
192
|
+
content.style.left = `${left - parentRect.left + offsetParent.scrollLeft}px`;
|
|
193
|
+
content.style.top = `${top - parentRect.top + offsetParent.scrollTop}px`;
|
|
194
|
+
}
|
|
175
195
|
content.style.right = 'auto';
|
|
176
196
|
content.style.bottom = 'auto';
|
|
177
197
|
content.style.transform = 'translate(0, 0)';
|
|
@@ -217,11 +237,9 @@ export function Popover(props: PopoverProps): HTMLDivElement & PopoverHandle {
|
|
|
217
237
|
const toggle = () => setOpen(!open);
|
|
218
238
|
|
|
219
239
|
const handleOutsideClick = (event: MouseEvent) => {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
(isPortal ? !content.contains(targetNode) : true)
|
|
224
|
-
) {
|
|
240
|
+
const insideTrigger = eventPathContains(event, container);
|
|
241
|
+
const insideContent = eventPathContains(event, content);
|
|
242
|
+
if (!insideTrigger && !insideContent) {
|
|
225
243
|
setOpen(false);
|
|
226
244
|
}
|
|
227
245
|
};
|
|
@@ -296,7 +314,7 @@ export function Popover(props: PopoverProps): HTMLDivElement & PopoverHandle {
|
|
|
296
314
|
return Object.assign(container, api);
|
|
297
315
|
}
|
|
298
316
|
|
|
299
|
-
function ensurePopoverStyle() {
|
|
317
|
+
function ensurePopoverStyle(target?: Node) {
|
|
300
318
|
injectStyleOnce(
|
|
301
319
|
POPOVER_STYLE_ID,
|
|
302
320
|
`
|
|
@@ -442,5 +460,6 @@ function ensurePopoverStyle() {
|
|
|
442
460
|
transform: translate(0, -50%);
|
|
443
461
|
}
|
|
444
462
|
`,
|
|
463
|
+
target,
|
|
445
464
|
);
|
|
446
465
|
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
isIconElement,
|
|
11
11
|
setElementRole,
|
|
12
12
|
} from '../../../utils';
|
|
13
|
+
import { getOverlayContainer } from '../../utils';
|
|
13
14
|
import type {
|
|
14
15
|
IPlugin,
|
|
15
16
|
PluginInitOptions,
|
|
@@ -29,9 +30,11 @@ import {
|
|
|
29
30
|
export interface EditBarOptions {
|
|
30
31
|
style?: Partial<CSSStyleDeclaration>;
|
|
31
32
|
className?: string;
|
|
32
|
-
getContainer?:
|
|
33
|
+
getContainer?: OverlayRoot | (() => OverlayRoot);
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
type OverlayRoot = HTMLElement | ShadowRoot;
|
|
37
|
+
|
|
35
38
|
type EditItem = HTMLElement;
|
|
36
39
|
|
|
37
40
|
export class EditBar extends Plugin implements IPlugin {
|
|
@@ -169,12 +172,7 @@ export class EditBar extends Plugin implements IPlugin {
|
|
|
169
172
|
setElementRole(container, COMPONENT_ROLE);
|
|
170
173
|
|
|
171
174
|
this.container = container;
|
|
172
|
-
|
|
173
|
-
const { getContainer } = this.options || {};
|
|
174
|
-
const resolvedContainer =
|
|
175
|
-
typeof getContainer === 'function' ? getContainer() : getContainer;
|
|
176
|
-
const containerParent = resolvedContainer ?? document.body;
|
|
177
|
-
|
|
175
|
+
const containerParent = this.resolveOverlayRoot();
|
|
178
176
|
containerParent?.appendChild(container);
|
|
179
177
|
|
|
180
178
|
return container;
|
|
@@ -182,8 +180,9 @@ export class EditBar extends Plugin implements IPlugin {
|
|
|
182
180
|
|
|
183
181
|
protected getTextEditItems(text: TextElement): EditItem[] {
|
|
184
182
|
const { attributes = {} } = getTextElementProps(text);
|
|
183
|
+
const root = this.resolveOverlayRoot();
|
|
185
184
|
return [FontColor, FontSize, FontAlign, FontFamily].map((item) =>
|
|
186
|
-
item([text], attributes, this.commander),
|
|
185
|
+
item([text], attributes, this.commander, { root }),
|
|
187
186
|
);
|
|
188
187
|
}
|
|
189
188
|
|
|
@@ -191,8 +190,9 @@ export class EditBar extends Plugin implements IPlugin {
|
|
|
191
190
|
const attrs = getCommonAttrs(
|
|
192
191
|
selection.map((text) => getTextElementProps(text).attributes || {}),
|
|
193
192
|
);
|
|
193
|
+
const root = this.resolveOverlayRoot();
|
|
194
194
|
const items = [FontColor, FontSize, FontAlign, FontFamily].map((item) =>
|
|
195
|
-
item(selection, attrs, this.commander),
|
|
195
|
+
item(selection, attrs, this.commander, { root }),
|
|
196
196
|
);
|
|
197
197
|
const commonItems = this.getElementCollectionEditItems(selection);
|
|
198
198
|
return [...items, ...commonItems];
|
|
@@ -200,13 +200,19 @@ export class EditBar extends Plugin implements IPlugin {
|
|
|
200
200
|
|
|
201
201
|
protected getIconEditItems(selection: Selection): EditItem[] {
|
|
202
202
|
const attrs = getIconAttrs(selection[0] as IconElement);
|
|
203
|
-
|
|
203
|
+
const root = this.resolveOverlayRoot();
|
|
204
|
+
return [IconColor].map((item) =>
|
|
205
|
+
item(selection, attrs, this.commander, { root }),
|
|
206
|
+
);
|
|
204
207
|
}
|
|
205
208
|
protected getIconCollectionEditItems(selection: Selection): EditItem[] {
|
|
206
209
|
const attrs = getCommonAttrs(
|
|
207
210
|
selection.map((icon) => getIconAttrs(icon as IconElement)),
|
|
208
211
|
);
|
|
209
|
-
|
|
212
|
+
const root = this.resolveOverlayRoot();
|
|
213
|
+
return [IconColor].map((item) =>
|
|
214
|
+
item(selection, attrs, this.commander, { root }),
|
|
215
|
+
);
|
|
210
216
|
}
|
|
211
217
|
|
|
212
218
|
protected getGeometryEditItems(_selection: Selection): EditItem[] {
|
|
@@ -220,13 +226,22 @@ export class EditBar extends Plugin implements IPlugin {
|
|
|
220
226
|
|
|
221
227
|
protected getElementCollectionEditItems(selection: Selection): EditItem[] {
|
|
222
228
|
if (selection.length <= 1) return [];
|
|
229
|
+
const root = this.resolveOverlayRoot();
|
|
223
230
|
return [
|
|
224
231
|
ElementAlign(selection, {}, this.commander, {
|
|
225
232
|
enableDistribution: selection.length > 2,
|
|
233
|
+
root,
|
|
226
234
|
}),
|
|
227
235
|
];
|
|
228
236
|
}
|
|
229
237
|
|
|
238
|
+
private resolveOverlayRoot(): OverlayRoot {
|
|
239
|
+
const { getContainer } = this.options || {};
|
|
240
|
+
const resolvedContainer =
|
|
241
|
+
typeof getContainer === 'function' ? getContainer() : getContainer;
|
|
242
|
+
return resolvedContainer ?? getOverlayContainer(this.editor.getDocument());
|
|
243
|
+
}
|
|
244
|
+
|
|
230
245
|
private placeEditBar(container: HTMLDivElement, selection: Selection) {
|
|
231
246
|
if (selection.length === 0) return;
|
|
232
247
|
|
|
@@ -40,6 +40,7 @@ type AlignAction =
|
|
|
40
40
|
|
|
41
41
|
type AlignOptions = {
|
|
42
42
|
enableDistribution?: boolean;
|
|
43
|
+
root?: HTMLElement | ShadowRoot;
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
type TransformParts = {
|
|
@@ -79,17 +80,19 @@ export const ElementAlign: EditItem = (
|
|
|
79
80
|
commander: ICommandManager,
|
|
80
81
|
options?: AlignOptions,
|
|
81
82
|
) => {
|
|
82
|
-
injectStyleOnce(GRID_STYLE_ID, GRID_STYLES);
|
|
83
|
+
injectStyleOnce(GRID_STYLE_ID, GRID_STYLES, options?.root);
|
|
83
84
|
const enableDistribution = options?.enableDistribution ?? true;
|
|
84
85
|
|
|
85
86
|
const content = createAlignContent(
|
|
86
87
|
(action) => alignSelection(selection, action, commander),
|
|
87
88
|
enableDistribution,
|
|
89
|
+
options?.root,
|
|
88
90
|
);
|
|
89
91
|
|
|
90
92
|
return Popover({
|
|
91
|
-
target: IconButton({ icon: ELEMENT_ICONS.align }),
|
|
93
|
+
target: IconButton({ icon: ELEMENT_ICONS.align, root: options?.root }),
|
|
92
94
|
content,
|
|
95
|
+
getContainer: options?.root,
|
|
93
96
|
placement: 'top',
|
|
94
97
|
offset: 12,
|
|
95
98
|
});
|
|
@@ -98,6 +101,7 @@ export const ElementAlign: EditItem = (
|
|
|
98
101
|
function createAlignContent(
|
|
99
102
|
onSelect: (action: AlignAction) => void,
|
|
100
103
|
enableDistribution: boolean,
|
|
104
|
+
root?: Node,
|
|
101
105
|
) {
|
|
102
106
|
const content = document.createElement('div');
|
|
103
107
|
content.classList.add(GRID_CLASS);
|
|
@@ -111,6 +115,7 @@ function createAlignContent(
|
|
|
111
115
|
|
|
112
116
|
visibleOptions.forEach(({ icon, action }) => {
|
|
113
117
|
const button = IconButton({
|
|
118
|
+
root,
|
|
114
119
|
icon,
|
|
115
120
|
onClick: () => onSelect(action),
|
|
116
121
|
});
|
|
@@ -48,15 +48,17 @@ export const FontAlign: EditItem<TextAttributes> = (
|
|
|
48
48
|
selection,
|
|
49
49
|
attrs,
|
|
50
50
|
commander,
|
|
51
|
+
options,
|
|
51
52
|
) => {
|
|
52
|
-
|
|
53
|
+
const root = options?.root;
|
|
54
|
+
injectStyleOnce(GRID_STYLE_ID, GRID_STYLES, root);
|
|
53
55
|
|
|
54
56
|
const state: AlignState = {
|
|
55
57
|
horizontal: attrs['data-horizontal-align'],
|
|
56
58
|
vertical: attrs['data-vertical-align'],
|
|
57
59
|
};
|
|
58
60
|
|
|
59
|
-
const button = IconButton({ icon: TEXT_ICONS.align });
|
|
61
|
+
const button = IconButton({ icon: TEXT_ICONS.align, root });
|
|
60
62
|
|
|
61
63
|
const content = createAlignContent(state, (align) => {
|
|
62
64
|
const attributes: Partial<TextAttributes> = {};
|
|
@@ -74,11 +76,12 @@ export const FontAlign: EditItem<TextAttributes> = (
|
|
|
74
76
|
}),
|
|
75
77
|
),
|
|
76
78
|
);
|
|
77
|
-
});
|
|
79
|
+
}, root);
|
|
78
80
|
|
|
79
81
|
return Popover({
|
|
80
82
|
target: button,
|
|
81
83
|
content,
|
|
84
|
+
getContainer: root,
|
|
82
85
|
placement: 'top',
|
|
83
86
|
offset: 12,
|
|
84
87
|
});
|
|
@@ -87,6 +90,7 @@ export const FontAlign: EditItem<TextAttributes> = (
|
|
|
87
90
|
function createAlignContent(
|
|
88
91
|
state: AlignState,
|
|
89
92
|
onAlignChange: (align: AlignState) => void,
|
|
93
|
+
root?: Node,
|
|
90
94
|
) {
|
|
91
95
|
const content = document.createElement('div');
|
|
92
96
|
content.classList.add(GRID_CLASS);
|
|
@@ -106,6 +110,7 @@ function createAlignContent(
|
|
|
106
110
|
) => {
|
|
107
111
|
options.forEach(({ icon, align }) => {
|
|
108
112
|
const button = IconButton({
|
|
113
|
+
root,
|
|
109
114
|
icon,
|
|
110
115
|
onClick: () => {
|
|
111
116
|
if (state[stateKey] === align) return;
|
|
@@ -12,8 +12,10 @@ export const FontColor: EditItem<TextAttributes> = (
|
|
|
12
12
|
selection,
|
|
13
13
|
attrs,
|
|
14
14
|
commander,
|
|
15
|
+
options,
|
|
15
16
|
) => {
|
|
16
|
-
|
|
17
|
+
const root = options?.root;
|
|
18
|
+
ensureFontColorStyles(root);
|
|
17
19
|
|
|
18
20
|
const color = normalizeColor(attrs.fill);
|
|
19
21
|
const isMixed = attrs.fill === undefined && selection.length > 1;
|
|
@@ -24,6 +26,7 @@ export const FontColor: EditItem<TextAttributes> = (
|
|
|
24
26
|
setButtonColor(button, color ?? DEFAULT_COLOR, isMixed);
|
|
25
27
|
|
|
26
28
|
const picker = ColorPicker({
|
|
29
|
+
root,
|
|
27
30
|
value: color ?? DEFAULT_COLOR,
|
|
28
31
|
onChange: (nextColor) => {
|
|
29
32
|
setButtonColor(button, nextColor, false);
|
|
@@ -41,6 +44,7 @@ export const FontColor: EditItem<TextAttributes> = (
|
|
|
41
44
|
return Popover({
|
|
42
45
|
target: button,
|
|
43
46
|
content: picker,
|
|
47
|
+
getContainer: root,
|
|
44
48
|
placement: ['top', 'bottom'],
|
|
45
49
|
offset: 12,
|
|
46
50
|
trigger: 'hover',
|
|
@@ -65,7 +69,7 @@ function setButtonColor(
|
|
|
65
69
|
else button.removeAttribute('data-mixed');
|
|
66
70
|
}
|
|
67
71
|
|
|
68
|
-
function ensureFontColorStyles() {
|
|
72
|
+
function ensureFontColorStyles(target?: Node) {
|
|
69
73
|
injectStyleOnce(
|
|
70
74
|
FONT_COLOR_STYLE_ID,
|
|
71
75
|
`
|
|
@@ -97,5 +101,6 @@ function ensureFontColorStyles() {
|
|
|
97
101
|
);
|
|
98
102
|
}
|
|
99
103
|
`,
|
|
104
|
+
target,
|
|
100
105
|
);
|
|
101
106
|
}
|
|
@@ -18,27 +18,29 @@ export const FontFamily: EditItem<TextAttributes> = (
|
|
|
18
18
|
selection,
|
|
19
19
|
attrs,
|
|
20
20
|
commander,
|
|
21
|
+
editItemOptions,
|
|
21
22
|
) => {
|
|
22
|
-
|
|
23
|
+
const root = editItemOptions?.root;
|
|
24
|
+
ensureFontFamilyListStyle(root);
|
|
23
25
|
|
|
24
26
|
const fonts = getFonts();
|
|
25
27
|
const current = normalizeFontFamily(attrs['font-family']);
|
|
26
28
|
|
|
27
|
-
const
|
|
29
|
+
const fontOptions = fonts.map((font) => ({
|
|
28
30
|
label: font.name || font.fontFamily,
|
|
29
31
|
value: font.fontFamily,
|
|
30
32
|
}));
|
|
31
33
|
if (
|
|
32
|
-
!
|
|
34
|
+
!fontOptions.some((option) => normalizeFontFamily(option.value) === current)
|
|
33
35
|
) {
|
|
34
|
-
|
|
36
|
+
fontOptions.unshift({
|
|
35
37
|
label: DEFAULT_FONT_LABEL,
|
|
36
38
|
value: current,
|
|
37
39
|
});
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
let selected = current;
|
|
41
|
-
const content = createFontList(
|
|
43
|
+
const content = createFontList(fontOptions, selected, (value) => {
|
|
42
44
|
if (selected === value) return;
|
|
43
45
|
selected = value;
|
|
44
46
|
commander.executeBatch(
|
|
@@ -51,11 +53,12 @@ export const FontFamily: EditItem<TextAttributes> = (
|
|
|
51
53
|
);
|
|
52
54
|
});
|
|
53
55
|
|
|
54
|
-
const button = IconButton({ icon: TEXT_ICONS.fontFamily });
|
|
56
|
+
const button = IconButton({ icon: TEXT_ICONS.fontFamily, root });
|
|
55
57
|
|
|
56
58
|
const popover = Popover({
|
|
57
59
|
target: button,
|
|
58
60
|
content,
|
|
61
|
+
getContainer: root,
|
|
59
62
|
placement: ['top', 'bottom'],
|
|
60
63
|
offset: 12,
|
|
61
64
|
trigger: 'hover',
|
|
@@ -110,7 +113,7 @@ function normalizeFontFamily(font: TextAttributes['font-family']) {
|
|
|
110
113
|
return encodeFontFamily(String(font));
|
|
111
114
|
}
|
|
112
115
|
|
|
113
|
-
function ensureFontFamilyListStyle() {
|
|
116
|
+
function ensureFontFamilyListStyle(target?: Node) {
|
|
114
117
|
injectStyleOnce(
|
|
115
118
|
FONT_LIST_STYLE_ID,
|
|
116
119
|
`
|
|
@@ -143,5 +146,6 @@ function ensureFontFamilyListStyle() {
|
|
|
143
146
|
color: #0958d9;
|
|
144
147
|
}
|
|
145
148
|
`,
|
|
149
|
+
target,
|
|
146
150
|
);
|
|
147
151
|
}
|
|
@@ -30,10 +30,12 @@ export const FontSize: EditItem<TextAttributes> = (
|
|
|
30
30
|
selection,
|
|
31
31
|
attrs,
|
|
32
32
|
commander,
|
|
33
|
+
options,
|
|
33
34
|
) => {
|
|
34
|
-
|
|
35
|
+
const root = options?.root;
|
|
36
|
+
injectStyleOnce(FONT_SIZE_STYLE_ID, FONT_SIZE_STYLES, root);
|
|
35
37
|
|
|
36
|
-
const button = IconButton({ icon: TEXT_ICONS.fontSize });
|
|
38
|
+
const button = IconButton({ icon: TEXT_ICONS.fontSize, root });
|
|
37
39
|
const currentSize = normalizeFontSize(attrs['font-size']);
|
|
38
40
|
const content = createFontSizeContent(currentSize, (size) => {
|
|
39
41
|
commander.executeBatch(
|
|
@@ -44,11 +46,12 @@ export const FontSize: EditItem<TextAttributes> = (
|
|
|
44
46
|
}),
|
|
45
47
|
),
|
|
46
48
|
);
|
|
47
|
-
});
|
|
49
|
+
}, root);
|
|
48
50
|
|
|
49
51
|
return Popover({
|
|
50
52
|
target: button,
|
|
51
53
|
content,
|
|
54
|
+
getContainer: root,
|
|
52
55
|
placement: 'top',
|
|
53
56
|
offset: 12,
|
|
54
57
|
});
|
|
@@ -57,6 +60,7 @@ export const FontSize: EditItem<TextAttributes> = (
|
|
|
57
60
|
function createFontSizeContent(
|
|
58
61
|
defaultSize: number,
|
|
59
62
|
onSizeChange: (size: number) => void,
|
|
63
|
+
root?: Node,
|
|
60
64
|
) {
|
|
61
65
|
const content = document.createElement('div');
|
|
62
66
|
content.classList.add(FONT_SIZE_CLASS);
|
|
@@ -73,6 +77,7 @@ function createFontSizeContent(
|
|
|
73
77
|
|
|
74
78
|
FONT_SIZE_OPTIONS.forEach(({ label, value }) => {
|
|
75
79
|
const button = IconButton({
|
|
80
|
+
root,
|
|
76
81
|
icon: createLabelIcon(label),
|
|
77
82
|
onClick: () => {
|
|
78
83
|
if (selected === value) return;
|