@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.
@@ -1,20 +1,22 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('events'), require('moveable'), require('moveable-helper'), require('@tmagic/utils'), require('lodash-es'), require('@scena/guides')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'events', 'moveable', 'moveable-helper', '@tmagic/utils', 'lodash-es', '@scena/guides'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TMagicStage = {}, global.EventEmitter, global.Moveable, global.MoveableHelper, global.utils, global.lodashEs, global.Guides));
5
- })(this, (function (exports, EventEmitter, Moveable, MoveableHelper, utils, lodashEs, Guides) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('events'), require('@tmagic/utils'), require('keycon'), require('moveable'), require('moveable-helper'), require('lodash-es'), require('@scena/guides')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'events', '@tmagic/utils', 'keycon', 'moveable', 'moveable-helper', 'lodash-es', '@scena/guides'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TMagicStage = {}, global.EventEmitter, global.utils, global.KeyController, global.Moveable, global.MoveableHelper, global.lodashEs, global.Guides));
5
+ })(this, (function (exports, EventEmitter, utils, KeyController, Moveable, MoveableHelper, lodashEs, Guides) { 'use strict';
6
6
 
7
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
7
+ const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
8
8
 
9
- var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
10
- var Moveable__default = /*#__PURE__*/_interopDefaultLegacy(Moveable);
11
- var MoveableHelper__default = /*#__PURE__*/_interopDefaultLegacy(MoveableHelper);
12
- var Guides__default = /*#__PURE__*/_interopDefaultLegacy(Guides);
9
+ const EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
10
+ const KeyController__default = /*#__PURE__*/_interopDefaultLegacy(KeyController);
11
+ const Moveable__default = /*#__PURE__*/_interopDefaultLegacy(Moveable);
12
+ const MoveableHelper__default = /*#__PURE__*/_interopDefaultLegacy(MoveableHelper);
13
+ const Guides__default = /*#__PURE__*/_interopDefaultLegacy(Guides);
13
14
 
14
15
  const GHOST_EL_ID_PREFIX = "ghost_el_";
15
16
  const DRAG_EL_ID_PREFIX = "drag_el_";
16
17
  const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
17
18
  const CONTAINER_HIGHLIGHT_CLASS = "tmagic-stage-container-highlight";
19
+ const PAGE_CLASS = "magic-ui-page";
18
20
  const DEFAULT_ZOOM = 1;
19
21
  var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
20
22
  GuidesType2["HORIZONTAL"] = "horizontal";
@@ -42,6 +44,18 @@
42
44
  })(Mode || {});
43
45
  const SELECTED_CLASS = "tmagic-stage-selected-area";
44
46
 
47
+ var ContainerHighlightType = /* @__PURE__ */ ((ContainerHighlightType2) => {
48
+ ContainerHighlightType2["DEFAULT"] = "default";
49
+ ContainerHighlightType2["ALT"] = "alt";
50
+ return ContainerHighlightType2;
51
+ })(ContainerHighlightType || {});
52
+ var StageDragStatus = /* @__PURE__ */ ((StageDragStatus2) => {
53
+ StageDragStatus2["START"] = "start";
54
+ StageDragStatus2["ING"] = "ing";
55
+ StageDragStatus2["END"] = "end";
56
+ return StageDragStatus2;
57
+ })(StageDragStatus || {});
58
+
45
59
  const getParents = (el, relative) => {
46
60
  let cur = el.parentElement;
47
61
  const parents = [];
@@ -67,6 +81,19 @@
67
81
  top
68
82
  };
69
83
  };
84
+ const getTargetElStyle = (el) => {
85
+ const offset = getOffset(el);
86
+ const { transform } = getComputedStyle(el);
87
+ return `
88
+ position: absolute;
89
+ transform: ${transform};
90
+ left: ${offset.left}px;
91
+ top: ${offset.top}px;
92
+ width: ${el.clientWidth}px;
93
+ height: ${el.clientHeight}px;
94
+ z-index: ${ZIndex.DRAG_EL};
95
+ `;
96
+ };
70
97
  const getAbsolutePosition = (el, { top, left }) => {
71
98
  const { offsetParent } = el;
72
99
  if (offsetParent) {
@@ -147,27 +174,93 @@
147
174
  }
148
175
  return value;
149
176
  };
177
+ const down = (deltaTop, target) => {
178
+ let swapIndex = 0;
179
+ let addUpH = target.clientHeight;
180
+ const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
181
+ const index = brothers.indexOf(target);
182
+ const downEls = brothers.slice(index + 1);
183
+ for (let i = 0; i < downEls.length; i++) {
184
+ const ele = downEls[i];
185
+ if (ele.style?.position === "fixed") {
186
+ continue;
187
+ }
188
+ addUpH += ele.clientHeight / 2;
189
+ if (deltaTop <= addUpH) {
190
+ break;
191
+ }
192
+ addUpH += ele.clientHeight / 2;
193
+ swapIndex = i;
194
+ }
195
+ return {
196
+ src: target.id,
197
+ dist: downEls.length && swapIndex > -1 ? downEls[swapIndex].id : target.id
198
+ };
199
+ };
200
+ const up = (deltaTop, target) => {
201
+ const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
202
+ const index = brothers.indexOf(target);
203
+ const upEls = brothers.slice(0, index);
204
+ let addUpH = target.clientHeight;
205
+ let swapIndex = upEls.length - 1;
206
+ for (let i = upEls.length - 1; i >= 0; i--) {
207
+ const ele = upEls[i];
208
+ if (!ele)
209
+ continue;
210
+ if (ele.style.position === "fixed")
211
+ continue;
212
+ addUpH += ele.clientHeight / 2;
213
+ if (-deltaTop <= addUpH)
214
+ break;
215
+ addUpH += ele.clientHeight / 2;
216
+ swapIndex = i;
217
+ }
218
+ return {
219
+ src: target.id,
220
+ dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
221
+ };
222
+ };
150
223
 
