@tmagic/editor 1.0.4 → 1.1.0-beta.1
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/dist/tmagic-editor.es.js +237 -98
- package/dist/tmagic-editor.es.js.map +1 -1
- package/dist/tmagic-editor.umd.js +269 -129
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/dist/types/src/Editor.vue.d.ts +28 -1
- package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +2 -0
- package/dist/types/src/services/editor.d.ts +6 -0
- package/dist/types/src/type.d.ts +3 -0
- package/dist/types/src/utils/editor.d.ts +8 -4
- package/package.json +8 -8
- package/src/Editor.vue +28 -6
- package/src/components/Icon.vue +1 -1
- package/src/components/ToolButton.vue +1 -1
- package/src/fields/UISelect.vue +1 -1
- package/src/layouts/AddPageBox.vue +1 -1
- package/src/layouts/PropsPanel.vue +12 -9
- package/src/layouts/sidebar/ComponentListPanel.vue +55 -2
- package/src/layouts/sidebar/LayerMenu.vue +1 -1
- package/src/layouts/sidebar/LayerPanel.vue +1 -1
- package/src/layouts/sidebar/Sidebar.vue +4 -4
- package/src/layouts/sidebar/TabPane.vue +7 -5
- package/src/layouts/workspace/PageBar.vue +1 -1
- package/src/layouts/workspace/Stage.vue +52 -11
- package/src/layouts/workspace/ViewerMenu.vue +1 -1
- package/src/services/editor.ts +74 -17
- package/src/type.ts +3 -0
- package/src/utils/editor.ts +45 -35
package/src/services/editor.ts
CHANGED
|
@@ -33,9 +33,10 @@ import {
|
|
|
33
33
|
change2Fixed,
|
|
34
34
|
COPY_STORAGE_KEY,
|
|
35
35
|
Fixed2Other,
|
|
36
|
+
fixNodeLeft,
|
|
36
37
|
generatePageNameByApp,
|
|
38
|
+
getInitPositionStyle,
|
|
37
39
|
getNodeIndex,
|
|
38
|
-
initPosition,
|
|
39
40
|
isFixed,
|
|
40
41
|
setLayout,
|
|
41
42
|
} from '@editor/utils/editor';
|
|
@@ -70,6 +71,7 @@ class Editor extends BaseService {
|
|
|
70
71
|
'paste',
|
|
71
72
|
'alignCenter',
|
|
72
73
|
'moveLayer',
|
|
74
|
+
'moveToContainer',
|
|
73
75
|
'move',
|
|
74
76
|
'undo',
|
|
75
77
|
'redo',
|
|
@@ -274,7 +276,7 @@ class Editor extends BaseService {
|
|
|
274
276
|
const { type, ...config } = addNode;
|
|
275
277
|
const curNode = this.get<MContainer>('node');
|
|
276
278
|
|
|
277
|
-
let parentNode:
|
|
279
|
+
let parentNode: MContainer | undefined;
|
|
278
280
|
const isPage = type === NodeType.PAGE;
|
|
279
281
|
|
|
280
282
|
if (isPage) {
|
|
@@ -291,12 +293,8 @@ class Editor extends BaseService {
|
|
|
291
293
|
if (!parentNode) throw new Error('未找到父元素');
|
|
292
294
|
|
|
293
295
|
const layout = await this.getLayout(toRaw(parentNode), addNode as MNode);
|
|
294
|
-
const newNode =
|
|
295
|
-
|
|
296
|
-
layout,
|
|
297
|
-
parentNode,
|
|
298
|
-
this.get<StageCore>('stage'),
|
|
299
|
-
);
|
|
296
|
+
const newNode = { ...toRaw(await propsService.getPropsValue(type, config)) };
|
|
297
|
+
newNode.style = getInitPositionStyle(newNode.style, layout, parentNode, this.get<StageCore>('stage'));
|
|
300
298
|
|
|
301
299
|
if ((parentNode?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && newNode.type !== NodeType.PAGE) {
|
|
302
300
|
throw new Error('app下不能添加组件');
|
|
@@ -305,8 +303,17 @@ class Editor extends BaseService {
|
|
|
305
303
|
parentNode?.items?.push(newNode);
|
|
306
304
|
|
|
307
305
|
const stage = this.get<StageCore | null>('stage');
|
|
306
|
+
const root = this.get<MApp>('root');
|
|
307
|
+
|
|
308
|
+
await stage?.add({ config: cloneDeep(newNode), root: cloneDeep(root) });
|
|
308
309
|
|
|
309
|
-
|
|
310
|
+
if (layout === Layout.ABSOLUTE) {
|
|
311
|
+
const fixedLeft = fixNodeLeft(newNode, parentNode, stage?.renderer.contentWindow?.document);
|
|
312
|
+
if (typeof fixedLeft !== 'undefined') {
|
|
313
|
+
newNode.style.left = fixedLeft;
|
|
314
|
+
await stage?.update({ config: cloneDeep(newNode), root: cloneDeep(root) });
|
|
315
|
+
}
|
|
316
|
+
}
|
|
310
317
|
|
|
311
318
|
await this.select(newNode);
|
|
312
319
|
|
|
@@ -348,7 +355,7 @@ class Editor extends BaseService {
|
|
|
348
355
|
|
|
349
356
|
parent.items?.splice(index, 1);
|
|
350
357
|
const stage = this.get<StageCore | null>('stage');
|
|
351
|
-
stage?.remove({ id: node.id, root: this.get('root') });
|
|
358
|
+
stage?.remove({ id: node.id, root: cloneDeep(this.get('root')) });
|
|
352
359
|
|
|
353
360
|
if (node.type === NodeType.PAGE) {
|
|
354
361
|
this.state.pageLength -= 1;
|
|
@@ -431,7 +438,7 @@ class Editor extends BaseService {
|
|
|
431
438
|
this.set('node', newConfig);
|
|
432
439
|
}
|
|
433
440
|
|
|
434
|
-
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
|
|
441
|
+
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(newConfig), root: cloneDeep(this.get('root')) });
|
|
435
442
|
|
|
436
443
|
if (newConfig.type === NodeType.PAGE) {
|
|
437
444
|
this.set('page', newConfig);
|
|
@@ -464,7 +471,7 @@ class Editor extends BaseService {
|
|
|
464
471
|
await this.update(parent);
|
|
465
472
|
await this.select(node);
|
|
466
473
|
|
|
467
|
-
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(node), root: this.get('root') });
|
|
474
|
+
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(node), root: cloneDeep(this.get('root')) });
|
|
468
475
|
|
|
469
476
|
this.addModifiedNodeId(parent.id);
|
|
470
477
|
this.pushHistoryState();
|
|
@@ -544,7 +551,10 @@ class Editor extends BaseService {
|
|
|
544
551
|
}
|
|
545
552
|
|
|
546
553
|
await this.update(node);
|
|
547
|
-
this.get<StageCore | null>('stage')?.update({
|
|
554
|
+
this.get<StageCore | null>('stage')?.update({
|
|
555
|
+
config: cloneDeep(toRaw(node)),
|
|
556
|
+
root: cloneDeep(this.get<MApp>('root')),
|
|
557
|
+
});
|
|
548
558
|
this.addModifiedNodeId(config.id);
|
|
549
559
|
this.pushHistoryState();
|
|
550
560
|
|
|
@@ -569,7 +579,54 @@ class Editor extends BaseService {
|
|
|
569
579
|
brothers.splice(index + parseInt(`${offset}`, 10), 0, brothers.splice(index, 1)[0]);
|
|
570
580
|
}
|
|
571
581
|
|
|
572
|
-
this.get<StageCore | null>('stage')?.update({
|
|
582
|
+
this.get<StageCore | null>('stage')?.update({
|
|
583
|
+
config: cloneDeep(toRaw(parent)),
|
|
584
|
+
root: cloneDeep(this.get<MApp>('root')),
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* 移动到指定容器中
|
|
590
|
+
* @param config 需要移动的节点
|
|
591
|
+
* @param targetId 容器ID
|
|
592
|
+
*/
|
|
593
|
+
public async moveToContainer(config: MNode, targetId: Id): Promise<MNode | undefined> {
|
|
594
|
+
const { node, parent } = this.getNodeInfo(config.id, false);
|
|
595
|
+
const target = this.getNodeById(targetId, false) as MContainer;
|
|
596
|
+
|
|
597
|
+
const stage = this.get<StageCore | null>('stage');
|
|
598
|
+
|
|
599
|
+
if (node && parent && stage) {
|
|
600
|
+
const root = cloneDeep(this.get<MApp>('root'));
|
|
601
|
+
const index = getNodeIndex(node, parent);
|
|
602
|
+
parent.items?.splice(index, 1);
|
|
603
|
+
|
|
604
|
+
await stage.remove({ id: node.id, root });
|
|
605
|
+
|
|
606
|
+
const layout = await this.getLayout(target);
|
|
607
|
+
|
|
608
|
+
const newConfig = mergeWith(cloneDeep(node), config, (objValue, srcValue) => {
|
|
609
|
+
if (Array.isArray(srcValue)) {
|
|
610
|
+
return srcValue;
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
newConfig.style = getInitPositionStyle(newConfig.style, layout, target, stage);
|
|
614
|
+
|
|
615
|
+
target.items.push(newConfig);
|
|
616
|
+
|
|
617
|
+
await stage.select(targetId);
|
|
618
|
+
|
|
619
|
+
await stage.update({ config: cloneDeep(target), root });
|
|
620
|
+
|
|
621
|
+
await this.select(newConfig);
|
|
622
|
+
stage.select(newConfig.id);
|
|
623
|
+
|
|
624
|
+
this.addModifiedNodeId(target.id);
|
|
625
|
+
this.addModifiedNodeId(parent.id);
|
|
626
|
+
this.pushHistoryState();
|
|
627
|
+
|
|
628
|
+
return newConfig;
|
|
629
|
+
}
|
|
573
630
|
}
|
|
574
631
|
|
|
575
632
|
/**
|
|
@@ -656,13 +713,13 @@ class Editor extends BaseService {
|
|
|
656
713
|
}
|
|
657
714
|
|
|
658
715
|
private async toggleFixedPosition(dist: MNode, src: MNode, root: MApp) {
|
|
659
|
-
|
|
716
|
+
const newConfig = cloneDeep(dist);
|
|
660
717
|
|
|
661
718
|
if (!isPop(src) && newConfig.style?.position) {
|
|
662
719
|
if (isFixed(newConfig) && !isFixed(src)) {
|
|
663
|
-
newConfig = change2Fixed(newConfig, root);
|
|
720
|
+
newConfig.style = change2Fixed(newConfig, root);
|
|
664
721
|
} else if (!isFixed(newConfig) && isFixed(src)) {
|
|
665
|
-
newConfig = await Fixed2Other(newConfig, root, this.getLayout);
|
|
722
|
+
newConfig.style = await Fixed2Other(newConfig, root, this.getLayout);
|
|
666
723
|
}
|
|
667
724
|
}
|
|
668
725
|
|
package/src/type.ts
CHANGED
|
@@ -49,9 +49,12 @@ export interface Services {
|
|
|
49
49
|
export interface StageOptions {
|
|
50
50
|
runtimeUrl: string;
|
|
51
51
|
autoScrollIntoView: boolean;
|
|
52
|
+
containerHighlightClassName: string;
|
|
53
|
+
containerHighlightDuration: number;
|
|
52
54
|
render: () => HTMLDivElement;
|
|
53
55
|
moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
|
|
54
56
|
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
|
57
|
+
isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
|
|
55
58
|
updateDragEl: (el: HTMLDivElement) => void;
|
|
56
59
|
}
|
|
57
60
|
|
package/src/utils/editor.ts
CHANGED
|
@@ -81,21 +81,17 @@ export const getNodeIndex = (node: MNode, parent: MContainer | MApp): number =>
|
|
|
81
81
|
return items.findIndex((item: MNode) => `${item.id}` === `${node.id}`);
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
export const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const setTop2Middle = (node: MNode, parentNode: MNode, stage: StageCore) => {
|
|
95
|
-
const style = node.style || {};
|
|
84
|
+
export const getRelativeStyle = (style: Record<string, any> = {}): Record<string, any> => ({
|
|
85
|
+
...style,
|
|
86
|
+
position: 'relative',
|
|
87
|
+
top: 0,
|
|
88
|
+
left: 0,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const getMiddleTop = (style: Record<string, any> = {}, parentNode: MNode, stage: StageCore) => {
|
|
96
92
|
let height = style.height || 0;
|
|
97
93
|
|
|
98
|
-
if (!stage || typeof style.top !== 'undefined' || !parentNode.style) return style;
|
|
94
|
+
if (!stage || typeof style.top !== 'undefined' || !parentNode.style) return style.top;
|
|
99
95
|
|
|
100
96
|
if (!isNumber(height)) {
|
|
101
97
|
height = 0;
|
|
@@ -105,43 +101,45 @@ const setTop2Middle = (node: MNode, parentNode: MNode, stage: StageCore) => {
|
|
|
105
101
|
|
|
106
102
|
if (isPage(parentNode)) {
|
|
107
103
|
const { scrollTop = 0, wrapperHeight } = stage.mask;
|
|
108
|
-
|
|
109
|
-
} else {
|
|
110
|
-
style.top = (parentHeight - height) / 2;
|
|
104
|
+
return (wrapperHeight - height) / 2 + scrollTop;
|
|
111
105
|
}
|
|
112
|
-
|
|
113
|
-
return style;
|
|
106
|
+
return (parentHeight - height) / 2;
|
|
114
107
|
};
|
|
115
108
|
|
|
116
|
-
export const
|
|
109
|
+
export const getInitPositionStyle = (
|
|
110
|
+
style: Record<string, any> = {},
|
|
111
|
+
layout: Layout,
|
|
112
|
+
parentNode: MNode,
|
|
113
|
+
stage: StageCore,
|
|
114
|
+
) => {
|
|
117
115
|
if (layout === Layout.ABSOLUTE) {
|
|
118
|
-
|
|
116
|
+
return {
|
|
117
|
+
...style,
|
|
119
118
|
position: 'absolute',
|
|
120
|
-
|
|
119
|
+
top: getMiddleTop(style, parentNode, stage),
|
|
121
120
|
};
|
|
122
|
-
return node;
|
|
123
121
|
}
|
|
124
122
|
|
|
125
123
|
if (layout === Layout.RELATIVE) {
|
|
126
|
-
return
|
|
124
|
+
return getRelativeStyle(style);
|
|
127
125
|
}
|
|
128
126
|
|
|
129
|
-
return
|
|
127
|
+
return style;
|
|
130
128
|
};
|
|
131
129
|
|
|
132
130
|
export const setLayout = (node: MNode, layout: Layout) => {
|
|
133
131
|
node.items?.forEach((child: MNode) => {
|
|
134
132
|
if (isPop(child)) return;
|
|
135
133
|
|
|
136
|
-
|
|
134
|
+
const style = child.style || {};
|
|
137
135
|
|
|
138
136
|
// 是 fixed 不做处理
|
|
139
|
-
if (
|
|
137
|
+
if (style.position === 'fixed') return;
|
|
140
138
|
|
|
141
139
|
if (layout !== Layout.RELATIVE) {
|
|
142
|
-
|
|
140
|
+
style.position = 'absolute';
|
|
143
141
|
} else {
|
|
144
|
-
|
|
142
|
+
child.style = getRelativeStyle(style);
|
|
145
143
|
child.style.right = 'auto';
|
|
146
144
|
child.style.bottom = 'auto';
|
|
147
145
|
}
|
|
@@ -161,11 +159,10 @@ export const change2Fixed = (node: MNode, root: MApp) => {
|
|
|
161
159
|
offset.top = offset.top + globalThis.parseFloat(value.style?.top || 0);
|
|
162
160
|
});
|
|
163
161
|
|
|
164
|
-
|
|
162
|
+
return {
|
|
165
163
|
...(node.style || {}),
|
|
166
164
|
...offset,
|
|
167
165
|
};
|
|
168
|
-
return node;
|
|
169
166
|
};
|
|
170
167
|
|
|
171
168
|
export const Fixed2Other = async (
|
|
@@ -186,23 +183,23 @@ export const Fixed2Other = async (
|
|
|
186
183
|
offset.left = offset.left - globalThis.parseFloat(value.style?.left || 0);
|
|
187
184
|
offset.top = offset.top - globalThis.parseFloat(value.style?.top || 0);
|
|
188
185
|
});
|
|
186
|
+
const style = node.style || {};
|
|
189
187
|
|
|
190
188
|
const parent = path.pop();
|
|
191
189
|
if (!parent) {
|
|
192
|
-
return
|
|
190
|
+
return getRelativeStyle(style);
|
|
193
191
|
}
|
|
194
192
|
|
|
195
193
|
const layout = await getLayout(parent);
|
|
196
194
|
if (layout !== Layout.RELATIVE) {
|
|
197
|
-
|
|
198
|
-
...
|
|
195
|
+
return {
|
|
196
|
+
...style,
|
|
199
197
|
...offset,
|
|
200
198
|
position: 'absolute',
|
|
201
199
|
};
|
|
202
|
-
return node;
|
|
203
200
|
}
|
|
204
201
|
|
|
205
|
-
return
|
|
202
|
+
return getRelativeStyle(style);
|
|
206
203
|
};
|
|
207
204
|
|
|
208
205
|
export const getGuideLineFromCache = (key: string): number[] => {
|
|
@@ -219,3 +216,16 @@ export const getGuideLineFromCache = (key: string): number[] => {
|
|
|
219
216
|
|
|
220
217
|
return [];
|
|
221
218
|
};
|
|
219
|
+
|
|
220
|
+
export const fixNodeLeft = (config: MNode, parent: MContainer, doc?: Document) => {
|
|
221
|
+
if (!doc || !config.style || !isNumber(config.style.left)) return config.style?.left;
|
|
222
|
+
|
|
223
|
+
const el = doc.getElementById(`${config.id}`);
|
|
224
|
+
const parentEl = doc.getElementById(`${parent.id}`);
|
|
225
|
+
|
|
226
|
+
if (el && parentEl && el.offsetWidth + config.style?.left > parentEl.offsetWidth) {
|
|
227
|
+
return parentEl.offsetWidth - el.offsetWidth;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return config.style.left;
|
|
231
|
+
};
|