@tmagic/stage 1.1.0-beta.1 → 1.1.0-beta.12
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-stage.es.js → tmagic-stage.mjs} +617 -259
- package/dist/tmagic-stage.mjs.map +1 -0
- package/dist/tmagic-stage.umd.js +634 -270
- package/dist/tmagic-stage.umd.js.map +1 -1
- package/package.json +14 -11
- package/src/StageCore.ts +115 -20
- package/src/StageDragResize.ts +86 -144
- package/src/StageHighlight.ts +1 -1
- package/src/StageMask.ts +29 -5
- package/src/StageMultiDragResize.ts +260 -0
- package/src/StageRender.ts +28 -18
- package/src/TargetCalibrate.ts +2 -1
- package/src/const.ts +2 -0
- package/src/style.css +1 -0
- package/src/types.ts +38 -16
- package/src/util.ts +87 -2
- package/tsconfig.build.json +13 -0
- package/{dist/types/src → types}/Rule.d.ts +0 -0
- package/{dist/types/src → types}/StageCore.d.ts +21 -3
- package/{dist/types/src → types}/StageDragResize.d.ts +9 -18
- package/{dist/types/src → types}/StageHighlight.d.ts +0 -0
- package/{dist/types/src → types}/StageMask.d.ts +1 -0
- package/types/StageMultiDragResize.d.ts +51 -0
- package/{dist/types/src → types}/StageRender.d.ts +1 -0
- package/{dist/types/src → types}/TargetCalibrate.d.ts +0 -0
- package/{dist/types/src → types}/const.d.ts +1 -0
- package/{dist/types/src → types}/index.d.ts +0 -0
- package/types/logger.d.ts +5 -0
- package/{dist/types/src → types}/types.d.ts +36 -16
- package/{dist/types/src → types}/util.d.ts +16 -1
- package/dist/tmagic-stage.es.js.map +0 -1
- package/dist/types/src/vite-env.d.ts +0 -1
- package/src/vite-env.d.ts +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import EventEmitter$1, { EventEmitter } from 'events';
|
|
2
|
+
import { removeClassName, removeClassNameByClassName, createDiv, injectStyle, isSameDomain, getHost, addClassName } from '@tmagic/utils';
|
|
3
|
+
import KeyController from 'keycon';
|
|
2
4
|
import Moveable from 'moveable';
|
|
3
5
|
import MoveableHelper from 'moveable-helper';
|
|
4
|
-
import { removeClassName, addClassName, removeClassNameByClassName, createDiv, injectStyle, isSameDomain, getHost } from '@tmagic/utils';
|
|
5
6
|
import { throttle } from 'lodash-es';
|
|
6
7
|
import Guides from '@scena/guides';
|
|
7
8
|
|
|
@@ -9,6 +10,7 @@ const GHOST_EL_ID_PREFIX = "ghost_el_";
|
|
|
9
10
|
const DRAG_EL_ID_PREFIX = "drag_el_";
|
|
10
11
|
const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
|
|
11
12
|
const CONTAINER_HIGHLIGHT_CLASS = "tmagic-stage-container-highlight";
|
|
13
|
+
const PAGE_CLASS = "magic-ui-page";
|
|
12
14
|
const DEFAULT_ZOOM = 1;
|
|
13
15
|
var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
|
|
14
16
|
GuidesType2["HORIZONTAL"] = "horizontal";
|
|
@@ -36,6 +38,18 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
|
|
|
36
38
|
})(Mode || {});
|
|
37
39
|
const SELECTED_CLASS = "tmagic-stage-selected-area";
|
|
38
40
|
|
|
41
|
+
var ContainerHighlightType = /* @__PURE__ */ ((ContainerHighlightType2) => {
|
|
42
|
+
ContainerHighlightType2["DEFAULT"] = "default";
|
|
43
|
+
ContainerHighlightType2["ALT"] = "alt";
|
|
44
|
+
return ContainerHighlightType2;
|
|
45
|
+
})(ContainerHighlightType || {});
|
|
46
|
+
var StageDragStatus = /* @__PURE__ */ ((StageDragStatus2) => {
|
|
47
|
+
StageDragStatus2["START"] = "start";
|
|
48
|
+
StageDragStatus2["ING"] = "ing";
|
|
49
|
+
StageDragStatus2["END"] = "end";
|
|
50
|
+
return StageDragStatus2;
|
|
51
|
+
})(StageDragStatus || {});
|
|
52
|
+
|
|
39
53
|
const getParents = (el, relative) => {
|
|
40
54
|
let cur = el.parentElement;
|
|
41
55
|
const parents = [];
|
|
@@ -61,6 +75,19 @@ const getOffset = (el) => {
|
|
|
61
75
|
top
|
|
62
76
|
};
|
|
63
77
|
};
|
|
78
|
+
const getTargetElStyle = (el) => {
|
|
79
|
+
const offset = getOffset(el);
|
|
80
|
+
const { transform } = getComputedStyle(el);
|
|
81
|
+
return `
|
|
82
|
+
position: absolute;
|
|
83
|
+
transform: ${transform};
|
|
84
|
+
left: ${offset.left}px;
|
|
85
|
+
top: ${offset.top}px;
|
|
86
|
+
width: ${el.clientWidth}px;
|
|
87
|
+
height: ${el.clientHeight}px;
|
|
88
|
+
z-index: ${ZIndex.DRAG_EL};
|
|
89
|
+
`;
|
|
90
|
+
};
|
|
64
91
|
const getAbsolutePosition = (el, { top, left }) => {
|
|
65
92
|
const { offsetParent } = el;
|
|
66
93
|
if (offsetParent) {
|
|
@@ -141,20 +168,86 @@ const calcValueByFontsize = (doc, value) => {
|
|
|
141
168
|
}
|
|
142
169
|
return value;
|
|
143
170
|
};
|
|
171
|
+
const down = (deltaTop, target) => {
|
|
172
|
+
let swapIndex = 0;
|
|
173
|
+
let addUpH = target.clientHeight;
|
|
174
|
+
const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
|
|
175
|
+
const index = brothers.indexOf(target);
|
|
176
|
+
const downEls = brothers.slice(index + 1);
|
|
177
|
+
for (let i = 0; i < downEls.length; i++) {
|
|
178
|
+
const ele = downEls[i];
|
|
179
|
+
if (ele.style?.position === "fixed") {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
addUpH += ele.clientHeight / 2;
|
|
183
|
+
if (deltaTop <= addUpH) {
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
addUpH += ele.clientHeight / 2;
|
|
187
|
+
swapIndex = i;
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
src: target.id,
|
|
191
|
+
dist: downEls.length && swapIndex > -1 ? downEls[swapIndex].id : target.id
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
const up = (deltaTop, target) => {
|
|
195
|
+
const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
|
|
196
|
+
const index = brothers.indexOf(target);
|
|
197
|
+
const upEls = brothers.slice(0, index);
|
|
198
|
+
let addUpH = target.clientHeight;
|
|
199
|
+
let swapIndex = upEls.length - 1;
|
|
200
|
+
for (let i = upEls.length - 1; i >= 0; i--) {
|
|
201
|
+
const ele = upEls[i];
|
|
202
|
+
if (!ele)
|
|
203
|
+
continue;
|
|
204
|
+
if (ele.style.position === "fixed")
|
|
205
|
+
continue;
|
|
206
|
+
addUpH += ele.clientHeight / 2;
|
|
207
|
+
if (-deltaTop <= addUpH)
|
|
208
|
+
break;
|
|
209
|
+
addUpH += ele.clientHeight / 2;
|
|
210
|
+
swapIndex = i;
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
src: target.id,
|
|
214
|
+
dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
|
|
215
|
+
};
|
|
216
|
+
};
|
|
144
217
|
|
|
145
218
|
class StageDragResize extends EventEmitter {
|
|
219
|
+
core;
|
|
220
|
+
mask;
|
|
221
|
+
container;
|
|
222
|
+
target;
|
|
223
|
+
dragEl;
|
|
224
|
+
moveable;
|
|
225
|
+
horizontalGuidelines = [];
|
|
226
|
+
verticalGuidelines = [];
|
|
227
|
+
elementGuidelines = [];
|
|
228
|
+
mode = Mode.ABSOLUTE;
|
|
229
|
+
moveableOptions = {};
|
|
230
|
+
dragStatus = StageDragStatus.END;
|
|
231
|
+
ghostEl;
|
|
232
|
+
moveableHelper;
|
|
233
|
+
isContainerHighlight = false;
|
|
146
234
|
constructor(config) {
|
|
147
235
|
super();
|
|
148
|
-
this.horizontalGuidelines = [];
|
|
149
|
-
this.verticalGuidelines = [];
|
|
150
|
-
this.elementGuidelines = [];
|
|
151
|
-
this.mode = Mode.ABSOLUTE;
|
|
152
|
-
this.moveableOptions = {};
|
|
153
|
-
this.dragStatus = "end" /* END */;
|
|
154
236
|
this.core = config.core;
|
|
155
237
|
this.container = config.container;
|
|
156
|
-
this.
|
|
157
|
-
|
|
238
|
+
this.mask = config.mask;
|
|
239
|
+
KeyController.global.keydown("alt", (e) => {
|
|
240
|
+
e.inputEvent.preventDefault();
|
|
241
|
+
this.isContainerHighlight = true;
|
|
242
|
+
});
|
|
243
|
+
KeyController.global.keyup("alt", (e) => {
|
|
244
|
+
e.inputEvent.preventDefault();
|
|
245
|
+
const doc = this.core.renderer.contentWindow?.document;
|
|
246
|
+
if (doc && this.canContainerHighlight()) {
|
|
247
|
+
removeClassNameByClassName(doc, this.core.containerHighlightClassName);
|
|
248
|
+
}
|
|
249
|
+
this.isContainerHighlight = false;
|
|
250
|
+
});
|
|
158
251
|
}
|
|
159
252
|
select(el, event) {
|
|
160
253
|
const oldTarget = this.target;
|
|
@@ -205,11 +298,21 @@ class StageDragResize extends EventEmitter {
|
|
|
205
298
|
this.moveableOptions.verticalGuidelines = [];
|
|
206
299
|
this.updateMoveable();
|
|
207
300
|
}
|
|
301
|
+
clearSelectStatus() {
|
|
302
|
+
if (!this.moveable)
|
|
303
|
+
return;
|
|
304
|
+
this.destroyDragEl();
|
|
305
|
+
this.moveable.target = null;
|
|
306
|
+
this.moveable.updateTarget();
|
|
307
|
+
}
|
|
308
|
+
destroyDragEl() {
|
|
309
|
+
this.dragEl?.remove();
|
|
310
|
+
}
|
|
208
311
|
destroy() {
|
|
209
312
|
this.moveable?.destroy();
|
|
210
313
|
this.destroyGhostEl();
|
|
211
314
|
this.destroyDragEl();
|
|
212
|
-
this.dragStatus =
|
|
315
|
+
this.dragStatus = StageDragStatus.END;
|
|
213
316
|
this.removeAllListeners();
|
|
214
317
|
}
|
|
215
318
|
init(el) {
|
|
@@ -218,7 +321,14 @@ class StageDragResize extends EventEmitter {
|
|
|
218
321
|
}
|
|
219
322
|
this.mode = getMode(el);
|
|
220
323
|
this.destroyGhostEl();
|
|
221
|
-
this.
|
|
324
|
+
this.destroyDragEl();
|
|
325
|
+
this.dragEl = globalThis.document.createElement("div");
|
|
326
|
+
this.container.append(this.dragEl);
|
|
327
|
+
this.dragEl.style.cssText = getTargetElStyle(el);
|
|
328
|
+
this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
|
|
329
|
+
if (typeof this.core.config.updateDragEl === "function") {
|
|
330
|
+
this.core.config.updateDragEl(this.dragEl, el);
|
|
331
|
+
}
|
|
222
332
|
this.moveableOptions = this.getOptions({
|
|
223
333
|
target: this.dragEl
|
|
224
334
|
});
|
|
@@ -266,7 +376,7 @@ class StageDragResize extends EventEmitter {
|
|
|
266
376
|
this.moveable.on("resizeStart", (e) => {
|
|
267
377
|
if (!this.target)
|
|
268
378
|
return;
|
|
269
|
-
this.dragStatus =
|
|
379
|
+
this.dragStatus = StageDragStatus.START;
|
|
270
380
|
this.moveableHelper?.onResizeStart(e);
|
|
271
381
|
frame.top = this.target.offsetTop;
|
|
272
382
|
frame.left = this.target.offsetLeft;
|
|
@@ -275,7 +385,7 @@ class StageDragResize extends EventEmitter {
|
|
|
275
385
|
if (!this.moveable || !this.target || !this.dragEl)
|
|
276
386
|
return;
|
|
277
387
|
const { beforeTranslate } = drag;
|
|
278
|
-
this.dragStatus =
|
|
388
|
+
this.dragStatus = StageDragStatus.ING;
|
|
279
389
|
this.moveableHelper?.onResize(e);
|
|
280
390
|
if (this.mode === Mode.SORTABLE) {
|
|
281
391
|
this.target.style.top = "0px";
|
|
@@ -286,7 +396,7 @@ class StageDragResize extends EventEmitter {
|
|
|
286
396
|
this.target.style.width = `${width}px`;
|
|
287
397
|
this.target.style.height = `${height}px`;
|
|
288
398
|
}).on("resizeEnd", () => {
|
|
289
|
-
this.dragStatus =
|
|
399
|
+
this.dragStatus = StageDragStatus.END;
|
|
290
400
|
this.update(true);
|
|
291
401
|
});
|
|
292
402
|
}
|
|
@@ -303,7 +413,7 @@ class StageDragResize extends EventEmitter {
|
|
|
303
413
|
this.moveable.on("dragStart", (e) => {
|
|
304
414
|
if (!this.target)
|
|
305
415
|
throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
|
|
306
|
-
this.dragStatus =
|
|
416
|
+
this.dragStatus = StageDragStatus.START;
|
|
307
417
|
this.moveableHelper?.onDragStart(e);
|
|
308
418
|
if (this.mode === Mode.SORTABLE) {
|
|
309
419
|
this.ghostEl = this.generateGhostEl(this.target);
|
|
@@ -317,16 +427,10 @@ class StageDragResize extends EventEmitter {
|
|
|
317
427
|
globalThis.clearTimeout(timeout);
|
|
318
428
|
timeout = void 0;
|
|
319
429
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
addClassName(el, doc, this.core.containerHighlightClassName);
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}, this.core.containerHighlightDuration);
|
|
329
|
-
this.dragStatus = "ing" /* ING */;
|
|
430
|
+
if (this.canContainerHighlight()) {
|
|
431
|
+
timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
|
|
432
|
+
}
|
|
433
|
+
this.dragStatus = StageDragStatus.ING;
|
|
330
434
|
if (this.ghostEl) {
|
|
331
435
|
this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
|
|
332
436
|
return;
|
|
@@ -340,10 +444,10 @@ class StageDragResize extends EventEmitter {
|
|
|
340
444
|
timeout = void 0;
|
|
341
445
|
}
|
|
342
446
|
let parentEl = null;
|
|
343
|
-
if (doc) {
|
|
447
|
+
if (doc && this.canContainerHighlight()) {
|
|
344
448
|
parentEl = removeClassNameByClassName(doc, this.core.containerHighlightClassName);
|
|
345
449
|
}
|
|
346
|
-
if (this.dragStatus ===
|
|
450
|
+
if (this.dragStatus === StageDragStatus.ING) {
|
|
347
451
|
if (parentEl) {
|
|
348
452
|
this.update(false, parentEl);
|
|
349
453
|
} else {
|
|
@@ -356,7 +460,7 @@ class StageDragResize extends EventEmitter {
|
|
|
356
460
|
}
|
|
357
461
|
}
|
|
358
462
|
}
|
|
359
|
-
this.dragStatus =
|
|
463
|
+
this.dragStatus = StageDragStatus.END;
|
|
360
464
|
this.destroyGhostEl();
|
|
361
465
|
});
|
|
362
466
|
}
|
|
@@ -364,17 +468,17 @@ class StageDragResize extends EventEmitter {
|
|
|
364
468
|
if (!this.moveable)
|
|
365
469
|
throw new Error("moveable \u672A\u521D\u59CB\u5316");
|
|
366
470
|
this.moveable.on("rotateStart", (e) => {
|
|
367
|
-
this.dragStatus =
|
|
471
|
+
this.dragStatus = StageDragStatus.START;
|
|
368
472
|
this.moveableHelper?.onRotateStart(e);
|
|
369
473
|
}).on("rotate", (e) => {
|
|
370
474
|
if (!this.target || !this.dragEl)
|
|
371
475
|
return;
|
|
372
|
-
this.dragStatus =
|
|
476
|
+
this.dragStatus = StageDragStatus.ING;
|
|
373
477
|
this.moveableHelper?.onRotate(e);
|
|
374
478
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
375
479
|
this.target.style.transform = frame?.toCSSObject().transform || "";
|
|
376
480
|
}).on("rotateEnd", (e) => {
|
|
377
|
-
this.dragStatus =
|
|
481
|
+
this.dragStatus = StageDragStatus.END;
|
|
378
482
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
379
483
|
this.emit("update", {
|
|
380
484
|
el: this.target,
|
|
@@ -388,17 +492,17 @@ class StageDragResize extends EventEmitter {
|
|
|
388
492
|
if (!this.moveable)
|
|
389
493
|
throw new Error("moveable \u672A\u521D\u59CB\u5316");
|
|
390
494
|
this.moveable.on("scaleStart", (e) => {
|
|
391
|
-
this.dragStatus =
|
|
495
|
+
this.dragStatus = StageDragStatus.START;
|
|
392
496
|
this.moveableHelper?.onScaleStart(e);
|
|
393
497
|
}).on("scale", (e) => {
|
|
394
498
|
if (!this.target || !this.dragEl)
|
|
395
499
|
return;
|
|
396
|
-
this.dragStatus =
|
|
500
|
+
this.dragStatus = StageDragStatus.ING;
|
|
397
501
|
this.moveableHelper?.onScale(e);
|
|
398
502
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
399
503
|
this.target.style.transform = frame?.toCSSObject().transform || "";
|
|
400
504
|
}).on("scaleEnd", (e) => {
|
|
401
|
-
this.dragStatus =
|
|
505
|
+
this.dragStatus = StageDragStatus.END;
|
|
402
506
|
const frame = this.moveableHelper?.getFrame(e.target);
|
|
403
507
|
this.emit("update", {
|
|
404
508
|
el: this.target,
|
|
@@ -446,9 +550,13 @@ class StageDragResize extends EventEmitter {
|
|
|
446
550
|
top = calcValueByFontsize(doc, this.dragEl.offsetTop) + parseFloat(translateY) - calcValueByFontsize(doc, parentTop);
|
|
447
551
|
}
|
|
448
552
|
this.emit("update", {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
553
|
+
data: [
|
|
554
|
+
{
|
|
555
|
+
el: this.target,
|
|
556
|
+
style: isResize ? { left, top, width, height } : { left, top }
|
|
557
|
+
}
|
|
558
|
+
],
|
|
559
|
+
parentEl
|
|
452
560
|
});
|
|
453
561
|
}
|
|
454
562
|
generateGhostEl(el) {
|
|
@@ -456,6 +564,7 @@ class StageDragResize extends EventEmitter {
|
|
|
456
564
|
this.destroyGhostEl();
|
|
457
565
|
}
|
|
458
566
|
const ghostEl = el.cloneNode(true);
|
|
567
|
+
this.setGhostElChildrenId(ghostEl);
|
|
459
568
|
const { top, left } = getAbsolutePosition(el, getOffset(el));
|
|
460
569
|
ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
|
|
461
570
|
ghostEl.style.zIndex = ZIndex.GHOST_EL;
|
|
@@ -466,30 +575,20 @@ class StageDragResize extends EventEmitter {
|
|
|
466
575
|
el.after(ghostEl);
|
|
467
576
|
return ghostEl;
|
|
468
577
|
}
|
|
578
|
+
setGhostElChildrenId(el) {
|
|
579
|
+
for (const child of Array.from(el.children)) {
|
|
580
|
+
if (child.id) {
|
|
581
|
+
child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
|
|
582
|
+
}
|
|
583
|
+
if (child.children.length) {
|
|
584
|
+
this.setGhostElChildrenId(child);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
469
588
|
destroyGhostEl() {
|
|
470
589
|
this.ghostEl?.remove();
|
|
471
590
|
this.ghostEl = void 0;
|
|
472
591
|
}
|
|
473
|
-
updateDragEl(el) {
|
|
474
|
-
const offset = getOffset(el);
|
|
475
|
-
const { transform } = getComputedStyle(el);
|
|
476
|
-
this.dragEl.style.cssText = `
|
|
477
|
-
position: absolute;
|
|
478
|
-
transform: ${transform};
|
|
479
|
-
left: ${offset.left}px;
|
|
480
|
-
top: ${offset.top}px;
|
|
481
|
-
width: ${el.clientWidth}px;
|
|
482
|
-
height: ${el.clientHeight}px;
|
|
483
|
-
z-index: ${ZIndex.DRAG_EL};
|
|
484
|
-
`;
|
|
485
|
-
this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
|
|
486
|
-
if (typeof this.core.config.updateDragEl === "function") {
|
|
487
|
-
this.core.config.updateDragEl(this.dragEl, el);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
destroyDragEl() {
|
|
491
|
-
this.dragEl?.remove();
|
|
492
|
-
}
|
|
493
592
|
getOptions(options = {}) {
|
|
494
593
|
if (!this.target)
|
|
495
594
|
return {};
|
|
@@ -540,7 +639,7 @@ class StageDragResize extends EventEmitter {
|
|
|
540
639
|
bounds: {
|
|
541
640
|
top: 0,
|
|
542
641
|
left: -1,
|
|
543
|
-
right: this.container.clientWidth,
|
|
642
|
+
right: this.container.clientWidth - 1,
|
|
544
643
|
bottom: this.container.clientHeight,
|
|
545
644
|
...moveableOptions.bounds || {}
|
|
546
645
|
},
|
|
@@ -548,55 +647,17 @@ class StageDragResize extends EventEmitter {
|
|
|
548
647
|
...moveableOptions
|
|
549
648
|
};
|
|
550
649
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
let swapIndex = 0;
|
|
554
|
-
let addUpH = target.clientHeight;
|
|
555
|
-
const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
|
|
556
|
-
const index = brothers.indexOf(target);
|
|
557
|
-
const downEls = brothers.slice(index + 1);
|
|
558
|
-
for (let i = 0; i < downEls.length; i++) {
|
|
559
|
-
const ele = downEls[i];
|
|
560
|
-
if (ele.style?.position === "fixed") {
|
|
561
|
-
continue;
|
|
562
|
-
}
|
|
563
|
-
addUpH += ele.clientHeight / 2;
|
|
564
|
-
if (deltaTop <= addUpH) {
|
|
565
|
-
break;
|
|
566
|
-
}
|
|
567
|
-
addUpH += ele.clientHeight / 2;
|
|
568
|
-
swapIndex = i;
|
|
569
|
-
}
|
|
570
|
-
return {
|
|
571
|
-
src: target.id,
|
|
572
|
-
dist: downEls.length && swapIndex > -1 ? downEls[swapIndex].id : target.id
|
|
573
|
-
};
|
|
574
|
-
};
|
|
575
|
-
const up = (deltaTop, target) => {
|
|
576
|
-
const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
|
|
577
|
-
const index = brothers.indexOf(target);
|
|
578
|
-
const upEls = brothers.slice(0, index);
|
|
579
|
-
let addUpH = target.clientHeight;
|
|
580
|
-
let swapIndex = upEls.length - 1;
|
|
581
|
-
for (let i = upEls.length - 1; i >= 0; i--) {
|
|
582
|
-
const ele = upEls[i];
|
|
583
|
-
if (!ele)
|
|
584
|
-
continue;
|
|
585
|
-
if (ele.style.position === "fixed")
|
|
586
|
-
continue;
|
|
587
|
-
addUpH += ele.clientHeight / 2;
|
|
588
|
-
if (-deltaTop <= addUpH)
|
|
589
|
-
break;
|
|
590
|
-
addUpH += ele.clientHeight / 2;
|
|
591
|
-
swapIndex = i;
|
|
650
|
+
canContainerHighlight() {
|
|
651
|
+
return this.core.containerHighlightType === ContainerHighlightType.DEFAULT || this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight;
|
|
592
652
|
}
|
|
593
|
-
|
|
594
|
-
src: target.id,
|
|
595
|
-
dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
|
|
596
|
-
};
|
|
597
|
-
};
|
|
653
|
+
}
|
|
598
654
|
|
|
599
655
|
class TargetCalibrate extends EventEmitter {
|
|
656
|
+
parent;
|
|
657
|
+
mask;
|
|
658
|
+
dr;
|
|
659
|
+
core;
|
|
660
|
+
operationEl;
|
|
600
661
|
constructor(config) {
|
|
601
662
|
super();
|
|
602
663
|
this.parent = config.parent;
|
|
@@ -616,6 +677,7 @@ class TargetCalibrate extends EventEmitter {
|
|
|
616
677
|
top: ${top}px;
|
|
617
678
|
width: ${el.clientWidth}px;
|
|
618
679
|
height: ${el.clientHeight}px;
|
|
680
|
+
z-index: ${ZIndex.DRAG_EL};
|
|
619
681
|
`;
|
|
620
682
|
this.operationEl.id = `${prefix}${el.id}`;
|
|
621
683
|
if (typeof this.core.config.updateDragEl === "function") {
|
|
@@ -663,6 +725,11 @@ class TargetCalibrate extends EventEmitter {
|
|
|
663
725
|
}
|
|
664
726
|
|
|
665
727
|
class StageHighlight extends EventEmitter {
|
|
728
|
+
core;
|
|
729
|
+
container;
|
|
730
|
+
target;
|
|
731
|
+
moveable;
|
|
732
|
+
calibrationTarget;
|
|
666
733
|
constructor(config) {
|
|
667
734
|
super();
|
|
668
735
|
this.core = config.core;
|
|
@@ -683,7 +750,7 @@ class StageHighlight extends EventEmitter {
|
|
|
683
750
|
target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
|
|
684
751
|
origin: false,
|
|
685
752
|
rootContainer: this.core.container,
|
|
686
|
-
zoom:
|
|
753
|
+
zoom: 2
|
|
687
754
|
});
|
|
688
755
|
}
|
|
689
756
|
clearHighlight() {
|
|
@@ -700,41 +767,14 @@ class StageHighlight extends EventEmitter {
|
|
|
700
767
|
}
|
|
701
768
|
|
|
702
769
|
class Rule extends EventEmitter$1 {
|
|
770
|
+
hGuides;
|
|
771
|
+
vGuides;
|
|
772
|
+
horizontalGuidelines = [];
|
|
773
|
+
verticalGuidelines = [];
|
|
774
|
+
container;
|
|
775
|
+
containerResizeObserver;
|
|
703
776
|
constructor(container) {
|
|
704
777
|
super();
|
|
705
|
-
this.horizontalGuidelines = [];
|
|
706
|
-
this.verticalGuidelines = [];
|
|
707
|
-
this.getGuidesStyle = (type) => ({
|
|
708
|
-
position: "fixed",
|
|
709
|
-
zIndex: 1,
|
|
710
|
-
left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
|
|
711
|
-
top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
|
|
712
|
-
width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
|
|
713
|
-
height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
|
|
714
|
-
});
|
|
715
|
-
this.createGuides = (type, defaultGuides = []) => new Guides(this.container, {
|
|
716
|
-
type,
|
|
717
|
-
defaultGuides,
|
|
718
|
-
displayDragPos: true,
|
|
719
|
-
backgroundColor: "#fff",
|
|
720
|
-
lineColor: "#000",
|
|
721
|
-
textColor: "#000",
|
|
722
|
-
style: this.getGuidesStyle(type)
|
|
723
|
-
});
|
|
724
|
-
this.hGuidesChangeGuidesHandler = (e) => {
|
|
725
|
-
this.horizontalGuidelines = e.guides;
|
|
726
|
-
this.emit("changeGuides", {
|
|
727
|
-
type: GuidesType.HORIZONTAL,
|
|
728
|
-
guides: this.horizontalGuidelines
|
|
729
|
-
});
|
|
730
|
-
};
|
|
731
|
-
this.vGuidesChangeGuidesHandler = (e) => {
|
|
732
|
-
this.verticalGuidelines = e.guides;
|
|
733
|
-
this.emit("changeGuides", {
|
|
734
|
-
type: GuidesType.VERTICAL,
|
|
735
|
-
guides: this.verticalGuidelines
|
|
736
|
-
});
|
|
737
|
-
};
|
|
738
778
|
this.container = container;
|
|
739
779
|
this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
|
|
740
780
|
this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
|
|
@@ -806,6 +846,37 @@ class Rule extends EventEmitter$1 {
|
|
|
806
846
|
this.containerResizeObserver.disconnect();
|
|
807
847
|
this.removeAllListeners();
|
|
808
848
|
}
|
|
849
|
+
getGuidesStyle = (type) => ({
|
|
850
|
+
position: "fixed",
|
|
851
|
+
zIndex: 1,
|
|
852
|
+
left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
|
|
853
|
+
top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
|
|
854
|
+
width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
|
|
855
|
+
height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
|
|
856
|
+
});
|
|
857
|
+
createGuides = (type, defaultGuides = []) => new Guides(this.container, {
|
|
858
|
+
type,
|
|
859
|
+
defaultGuides,
|
|
860
|
+
displayDragPos: true,
|
|
861
|
+
backgroundColor: "#fff",
|
|
862
|
+
lineColor: "#000",
|
|
863
|
+
textColor: "#000",
|
|
864
|
+
style: this.getGuidesStyle(type)
|
|
865
|
+
});
|
|
866
|
+
hGuidesChangeGuidesHandler = (e) => {
|
|
867
|
+
this.horizontalGuidelines = e.guides;
|
|
868
|
+
this.emit("changeGuides", {
|
|
869
|
+
type: GuidesType.HORIZONTAL,
|
|
870
|
+
guides: this.horizontalGuidelines
|
|
871
|
+
});
|
|
872
|
+
};
|
|
873
|
+
vGuidesChangeGuidesHandler = (e) => {
|
|
874
|
+
this.verticalGuidelines = e.guides;
|
|
875
|
+
this.emit("changeGuides", {
|
|
876
|
+
type: GuidesType.VERTICAL,
|
|
877
|
+
guides: this.verticalGuidelines
|
|
878
|
+
});
|
|
879
|
+
};
|
|
809
880
|
}
|
|
810
881
|
|
|
811
882
|
const wrapperClassName = "editor-mask-wrapper";
|
|
@@ -839,66 +910,30 @@ const createWrapper = () => {
|
|
|
839
910
|
return el;
|
|
840
911
|
};
|
|
841
912
|
class StageMask extends Rule {
|
|
913
|
+
content = createContent();
|
|
914
|
+
wrapper;
|
|
915
|
+
core;
|
|
916
|
+
page = null;
|
|
917
|
+
pageScrollParent = null;
|
|
918
|
+
scrollTop = 0;
|
|
919
|
+
scrollLeft = 0;
|
|
920
|
+
width = 0;
|
|
921
|
+
height = 0;
|
|
922
|
+
wrapperHeight = 0;
|
|
923
|
+
wrapperWidth = 0;
|
|
924
|
+
maxScrollTop = 0;
|
|
925
|
+
maxScrollLeft = 0;
|
|
926
|
+
intersectionObserver = null;
|
|
927
|
+
isMultiSelectStatus = false;
|
|
928
|
+
mode = Mode.ABSOLUTE;
|
|
929
|
+
pageResizeObserver = null;
|
|
930
|
+
wrapperResizeObserver = null;
|
|
931
|
+
highlightHandler = throttle((event) => {
|
|
932
|
+
this.emit("highlight", event);
|
|
933
|
+
}, throttleTime);
|
|
842
934
|
constructor(config) {
|
|
843
935
|
const wrapper = createWrapper();
|
|
844
936
|
super(wrapper);
|
|
845
|
-
this.content = createContent();
|
|
846
|
-
this.page = null;
|
|
847
|
-
this.pageScrollParent = null;
|
|
848
|
-
this.scrollTop = 0;
|
|
849
|
-
this.scrollLeft = 0;
|
|
850
|
-
this.width = 0;
|
|
851
|
-
this.height = 0;
|
|
852
|
-
this.wrapperHeight = 0;
|
|
853
|
-
this.wrapperWidth = 0;
|
|
854
|
-
this.maxScrollTop = 0;
|
|
855
|
-
this.maxScrollLeft = 0;
|
|
856
|
-
this.intersectionObserver = null;
|
|
857
|
-
this.mode = Mode.ABSOLUTE;
|
|
858
|
-
this.pageResizeObserver = null;
|
|
859
|
-
this.wrapperResizeObserver = null;
|
|
860
|
-
this.highlightHandler = throttle((event) => {
|
|
861
|
-
this.emit("highlight", event);
|
|
862
|
-
}, throttleTime);
|
|
863
|
-
this.mouseDownHandler = (event) => {
|
|
864
|
-
this.emit("clearHighlight");
|
|
865
|
-
event.stopImmediatePropagation();
|
|
866
|
-
event.stopPropagation();
|
|
867
|
-
if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
|
|
868
|
-
return;
|
|
869
|
-
if (event.target.className.indexOf("moveable-control") !== -1) {
|
|
870
|
-
return;
|
|
871
|
-
}
|
|
872
|
-
this.content.removeEventListener("mousemove", this.highlightHandler);
|
|
873
|
-
this.emit("beforeSelect", event);
|
|
874
|
-
globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
|
|
875
|
-
};
|
|
876
|
-
this.mouseUpHandler = () => {
|
|
877
|
-
globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
|
|
878
|
-
this.content.addEventListener("mousemove", this.highlightHandler);
|
|
879
|
-
this.emit("select");
|
|
880
|
-
};
|
|
881
|
-
this.mouseWheelHandler = (event) => {
|
|
882
|
-
this.emit("clearHighlight");
|
|
883
|
-
if (!this.page)
|
|
884
|
-
throw new Error("page \u672A\u521D\u59CB\u5316");
|
|
885
|
-
const { deltaY, deltaX } = event;
|
|
886
|
-
if (this.page.clientHeight < this.wrapperHeight && deltaY)
|
|
887
|
-
return;
|
|
888
|
-
if (this.page.clientWidth < this.wrapperWidth && deltaX)
|
|
889
|
-
return;
|
|
890
|
-
if (this.maxScrollTop > 0) {
|
|
891
|
-
this.scrollTop = this.scrollTop + deltaY;
|
|
892
|
-
}
|
|
893
|
-
if (this.maxScrollLeft > 0) {
|
|
894
|
-
this.scrollLeft = this.scrollLeft + deltaX;
|
|
895
|
-
}
|
|
896
|
-
this.scroll();
|
|
897
|
-
this.emit("scroll", event);
|
|
898
|
-
};
|
|
899
|
-
this.mouseLeaveHandler = () => {
|
|
900
|
-
setTimeout(() => this.emit("clearHighlight"), throttleTime);
|
|
901
|
-
};
|
|
902
937
|
this.wrapper = wrapper;
|
|
903
938
|
this.core = config.core;
|
|
904
939
|
this.content.addEventListener("mousedown", this.mouseDownHandler);
|
|
@@ -906,6 +941,16 @@ class StageMask extends Rule {
|
|
|
906
941
|
this.content.addEventListener("wheel", this.mouseWheelHandler);
|
|
907
942
|
this.content.addEventListener("mousemove", this.highlightHandler);
|
|
908
943
|
this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
|
|
944
|
+
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
|
945
|
+
const ctrl = isMac ? "meta" : "ctrl";
|
|
946
|
+
KeyController.global.keydown(ctrl, (e) => {
|
|
947
|
+
e.inputEvent.preventDefault();
|
|
948
|
+
this.isMultiSelectStatus = true;
|
|
949
|
+
});
|
|
950
|
+
KeyController.global.keyup(ctrl, (e) => {
|
|
951
|
+
e.inputEvent.preventDefault();
|
|
952
|
+
this.isMultiSelectStatus = false;
|
|
953
|
+
});
|
|
909
954
|
}
|
|
910
955
|
setMode(mode) {
|
|
911
956
|
this.mode = mode;
|
|
@@ -1034,49 +1079,237 @@ class StageMask extends Rule {
|
|
|
1034
1079
|
if (this.maxScrollLeft < this.scrollLeft)
|
|
1035
1080
|
this.scrollLeft = this.maxScrollLeft;
|
|
1036
1081
|
}
|
|
1082
|
+
mouseDownHandler = (event) => {
|
|
1083
|
+
this.emit("clearHighlight");
|
|
1084
|
+
event.stopImmediatePropagation();
|
|
1085
|
+
event.stopPropagation();
|
|
1086
|
+
if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
|
|
1087
|
+
return;
|
|
1088
|
+
if (!this.isMultiSelectStatus && event.target.className.indexOf("moveable-area") !== -1) {
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
if (event.target.className.indexOf("moveable-control") !== -1) {
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
this.content.removeEventListener("mousemove", this.highlightHandler);
|
|
1095
|
+
if (this.isMultiSelectStatus) {
|
|
1096
|
+
this.emit("beforeMultiSelect", event);
|
|
1097
|
+
} else {
|
|
1098
|
+
this.emit("beforeSelect", event);
|
|
1099
|
+
}
|
|
1100
|
+
globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
|
|
1101
|
+
};
|
|
1102
|
+
mouseUpHandler = () => {
|
|
1103
|
+
globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
|
|
1104
|
+
this.content.addEventListener("mousemove", this.highlightHandler);
|
|
1105
|
+
if (!this.isMultiSelectStatus) {
|
|
1106
|
+
this.emit("select");
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
1109
|
+
mouseWheelHandler = (event) => {
|
|
1110
|
+
this.emit("clearHighlight");
|
|
1111
|
+
if (!this.page)
|
|
1112
|
+
throw new Error("page \u672A\u521D\u59CB\u5316");
|
|
1113
|
+
const { deltaY, deltaX } = event;
|
|
1114
|
+
if (this.page.clientHeight < this.wrapperHeight && deltaY)
|
|
1115
|
+
return;
|
|
1116
|
+
if (this.page.clientWidth < this.wrapperWidth && deltaX)
|
|
1117
|
+
return;
|
|
1118
|
+
if (this.maxScrollTop > 0) {
|
|
1119
|
+
this.scrollTop = this.scrollTop + deltaY;
|
|
1120
|
+
}
|
|
1121
|
+
if (this.maxScrollLeft > 0) {
|
|
1122
|
+
this.scrollLeft = this.scrollLeft + deltaX;
|
|
1123
|
+
}
|
|
1124
|
+
this.scroll();
|
|
1125
|
+
this.emit("scroll", event);
|
|
1126
|
+
};
|
|
1127
|
+
mouseLeaveHandler = () => {
|
|
1128
|
+
setTimeout(() => this.emit("clearHighlight"), throttleTime);
|
|
1129
|
+
};
|
|
1037
1130
|
}
|
|
1038
1131
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1132
|
+
class StageMultiDragResize extends EventEmitter {
|
|
1133
|
+
core;
|
|
1134
|
+
mask;
|
|
1135
|
+
container;
|
|
1136
|
+
targetList = [];
|
|
1137
|
+
dragElList = [];
|
|
1138
|
+
moveableForMulti;
|
|
1139
|
+
dragStatus = StageDragStatus.END;
|
|
1140
|
+
multiMoveableHelper;
|
|
1141
|
+
constructor(config) {
|
|
1043
1142
|
super();
|
|
1044
|
-
this.
|
|
1045
|
-
this.
|
|
1046
|
-
this.
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1143
|
+
this.core = config.core;
|
|
1144
|
+
this.container = config.container;
|
|
1145
|
+
this.mask = config.mask;
|
|
1146
|
+
}
|
|
1147
|
+
multiSelect(els) {
|
|
1148
|
+
this.targetList = els;
|
|
1149
|
+
this.core.dr.destroyDragEl();
|
|
1150
|
+
this.destroyDragElList();
|
|
1151
|
+
this.dragElList = els.map((elItem) => {
|
|
1152
|
+
const dragElDiv = globalThis.document.createElement("div");
|
|
1153
|
+
this.container.append(dragElDiv);
|
|
1154
|
+
dragElDiv.style.cssText = getTargetElStyle(elItem);
|
|
1155
|
+
dragElDiv.id = `${DRAG_EL_ID_PREFIX}${elItem.id}`;
|
|
1156
|
+
if (typeof this.core.config.updateDragEl === "function") {
|
|
1157
|
+
this.core.config.updateDragEl(dragElDiv, elItem);
|
|
1052
1158
|
}
|
|
1159
|
+
return dragElDiv;
|
|
1053
1160
|
});
|
|
1054
|
-
this.
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1161
|
+
this.moveableForMulti?.destroy();
|
|
1162
|
+
this.multiMoveableHelper?.clear();
|
|
1163
|
+
this.moveableForMulti = new Moveable(this.container, this.getOptions({
|
|
1164
|
+
target: this.dragElList
|
|
1165
|
+
}));
|
|
1166
|
+
this.multiMoveableHelper = MoveableHelper.create({
|
|
1167
|
+
useBeforeRender: true,
|
|
1168
|
+
useRender: false,
|
|
1169
|
+
createAuto: true
|
|
1170
|
+
});
|
|
1171
|
+
const frames = [];
|
|
1172
|
+
this.moveableForMulti.on("dragGroupStart", (params) => {
|
|
1173
|
+
const { events } = params;
|
|
1174
|
+
this.multiMoveableHelper?.onDragGroupStart(params);
|
|
1175
|
+
events.forEach((ev) => {
|
|
1176
|
+
const matchEventTarget = this.targetList.find((targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
|
|
1177
|
+
if (!matchEventTarget)
|
|
1178
|
+
return;
|
|
1179
|
+
frames.push({
|
|
1180
|
+
left: matchEventTarget.offsetLeft,
|
|
1181
|
+
top: matchEventTarget.offsetTop,
|
|
1182
|
+
id: matchEventTarget.id
|
|
1183
|
+
});
|
|
1063
1184
|
});
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1185
|
+
this.dragStatus = StageDragStatus.START;
|
|
1186
|
+
}).on("dragGroup", (params) => {
|
|
1187
|
+
const { events } = params;
|
|
1188
|
+
events.forEach((ev) => {
|
|
1189
|
+
const frameSnapShot = frames.find((frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
|
|
1190
|
+
if (!frameSnapShot)
|
|
1191
|
+
return;
|
|
1192
|
+
const targeEl = this.targetList.find((targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
|
|
1193
|
+
if (!targeEl)
|
|
1194
|
+
return;
|
|
1195
|
+
const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
|
|
1196
|
+
if (!isParentIncluded) {
|
|
1197
|
+
targeEl.style.left = `${frameSnapShot.left + ev.beforeTranslate[0]}px`;
|
|
1198
|
+
targeEl.style.top = `${frameSnapShot.top + ev.beforeTranslate[1]}px`;
|
|
1072
1199
|
}
|
|
1200
|
+
});
|
|
1201
|
+
this.multiMoveableHelper?.onDragGroup(params);
|
|
1202
|
+
this.dragStatus = StageDragStatus.ING;
|
|
1203
|
+
}).on("dragGroupEnd", () => {
|
|
1204
|
+
this.update();
|
|
1205
|
+
this.dragStatus = StageDragStatus.END;
|
|
1206
|
+
}).on("clickGroup", (params) => {
|
|
1207
|
+
const { inputTarget, targets } = params;
|
|
1208
|
+
if (!this.mask.isMultiSelectStatus && targets.length > 1 && targets.includes(inputTarget)) {
|
|
1209
|
+
this.emit("select", inputTarget.id.replace(DRAG_EL_ID_PREFIX, ""));
|
|
1073
1210
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
canSelect(el, stop) {
|
|
1214
|
+
if (el.className.includes(PAGE_CLASS)) {
|
|
1215
|
+
this.core.highlightedDom = void 0;
|
|
1216
|
+
this.core.highlightLayer.clearHighlight();
|
|
1217
|
+
stop();
|
|
1218
|
+
return false;
|
|
1219
|
+
}
|
|
1220
|
+
const currentTargetMode = getMode(el);
|
|
1221
|
+
let selectedDomMode = "";
|
|
1222
|
+
if (this.core.selectedDom?.className.includes(PAGE_CLASS)) {
|
|
1223
|
+
return true;
|
|
1224
|
+
}
|
|
1225
|
+
if (this.targetList.length === 0 && this.core.selectedDom) {
|
|
1226
|
+
selectedDomMode = getMode(this.core.selectedDom);
|
|
1227
|
+
} else if (this.targetList.length > 0) {
|
|
1228
|
+
selectedDomMode = getMode(this.targetList[0]);
|
|
1229
|
+
}
|
|
1230
|
+
if (currentTargetMode !== selectedDomMode) {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
return true;
|
|
1234
|
+
}
|
|
1235
|
+
clearSelectStatus() {
|
|
1236
|
+
if (!this.moveableForMulti)
|
|
1237
|
+
return;
|
|
1238
|
+
this.destroyDragElList();
|
|
1239
|
+
this.moveableForMulti.target = null;
|
|
1240
|
+
this.moveableForMulti.updateTarget();
|
|
1241
|
+
this.targetList = [];
|
|
1242
|
+
}
|
|
1243
|
+
destroy() {
|
|
1244
|
+
this.moveableForMulti?.destroy();
|
|
1245
|
+
this.destroyDragElList();
|
|
1246
|
+
}
|
|
1247
|
+
destroyDragElList() {
|
|
1248
|
+
this.dragElList.forEach((dragElItem) => dragElItem?.remove());
|
|
1249
|
+
}
|
|
1250
|
+
update(isResize = false) {
|
|
1251
|
+
if (this.targetList.length === 0)
|
|
1252
|
+
return;
|
|
1253
|
+
const { contentWindow } = this.core.renderer;
|
|
1254
|
+
const doc = contentWindow?.document;
|
|
1255
|
+
if (!doc)
|
|
1256
|
+
return;
|
|
1257
|
+
this.emit("update", {
|
|
1258
|
+
data: this.targetList.map((targetItem) => {
|
|
1259
|
+
const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop };
|
|
1260
|
+
const left = calcValueByFontsize(doc, offset.left);
|
|
1261
|
+
const top = calcValueByFontsize(doc, offset.top);
|
|
1262
|
+
const width = calcValueByFontsize(doc, targetItem.clientWidth);
|
|
1263
|
+
const height = calcValueByFontsize(doc, targetItem.clientHeight);
|
|
1264
|
+
return {
|
|
1265
|
+
el: targetItem,
|
|
1266
|
+
style: isResize ? { left, top, width, height } : { left, top }
|
|
1267
|
+
};
|
|
1268
|
+
}),
|
|
1269
|
+
parentEl: null
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
getOptions(options = {}) {
|
|
1273
|
+
let { multiMoveableOptions = {} } = this.core.config;
|
|
1274
|
+
if (typeof multiMoveableOptions === "function") {
|
|
1275
|
+
multiMoveableOptions = multiMoveableOptions(this.core);
|
|
1276
|
+
}
|
|
1277
|
+
return {
|
|
1278
|
+
defaultGroupRotate: 0,
|
|
1279
|
+
defaultGroupOrigin: "50% 50%",
|
|
1280
|
+
draggable: true,
|
|
1281
|
+
resizable: false,
|
|
1282
|
+
throttleDrag: 0,
|
|
1283
|
+
startDragRotate: 0,
|
|
1284
|
+
throttleDragRotate: 0,
|
|
1285
|
+
zoom: 1,
|
|
1286
|
+
origin: true,
|
|
1287
|
+
padding: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
1288
|
+
snappable: true,
|
|
1289
|
+
bounds: {
|
|
1290
|
+
top: 0,
|
|
1291
|
+
left: -1,
|
|
1292
|
+
right: this.container.clientWidth - 1,
|
|
1293
|
+
bottom: this.container.clientHeight,
|
|
1294
|
+
...multiMoveableOptions.bounds || {}
|
|
1295
|
+
},
|
|
1296
|
+
...options,
|
|
1297
|
+
...multiMoveableOptions
|
|
1079
1298
|
};
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
const style = ".tmagic-stage-container-highlight::after {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n background-color: #000;\n opacity: .1;\n pointer-events: none;\n}\n";
|
|
1303
|
+
|
|
1304
|
+
class StageRender extends EventEmitter {
|
|
1305
|
+
contentWindow = null;
|
|
1306
|
+
runtime = null;
|
|
1307
|
+
iframe;
|
|
1308
|
+
runtimeUrl;
|
|
1309
|
+
core;
|
|
1310
|
+
render;
|
|
1311
|
+
constructor({ core }) {
|
|
1312
|
+
super();
|
|
1080
1313
|
this.core = core;
|
|
1081
1314
|
this.runtimeUrl = core.config.runtimeUrl || "";
|
|
1082
1315
|
this.render = core.config.render;
|
|
@@ -1089,20 +1322,39 @@ class StageRender extends EventEmitter {
|
|
|
1089
1322
|
`;
|
|
1090
1323
|
this.iframe.addEventListener("load", this.loadHandler);
|
|
1091
1324
|
}
|
|
1325
|
+
getMagicApi = () => ({
|
|
1326
|
+
onPageElUpdate: (el) => this.emit("page-el-update", el),
|
|
1327
|
+
onRuntimeReady: (runtime) => {
|
|
1328
|
+
this.runtime = runtime;
|
|
1329
|
+
globalThis.runtime = runtime;
|
|
1330
|
+
this.emit("runtime-ready", runtime);
|
|
1331
|
+
}
|
|
1332
|
+
});
|
|
1092
1333
|
async mount(el) {
|
|
1093
|
-
if (this.iframe) {
|
|
1094
|
-
if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
|
|
1095
|
-
let html = await fetch(this.runtimeUrl).then((res) => res.text());
|
|
1096
|
-
const base = `${location.protocol}//${getHost(this.runtimeUrl)}`;
|
|
1097
|
-
html = html.replace("<head>", `<head>
|
|
1098
|
-
<base href="${base}">`);
|
|
1099
|
-
this.iframe.srcdoc = html;
|
|
1100
|
-
}
|
|
1101
|
-
el.appendChild(this.iframe);
|
|
1102
|
-
} else {
|
|
1334
|
+
if (!this.iframe) {
|
|
1103
1335
|
throw Error("mount \u5931\u8D25");
|
|
1104
1336
|
}
|
|
1105
|
-
|
|
1337
|
+
if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
|
|
1338
|
+
let html = await fetch(this.runtimeUrl).then((res) => res.text());
|
|
1339
|
+
const base = `${location.protocol}//${getHost(this.runtimeUrl)}`;
|
|
1340
|
+
html = html.replace("<head>", `<head>
|
|
1341
|
+
<base href="${base}">`);
|
|
1342
|
+
this.iframe.srcdoc = html;
|
|
1343
|
+
}
|
|
1344
|
+
el.appendChild(this.iframe);
|
|
1345
|
+
this.postTmagicRuntimeReady();
|
|
1346
|
+
}
|
|
1347
|
+
getRuntime = () => {
|
|
1348
|
+
if (this.runtime)
|
|
1349
|
+
return Promise.resolve(this.runtime);
|
|
1350
|
+
return new Promise((resolve) => {
|
|
1351
|
+
const listener = (runtime) => {
|
|
1352
|
+
this.off("runtime-ready", listener);
|
|
1353
|
+
resolve(runtime);
|
|
1354
|
+
};
|
|
1355
|
+
this.on("runtime-ready", listener);
|
|
1356
|
+
});
|
|
1357
|
+
};
|
|
1106
1358
|
destroy() {
|
|
1107
1359
|
this.iframe?.removeEventListener("load", this.loadHandler);
|
|
1108
1360
|
this.contentWindow = null;
|
|
@@ -1110,21 +1362,60 @@ class StageRender extends EventEmitter {
|
|
|
1110
1362
|
this.iframe = void 0;
|
|
1111
1363
|
this.removeAllListeners();
|
|
1112
1364
|
}
|
|
1365
|
+
loadHandler = async () => {
|
|
1366
|
+
if (!this.contentWindow?.magic) {
|
|
1367
|
+
this.postTmagicRuntimeReady();
|
|
1368
|
+
}
|
|
1369
|
+
if (!this.contentWindow)
|
|
1370
|
+
return;
|
|
1371
|
+
if (this.render) {
|
|
1372
|
+
const el = await this.render(this.core);
|
|
1373
|
+
if (el) {
|
|
1374
|
+
this.contentWindow.document?.body?.appendChild(el);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
this.emit("onload");
|
|
1378
|
+
injectStyle(this.contentWindow.document, style);
|
|
1379
|
+
};
|
|
1380
|
+
postTmagicRuntimeReady() {
|
|
1381
|
+
this.contentWindow = this.iframe?.contentWindow;
|
|
1382
|
+
this.contentWindow.magic = this.getMagicApi();
|
|
1383
|
+
this.contentWindow.postMessage({
|
|
1384
|
+
tmagicRuntimeReady: true
|
|
1385
|
+
}, "*");
|
|
1386
|
+
}
|
|
1113
1387
|
}
|
|
1114
1388
|
|
|
1115
1389
|
class StageCore extends EventEmitter {
|
|
1390
|
+
container;
|
|
1391
|
+
selectedDom;
|
|
1392
|
+
selectedDomList = [];
|
|
1393
|
+
highlightedDom;
|
|
1394
|
+
renderer;
|
|
1395
|
+
mask;
|
|
1396
|
+
dr;
|
|
1397
|
+
multiDr;
|
|
1398
|
+
highlightLayer;
|
|
1399
|
+
config;
|
|
1400
|
+
zoom = DEFAULT_ZOOM;
|
|
1401
|
+
containerHighlightClassName;
|
|
1402
|
+
containerHighlightDuration;
|
|
1403
|
+
containerHighlightType;
|
|
1404
|
+
isContainer;
|
|
1405
|
+
canSelect;
|
|
1116
1406
|
constructor(config) {
|
|
1117
1407
|
super();
|
|
1118
|
-
this.zoom = DEFAULT_ZOOM;
|
|
1119
1408
|
this.config = config;
|
|
1120
1409
|
this.setZoom(config.zoom);
|
|
1121
1410
|
this.canSelect = config.canSelect || ((el) => !!el.id);
|
|
1122
1411
|
this.isContainer = config.isContainer;
|
|
1123
|
-
this.containerHighlightClassName = config.containerHighlightClassName;
|
|
1124
|
-
this.containerHighlightDuration = config.containerHighlightDuration;
|
|
1412
|
+
this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
|
|
1413
|
+
this.containerHighlightDuration = config.containerHighlightDuration || 800;
|
|
1414
|
+
this.containerHighlightType = config.containerHighlightType;
|
|
1125
1415
|
this.renderer = new StageRender({ core: this });
|
|
1126
1416
|
this.mask = new StageMask({ core: this });
|
|
1127
|
-
this.dr = new StageDragResize({ core: this, container: this.mask.content });
|
|
1417
|
+
this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
|
|
1418
|
+
this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
|
|
1128
1419
|
this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
|
|
1129
1420
|
this.renderer.on("runtime-ready", (runtime) => {
|
|
1130
1421
|
this.emit("runtime-ready", runtime);
|
|
@@ -1132,29 +1423,59 @@ class StageCore extends EventEmitter {
|
|
|
1132
1423
|
this.renderer.on("page-el-update", (el) => {
|
|
1133
1424
|
this.mask?.observe(el);
|
|
1134
1425
|
});
|
|
1135
|
-
this.mask.on("beforeSelect", (event) => {
|
|
1136
|
-
this.
|
|
1426
|
+
this.mask.on("beforeSelect", async (event) => {
|
|
1427
|
+
this.clearSelectStatus("multiSelect");
|
|
1428
|
+
const el = await this.getElementFromPoint(event);
|
|
1429
|
+
if (!el)
|
|
1430
|
+
return;
|
|
1431
|
+
this.select(el, event);
|
|
1137
1432
|
}).on("select", () => {
|
|
1138
1433
|
this.emit("select", this.selectedDom);
|
|
1139
1434
|
}).on("changeGuides", (data) => {
|
|
1140
1435
|
this.dr.setGuidelines(data.type, data.guides);
|
|
1141
1436
|
this.emit("changeGuides", data);
|
|
1142
1437
|
}).on("highlight", async (event) => {
|
|
1143
|
-
await this.
|
|
1438
|
+
const el = await this.getElementFromPoint(event);
|
|
1439
|
+
if (!el)
|
|
1440
|
+
return;
|
|
1441
|
+
if (this.multiDr.dragStatus === StageDragStatus.ING)
|
|
1442
|
+
return;
|
|
1443
|
+
await this.highlight(el);
|
|
1144
1444
|
if (this.highlightedDom === this.selectedDom) {
|
|
1145
1445
|
this.highlightLayer.clearHighlight();
|
|
1146
1446
|
return;
|
|
1147
1447
|
}
|
|
1148
|
-
this.highlightLayer.highlight(this.highlightedDom);
|
|
1149
1448
|
this.emit("highlight", this.highlightedDom);
|
|
1150
1449
|
}).on("clearHighlight", async () => {
|
|
1151
1450
|
this.highlightLayer.clearHighlight();
|
|
1451
|
+
}).on("beforeMultiSelect", async (event) => {
|
|
1452
|
+
const el = await this.getElementFromPoint(event);
|
|
1453
|
+
if (!el)
|
|
1454
|
+
return;
|
|
1455
|
+
if (this.selectedDom && !this.selectedDom.className.includes(PAGE_CLASS)) {
|
|
1456
|
+
this.selectedDomList.push(this.selectedDom);
|
|
1457
|
+
this.selectedDom = void 0;
|
|
1458
|
+
}
|
|
1459
|
+
const existIndex = this.selectedDomList.findIndex((selectedDom) => selectedDom.id === el.id);
|
|
1460
|
+
if (existIndex !== -1) {
|
|
1461
|
+
this.selectedDomList.splice(existIndex, 1);
|
|
1462
|
+
} else {
|
|
1463
|
+
this.selectedDomList.push(el);
|
|
1464
|
+
}
|
|
1465
|
+
this.multiSelect(this.selectedDomList);
|
|
1152
1466
|
});
|
|
1153
1467
|
this.dr.on("update", (data) => {
|
|
1154
1468
|
setTimeout(() => this.emit("update", data));
|
|
1155
1469
|
}).on("sort", (data) => {
|
|
1156
1470
|
setTimeout(() => this.emit("sort", data));
|
|
1157
1471
|
});
|
|
1472
|
+
this.multiDr.on("update", (data) => {
|
|
1473
|
+
setTimeout(() => this.emit("update", data));
|
|
1474
|
+
}).on("select", async (id) => {
|
|
1475
|
+
const el = await this.getTargetElement(id);
|
|
1476
|
+
this.select(el);
|
|
1477
|
+
setTimeout(() => this.emit("select", el));
|
|
1478
|
+
});
|
|
1158
1479
|
}
|
|
1159
1480
|
getElementsFromPoint(event) {
|
|
1160
1481
|
const { renderer, zoom } = this;
|
|
@@ -1170,24 +1491,29 @@ class StageCore extends EventEmitter {
|
|
|
1170
1491
|
}
|
|
1171
1492
|
return doc?.elementsFromPoint(x / zoom, y / zoom);
|
|
1172
1493
|
}
|
|
1173
|
-
async
|
|
1494
|
+
async getElementFromPoint(event) {
|
|
1174
1495
|
const els = this.getElementsFromPoint(event);
|
|
1175
1496
|
let stopped = false;
|
|
1176
1497
|
const stop = () => stopped = true;
|
|
1177
1498
|
for (const el of els) {
|
|
1178
|
-
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.
|
|
1499
|
+
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isElCanSelect(el, event, stop)) {
|
|
1179
1500
|
if (stopped)
|
|
1180
1501
|
break;
|
|
1181
|
-
|
|
1182
|
-
this.highlight(el);
|
|
1183
|
-
break;
|
|
1184
|
-
}
|
|
1185
|
-
this.select(el, event);
|
|
1186
|
-
break;
|
|
1502
|
+
return el;
|
|
1187
1503
|
}
|
|
1188
1504
|
}
|
|
1189
1505
|
}
|
|
1506
|
+
async isElCanSelect(el, event, stop) {
|
|
1507
|
+
const canSelectByProp = await this.canSelect(el, event, stop);
|
|
1508
|
+
if (!canSelectByProp)
|
|
1509
|
+
return false;
|
|
1510
|
+
if (this.mask.isMultiSelectStatus) {
|
|
1511
|
+
return this.multiDr.canSelect(el, stop);
|
|
1512
|
+
}
|
|
1513
|
+
return true;
|
|
1514
|
+
}
|
|
1190
1515
|
async select(idOrEl, event) {
|
|
1516
|
+
this.clearSelectStatus("multiSelect");
|
|
1191
1517
|
const el = await this.getTargetElement(idOrEl);
|
|
1192
1518
|
if (el === this.selectedDom)
|
|
1193
1519
|
return;
|
|
@@ -1209,6 +1535,12 @@ class StageCore extends EventEmitter {
|
|
|
1209
1535
|
}
|
|
1210
1536
|
}
|
|
1211
1537
|
}
|
|
1538
|
+
async multiSelect(idOrElList) {
|
|
1539
|
+
this.clearSelectStatus("select");
|
|
1540
|
+
const elList = await Promise.all(idOrElList.map(async (idOrEl) => await this.getTargetElement(idOrEl)));
|
|
1541
|
+
this.multiDr.multiSelect(elList);
|
|
1542
|
+
this.emit("multiSelect", elList);
|
|
1543
|
+
}
|
|
1212
1544
|
update(data) {
|
|
1213
1545
|
const { config } = data;
|
|
1214
1546
|
return this.renderer?.getRuntime().then((runtime) => {
|
|
@@ -1231,7 +1563,7 @@ class StageCore extends EventEmitter {
|
|
|
1231
1563
|
this.highlightLayer.clearHighlight();
|
|
1232
1564
|
return;
|
|
1233
1565
|
}
|
|
1234
|
-
if (el === this.highlightedDom)
|
|
1566
|
+
if (el === this.highlightedDom || !el)
|
|
1235
1567
|
return;
|
|
1236
1568
|
this.highlightLayer.highlight(el);
|
|
1237
1569
|
this.highlightedDom = el;
|
|
@@ -1248,6 +1580,14 @@ class StageCore extends EventEmitter {
|
|
|
1248
1580
|
setZoom(zoom = DEFAULT_ZOOM) {
|
|
1249
1581
|
this.zoom = zoom;
|
|
1250
1582
|
}
|
|
1583
|
+
clearSelectStatus(selectType) {
|
|
1584
|
+
if (selectType === "multiSelect") {
|
|
1585
|
+
this.multiDr.clearSelectStatus();
|
|
1586
|
+
this.selectedDomList = [];
|
|
1587
|
+
} else {
|
|
1588
|
+
this.dr.clearSelectStatus();
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1251
1591
|
async mount(el) {
|
|
1252
1592
|
this.container = el;
|
|
1253
1593
|
const { mask, renderer } = this;
|
|
@@ -1259,6 +1599,24 @@ class StageCore extends EventEmitter {
|
|
|
1259
1599
|
this.mask.clearGuides();
|
|
1260
1600
|
this.dr.clearGuides();
|
|
1261
1601
|
}
|
|
1602
|
+
async addContainerHighlightClassName(event, exclude) {
|
|
1603
|
+
const els = this.getElementsFromPoint(event);
|
|
1604
|
+
const { renderer } = this;
|
|
1605
|
+
const doc = renderer.contentWindow?.document;
|
|
1606
|
+
if (!doc)
|
|
1607
|
+
return;
|
|
1608
|
+
for (const el of els) {
|
|
1609
|
+
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isContainer(el) && !exclude.includes(el)) {
|
|
1610
|
+
addClassName(el, doc, this.containerHighlightClassName);
|
|
1611
|
+
break;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
getAddContainerHighlightClassNameTimeout(event, exclude = []) {
|
|
1616
|
+
return globalThis.setTimeout(() => {
|
|
1617
|
+
this.addContainerHighlightClassName(event, exclude);
|
|
1618
|
+
}, this.containerHighlightDuration);
|
|
1619
|
+
}
|
|
1262
1620
|
destroy() {
|
|
1263
1621
|
const { mask, renderer, dr, highlightLayer } = this;
|
|
1264
1622
|
renderer.destroy();
|
|
@@ -1279,5 +1637,5 @@ class StageCore extends EventEmitter {
|
|
|
1279
1637
|
}
|
|
1280
1638
|
}
|
|
1281
1639
|
|
|
1282
|
-
export { CONTAINER_HIGHLIGHT_CLASS, DEFAULT_ZOOM, DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, HIGHLIGHT_EL_ID_PREFIX, Mode, MouseButton, SELECTED_CLASS, StageDragResize, StageMask, StageRender, ZIndex, addSelectedClassName, calcValueByFontsize, StageCore as default, getAbsolutePosition, getMode, getOffset, getScrollParent, isAbsolute, isFixed, isFixedParent, isRelative, isStatic, removeSelectedClassName };
|
|
1283
|
-
//# sourceMappingURL=tmagic-stage.
|
|
1640
|
+
export { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, DEFAULT_ZOOM, DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, HIGHLIGHT_EL_ID_PREFIX, Mode, MouseButton, PAGE_CLASS, SELECTED_CLASS, StageDragResize, StageDragStatus, StageMask, StageRender, ZIndex, addSelectedClassName, calcValueByFontsize, StageCore as default, down, getAbsolutePosition, getMode, getOffset, getScrollParent, getTargetElStyle, isAbsolute, isFixed, isFixedParent, isRelative, isStatic, removeSelectedClassName, up };
|
|
1641
|
+
//# sourceMappingURL=tmagic-stage.mjs.map
|