151
224
  class StageDragResize extends EventEmitter.EventEmitter {
225
+ core;
226
+ mask;
227
+ container;
228
+ target;
229
+ dragEl;
230
+ moveable;
231
+ horizontalGuidelines = [];
232
+ verticalGuidelines = [];
233
+ elementGuidelines = [];
234
+ mode = Mode.ABSOLUTE;
235
+ moveableOptions = {};
236
+ dragStatus = StageDragStatus.END;
237
+ ghostEl;
238
+ moveableHelper;
239
+ isContainerHighlight = false;
152
240
  constructor(config) {
153
241
  super();
154
- this.horizontalGuidelines = [];
155
- this.verticalGuidelines = [];
156
- this.elementGuidelines = [];
157
- this.mode = Mode.ABSOLUTE;
158
- this.moveableOptions = {};
159
- this.dragStatus = "end" /* END */;
160
242
  this.core = config.core;
161
243
  this.container = config.container;
162
- this.dragEl = globalThis.document.createElement("div");
163
- this.container.append(this.dragEl);
244
+ this.mask = config.mask;
245
+ KeyController__default.default.global.keydown("alt", (e) => {
246
+ e.inputEvent.preventDefault();
247
+ this.isContainerHighlight = true;
248
+ });
249
+ KeyController__default.default.global.keyup("alt", (e) => {
250
+ e.inputEvent.preventDefault();
251
+ const doc = this.core.renderer.contentWindow?.document;
252
+ if (doc && this.canContainerHighlight()) {
253
+ utils.removeClassNameByClassName(doc, this.core.containerHighlightClassName);
254
+ }
255
+ this.isContainerHighlight = false;
256
+ });
164
257
  }
165
258
  select(el, event) {
166
259
  const oldTarget = this.target;
167
260
  this.target = el;
168
261
  if (!this.moveable || this.target !== oldTarget) {
169
262
  this.init(el);
170
- this.moveableHelper = MoveableHelper__default["default"].create({
263
+ this.moveableHelper = MoveableHelper__default.default.create({
171
264
  useBeforeRender: true,
172
265
  useRender: false,
173
266
  createAuto: true
@@ -211,11 +304,21 @@
211
304
  this.moveableOptions.verticalGuidelines = [];
212
305
  this.updateMoveable();
213
306
  }
307
+ clearSelectStatus() {
308
+ if (!this.moveable)
309
+ return;
310
+ this.destroyDragEl();
311
+ this.moveable.target = null;
312
+ this.moveable.updateTarget();
313
+ }
314
+ destroyDragEl() {
315
+ this.dragEl?.remove();
316
+ }
214
317
  destroy() {
215
318
  this.moveable?.destroy();
216
319
  this.destroyGhostEl();
217
320
  this.destroyDragEl();
218
- this.dragStatus = "end" /* END */;
321
+ this.dragStatus = StageDragStatus.END;
219
322
  this.removeAllListeners();
220
323
  }
221
324
  init(el) {
@@ -224,7 +327,14 @@
224
327
  }
225
328
  this.mode = getMode(el);
226
329
  this.destroyGhostEl();
227
- this.updateDragEl(el);
330
+ this.destroyDragEl();
331
+ this.dragEl = globalThis.document.createElement("div");
332
+ this.container.append(this.dragEl);
333
+ this.dragEl.style.cssText = getTargetElStyle(el);
334
+ this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
335
+ if (typeof this.core.config.updateDragEl === "function") {
336
+ this.core.config.updateDragEl(this.dragEl, el);
337
+ }
228
338
  this.moveableOptions = this.getOptions({
229
339
  target: this.dragEl
230
340
  });
@@ -254,7 +364,7 @@
254
364
  }
255
365
  initMoveable() {
256
366
  this.moveable?.destroy();
257
- this.moveable = new Moveable__default["default"](this.container, {
367
+ this.moveable = new Moveable__default.default(this.container, {
258
368
  ...this.moveableOptions
259
369
  });
260
370
  this.bindResizeEvent();
@@ -272,7 +382,7 @@
272
382
  this.moveable.on("resizeStart", (e) => {
273
383
  if (!this.target)
274
384
  return;
275
- this.dragStatus = "start" /* START */;
385
+ this.dragStatus = StageDragStatus.START;
276
386
  this.moveableHelper?.onResizeStart(e);
277
387
  frame.top = this.target.offsetTop;
278
388
  frame.left = this.target.offsetLeft;
@@ -281,7 +391,7 @@
281
391
  if (!this.moveable || !this.target || !this.dragEl)
282
392
  return;
283
393
  const { beforeTranslate } = drag;
284
- this.dragStatus = "ing" /* ING */;
394
+ this.dragStatus = StageDragStatus.ING;
285
395
  this.moveableHelper?.onResize(e);
286
396
  if (this.mode === Mode.SORTABLE) {
287
397
  this.target.style.top = "0px";
@@ -292,7 +402,7 @@
292
402
  this.target.style.width = `${width}px`;
293
403
  this.target.style.height = `${height}px`;
294
404
  }).on("resizeEnd", () => {
295
- this.dragStatus = "end" /* END */;
405
+ this.dragStatus = StageDragStatus.END;
296
406
  this.update(true);
297
407
  });
298
408
  }
@@ -309,7 +419,7 @@
309
419
  this.moveable.on("dragStart", (e) => {
310
420
  if (!this.target)
311
421
  throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
312
- this.dragStatus = "start" /* START */;
422
+ this.dragStatus = StageDragStatus.START;
313
423
  this.moveableHelper?.onDragStart(e);
314
424
  if (this.mode === Mode.SORTABLE) {
315
425
  this.ghostEl = this.generateGhostEl(this.target);
@@ -323,16 +433,10 @@
323
433
  globalThis.clearTimeout(timeout);
324
434
  timeout = void 0;
325
435
  }
326
- timeout = globalThis.setTimeout(async () => {
327
- const els = this.core.getElementsFromPoint(e.inputEvent);
328
- for (const el of els) {
329
- if (doc && !el.id.startsWith(GHOST_EL_ID_PREFIX) && el !== this.target && await this.core.isContainer(el)) {
330
- utils.addClassName(el, doc, this.core.containerHighlightClassName);
331
- break;
332
- }
333
- }
334
- }, this.core.containerHighlightDuration);
335
- this.dragStatus = "ing" /* ING */;
436
+ if (this.canContainerHighlight()) {
437
+ timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
438
+ }
439
+ this.dragStatus = StageDragStatus.ING;
336
440
  if (this.ghostEl) {
337
441
  this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
338
442
  return;
@@ -346,10 +450,10 @@
346
450
  timeout = void 0;
347
451
  }
348
452
  let parentEl = null;
349
- if (doc) {
453
+ if (doc && this.canContainerHighlight()) {
350
454
  parentEl = utils.removeClassNameByClassName(doc, this.core.containerHighlightClassName);
351
455
  }
352
- if (this.dragStatus === "ing" /* ING */) {
456
+ if (this.dragStatus === StageDragStatus.ING) {
353
457
  if (parentEl) {
354
458
  this.update(false, parentEl);
355
459
  } else {
@@ -362,7 +466,7 @@
362
466
  }
363
467
  }
364
468
  }
365
- this.dragStatus = "end" /* END */;
469
+ this.dragStatus = StageDragStatus.END;
366
470
  this.destroyGhostEl();
367
471
  });
368
472
  }
@@ -370,17 +474,17 @@
370
474
  if (!this.moveable)
371
475
  throw new Error("moveable \u672A\u521D\u59CB\u5316");
372
476
  this.moveable.on("rotateStart", (e) => {
373
- this.dragStatus = "start" /* START */;
477
+ this.dragStatus = StageDragStatus.START;
374
478
  this.moveableHelper?.onRotateStart(e);
375
479
  }).on("rotate", (e) => {
376
480
  if (!this.target || !this.dragEl)
377
481
  return;
378
- this.dragStatus = "ing" /* ING */;
482
+ this.dragStatus = StageDragStatus.ING;
379
483
  this.moveableHelper?.onRotate(e);
380
484
  const frame = this.moveableHelper?.getFrame(e.target);
381
485
  this.target.style.transform = frame?.toCSSObject().transform || "";
382
486
  }).on("rotateEnd", (e) => {
383
- this.dragStatus = "end" /* END */;
487
+ this.dragStatus = StageDragStatus.END;
384
488
  const frame = this.moveableHelper?.getFrame(e.target);
385
489
  this.emit("update", {
386
490
  el: this.target,
@@ -394,17 +498,17 @@
394
498
  if (!this.moveable)
395
499
  throw new Error("moveable \u672A\u521D\u59CB\u5316");
396
500
  this.moveable.on("scaleStart", (e) => {
397
- this.dragStatus = "start" /* START */;
501
+ this.dragStatus = StageDragStatus.START;
398
502
  this.moveableHelper?.onScaleStart(e);
399
503
  }).on("scale", (e) => {
400
504
  if (!this.target || !this.dragEl)
401
505
  return;
402
- this.dragStatus = "ing" /* ING */;
506
+ this.dragStatus = StageDragStatus.ING;
403
507
  this.moveableHelper?.onScale(e);
404
508
  const frame = this.moveableHelper?.getFrame(e.target);
405
509
  this.target.style.transform = frame?.toCSSObject().transform || "";
406
510
  }).on("scaleEnd", (e) => {
407
- this.dragStatus = "end" /* END */;
511
+ this.dragStatus = StageDragStatus.END;
408
512
  const frame = this.moveableHelper?.getFrame(e.target);
409
513
  this.emit("update", {
410
514
  el: this.target,
@@ -452,9 +556,13 @@
452
556
  top = calcValueByFontsize(doc, this.dragEl.offsetTop) + parseFloat(translateY) - calcValueByFontsize(doc, parentTop);
453
557
  }
454
558
  this.emit("update", {
455
- el: this.target,
456
- parentEl,
457
- style: isResize ? { left, top, width, height } : { left, top }
559
+ data: [
560
+ {
561
+ el: this.target,
562
+ style: isResize ? { left, top, width, height } : { left, top }
563
+ }
564
+ ],
565
+ parentEl
458
566
  });
459
567
  }
460
568
  generateGhostEl(el) {
@@ -462,6 +570,7 @@
462
570
  this.destroyGhostEl();
463
571
  }
464
572
  const ghostEl = el.cloneNode(true);
573
+ this.setGhostElChildrenId(ghostEl);
465
574
  const { top, left } = getAbsolutePosition(el, getOffset(el));
466
575
  ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
467
576
  ghostEl.style.zIndex = ZIndex.GHOST_EL;
@@ -472,30 +581,20 @@
472
581
  el.after(ghostEl);
473
582
  return ghostEl;
474
583
  }
584
+ setGhostElChildrenId(el) {
585
+ for (const child of Array.from(el.children)) {
586
+ if (child.id) {
587
+ child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
588
+ }
589
+ if (child.children.length) {
590
+ this.setGhostElChildrenId(child);
591
+ }
592
+ }
593
+ }
475
594
  destroyGhostEl() {
476
595
  this.ghostEl?.remove();
477
596
  this.ghostEl = void 0;
478
597
  }
479
- updateDragEl(el) {
480
- const offset = getOffset(el);
481
- const { transform } = getComputedStyle(el);
482
- this.dragEl.style.cssText = `
483
- position: absolute;
484
- transform: ${transform};
485
- left: ${offset.left}px;
486
- top: ${offset.top}px;
487
- width: ${el.clientWidth}px;
488
- height: ${el.clientHeight}px;
489
- z-index: ${ZIndex.DRAG_EL};
490
- `;
491
- this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
492
- if (typeof this.core.config.updateDragEl === "function") {
493
- this.core.config.updateDragEl(this.dragEl, el);
494
- }
495
- }
496
- destroyDragEl() {
497
- this.dragEl?.remove();
498
- }
499
598
  getOptions(options = {}) {
500
599
  if (!this.target)
501
600
  return {};
@@ -546,7 +645,7 @@
546
645
  bounds: {
547
646
  top: 0,
548
647
  left: -1,
549
- right: this.container.clientWidth,
648
+ right: this.container.clientWidth - 1,
550
649
  bottom: this.container.clientHeight,
551
650
  ...moveableOptions.bounds || {}
552
651
  },
@@ -554,55 +653,17 @@
554
653
  ...moveableOptions
555
654
  };
556
655
  }
557
- }
558
- const down = (deltaTop, target) => {
559
- let swapIndex = 0;
560
- let addUpH = target.clientHeight;
561
- const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
562
- const index = brothers.indexOf(target);
563
- const downEls = brothers.slice(index + 1);
564
- for (let i = 0; i < downEls.length; i++) {
565
- const ele = downEls[i];
566
- if (ele.style?.position === "fixed") {
567
- continue;
568
- }
569
- addUpH += ele.clientHeight / 2;
570
- if (deltaTop <= addUpH) {
571
- break;
572
- }
573
- addUpH += ele.clientHeight / 2;
574
- swapIndex = i;
575
- }
576
- return {
577
- src: target.id,
578
- dist: downEls.length && swapIndex > -1 ? downEls[swapIndex].id : target.id
579
- };
580
- };
581
- const up = (deltaTop, target) => {
582
- const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
583
- const index = brothers.indexOf(target);
584
- const upEls = brothers.slice(0, index);
585
- let addUpH = target.clientHeight;
586
- let swapIndex = upEls.length - 1;
587
- for (let i = upEls.length - 1; i >= 0; i--) {
588
- const ele = upEls[i];
589
- if (!ele)
590
- continue;
591
- if (ele.style.position === "fixed")
592
- continue;
593
- addUpH += ele.clientHeight / 2;
594
- if (-deltaTop <= addUpH)
595
- break;
596
- addUpH += ele.clientHeight / 2;
597
- swapIndex = i;
656
+ canContainerHighlight() {
657
+ return this.core.containerHighlightType === ContainerHighlightType.DEFAULT || this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight;
598
658
  }
599
- return {
600
- src: target.id,
601
- dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
602
- };
603
- };
659
+ }
604
660
 
605
661
  class TargetCalibrate extends EventEmitter.EventEmitter {
662
+ parent;
663
+ mask;
664
+ dr;
665
+ core;
666
+ operationEl;
606
667
  constructor(config) {
607
668
  super();
608
669
  this.parent = config.parent;
@@ -622,6 +683,7 @@
622
683
  top: ${top}px;
623
684
  width: ${el.clientWidth}px;
624
685
  height: ${el.clientHeight}px;
686
+ z-index: ${ZIndex.DRAG_EL};
625
687
  `;
626
688
  this.operationEl.id = `${prefix}${el.id}`;
627
689
  if (typeof this.core.config.updateDragEl === "function") {
@@ -669,6 +731,11 @@
669
731
  }
670
732
 
671
733
  class StageHighlight extends EventEmitter.EventEmitter {
734
+ core;
735
+ container;
736
+ target;
737
+ moveable;
738
+ calibrationTarget;
672
739
  constructor(config) {
673
740
  super();
674
741
  this.core = config.core;
@@ -685,11 +752,11 @@
685
752
  return;
686
753
  this.target = el;
687
754
  this.moveable?.destroy();
688
- this.moveable = new Moveable__default["default"](this.container, {
755
+ this.moveable = new Moveable__default.default(this.container, {
689
756
  target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
690
757
  origin: false,
691
758
  rootContainer: this.core.container,
692
- zoom: 1
759
+ zoom: 2
693
760
  });
694
761
  }
695
762
  clearHighlight() {
@@ -705,42 +772,15 @@
705
772
  }
706
773
  }
707
774
 
708
- class Rule extends EventEmitter__default["default"] {
775
+ class Rule extends EventEmitter__default.default {
776
+ hGuides;
777
+ vGuides;
778
+ horizontalGuidelines = [];
779
+ verticalGuidelines = [];
780
+ container;
781
+ containerResizeObserver;
709
782
  constructor(container) {
710
783
  super();
711
- this.horizontalGuidelines = [];
712
- this.verticalGuidelines = [];
713
- this.getGuidesStyle = (type) => ({
714
- position: "fixed",
715
- zIndex: 1,
716
- left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
717
- top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
718
- width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
719
- height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
720
- });
721
- this.createGuides = (type, defaultGuides = []) => new Guides__default["default"](this.container, {
722
- type,
723
- defaultGuides,
724
- displayDragPos: true,
725
- backgroundColor: "#fff",
726
- lineColor: "#000",
727
- textColor: "#000",
728
- style: this.getGuidesStyle(type)
729
- });
730
- this.hGuidesChangeGuidesHandler = (e) => {
731
- this.horizontalGuidelines = e.guides;
732
- this.emit("changeGuides", {
733
- type: GuidesType.HORIZONTAL,
734
- guides: this.horizontalGuidelines
735
- });
736
- };
737
- this.vGuidesChangeGuidesHandler = (e) => {
738
- this.verticalGuidelines = e.guides;
739
- this.emit("changeGuides", {
740
- type: GuidesType.VERTICAL,
741
- guides: this.verticalGuidelines
742
- });
743
- };
744
784
  this.container = container;
745
785
  this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
746
786
  this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
@@ -812,6 +852,37 @@
812
852
  this.containerResizeObserver.disconnect();
813
853
  this.removeAllListeners();
814
854
  }
855
+ getGuidesStyle = (type) => ({
856
+ position: "fixed",
857
+ zIndex: 1,
858
+ left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
859
+ top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
860
+ width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
861
+ height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
862
+ });
863
+ createGuides = (type, defaultGuides = []) => new Guides__default.default(this.container, {
864
+ type,
865
+ defaultGuides,
866
+ displayDragPos: true,
867
+ backgroundColor: "#fff",
868
+ lineColor: "#000",
869
+ textColor: "#000",
870
+ style: this.getGuidesStyle(type)
871
+ });
872
+ hGuidesChangeGuidesHandler = (e) => {
873
+ this.horizontalGuidelines = e.guides;
874
+ this.emit("changeGuides", {
875
+ type: GuidesType.HORIZONTAL,
876
+ guides: this.horizontalGuidelines
877
+ });
878
+ };
879
+ vGuidesChangeGuidesHandler = (e) => {
880
+ this.verticalGuidelines = e.guides;
881
+ this.emit("changeGuides", {
882
+ type: GuidesType.VERTICAL,
883
+ guides: this.verticalGuidelines
884
+ });
885
+ };
815
886
  }
816
887
 
817
888
  const wrapperClassName = "editor-mask-wrapper";
@@ -845,66 +916,30 @@
845
916
  return el;
846
917
  };
847
918
  class StageMask extends Rule {
919
+ content = createContent();
920
+ wrapper;
921
+ core;
922
+ page = null;
923
+ pageScrollParent = null;
924
+ scrollTop = 0;
925
+ scrollLeft = 0;
926
+ width = 0;
927
+ height = 0;
928
+ wrapperHeight = 0;
929
+ wrapperWidth = 0;
930
+ maxScrollTop = 0;
931
+ maxScrollLeft = 0;
932
+ intersectionObserver = null;
933
+ isMultiSelectStatus = false;
934
+ mode = Mode.ABSOLUTE;
935
+ pageResizeObserver = null;
936
+ wrapperResizeObserver = null;
937
+ highlightHandler = lodashEs.throttle((event) => {
938
+ this.emit("highlight", event);
939
+ }, throttleTime);
848
940
  constructor(config) {
849
941
  const wrapper = createWrapper();
850
942
  super(wrapper);
851
- this.content = createContent();
852
- this.page = null;
853
- this.pageScrollParent = null;
854
- this.scrollTop = 0;
855
- this.scrollLeft = 0;
856
- this.width = 0;
857
- this.height = 0;
858
- this.wrapperHeight = 0;
859
- this.wrapperWidth = 0;
860
- this.maxScrollTop = 0;
861
- this.maxScrollLeft = 0;
862
- this.intersectionObserver = null;
863
- this.mode = Mode.ABSOLUTE;
864
- this.pageResizeObserver = null;
865
- this.wrapperResizeObserver = null;
866
- this.highlightHandler = lodashEs.throttle((event) => {
867
- this.emit("highlight", event);
868
- }, throttleTime);
869
- this.mouseDownHandler = (event) => {
870
- this.emit("clearHighlight");
871
- event.stopImmediatePropagation();
872
- event.stopPropagation();
873
- if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
874
- return;
875
- if (event.target.className.indexOf("moveable-control") !== -1) {
876
- return;
877
- }
878
- this.content.removeEventListener("mousemove", this.highlightHandler);
879
- this.emit("beforeSelect", event);
880
- globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
881
- };
882
- this.mouseUpHandler = () => {
883
- globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
884
- this.content.addEventListener("mousemove", this.highlightHandler);
885
- this.emit("select");
886
- };
887
- this.mouseWheelHandler = (event) => {
888
- this.emit("clearHighlight");
889
- if (!this.page)
890
- throw new Error("page \u672A\u521D\u59CB\u5316");
891
- const { deltaY, deltaX } = event;
892
- if (this.page.clientHeight < this.wrapperHeight && deltaY)
893
- return;
894
- if (this.page.clientWidth < this.wrapperWidth && deltaX)
895
- return;
896
- if (this.maxScrollTop > 0) {
897
- this.scrollTop = this.scrollTop + deltaY;
898
- }
899
- if (this.maxScrollLeft > 0) {
900
- this.scrollLeft = this.scrollLeft + deltaX;
901
- }
902
- this.scroll();
903
- this.emit("scroll", event);
904
- };
905
- this.mouseLeaveHandler = () => {
906
- setTimeout(() => this.emit("clearHighlight"), throttleTime);
907
- };
908
943
  this.wrapper = wrapper;
909
944
  this.core = config.core;
910
945
  this.content.addEventListener("mousedown", this.mouseDownHandler);
@@ -912,6 +947,16 @@
912
947
  this.content.addEventListener("wheel", this.mouseWheelHandler);
913
948
  this.content.addEventListener("mousemove", this.highlightHandler);
914
949
  this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
950
+ const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
951
+ const ctrl = isMac ? "meta" : "ctrl";
952
+ KeyController__default.default.global.keydown(ctrl, (e) => {
953
+ e.inputEvent.preventDefault();
954
+ this.isMultiSelectStatus = true;
955
+ });
956
+ KeyController__default.default.global.keyup(ctrl, (e) => {
957
+ e.inputEvent.preventDefault();
958
+ this.isMultiSelectStatus = false;
959
+ });
915
960
  }
916
961
  setMode(mode) {
917
962
  this.mode = mode;
@@ -1040,49 +1085,237 @@
1040
1085
  if (this.maxScrollLeft < this.scrollLeft)
1041
1086
  this.scrollLeft = this.maxScrollLeft;
1042
1087
  }
1088
+ mouseDownHandler = (event) => {
1089
+ this.emit("clearHighlight");
1090
+ event.stopImmediatePropagation();
1091
+ event.stopPropagation();
1092
+ if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
1093
+ return;
1094
+ if (!this.isMultiSelectStatus && event.target.className.indexOf("moveable-area") !== -1) {
1095
+ return;
1096
+ }
1097
+ if (event.target.className.indexOf("moveable-control") !== -1) {
1098
+ return;
1099
+ }
1100
+ this.content.removeEventListener("mousemove", this.highlightHandler);
1101
+ if (this.isMultiSelectStatus) {
1102
+ this.emit("beforeMultiSelect", event);
1103
+ } else {
1104
+ this.emit("beforeSelect", event);
1105
+ }
1106
+ globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
1107
+ };
1108
+ mouseUpHandler = () => {
1109
+ globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
1110
+ this.content.addEventListener("mousemove", this.highlightHandler);
1111
+ if (!this.isMultiSelectStatus) {
1112
+ this.emit("select");
1113
+ }
1114
+ };
1115
+ mouseWheelHandler = (event) => {
1116
+ this.emit("clearHighlight");
1117
+ if (!this.page)
1118
+ throw new Error("page \u672A\u521D\u59CB\u5316");
1119
+ const { deltaY, deltaX } = event;
1120
+ if (this.page.clientHeight < this.wrapperHeight && deltaY)
1121
+ return;
1122
+ if (this.page.clientWidth < this.wrapperWidth && deltaX)
1123
+ return;
1124
+ if (this.maxScrollTop > 0) {
1125
+ this.scrollTop = this.scrollTop + deltaY;
1126
+ }
1127
+ if (this.maxScrollLeft > 0) {
1128
+ this.scrollLeft = this.scrollLeft + deltaX;
1129
+ }
1130
+ this.scroll();
1131
+ this.emit("scroll", event);
1132
+ };
1133
+ mouseLeaveHandler = () => {
1134
+ setTimeout(() => this.emit("clearHighlight"), throttleTime);
1135
+ };
1043
1136
  }
1044
1137
 
1045
- var 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}\n";
1046
-
1047
- class StageRender extends EventEmitter.EventEmitter {
1048
- constructor({ core }) {
1138
+ class StageMultiDragResize extends EventEmitter.EventEmitter {
1139
+ core;
1140
+ mask;
1141
+ container;
1142
+ targetList = [];
1143
+ dragElList = [];
1144
+ moveableForMulti;
1145
+ dragStatus = StageDragStatus.END;
1146
+ multiMoveableHelper;
1147
+ constructor(config) {
1049
1148
  super();
1050
- this.contentWindow = null;
1051
- this.runtime = null;
1052
- this.getMagicApi = () => ({
1053
- onPageElUpdate: (el) => this.emit("page-el-update", el),
1054
- onRuntimeReady: (runtime) => {
1055
- this.runtime = runtime;
1056
- globalThis.runtime = runtime;
1057
- this.emit("runtime-ready", runtime);
1149
+ this.core = config.core;
1150
+ this.container = config.container;
1151
+ this.mask = config.mask;
1152
+ }
1153
+ multiSelect(els) {
1154
+ this.targetList = els;
1155
+ this.core.dr.destroyDragEl();
1156
+ this.destroyDragElList();
1157
+ this.dragElList = els.map((elItem) => {
1158
+ const dragElDiv = globalThis.document.createElement("div");
1159
+ this.container.append(dragElDiv);
1160
+ dragElDiv.style.cssText = getTargetElStyle(elItem);
1161
+ dragElDiv.id = `${DRAG_EL_ID_PREFIX}${elItem.id}`;
1162
+ if (typeof this.core.config.updateDragEl === "function") {
1163
+ this.core.config.updateDragEl(dragElDiv, elItem);
1058
1164
  }
1165
+ return dragElDiv;
1059
1166
  });
1060
- this.getRuntime = () => {
1061
- if (this.runtime)
1062
- return Promise.resolve(this.runtime);
1063
- return new Promise((resolve) => {
1064
- const listener = (runtime) => {
1065
- this.off("runtime-ready", listener);
1066
- resolve(runtime);
1067
- };
1068
- this.on("runtime-ready", listener);
1167
+ this.moveableForMulti?.destroy();
1168
+ this.multiMoveableHelper?.clear();
1169
+ this.moveableForMulti = new Moveable__default.default(this.container, this.getOptions({
1170
+ target: this.dragElList
1171
+ }));
1172
+ this.multiMoveableHelper = MoveableHelper__default.default.create({
1173
+ useBeforeRender: true,
1174
+ useRender: false,
1175
+ createAuto: true
1176
+ });
1177
+ const frames = [];
1178
+ this.moveableForMulti.on("dragGroupStart", (params) => {
1179
+ const { events } = params;
1180
+ this.multiMoveableHelper?.onDragGroupStart(params);
1181
+ events.forEach((ev) => {
1182
+ const matchEventTarget = this.targetList.find((targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
1183
+ if (!matchEventTarget)
1184
+ return;
1185
+ frames.push({
1186
+ left: matchEventTarget.offsetLeft,
1187
+ top: matchEventTarget.offsetTop,
1188
+ id: matchEventTarget.id
1189
+ });
1069
1190
  });
1070
- };
1071
- this.loadHandler = async () => {
1072
- this.contentWindow = this.iframe?.contentWindow;
1073
- this.contentWindow.magic = this.getMagicApi();
1074
- if (this.render) {
1075
- const el = await this.render(this.core);
1076
- if (el) {
1077
- this.iframe?.contentDocument?.body?.appendChild(el);
1191
+ this.dragStatus = StageDragStatus.START;
1192
+ }).on("dragGroup", (params) => {
1193
+ const { events } = params;
1194
+ events.forEach((ev) => {
1195
+ const frameSnapShot = frames.find((frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
1196
+ if (!frameSnapShot)
1197
+ return;
1198
+ const targeEl = this.targetList.find((targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
1199
+ if (!targeEl)
1200
+ return;
1201
+ const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
1202
+ if (!isParentIncluded) {
1203
+ targeEl.style.left = `${frameSnapShot.left + ev.beforeTranslate[0]}px`;
1204
+ targeEl.style.top = `${frameSnapShot.top + ev.beforeTranslate[1]}px`;
1078
1205
  }
1206
+ });
1207
+ this.multiMoveableHelper?.onDragGroup(params);
1208
+ this.dragStatus = StageDragStatus.ING;
1209
+ }).on("dragGroupEnd", () => {
1210
+ this.update();
1211
+ this.dragStatus = StageDragStatus.END;
1212
+ }).on("clickGroup", (params) => {
1213
+ const { inputTarget, targets } = params;
1214
+ if (!this.mask.isMultiSelectStatus && targets.length > 1 && targets.includes(inputTarget)) {
1215
+ this.emit("select", inputTarget.id.replace(DRAG_EL_ID_PREFIX, ""));
1079
1216
  }
1080
- this.emit("onload");
1081
- this.contentWindow.postMessage({
1082
- tmagicRuntimeReady: true
1083
- }, "*");
1084
- utils.injectStyle(this.contentWindow.document, style);
1217
+ });
1218
+ }
1219
+ canSelect(el, stop) {
1220
+ if (el.className.includes(PAGE_CLASS)) {
1221
+ this.core.highlightedDom = void 0;
1222
+ this.core.highlightLayer.clearHighlight();
1223
+ stop();
1224
+ return false;
1225
+ }
1226
+ const currentTargetMode = getMode(el);
1227
+ let selectedDomMode = "";
1228
+ if (this.core.selectedDom?.className.includes(PAGE_CLASS)) {
1229
+ return true;
1230
+ }
1231
+ if (this.targetList.length === 0 && this.core.selectedDom) {
1232
+ selectedDomMode = getMode(this.core.selectedDom);
1233
+ } else if (this.targetList.length > 0) {
1234
+ selectedDomMode = getMode(this.targetList[0]);
1235
+ }
1236
+ if (currentTargetMode !== selectedDomMode) {
1237
+ return false;
1238
+ }
1239
+ return true;
1240
+ }
1241
+ clearSelectStatus() {
1242
+ if (!this.moveableForMulti)
1243
+ return;
1244
+ this.destroyDragElList();
1245
+ this.moveableForMulti.target = null;
1246
+ this.moveableForMulti.updateTarget();
1247
+ this.targetList = [];
1248
+ }
1249
+ destroy() {
1250
+ this.moveableForMulti?.destroy();
1251
+ this.destroyDragElList();
1252
+ }
1253
+ destroyDragElList() {
1254
+ this.dragElList.forEach((dragElItem) => dragElItem?.remove());
1255
+ }
1256
+ update(isResize = false) {
1257
+ if (this.targetList.length === 0)
1258
+ return;
1259
+ const { contentWindow } = this.core.renderer;
1260
+ const doc = contentWindow?.document;
1261
+ if (!doc)
1262
+ return;
1263
+ this.emit("update", {
1264
+ data: this.targetList.map((targetItem) => {
1265
+ const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop };
1266
+ const left = calcValueByFontsize(doc, offset.left);
1267
+ const top = calcValueByFontsize(doc, offset.top);
1268
+ const width = calcValueByFontsize(doc, targetItem.clientWidth);
1269
+ const height = calcValueByFontsize(doc, targetItem.clientHeight);
1270
+ return {
1271
+ el: targetItem,
1272
+ style: isResize ? { left, top, width, height } : { left, top }
1273
+ };
1274
+ }),
1275
+ parentEl: null
1276
+ });
1277
+ }
1278
+ getOptions(options = {}) {
1279
+ let { multiMoveableOptions = {} } = this.core.config;
1280
+ if (typeof multiMoveableOptions === "function") {
1281
+ multiMoveableOptions = multiMoveableOptions(this.core);
1282
+ }
1283
+ return {
1284
+ defaultGroupRotate: 0,
1285
+ defaultGroupOrigin: "50% 50%",
1286
+ draggable: true,
1287
+ resizable: false,
1288
+ throttleDrag: 0,
1289
+ startDragRotate: 0,
1290
+ throttleDragRotate: 0,
1291
+ zoom: 1,
1292
+ origin: true,
1293
+ padding: { left: 0, top: 0, right: 0, bottom: 0 },
1294
+ snappable: true,
1295
+ bounds: {
1296
+ top: 0,
1297
+ left: -1,
1298
+ right: this.container.clientWidth - 1,
1299
+ bottom: this.container.clientHeight,
1300
+ ...multiMoveableOptions.bounds || {}
1301
+ },
1302
+ ...options,
1303
+ ...multiMoveableOptions
1085
1304
  };
1305
+ }
1306
+ }
1307
+
1308
+ 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";
1309
+
1310
+ class StageRender extends EventEmitter.EventEmitter {
1311
+ contentWindow = null;
1312
+ runtime = null;
1313
+ iframe;
1314
+ runtimeUrl;
1315
+ core;
1316
+ render;
1317
+ constructor({ core }) {
1318
+ super();
1086
1319
  this.core = core;
1087
1320
  this.runtimeUrl = core.config.runtimeUrl || "";
1088
1321
  this.render = core.config.render;
@@ -1095,20 +1328,39 @@
1095
1328
  `;
1096
1329
  this.iframe.addEventListener("load", this.loadHandler);
1097
1330
  }
1331
+ getMagicApi = () => ({
1332
+ onPageElUpdate: (el) => this.emit("page-el-update", el),
1333
+ onRuntimeReady: (runtime) => {
1334
+ this.runtime = runtime;
1335
+ globalThis.runtime = runtime;
1336
+ this.emit("runtime-ready", runtime);
1337
+ }
1338
+ });
1098
1339
  async mount(el) {
1099
- if (this.iframe) {
1100
- if (!utils.isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
1101
- let html = await fetch(this.runtimeUrl).then((res) => res.text());
1102
- const base = `${location.protocol}//${utils.getHost(this.runtimeUrl)}`;
1103
- html = html.replace("<head>", `<head>
1104
- <base href="${base}">`);
1105
- this.iframe.srcdoc = html;
1106
- }
1107
- el.appendChild(this.iframe);
1108
- } else {
1340
+ if (!this.iframe) {
1109
1341
  throw Error("mount \u5931\u8D25");
1110
1342
  }
1111
- }
1343
+ if (!utils.isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
1344
+ let html = await fetch(this.runtimeUrl).then((res) => res.text());
1345
+ const base = `${location.protocol}//${utils.getHost(this.runtimeUrl)}`;
1346
+ html = html.replace("<head>", `<head>
1347
+ <base href="${base}">`);
1348
+ this.iframe.srcdoc = html;
1349
+ }
1350
+ el.appendChild(this.iframe);
1351
+ this.postTmagicRuntimeReady();
1352
+ }
1353
+ getRuntime = () => {
1354
+ if (this.runtime)
1355
+ return Promise.resolve(this.runtime);
1356
+ return new Promise((resolve) => {
1357
+ const listener = (runtime) => {
1358
+ this.off("runtime-ready", listener);
1359
+ resolve(runtime);
1360
+ };
1361
+ this.on("runtime-ready", listener);
1362
+ });
1363
+ };
1112
1364
  destroy() {
1113
1365
  this.iframe?.removeEventListener("load", this.loadHandler);
1114
1366
  this.contentWindow = null;
@@ -1116,21 +1368,60 @@
1116
1368
  this.iframe = void 0;
1117
1369
  this.removeAllListeners();
1118
1370
  }
1371
+ loadHandler = async () => {
1372
+ if (!this.contentWindow?.magic) {
1373
+ this.postTmagicRuntimeReady();
1374
+ }
1375
+ if (!this.contentWindow)
1376
+ return;
1377
+ if (this.render) {
1378
+ const el = await this.render(this.core);
1379
+ if (el) {
1380
+ this.contentWindow.document?.body?.appendChild(el);
1381
+ }
1382
+ }
1383
+ this.emit("onload");
1384
+ utils.injectStyle(this.contentWindow.document, style);
1385
+ };
1386
+ postTmagicRuntimeReady() {
1387
+ this.contentWindow = this.iframe?.contentWindow;
1388
+ this.contentWindow.magic = this.getMagicApi();
1389
+ this.contentWindow.postMessage({
1390
+ tmagicRuntimeReady: true
1391
+ }, "*");
1392
+ }
1119
1393
  }
1120
1394
 
1121
1395
  class StageCore extends EventEmitter.EventEmitter {
1396
+ container;
1397
+ selectedDom;
1398
+ selectedDomList = [];
1399
+ highlightedDom;
1400
+ renderer;
1401
+ mask;
1402
+ dr;
1403
+ multiDr;
1404
+ highlightLayer;
1405
+ config;
1406
+ zoom = DEFAULT_ZOOM;
1407
+ containerHighlightClassName;
1408
+ containerHighlightDuration;
1409
+ containerHighlightType;
1410
+ isContainer;
1411
+ canSelect;
1122
1412
  constructor(config) {
1123
1413
  super();
1124
- this.zoom = DEFAULT_ZOOM;
1125
1414
  this.config = config;
1126
1415
  this.setZoom(config.zoom);
1127
1416
  this.canSelect = config.canSelect || ((el) => !!el.id);
1128
1417
  this.isContainer = config.isContainer;
1129
- this.containerHighlightClassName = config.containerHighlightClassName;
1130
- this.containerHighlightDuration = config.containerHighlightDuration;
1418
+ this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
1419
+ this.containerHighlightDuration = config.containerHighlightDuration || 800;
1420
+ this.containerHighlightType = config.containerHighlightType;
1131
1421
  this.renderer = new StageRender({ core: this });
1132
1422
  this.mask = new StageMask({ core: this });
1133
- this.dr = new StageDragResize({ core: this, container: this.mask.content });
1423
+ this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
1424
+ this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
1134
1425
  this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
1135
1426
  this.renderer.on("runtime-ready", (runtime) => {
1136
1427
  this.emit("runtime-ready", runtime);
@@ -1138,29 +1429,59 @@
1138
1429
  this.renderer.on("page-el-update", (el) => {
1139
1430
  this.mask?.observe(el);
1140
1431
  });
1141
- this.mask.on("beforeSelect", (event) => {
1142
- this.setElementFromPoint(event);
1432
+ this.mask.on("beforeSelect", async (event) => {
1433
+ this.clearSelectStatus("multiSelect");
1434
+ const el = await this.getElementFromPoint(event);
1435
+ if (!el)
1436
+ return;
1437
+ this.select(el, event);
1143
1438
  }).on("select", () => {
1144
1439
  this.emit("select", this.selectedDom);
1145
1440
  }).on("changeGuides", (data) => {
1146
1441
  this.dr.setGuidelines(data.type, data.guides);
1147
1442
  this.emit("changeGuides", data);
1148
1443
  }).on("highlight", async (event) => {
1149
- await this.setElementFromPoint(event);
1444
+ const el = await this.getElementFromPoint(event);
1445
+ if (!el)
1446
+ return;
1447
+ if (this.multiDr.dragStatus === StageDragStatus.ING)
1448
+ return;
1449
+ await this.highlight(el);
1150
1450
  if (this.highlightedDom === this.selectedDom) {
1151
1451
  this.highlightLayer.clearHighlight();
1152
1452
  return;
1153
1453
  }
1154
- this.highlightLayer.highlight(this.highlightedDom);
1155
1454
  this.emit("highlight", this.highlightedDom);
1156
1455
  }).on("clearHighlight", async () => {
1157
1456
  this.highlightLayer.clearHighlight();
1457
+ }).on("beforeMultiSelect", async (event) => {
1458
+ const el = await this.getElementFromPoint(event);
1459
+ if (!el)
1460
+ return;
1461
+ if (this.selectedDom && !this.selectedDom.className.includes(PAGE_CLASS)) {
1462
+ this.selectedDomList.push(this.selectedDom);
1463
+ this.selectedDom = void 0;
1464
+ }
1465
+ const existIndex = this.selectedDomList.findIndex((selectedDom) => selectedDom.id === el.id);
1466
+ if (existIndex !== -1) {
1467
+ this.selectedDomList.splice(existIndex, 1);
1468
+ } else {
1469
+ this.selectedDomList.push(el);
1470
+ }
1471
+ this.multiSelect(this.selectedDomList);
1158
1472
  });
1159
1473
  this.dr.on("update", (data) => {
1160
1474
  setTimeout(() => this.emit("update", data));
1161
1475
  }).on("sort", (data) => {
1162
1476
  setTimeout(() => this.emit("sort", data));
1163
1477
  });
1478
+ this.multiDr.on("update", (data) => {
1479
+ setTimeout(() => this.emit("update", data));
1480
+ }).on("select", async (id) => {
1481
+ const el = await this.getTargetElement(id);
1482
+ this.select(el);
1483
+ setTimeout(() => this.emit("select", el));
1484
+ });
1164
1485
  }
1165
1486
  getElementsFromPoint(event) {
1166
1487
  const { renderer, zoom } = this;
@@ -1176,24 +1497,29 @@
1176
1497
  }
1177
1498
  return doc?.elementsFromPoint(x / zoom, y / zoom);
1178
1499
  }
1179
- async setElementFromPoint(event) {
1500
+ async getElementFromPoint(event) {
1180
1501
  const els = this.getElementsFromPoint(event);
1181
1502
  let stopped = false;
1182
1503
  const stop = () => stopped = true;
1183
1504
  for (const el of els) {
1184
- if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, event, stop)) {
1505
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isElCanSelect(el, event, stop)) {
1185
1506
  if (stopped)
1186
1507
  break;
1187
- if (event.type === "mousemove") {
1188
- this.highlight(el);
1189
- break;
1190
- }
1191
- this.select(el, event);
1192
- break;
1508
+ return el;
1193
1509
  }
1194
1510
  }
1195
1511
  }
1512
+ async isElCanSelect(el, event, stop) {
1513
+ const canSelectByProp = await this.canSelect(el, event, stop);
1514
+ if (!canSelectByProp)
1515
+ return false;
1516
+ if (this.mask.isMultiSelectStatus) {
1517
+ return this.multiDr.canSelect(el, stop);
1518
+ }
1519
+ return true;
1520
+ }
1196
1521
  async select(idOrEl, event) {
1522
+ this.clearSelectStatus("multiSelect");
1197
1523
  const el = await this.getTargetElement(idOrEl);
1198
1524
  if (el === this.selectedDom)
1199
1525
  return;
@@ -1215,6 +1541,12 @@
1215
1541
  }
1216
1542
  }
1217
1543
  }
1544
+ async multiSelect(idOrElList) {
1545
+ this.clearSelectStatus("select");
1546
+ const elList = await Promise.all(idOrElList.map(async (idOrEl) => await this.getTargetElement(idOrEl)));
1547
+ this.multiDr.multiSelect(elList);
1548
+ this.emit("multiSelect", elList);
1549
+ }
1218
1550
  update(data) {
1219
1551
  const { config } = data;
1220
1552
  return this.renderer?.getRuntime().then((runtime) => {
@@ -1237,7 +1569,7 @@
1237
1569
  this.highlightLayer.clearHighlight();
1238
1570
  return;
1239
1571
  }
1240
- if (el === this.highlightedDom)
1572
+ if (el === this.highlightedDom || !el)
1241
1573
  return;
1242
1574
  this.highlightLayer.highlight(el);
1243
1575
  this.highlightedDom = el;
@@ -1254,6 +1586,14 @@
1254
1586
  setZoom(zoom = DEFAULT_ZOOM) {
1255
1587
  this.zoom = zoom;
1256
1588
  }
1589
+ clearSelectStatus(selectType) {
1590
+ if (selectType === "multiSelect") {
1591
+ this.multiDr.clearSelectStatus();
1592
+ this.selectedDomList = [];
1593
+ } else {
1594
+ this.dr.clearSelectStatus();
1595
+ }
1596
+ }
1257
1597
  async mount(el) {
1258
1598
  this.container = el;
1259
1599
  const { mask, renderer } = this;
@@ -1265,6 +1605,24 @@
1265
1605
  this.mask.clearGuides();
1266
1606
  this.dr.clearGuides();
1267
1607
  }
1608
+ async addContainerHighlightClassName(event, exclude) {
1609
+ const els = this.getElementsFromPoint(event);
1610
+ const { renderer } = this;
1611
+ const doc = renderer.contentWindow?.document;
1612
+ if (!doc)
1613
+ return;
1614
+ for (const el of els) {
1615
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isContainer(el) && !exclude.includes(el)) {
1616
+ utils.addClassName(el, doc, this.containerHighlightClassName);
1617
+ break;
1618
+ }
1619
+ }
1620
+ }
1621
+ getAddContainerHighlightClassNameTimeout(event, exclude = []) {
1622
+ return globalThis.setTimeout(() => {
1623
+ this.addContainerHighlightClassName(event, exclude);
1624
+ }, this.containerHighlightDuration);
1625
+ }
1268
1626
  destroy() {
1269
1627
  const { mask, renderer, dr, highlightLayer } = this;
1270
1628
  renderer.destroy();
@@ -1286,6 +1644,7 @@
1286
1644
  }
1287
1645
 
1288
1646
  exports.CONTAINER_HIGHLIGHT_CLASS = CONTAINER_HIGHLIGHT_CLASS;
1647
+ exports.ContainerHighlightType = ContainerHighlightType;
1289
1648
  exports.DEFAULT_ZOOM = DEFAULT_ZOOM;
1290
1649
  exports.DRAG_EL_ID_PREFIX = DRAG_EL_ID_PREFIX;
1291
1650
  exports.GHOST_EL_ID_PREFIX = GHOST_EL_ID_PREFIX;
@@ -1293,24 +1652,29 @@
1293
1652
  exports.HIGHLIGHT_EL_ID_PREFIX = HIGHLIGHT_EL_ID_PREFIX;
1294
1653
  exports.Mode = Mode;
1295
1654
  exports.MouseButton = MouseButton;
1655
+ exports.PAGE_CLASS = PAGE_CLASS;
1296
1656
  exports.SELECTED_CLASS = SELECTED_CLASS;
1297
1657
  exports.StageDragResize = StageDragResize;
1658
+ exports.StageDragStatus = StageDragStatus;
1298
1659
  exports.StageMask = StageMask;
1299
1660
  exports.StageRender = StageRender;
1300
1661
  exports.ZIndex = ZIndex;
1301
1662
  exports.addSelectedClassName = addSelectedClassName;
1302
1663
  exports.calcValueByFontsize = calcValueByFontsize;
1303
- exports["default"] = StageCore;
1664
+ exports.default = StageCore;
1665
+ exports.down = down;
1304
1666
  exports.getAbsolutePosition = getAbsolutePosition;
1305
1667
  exports.getMode = getMode;
1306
1668
  exports.getOffset = getOffset;
1307
1669
  exports.getScrollParent = getScrollParent;
1670
+ exports.getTargetElStyle = getTargetElStyle;
1308
1671
  exports.isAbsolute = isAbsolute;
1309
1672
  exports.isFixed = isFixed;
1310
1673
  exports.isFixedParent = isFixedParent;
1311
1674
  exports.isRelative = isRelative;
1312
1675
  exports.isStatic = isStatic;
1313
1676
  exports.removeSelectedClassName = removeSelectedClassName;
1677
+ exports.up = up;
1314
1678
 
1315
1679
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
1316
1680