@tmagic/stage 1.1.0-beta.2 → 1.1.0-beta.5

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,7 +1,8 @@
1
1
  import EventEmitter$1, { EventEmitter } from 'events';
2
+ import { removeClassName, removeClassNameByClassName, createDiv, injectStyle, isSameDomain, getHost, addClassName } from '@tmagic/utils';
2
3
  import Moveable from 'moveable';
3
4
  import MoveableHelper from 'moveable-helper';
4
- import { removeClassName, addClassName, removeClassNameByClassName, createDiv, injectStyle, isSameDomain, getHost } from '@tmagic/utils';
5
+ import KeyController from 'keycon';
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";
@@ -61,6 +63,19 @@ const getOffset = (el) => {
61
63
  top
62
64
  };
63
65
  };
66
+ const getTargetElStyle = (el) => {
67
+ const offset = getOffset(el);
68
+ const { transform } = getComputedStyle(el);
69
+ return `
70
+ position: absolute;
71
+ transform: ${transform};
72
+ left: ${offset.left}px;
73
+ top: ${offset.top}px;
74
+ width: ${el.clientWidth}px;
75
+ height: ${el.clientHeight}px;
76
+ z-index: ${ZIndex.DRAG_EL};
77
+ `;
78
+ };
64
79
  const getAbsolutePosition = (el, { top, left }) => {
65
80
  const { offsetParent } = el;
66
81
  if (offsetParent) {
@@ -141,6 +156,52 @@ const calcValueByFontsize = (doc, value) => {
141
156
  }
142
157
  return value;
143
158
  };
159
+ const down = (deltaTop, target) => {
160
+ let swapIndex = 0;
161
+ let addUpH = target.clientHeight;
162
+ const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
163
+ const index = brothers.indexOf(target);
164
+ const downEls = brothers.slice(index + 1);
165
+ for (let i = 0; i < downEls.length; i++) {
166
+ const ele = downEls[i];
167
+ if (ele.style?.position === "fixed") {
168
+ continue;
169
+ }
170
+ addUpH += ele.clientHeight / 2;
171
+ if (deltaTop <= addUpH) {
172
+ break;
173
+ }
174
+ addUpH += ele.clientHeight / 2;
175
+ swapIndex = i;
176
+ }
177
+ return {
178
+ src: target.id,
179
+ dist: downEls.length && swapIndex > -1 ? downEls[swapIndex].id : target.id
180
+ };
181
+ };
182
+ const up = (deltaTop, target) => {
183
+ const brothers = Array.from(target.parentNode?.children || []).filter((node) => !node.id.startsWith(GHOST_EL_ID_PREFIX));
184
+ const index = brothers.indexOf(target);
185
+ const upEls = brothers.slice(0, index);
186
+ let addUpH = target.clientHeight;
187
+ let swapIndex = upEls.length - 1;
188
+ for (let i = upEls.length - 1; i >= 0; i--) {
189
+ const ele = upEls[i];
190
+ if (!ele)
191
+ continue;
192
+ if (ele.style.position === "fixed")
193
+ continue;
194
+ addUpH += ele.clientHeight / 2;
195
+ if (-deltaTop <= addUpH)
196
+ break;
197
+ addUpH += ele.clientHeight / 2;
198
+ swapIndex = i;
199
+ }
200
+ return {
201
+ src: target.id,
202
+ dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
203
+ };
204
+ };
144
205
 
145
206
  class StageDragResize extends EventEmitter {
146
207
  constructor(config) {
@@ -153,8 +214,7 @@ class StageDragResize extends EventEmitter {
153
214
  this.dragStatus = "end" /* END */;
154
215
  this.core = config.core;
155
216
  this.container = config.container;
156
- this.dragEl = globalThis.document.createElement("div");
157
- this.container.append(this.dragEl);
217
+ this.mask = config.mask;
158
218
  }
159
219
  select(el, event) {
160
220
  const oldTarget = this.target;
@@ -205,6 +265,16 @@ class StageDragResize extends EventEmitter {
205
265
  this.moveableOptions.verticalGuidelines = [];
206
266
  this.updateMoveable();
207
267
  }
268
+ clearSelectStatus() {
269
+ if (!this.moveable)
270
+ return;
271
+ this.destroyDragEl();
272
+ this.moveable.target = null;
273
+ this.moveable.updateTarget();
274
+ }
275
+ destroyDragEl() {
276
+ this.dragEl?.remove();
277
+ }
208
278
  destroy() {
209
279
  this.moveable?.destroy();
210
280
  this.destroyGhostEl();
@@ -218,7 +288,14 @@ class StageDragResize extends EventEmitter {
218
288
  }
219
289
  this.mode = getMode(el);
220
290
  this.destroyGhostEl();
221
- this.updateDragEl(el);
291
+ this.destroyDragEl();
292
+ this.dragEl = globalThis.document.createElement("div");
293
+ this.container.append(this.dragEl);
294
+ this.dragEl.style.cssText = getTargetElStyle(el);
295
+ this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
296
+ if (typeof this.core.config.updateDragEl === "function") {
297
+ this.core.config.updateDragEl(this.dragEl, el);
298
+ }
222
299
  this.moveableOptions = this.getOptions({
223
300
  target: this.dragEl
224
301
  });
@@ -317,15 +394,7 @@ class StageDragResize extends EventEmitter {
317
394
  globalThis.clearTimeout(timeout);
318
395
  timeout = void 0;
319
396
  }
320
- timeout = globalThis.setTimeout(async () => {
321
- const els = this.core.getElementsFromPoint(e.inputEvent);
322
- for (const el of els) {
323
- if (doc && !el.id.startsWith(GHOST_EL_ID_PREFIX) && el !== this.target && await this.core.isContainer(el)) {
324
- addClassName(el, doc, this.core.containerHighlightClassName);
325
- break;
326
- }
327
- }
328
- }, this.core.containerHighlightDuration);
397
+ timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
329
398
  this.dragStatus = "ing" /* ING */;
330
399
  if (this.ghostEl) {
331
400
  this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
@@ -456,6 +525,7 @@ class StageDragResize extends EventEmitter {
456
525
  this.destroyGhostEl();
457
526
  }
458
527
  const ghostEl = el.cloneNode(true);
528
+ this.setGhostElChildrenId(ghostEl);
459
529
  const { top, left } = getAbsolutePosition(el, getOffset(el));
460
530
  ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
461
531
  ghostEl.style.zIndex = ZIndex.GHOST_EL;
@@ -466,30 +536,20 @@ class StageDragResize extends EventEmitter {
466
536
  el.after(ghostEl);
467
537
  return ghostEl;
468
538
  }
539
+ setGhostElChildrenId(el) {
540
+ for (const child of el.children) {
541
+ if (child.id) {
542
+ child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
543
+ }
544
+ if (child.children.length) {
545
+ this.setGhostElChildrenId(child);
546
+ }
547
+ }
548
+ }
469
549
  destroyGhostEl() {
470
550
  this.ghostEl?.remove();
471
551
  this.ghostEl = void 0;
472
552
  }
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
553
  getOptions(options = {}) {
494
554
  if (!this.target)
495
555
  return {};
@@ -540,7 +600,7 @@ class StageDragResize extends EventEmitter {
540
600
  bounds: {
541
601
  top: 0,
542
602
  left: -1,
543
- right: this.container.clientWidth,
603
+ right: this.container.clientWidth - 1,
544
604
  bottom: this.container.clientHeight,
545
605
  ...moveableOptions.bounds || {}
546
606
  },
@@ -549,52 +609,6 @@ class StageDragResize extends EventEmitter {
549
609
  };
550
610
  }
551
611
  }
552
- const down = (deltaTop, target) => {
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;
592
- }
593
- return {
594
- src: target.id,
595
- dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
596
- };
597
- };
598
612
 
599
613
  class TargetCalibrate extends EventEmitter {
600
614
  constructor(config) {
@@ -616,6 +630,7 @@ class TargetCalibrate extends EventEmitter {
616
630
  top: ${top}px;
617
631
  width: ${el.clientWidth}px;
618
632
  height: ${el.clientHeight}px;
633
+ z-index: ${ZIndex.DRAG_EL};
619
634
  `;
620
635
  this.operationEl.id = `${prefix}${el.id}`;
621
636
  if (typeof this.core.config.updateDragEl === "function") {
@@ -683,7 +698,7 @@ class StageHighlight extends EventEmitter {
683
698
  target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
684
699
  origin: false,
685
700
  rootContainer: this.core.container,
686
- zoom: 1
701
+ zoom: 2
687
702
  });
688
703
  }
689
704
  clearHighlight() {
@@ -854,6 +869,7 @@ class StageMask extends Rule {
854
869
  this.maxScrollTop = 0;
855
870
  this.maxScrollLeft = 0;
856
871
  this.intersectionObserver = null;
872
+ this.isMultiSelectStatus = false;
857
873
  this.mode = Mode.ABSOLUTE;
858
874
  this.pageResizeObserver = null;
859
875
  this.wrapperResizeObserver = null;
@@ -866,11 +882,18 @@ class StageMask extends Rule {
866
882
  event.stopPropagation();
867
883
  if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
868
884
  return;
885
+ if (!this.isMultiSelectStatus && event.target.className.indexOf("moveable-area") !== -1) {
886
+ return;
887
+ }
869
888
  if (event.target.className.indexOf("moveable-control") !== -1) {
870
889
  return;
871
890
  }
872
891
  this.content.removeEventListener("mousemove", this.highlightHandler);
873
- this.emit("beforeSelect", event);
892
+ if (this.isMultiSelectStatus) {
893
+ this.emit("beforeMultiSelect", event);
894
+ } else {
895
+ this.emit("beforeSelect", event);
896
+ }
874
897
  globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
875
898
  };
876
899
  this.mouseUpHandler = () => {
@@ -906,6 +929,14 @@ class StageMask extends Rule {
906
929
  this.content.addEventListener("wheel", this.mouseWheelHandler);
907
930
  this.content.addEventListener("mousemove", this.highlightHandler);
908
931
  this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
932
+ KeyController.global.keydown("shift", (e) => {
933
+ e.inputEvent.preventDefault();
934
+ this.isMultiSelectStatus = true;
935
+ });
936
+ KeyController.global.keyup("shift", (e) => {
937
+ e.inputEvent.preventDefault();
938
+ this.isMultiSelectStatus = false;
939
+ });
909
940
  }
910
941
  setMode(mode) {
911
942
  this.mode = mode;
@@ -1036,7 +1067,148 @@ class StageMask extends Rule {
1036
1067
  }
1037
1068
  }
1038
1069
 
1039
- 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";
1070
+ class StageMultiDragResize extends EventEmitter {
1071
+ constructor(config) {
1072
+ super();
1073
+ this.targetList = [];
1074
+ this.dragElList = [];
1075
+ this.core = config.core;
1076
+ this.container = config.container;
1077
+ this.mask = config.mask;
1078
+ }
1079
+ multiSelect(els) {
1080
+ this.targetList = els;
1081
+ this.core.dr.destroyDragEl();
1082
+ this.destroyDragElList();
1083
+ this.dragElList = els.map((elItem) => {
1084
+ const dragElDiv = globalThis.document.createElement("div");
1085
+ this.container.append(dragElDiv);
1086
+ dragElDiv.style.cssText = getTargetElStyle(elItem);
1087
+ dragElDiv.id = `${DRAG_EL_ID_PREFIX}${elItem.id}`;
1088
+ if (typeof this.core.config.updateDragEl === "function") {
1089
+ this.core.config.updateDragEl(dragElDiv, elItem);
1090
+ }
1091
+ return dragElDiv;
1092
+ });
1093
+ this.moveableForMulti?.destroy();
1094
+ this.multiMoveableHelper?.clear();
1095
+ this.moveableForMulti = new Moveable(this.container, this.getOptions({
1096
+ target: this.dragElList
1097
+ }));
1098
+ this.multiMoveableHelper = MoveableHelper.create({
1099
+ useBeforeRender: true,
1100
+ useRender: false,
1101
+ createAuto: true
1102
+ });
1103
+ const frames = [];
1104
+ this.moveableForMulti.on("dragGroupStart", (params) => {
1105
+ const { events } = params;
1106
+ this.multiMoveableHelper?.onDragGroupStart(params);
1107
+ events.forEach((ev) => {
1108
+ const matchEventTarget = this.targetList.find((targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
1109
+ if (!matchEventTarget)
1110
+ return;
1111
+ frames.push({
1112
+ left: matchEventTarget.offsetLeft,
1113
+ top: matchEventTarget.offsetTop,
1114
+ id: matchEventTarget.id
1115
+ });
1116
+ });
1117
+ }).on("dragGroup", (params) => {
1118
+ const { events } = params;
1119
+ events.forEach((ev) => {
1120
+ const frameSnapShot = frames.find((frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
1121
+ if (!frameSnapShot)
1122
+ return;
1123
+ const targeEl = this.targetList.find((targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ""));
1124
+ if (!targeEl)
1125
+ return;
1126
+ const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
1127
+ if (!isParentIncluded) {
1128
+ targeEl.style.left = `${frameSnapShot.left + ev.beforeTranslate[0]}px`;
1129
+ targeEl.style.top = `${frameSnapShot.top + ev.beforeTranslate[1]}px`;
1130
+ }
1131
+ });
1132
+ this.multiMoveableHelper?.onDragGroup(params);
1133
+ }).on("dragGroupEnd", () => {
1134
+ this.update();
1135
+ });
1136
+ }
1137
+ canSelect(el) {
1138
+ if (el.className.includes(PAGE_CLASS)) {
1139
+ this.core.highlightedDom = void 0;
1140
+ this.core.highlightLayer.clearHighlight();
1141
+ return false;
1142
+ }
1143
+ const currentTargetMode = getMode(el);
1144
+ let selectedDomMode = "";
1145
+ if (this.targetList.length === 0 && this.core.selectedDom) {
1146
+ selectedDomMode = getMode(this.core.selectedDom);
1147
+ } else if (this.targetList.length > 0) {
1148
+ selectedDomMode = getMode(this.targetList[0]);
1149
+ }
1150
+ if (currentTargetMode !== selectedDomMode) {
1151
+ return false;
1152
+ }
1153
+ return true;
1154
+ }
1155
+ clearSelectStatus() {
1156
+ if (!this.moveableForMulti)
1157
+ return;
1158
+ this.destroyDragElList();
1159
+ this.moveableForMulti.target = null;
1160
+ this.moveableForMulti.updateTarget();
1161
+ this.targetList = [];
1162
+ }
1163
+ destroy() {
1164
+ this.moveableForMulti?.destroy();
1165
+ this.destroyDragElList();
1166
+ }
1167
+ destroyDragElList() {
1168
+ this.dragElList.forEach((dragElItem) => dragElItem?.remove());
1169
+ }
1170
+ update(isResize = false) {
1171
+ if (this.targetList.length === 0)
1172
+ return;
1173
+ const { contentWindow } = this.core.renderer;
1174
+ const doc = contentWindow?.document;
1175
+ if (!doc)
1176
+ return;
1177
+ this.targetList.forEach((targetItem) => {
1178
+ const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop };
1179
+ const left = calcValueByFontsize(doc, offset.left);
1180
+ const top = calcValueByFontsize(doc, offset.top);
1181
+ const width = calcValueByFontsize(doc, targetItem.clientWidth);
1182
+ const height = calcValueByFontsize(doc, targetItem.clientHeight);
1183
+ this.emit("update", {
1184
+ el: targetItem,
1185
+ style: isResize ? { left, top, width, height } : { left, top }
1186
+ });
1187
+ });
1188
+ }
1189
+ getOptions(options = {}) {
1190
+ let { moveableOptions = {} } = this.core.config;
1191
+ if (typeof moveableOptions === "function") {
1192
+ moveableOptions = moveableOptions(this.core);
1193
+ }
1194
+ return {
1195
+ defaultGroupRotate: 0,
1196
+ defaultGroupOrigin: "50% 50%",
1197
+ draggable: true,
1198
+ resizable: true,
1199
+ throttleDrag: 0,
1200
+ startDragRotate: 0,
1201
+ throttleDragRotate: 0,
1202
+ zoom: 1,
1203
+ origin: true,
1204
+ padding: { left: 0, top: 0, right: 0, bottom: 0 },
1205
+ ...options,
1206
+ ...moveableOptions
1207
+ };
1208
+ }
1209
+ }
1210
+
1211
+ 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 pointer-events: none;\n}\n";
1040
1212
 
1041
1213
  class StageRender extends EventEmitter {
1042
1214
  constructor({ core }) {
@@ -1063,18 +1235,18 @@ class StageRender extends EventEmitter {
1063
1235
  });
1064
1236
  };
1065
1237
  this.loadHandler = async () => {
1066
- this.contentWindow = this.iframe?.contentWindow;
1067
- this.contentWindow.magic = this.getMagicApi();
1238
+ if (!this.contentWindow?.magic) {
1239
+ this.postTmagicRuntimeReady();
1240
+ }
1241
+ if (!this.contentWindow)
1242
+ return;
1068
1243
  if (this.render) {
1069
1244
  const el = await this.render(this.core);
1070
1245
  if (el) {
1071
- this.iframe?.contentDocument?.body?.appendChild(el);
1246
+ this.contentWindow.document?.body?.appendChild(el);
1072
1247
  }
1073
1248
  }
1074
1249
  this.emit("onload");
1075
- this.contentWindow.postMessage({
1076
- tmagicRuntimeReady: true
1077
- }, "*");
1078
1250
  injectStyle(this.contentWindow.document, style);
1079
1251
  };
1080
1252
  this.core = core;
@@ -1090,18 +1262,18 @@ class StageRender extends EventEmitter {
1090
1262
  this.iframe.addEventListener("load", this.loadHandler);
1091
1263
  }
1092
1264
  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 {
1265
+ if (!this.iframe) {
1103
1266
  throw Error("mount \u5931\u8D25");
1104
1267
  }
1268
+ if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
1269
+ let html = await fetch(this.runtimeUrl).then((res) => res.text());
1270
+ const base = `${location.protocol}//${getHost(this.runtimeUrl)}`;
1271
+ html = html.replace("<head>", `<head>
1272
+ <base href="${base}">`);
1273
+ this.iframe.srcdoc = html;
1274
+ }
1275
+ el.appendChild(this.iframe);
1276
+ this.postTmagicRuntimeReady();
1105
1277
  }
1106
1278
  destroy() {
1107
1279
  this.iframe?.removeEventListener("load", this.loadHandler);
@@ -1110,11 +1282,19 @@ class StageRender extends EventEmitter {
1110
1282
  this.iframe = void 0;
1111
1283
  this.removeAllListeners();
1112
1284
  }
1285
+ postTmagicRuntimeReady() {
1286
+ this.contentWindow = this.iframe?.contentWindow;
1287
+ this.contentWindow.magic = this.getMagicApi();
1288
+ this.contentWindow.postMessage({
1289
+ tmagicRuntimeReady: true
1290
+ }, "*");
1291
+ }
1113
1292
  }
1114
1293
 
1115
1294
  class StageCore extends EventEmitter {
1116
1295
  constructor(config) {
1117
1296
  super();
1297
+ this.selectedDomList = [];
1118
1298
  this.zoom = DEFAULT_ZOOM;
1119
1299
  this.config = config;
1120
1300
  this.setZoom(config.zoom);
@@ -1124,7 +1304,8 @@ class StageCore extends EventEmitter {
1124
1304
  this.containerHighlightDuration = config.containerHighlightDuration;
1125
1305
  this.renderer = new StageRender({ core: this });
1126
1306
  this.mask = new StageMask({ core: this });
1127
- this.dr = new StageDragResize({ core: this, container: this.mask.content });
1307
+ this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
1308
+ this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
1128
1309
  this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
1129
1310
  this.renderer.on("runtime-ready", (runtime) => {
1130
1311
  this.emit("runtime-ready", runtime);
@@ -1132,29 +1313,55 @@ class StageCore extends EventEmitter {
1132
1313
  this.renderer.on("page-el-update", (el) => {
1133
1314
  this.mask?.observe(el);
1134
1315
  });
1135
- this.mask.on("beforeSelect", (event) => {
1136
- this.setElementFromPoint(event);
1316
+ this.mask.on("beforeSelect", async (event) => {
1317
+ this.clearSelectStatus("multiSelect");
1318
+ const el = await this.getElementFromPoint(event);
1319
+ if (!el)
1320
+ return;
1321
+ this.select(el, event);
1137
1322
  }).on("select", () => {
1138
1323
  this.emit("select", this.selectedDom);
1139
1324
  }).on("changeGuides", (data) => {
1140
1325
  this.dr.setGuidelines(data.type, data.guides);
1141
1326
  this.emit("changeGuides", data);
1142
1327
  }).on("highlight", async (event) => {
1143
- await this.setElementFromPoint(event);
1328
+ const el = await this.getElementFromPoint(event);
1329
+ if (!el)
1330
+ return;
1331
+ await this.highlight(el);
1144
1332
  if (this.highlightedDom === this.selectedDom) {
1145
1333
  this.highlightLayer.clearHighlight();
1146
1334
  return;
1147
1335
  }
1148
- this.highlightLayer.highlight(this.highlightedDom);
1149
1336
  this.emit("highlight", this.highlightedDom);
1150
1337
  }).on("clearHighlight", async () => {
1151
1338
  this.highlightLayer.clearHighlight();
1339
+ }).on("beforeMultiSelect", async (event) => {
1340
+ const el = await this.getElementFromPoint(event);
1341
+ if (!el)
1342
+ return;
1343
+ this.clearSelectStatus("select");
1344
+ if (this.selectedDom && !this.selectedDom.className.includes(PAGE_CLASS)) {
1345
+ this.selectedDomList.push(this.selectedDom);
1346
+ this.selectedDom = void 0;
1347
+ }
1348
+ const existIndex = this.selectedDomList.findIndex((selectedDom) => selectedDom.id === el.id);
1349
+ if (existIndex !== -1) {
1350
+ this.selectedDomList.splice(existIndex, 1);
1351
+ } else {
1352
+ this.selectedDomList.push(el);
1353
+ }
1354
+ this.multiDr.multiSelect(this.selectedDomList);
1355
+ this.emit("multiSelect", this.selectedDomList);
1152
1356
  });
1153
1357
  this.dr.on("update", (data) => {
1154
1358
  setTimeout(() => this.emit("update", data));
1155
1359
  }).on("sort", (data) => {
1156
1360
  setTimeout(() => this.emit("sort", data));
1157
1361
  });
1362
+ this.multiDr.on("update", (data) => {
1363
+ setTimeout(() => this.emit("update", data));
1364
+ });
1158
1365
  }
1159
1366
  getElementsFromPoint(event) {
1160
1367
  const { renderer, zoom } = this;
@@ -1170,24 +1377,29 @@ class StageCore extends EventEmitter {
1170
1377
  }
1171
1378
  return doc?.elementsFromPoint(x / zoom, y / zoom);
1172
1379
  }
1173
- async setElementFromPoint(event) {
1380
+ async getElementFromPoint(event) {
1174
1381
  const els = this.getElementsFromPoint(event);
1175
1382
  let stopped = false;
1176
1383
  const stop = () => stopped = true;
1177
1384
  for (const el of els) {
1178
- if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, event, stop)) {
1385
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isElCanSelect(el, event, stop)) {
1179
1386
  if (stopped)
1180
1387
  break;
1181
- if (event.type === "mousemove") {
1182
- this.highlight(el);
1183
- break;
1184
- }
1185
- this.select(el, event);
1186
- break;
1388
+ return el;
1187
1389
  }
1188
1390
  }
1189
1391
  }
1392
+ async isElCanSelect(el, event, stop) {
1393
+ const canSelectByProp = await this.canSelect(el, event, stop);
1394
+ if (!canSelectByProp)
1395
+ return false;
1396
+ if (this.mask.isMultiSelectStatus) {
1397
+ return this.multiDr.canSelect(el);
1398
+ }
1399
+ return true;
1400
+ }
1190
1401
  async select(idOrEl, event) {
1402
+ this.clearSelectStatus("multiSelect");
1191
1403
  const el = await this.getTargetElement(idOrEl);
1192
1404
  if (el === this.selectedDom)
1193
1405
  return;
@@ -1231,7 +1443,7 @@ class StageCore extends EventEmitter {
1231
1443
  this.highlightLayer.clearHighlight();
1232
1444
  return;
1233
1445
  }
1234
- if (el === this.highlightedDom)
1446
+ if (el === this.highlightedDom || !el)
1235
1447
  return;
1236
1448
  this.highlightLayer.highlight(el);
1237
1449
  this.highlightedDom = el;
@@ -1248,6 +1460,14 @@ class StageCore extends EventEmitter {
1248
1460
  setZoom(zoom = DEFAULT_ZOOM) {
1249
1461
  this.zoom = zoom;
1250
1462
  }
1463
+ clearSelectStatus(selectType) {
1464
+ if (selectType === "multiSelect") {
1465
+ this.multiDr.clearSelectStatus();
1466
+ this.selectedDomList = [];
1467
+ } else {
1468
+ this.dr.clearSelectStatus();
1469
+ }
1470
+ }
1251
1471
  async mount(el) {
1252
1472
  this.container = el;
1253
1473
  const { mask, renderer } = this;
@@ -1259,6 +1479,24 @@ class StageCore extends EventEmitter {
1259
1479
  this.mask.clearGuides();
1260
1480
  this.dr.clearGuides();
1261
1481
  }
1482
+ async addContainerHighlightClassName(event, exclude) {
1483
+ const els = this.getElementsFromPoint(event);
1484
+ const { renderer } = this;
1485
+ const doc = renderer.contentWindow?.document;
1486
+ if (!doc)
1487
+ return;
1488
+ for (const el of els) {
1489
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isContainer(el) && !exclude.includes(el)) {
1490
+ addClassName(el, doc, this.containerHighlightClassName);
1491
+ break;
1492
+ }
1493
+ }
1494
+ }
1495
+ getAddContainerHighlightClassNameTimeout(event, exclude = []) {
1496
+ return globalThis.setTimeout(() => {
1497
+ this.addContainerHighlightClassName(event, exclude);
1498
+ }, this.containerHighlightDuration);
1499
+ }
1262
1500
  destroy() {
1263
1501
  const { mask, renderer, dr, highlightLayer } = this;
1264
1502
  renderer.destroy();
@@ -1279,5 +1517,5 @@ class StageCore extends EventEmitter {
1279
1517
  }
1280
1518
  }
1281
1519
 
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 };
1520
+ export { CONTAINER_HIGHLIGHT_CLASS, DEFAULT_ZOOM, DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, HIGHLIGHT_EL_ID_PREFIX, Mode, MouseButton, PAGE_CLASS, SELECTED_CLASS, StageDragResize, StageMask, StageRender, ZIndex, addSelectedClassName, calcValueByFontsize, StageCore as default, down, getAbsolutePosition, getMode, getOffset, getScrollParent, getTargetElStyle, isAbsolute, isFixed, isFixedParent, isRelative, isStatic, removeSelectedClassName, up };
1283
1521
  //# sourceMappingURL=tmagic-stage.es.js.map