@tmagic/stage 1.2.0-beta.8 → 1.2.0

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.
Files changed (39) hide show
  1. package/README.md +62 -1
  2. package/dist/{tmagic-stage.mjs → tmagic-stage.js} +1395 -1062
  3. package/dist/tmagic-stage.js.map +1 -0
  4. package/dist/{tmagic-stage.umd.js → tmagic-stage.umd.cjs} +1393 -1060
  5. package/dist/tmagic-stage.umd.cjs.map +1 -0
  6. package/package.json +9 -8
  7. package/src/ActionManager.ts +535 -0
  8. package/src/DragResizeHelper.ts +338 -0
  9. package/src/MoveableOptionsManager.ts +249 -0
  10. package/src/MoveableSelectParentAble.ts +3 -5
  11. package/src/Rule.ts +4 -4
  12. package/src/StageCore.ts +203 -275
  13. package/src/StageDragResize.ts +86 -348
  14. package/src/StageHighlight.ts +17 -16
  15. package/src/StageMask.ts +19 -102
  16. package/src/StageMultiDragResize.ts +97 -198
  17. package/src/StageRender.ts +85 -10
  18. package/src/TargetShadow.ts +120 -0
  19. package/src/const.ts +1 -1
  20. package/src/types.ts +99 -19
  21. package/src/util.ts +18 -11
  22. package/types/ActionManager.d.ts +141 -0
  23. package/types/DragResizeHelper.d.ts +70 -0
  24. package/types/MoveableOptionsManager.d.ts +86 -0
  25. package/types/MoveableSelectParentAble.d.ts +1 -2
  26. package/types/StageCore.d.ts +58 -41
  27. package/types/StageDragResize.d.ts +12 -40
  28. package/types/StageHighlight.d.ts +3 -4
  29. package/types/StageMask.d.ts +0 -21
  30. package/types/StageMultiDragResize.d.ts +8 -24
  31. package/types/StageRender.d.ts +23 -4
  32. package/types/TargetShadow.d.ts +22 -0
  33. package/types/const.d.ts +1 -1
  34. package/types/types.d.ts +87 -18
  35. package/types/util.d.ts +8 -8
  36. package/dist/tmagic-stage.mjs.map +0 -1
  37. package/dist/tmagic-stage.umd.js.map +0 -1
  38. package/src/TargetCalibrate.ts +0 -119
  39. package/types/TargetCalibrate.d.ts +0 -20
@@ -1,15 +1,16 @@
1
- import EventEmitter$1, { EventEmitter } from 'events';
2
- import { removeClassName, removeClassNameByClassName, createDiv, injectStyle, isSameDomain, getHost, addClassName } from '@tmagic/utils';
1
+ import EventEmitter, { EventEmitter as EventEmitter$1 } from 'events';
3
2
  import KeyController from 'keycon';
3
+ import { merge, throttle } from 'lodash-es';
4
+ import { Env } from '@tmagic/core';
5
+ import { removeClassName, addClassName, removeClassNameByClassName, getDocument, createDiv, injectStyle, isSameDomain, getHost } from '@tmagic/utils';
4
6
  import Moveable from 'moveable';
5
7
  import MoveableHelper from 'moveable-helper';
6
- import { throttle } from 'lodash-es';
7
8
  import Guides from '@scena/guides';
8
9
 
9
10
  const GHOST_EL_ID_PREFIX = "ghost_el_";
10
11
  const DRAG_EL_ID_PREFIX = "drag_el_";
11
12
  const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
12
- const CONTAINER_HIGHLIGHT_CLASS = "tmagic-stage-container-highlight";
13
+ const CONTAINER_HIGHLIGHT_CLASS_NAME = "tmagic-stage-container-highlight";
13
14
  const PAGE_CLASS = "magic-ui-page";
14
15
  const DEFAULT_ZOOM = 1;
15
16
  var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
@@ -39,89 +40,6 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
39
40
  })(Mode || {});
40
41
  const SELECTED_CLASS = "tmagic-stage-selected-area";
41
42
 
42
- const selectParentAbles = (dr) => ({
43
- name: "selectParent",
44
- props: {},
45
- events: {},
46
- render(moveable, React) {
47
- const rect = moveable.getRect();
48
- const { pos2 } = moveable.state;
49
- const editableViewer = moveable.useCSS(
50
- "div",
51
- `
52
- {
53
- position: absolute;
54
- left: 0px;
55
- top: 0px;
56
- will-change: transform;
57
- transform-origin: 0px 0px;
58
- display: flex;
59
- }
60
- .moveable-button {
61
- width: 20px;
62
- height: 20px;
63
- background: #4af;
64
- border-radius: 4px;
65
- appearance: none;
66
- border: 0;
67
- color: white;
68
- font-size: 12px;
69
- font-weight: bold;
70
- }
71
- `
72
- );
73
- return React.createElement(
74
- editableViewer,
75
- {
76
- className: "moveable-editable",
77
- style: {
78
- transform: `translate(${pos2[0] - 25}px, ${pos2[1] - 30}px) rotate(${rect.rotation}deg) translate(10px)`
79
- }
80
- },
81
- React.createElement(
82
- "button",
83
- {
84
- className: "moveable-button",
85
- title: "\u9009\u4E2D\u7236\u7EC4\u4EF6",
86
- onClick: () => {
87
- dr.emit("select-parent");
88
- }
89
- },
90
- React.createElement(
91
- "svg",
92
- {
93
- width: "1em",
94
- height: "1em",
95
- viewBox: "0 0 16 16",
96
- fill: "none",
97
- xmlns: "http://www.w3.org/2000/svg",
98
- style: {
99
- transform: "rotate(90deg)"
100
- }
101
- },
102
- React.createElement("path", {
103
- d: "M13.0001 4V10H4.20718L5.85363 8.35355L5.14652 7.64645L2.64652 10.1464C2.45126 10.3417 2.45126 10.6583 2.64652 10.8536L5.14652 13.3536L5.85363 12.6464L4.20718 11H13.0001C13.5524 11 14.0001 10.5523 14.0001 10V4H13.0001Z",
104
- fill: "currentColor",
105
- fillOpacity: "0.9"
106
- })
107
- )
108
- )
109
- );
110
- }
111
- });
112
-
113
- var ContainerHighlightType = /* @__PURE__ */ ((ContainerHighlightType2) => {
114
- ContainerHighlightType2["DEFAULT"] = "default";
115
- ContainerHighlightType2["ALT"] = "alt";
116
- return ContainerHighlightType2;
117
- })(ContainerHighlightType || {});
118
- var StageDragStatus = /* @__PURE__ */ ((StageDragStatus2) => {
119
- StageDragStatus2["START"] = "start";
120
- StageDragStatus2["ING"] = "ing";
121
- StageDragStatus2["END"] = "end";
122
- return StageDragStatus2;
123
- })(StageDragStatus || {});
124
-
125
43
  const getParents = (el, relative) => {
126
44
  let cur = el.parentElement;
127
45
  const parents = [];
@@ -132,9 +50,10 @@ const getParents = (el, relative) => {
132
50
  return parents;
133
51
  };
134
52
  const getOffset = (el) => {
135
- const { offsetParent } = el;
136
- const left = el.offsetLeft;
137
- const top = el.offsetTop;
53
+ const htmlEl = el;
54
+ const { offsetParent } = htmlEl;
55
+ const left = htmlEl.offsetLeft || 0;
56
+ const top = htmlEl.offsetTop || 0;
138
57
  if (offsetParent) {
139
58
  const parentOffset = getOffset(offsetParent);
140
59
  return {
@@ -147,7 +66,7 @@ const getOffset = (el) => {
147
66
  top
148
67
  };
149
68
  };
150
- const getTargetElStyle = (el) => {
69
+ const getTargetElStyle = (el, zIndex) => {
151
70
  const offset = getOffset(el);
152
71
  const { transform } = getComputedStyle(el);
153
72
  return `
@@ -157,7 +76,7 @@ const getTargetElStyle = (el) => {
157
76
  top: ${offset.top}px;
158
77
  width: ${el.clientWidth}px;
159
78
  height: ${el.clientHeight}px;
160
- z-index: ${ZIndex.DRAG_EL};
79
+ ${typeof zIndex !== "undefined" ? `z-index: ${zIndex};` : ""}
161
80
  `;
162
81
  };
163
82
  const getAbsolutePosition = (el, { top, left }) => {
@@ -294,252 +213,668 @@ const up = (deltaTop, target) => {
294
213
  };
295
214
  const isMoveableButton = (target) => target.classList.contains("moveable-button") || target.parentElement?.classList.contains("moveable-button");
296
215
 
297
- class StageDragResize extends EventEmitter {
298
- core;
299
- mask;
216
+ class TargetShadow {
217
+ el;
218
+ els = [];
219
+ idPrefix = "target_calibrate_";
300
220
  container;
301
- target;
302
- dragEl;
303
- moveable;
304
- horizontalGuidelines = [];
305
- verticalGuidelines = [];
306
- elementGuidelines = [];
307
- mode = Mode.ABSOLUTE;
308
- moveableOptions = {};
309
- dragStatus = StageDragStatus.END;
310
- ghostEl;
311
- moveableHelper;
312
- isContainerHighlight = false;
221
+ scrollLeft = 0;
222
+ scrollTop = 0;
223
+ zIndex;
224
+ updateDragEl;
313
225
  constructor(config) {
314
- super();
315
- this.core = config.core;
316
226
  this.container = config.container;
317
- this.mask = config.mask;
318
- KeyController.global.keydown("alt", (e) => {
319
- e.inputEvent.preventDefault();
320
- this.isContainerHighlight = true;
321
- });
322
- KeyController.global.keyup("alt", (e) => {
323
- e.inputEvent.preventDefault();
324
- const doc = this.core.renderer.contentWindow?.document;
325
- if (doc && this.canContainerHighlight()) {
326
- removeClassNameByClassName(doc, this.core.containerHighlightClassName);
327
- }
328
- this.isContainerHighlight = false;
329
- });
227
+ if (config.updateDragEl) {
228
+ this.updateDragEl = config.updateDragEl;
229
+ }
230
+ if (typeof config.zIndex !== "undefined") {
231
+ this.zIndex = config.zIndex;
232
+ }
233
+ if (config.idPrefix) {
234
+ this.idPrefix = config.idPrefix;
235
+ }
236
+ this.container.addEventListener("customScroll", this.scrollHandler);
330
237
  }
331
- select(el, event) {
332
- const oldTarget = this.target;
333
- this.target = el;
334
- if (!this.dragEl) {
335
- this.dragEl = globalThis.document.createElement("div");
336
- this.container.append(this.dragEl);
337
- }
338
- if (!this.moveable || this.target !== oldTarget) {
339
- this.init(el);
340
- this.moveableHelper = MoveableHelper.create({
341
- useBeforeRender: true,
342
- useRender: false,
343
- createAuto: true
238
+ update(target) {
239
+ this.el = this.updateEl(target, this.el);
240
+ return this.el;
241
+ }
242
+ updateGroup(targetGroup) {
243
+ if (this.els.length > targetGroup.length) {
244
+ this.els.slice(targetGroup.length - 1).forEach((el) => {
245
+ el.remove();
344
246
  });
345
- this.initMoveable();
346
- } else {
347
- this.updateMoveable();
348
- }
349
- if (event) {
350
- this.moveable?.dragStart(event);
351
247
  }
248
+ this.els = targetGroup.map((target, index) => this.updateEl(target, this.els[index]));
249
+ return this.els;
352
250
  }
353
- updateMoveable(el = this.target) {
354
- if (!this.moveable)
355
- throw new Error("\u672A\u521D\u59CB\u5316moveable");
356
- if (!el)
357
- throw new Error("\u672A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
358
- this.target = el;
359
- this.init(el);
360
- Object.entries(this.moveableOptions).forEach(([key, value]) => {
361
- this.moveable[key] = value;
251
+ destroyEl() {
252
+ this.el?.remove();
253
+ this.el = void 0;
254
+ }
255
+ destroyEls() {
256
+ this.els.forEach((el) => {
257
+ el.remove();
362
258
  });
363
- this.moveable.updateTarget();
259
+ this.els = [];
364
260
  }
365
- setGuidelines(type, guidelines) {
366
- if (type === GuidesType.HORIZONTAL) {
367
- this.horizontalGuidelines = guidelines;
368
- this.moveableOptions.horizontalGuidelines = guidelines;
369
- } else if (type === GuidesType.VERTICAL) {
370
- this.verticalGuidelines = guidelines;
371
- this.moveableOptions.verticalGuidelines = guidelines;
261
+ destroy() {
262
+ this.container.removeEventListener("customScroll", this.scrollHandler);
263
+ this.destroyEl();
264
+ this.destroyEls();
265
+ }
266
+ updateEl(target, src) {
267
+ const el = src || globalThis.document.createElement("div");
268
+ el.id = `${this.idPrefix}${target.id}`;
269
+ el.style.cssText = getTargetElStyle(target, this.zIndex);
270
+ if (typeof this.updateDragEl === "function") {
271
+ this.updateDragEl(el, target);
372
272
  }
373
- if (this.moveable) {
374
- this.updateMoveable();
273
+ const isFixed = isFixedParent(target);
274
+ const mode = this.container.dataset.mode || Mode.ABSOLUTE;
275
+ if (isFixed && mode !== Mode.FIXED) {
276
+ el.style.transform = `translate3d(${this.scrollLeft}px, ${this.scrollTop}px, 0)`;
277
+ } else if (!isFixed && mode === Mode.FIXED) {
278
+ el.style.transform = `translate3d(${-this.scrollLeft}px, ${-this.scrollTop}px, 0)`;
375
279
  }
280
+ if (!globalThis.document.getElementById(el.id)) {
281
+ this.container.append(el);
282
+ }
283
+ return el;
376
284
  }
377
- clearGuides() {
378
- this.horizontalGuidelines = [];
379
- this.verticalGuidelines = [];
380
- this.moveableOptions.horizontalGuidelines = [];
381
- this.moveableOptions.verticalGuidelines = [];
382
- this.updateMoveable();
383
- }
384
- clearSelectStatus() {
385
- if (!this.moveable)
386
- return;
387
- this.destroyDragEl();
388
- this.dragEl = void 0;
389
- this.moveable.target = null;
390
- this.moveable.updateTarget();
391
- }
392
- destroyDragEl() {
393
- this.dragEl?.remove();
285
+ scrollHandler = (e) => {
286
+ this.scrollLeft = e.detail.scrollLeft;
287
+ this.scrollTop = e.detail.scrollTop;
288
+ };
289
+ }
290
+
291
+ class DragResizeHelper {
292
+ targetShadow;
293
+ target;
294
+ targetList = [];
295
+ moveableHelper;
296
+ ghostEl;
297
+ frameSnapShot = {
298
+ left: 0,
299
+ top: 0
300
+ };
301
+ framesSnapShot = [];
302
+ mode = Mode.ABSOLUTE;
303
+ constructor(config) {
304
+ this.moveableHelper = MoveableHelper.create({
305
+ useBeforeRender: true,
306
+ useRender: false,
307
+ createAuto: true
308
+ });
309
+ this.targetShadow = new TargetShadow({
310
+ container: config.container,
311
+ updateDragEl: config.updateDragEl,
312
+ zIndex: ZIndex.DRAG_EL,
313
+ idPrefix: DRAG_EL_ID_PREFIX
314
+ });
394
315
  }
395
316
  destroy() {
396
- this.moveable?.destroy();
317
+ this.targetShadow.destroy();
397
318
  this.destroyGhostEl();
398
- this.destroyDragEl();
399
- this.dragStatus = StageDragStatus.END;
400
- this.removeAllListeners();
319
+ this.moveableHelper.clear();
401
320
  }
402
- init(el) {
403
- if (/(auto|scroll)/.test(el.style.overflow)) {
404
- el.style.overflow = "hidden";
405
- }
406
- this.mode = getMode(el);
321
+ destroyShadowEl() {
322
+ this.targetShadow.destroyEl();
323
+ }
324
+ getShadowEl() {
325
+ return this.targetShadow.el;
326
+ }
327
+ updateShadowEl(el) {
407
328
  this.destroyGhostEl();
408
- if (!this.dragEl) {
409
- return;
410
- }
411
- this.dragEl.style.cssText = getTargetElStyle(el);
412
- this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
413
- if (typeof this.core.config.updateDragEl === "function") {
414
- this.core.config.updateDragEl(this.dragEl, el);
329
+ this.target = el;
330
+ this.targetShadow.update(el);
331
+ }
332
+ setMode(mode) {
333
+ this.mode = mode;
334
+ }
335
+ onResizeStart(e) {
336
+ this.moveableHelper.onResizeStart(e);
337
+ this.frameSnapShot.top = this.target.offsetTop;
338
+ this.frameSnapShot.left = this.target.offsetLeft;
339
+ }
340
+ onResize(e) {
341
+ const { width, height, drag } = e;
342
+ const { beforeTranslate } = drag;
343
+ if (this.mode === Mode.SORTABLE) {
344
+ this.target.style.top = "0px";
345
+ if (this.targetShadow.el) {
346
+ this.targetShadow.el.style.width = `${width}px`;
347
+ this.targetShadow.el.style.height = `${height}px`;
348
+ }
349
+ } else {
350
+ this.moveableHelper.onResize(e);
351
+ this.target.style.left = `${this.frameSnapShot.left + beforeTranslate[0]}px`;
352
+ this.target.style.top = `${this.frameSnapShot.top + beforeTranslate[1]}px`;
415
353
  }
416
- this.moveableOptions = this.getOptions({
417
- target: this.dragEl
418
- });
354
+ this.target.style.width = `${width}px`;
355
+ this.target.style.height = `${height}px`;
419
356
  }
420
- setElementGuidelines(nodes) {
421
- this.elementGuidelines.forEach((node) => {
422
- node.remove();
423
- });
424
- this.elementGuidelines = [];
425
- if (this.mode === Mode.ABSOLUTE) {
426
- this.container.append(this.createGuidelineElements(nodes));
357
+ onDragStart(e) {
358
+ this.moveableHelper.onDragStart(e);
359
+ if (this.mode === Mode.SORTABLE) {
360
+ this.ghostEl = this.generateGhostEl(this.target);
427
361
  }
362
+ this.frameSnapShot.top = this.target.offsetTop;
363
+ this.frameSnapShot.left = this.target.offsetLeft;
428
364
  }
429
- createGuidelineElements(nodes) {
430
- const frame = globalThis.document.createDocumentFragment();
431
- for (const node of nodes) {
432
- const { width, height } = node.getBoundingClientRect();
433
- if (node === this.target)
434
- continue;
435
- const { left, top } = getOffset(node);
436
- const elementGuideline = globalThis.document.createElement("div");
437
- elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
438
- this.elementGuidelines.push(elementGuideline);
439
- frame.append(elementGuideline);
365
+ onDrag(e) {
366
+ if (this.ghostEl) {
367
+ this.ghostEl.style.top = `${this.frameSnapShot.top + e.beforeTranslate[1]}px`;
368
+ return;
440
369
  }
441
- return frame;
370
+ this.moveableHelper.onDrag(e);
371
+ this.target.style.left = `${this.frameSnapShot.left + e.beforeTranslate[0]}px`;
372
+ this.target.style.top = `${this.frameSnapShot.top + e.beforeTranslate[1]}px`;
442
373
  }
443
- initMoveable() {
444
- this.moveable?.destroy();
445
- this.moveable = new Moveable(this.container, {
446
- ...this.moveableOptions
447
- });
448
- this.bindResizeEvent();
449
- this.bindDragEvent();
450
- this.bindRotateEvent();
451
- this.bindScaleEvent();
374
+ onRotateStart(e) {
375
+ this.moveableHelper.onRotateStart(e);
452
376
  }
453
- bindResizeEvent() {
454
- if (!this.moveable)
455
- throw new Error("moveable \u672A\u521D\u59CB\u5316");
456
- const frame = {
457
- left: 0,
458
- top: 0
459
- };
460
- this.moveable.on("resizeStart", (e) => {
461
- if (!this.target)
377
+ onRotate(e) {
378
+ this.moveableHelper.onRotate(e);
379
+ const frame = this.moveableHelper.getFrame(e.target);
380
+ this.target.style.transform = frame?.toCSSObject().transform || "";
381
+ }
382
+ onScaleStart(e) {
383
+ this.moveableHelper.onScaleStart(e);
384
+ }
385
+ onScale(e) {
386
+ this.moveableHelper.onScale(e);
387
+ const frame = this.moveableHelper.getFrame(e.target);
388
+ this.target.style.transform = frame?.toCSSObject().transform || "";
389
+ }
390
+ getGhostEl() {
391
+ return this.ghostEl;
392
+ }
393
+ destroyGhostEl() {
394
+ this.ghostEl?.remove();
395
+ this.ghostEl = void 0;
396
+ }
397
+ clear() {
398
+ this.moveableHelper.clear();
399
+ }
400
+ getFrame(el) {
401
+ return this.moveableHelper.getFrame(el);
402
+ }
403
+ getShadowEls() {
404
+ return this.targetShadow.els;
405
+ }
406
+ updateGroup(els) {
407
+ this.targetList = els;
408
+ this.framesSnapShot = [];
409
+ this.targetShadow.updateGroup(els);
410
+ }
411
+ setTargetList(targetList) {
412
+ this.targetList = targetList;
413
+ }
414
+ clearMultiSelectStatus() {
415
+ this.targetList = [];
416
+ this.targetShadow.destroyEls();
417
+ }
418
+ onResizeGroupStart(e) {
419
+ const { events } = e;
420
+ this.moveableHelper.onResizeGroupStart(e);
421
+ this.setFramesSnapShot(events);
422
+ }
423
+ onResizeGroup(e) {
424
+ const { events } = e;
425
+ events.forEach((ev) => {
426
+ const { width, height, beforeTranslate } = ev.drag;
427
+ const frameSnapShot = this.framesSnapShot.find(
428
+ (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
429
+ );
430
+ if (!frameSnapShot)
462
431
  return;
463
- this.dragStatus = StageDragStatus.START;
464
- this.moveableHelper?.onResizeStart(e);
465
- frame.top = this.target.offsetTop;
466
- frame.left = this.target.offsetLeft;
467
- }).on("resize", (e) => {
468
- const { width, height, drag } = e;
469
- if (!this.moveable || !this.target || !this.dragEl)
432
+ const targeEl = this.targetList.find(
433
+ (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
434
+ );
435
+ if (!targeEl)
470
436
  return;
471
- const { beforeTranslate } = drag;
472
- this.dragStatus = StageDragStatus.ING;
473
- if (this.mode === Mode.SORTABLE) {
474
- this.target.style.top = "0px";
475
- this.dragEl.style.width = `${width}px`;
476
- this.dragEl.style.height = `${height}px`;
477
- } else {
478
- this.moveableHelper?.onResize(e);
479
- this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
480
- this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
437
+ const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
438
+ if (!isParentIncluded) {
439
+ targeEl.style.left = `${frameSnapShot.left + beforeTranslate[0]}px`;
440
+ targeEl.style.top = `${frameSnapShot.top + beforeTranslate[1]}px`;
481
441
  }
482
- this.target.style.width = `${width}px`;
483
- this.target.style.height = `${height}px`;
484
- }).on("resizeEnd", () => {
485
- this.dragStatus = StageDragStatus.END;
486
- this.update(true);
442
+ targeEl.style.width = `${width}px`;
443
+ targeEl.style.height = `${height}px`;
487
444
  });
488
- }
489
- bindDragEvent() {
490
- if (!this.moveable)
491
- throw new Error("moveable \u672A\u521D\u59CB\u5316");
492
- const frame = {
493
- left: 0,
494
- top: 0
495
- };
496
- let timeout;
497
- const { contentWindow } = this.core.renderer;
498
- const doc = contentWindow?.document;
499
- this.moveable.on("dragStart", (e) => {
500
- if (!this.target)
501
- throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
502
- this.dragStatus = StageDragStatus.START;
503
- this.moveableHelper?.onDragStart(e);
504
- if (this.mode === Mode.SORTABLE) {
505
- this.ghostEl = this.generateGhostEl(this.target);
506
- }
507
- frame.top = this.target.offsetTop;
508
- frame.left = this.target.offsetLeft;
509
- }).on("drag", (e) => {
510
- if (!this.target || !this.dragEl)
445
+ this.moveableHelper.onResizeGroup(e);
446
+ }
447
+ onDragGroupStart(e) {
448
+ const { events } = e;
449
+ this.moveableHelper.onDragGroupStart(e);
450
+ this.setFramesSnapShot(events);
451
+ }
452
+ onDragGroup(e) {
453
+ const { events } = e;
454
+ events.forEach((ev) => {
455
+ const frameSnapShot = this.framesSnapShot.find(
456
+ (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
457
+ );
458
+ if (!frameSnapShot)
511
459
  return;
512
- if (timeout) {
513
- globalThis.clearTimeout(timeout);
514
- timeout = void 0;
515
- }
516
- if (this.canContainerHighlight()) {
517
- timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
518
- }
519
- this.dragStatus = StageDragStatus.ING;
520
- if (this.ghostEl) {
521
- this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
460
+ const targeEl = this.targetList.find(
461
+ (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
462
+ );
463
+ if (!targeEl)
522
464
  return;
465
+ const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
466
+ if (!isParentIncluded) {
467
+ targeEl.style.left = `${frameSnapShot.left + ev.beforeTranslate[0]}px`;
468
+ targeEl.style.top = `${frameSnapShot.top + ev.beforeTranslate[1]}px`;
523
469
  }
524
- this.moveableHelper?.onDrag(e);
525
- this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
526
- this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
527
- }).on("dragEnd", () => {
528
- if (timeout) {
529
- globalThis.clearTimeout(timeout);
530
- timeout = void 0;
531
- }
532
- let parentEl = null;
533
- if (doc && this.canContainerHighlight()) {
534
- parentEl = removeClassNameByClassName(doc, this.core.containerHighlightClassName);
535
- }
536
- if (this.dragStatus === StageDragStatus.ING) {
537
- if (parentEl) {
538
- this.update(false, parentEl);
539
- } else {
540
- switch (this.mode) {
541
- case Mode.SORTABLE:
542
- this.sort();
470
+ });
471
+ this.moveableHelper.onDragGroup(e);
472
+ }
473
+ setFramesSnapShot(events) {
474
+ if (this.framesSnapShot.length > 0)
475
+ return;
476
+ events.forEach((ev) => {
477
+ const matchEventTarget = this.targetList.find(
478
+ (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
479
+ );
480
+ if (!matchEventTarget)
481
+ return;
482
+ this.framesSnapShot.push({
483
+ left: matchEventTarget.offsetLeft,
484
+ top: matchEventTarget.offsetTop,
485
+ id: matchEventTarget.id
486
+ });
487
+ });
488
+ }
489
+ generateGhostEl(el) {
490
+ if (this.ghostEl) {
491
+ this.destroyGhostEl();
492
+ }
493
+ const ghostEl = el.cloneNode(true);
494
+ this.setGhostElChildrenId(ghostEl);
495
+ const { top, left } = getAbsolutePosition(el, getOffset(el));
496
+ ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
497
+ ghostEl.style.zIndex = ZIndex.GHOST_EL;
498
+ ghostEl.style.opacity = ".5";
499
+ ghostEl.style.position = "absolute";
500
+ ghostEl.style.left = `${left}px`;
501
+ ghostEl.style.top = `${top}px`;
502
+ el.after(ghostEl);
503
+ return ghostEl;
504
+ }
505
+ setGhostElChildrenId(el) {
506
+ for (const child of Array.from(el.children)) {
507
+ if (child.id) {
508
+ child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
509
+ }
510
+ if (child.children.length) {
511
+ this.setGhostElChildrenId(child);
512
+ }
513
+ }
514
+ }
515
+ }
516
+
517
+ const selectParentAbles = (selectParentHandler) => ({
518
+ name: "select-parent",
519
+ props: {},
520
+ events: {},
521
+ render(moveable, React) {
522
+ const rect = moveable.getRect();
523
+ const { pos2 } = moveable.state;
524
+ const editableViewer = moveable.useCSS(
525
+ "div",
526
+ `
527
+ {
528
+ position: absolute;
529
+ left: 0px;
530
+ top: 0px;
531
+ will-change: transform;
532
+ transform-origin: 0px 0px;
533
+ display: flex;
534
+ }
535
+ .moveable-button {
536
+ width: 20px;
537
+ height: 20px;
538
+ background: #4af;
539
+ border-radius: 4px;
540
+ appearance: none;
541
+ border: 0;
542
+ color: white;
543
+ font-size: 12px;
544
+ font-weight: bold;
545
+ }
546
+ `
547
+ );
548
+ return React.createElement(
549
+ editableViewer,
550
+ {
551
+ className: "moveable-editable",
552
+ style: {
553
+ transform: `translate(${pos2[0] - 25}px, ${pos2[1] - 30}px) rotate(${rect.rotation}deg) translate(10px)`
554
+ }
555
+ },
556
+ React.createElement(
557
+ "button",
558
+ {
559
+ className: "moveable-button",
560
+ title: "\u9009\u4E2D\u7236\u7EC4\u4EF6",
561
+ onClick: () => {
562
+ selectParentHandler();
563
+ }
564
+ },
565
+ React.createElement(
566
+ "svg",
567
+ {
568
+ width: "1em",
569
+ height: "1em",
570
+ viewBox: "0 0 16 16",
571
+ fill: "none",
572
+ xmlns: "http://www.w3.org/2000/svg",
573
+ style: {
574
+ transform: "rotate(90deg)"
575
+ }
576
+ },
577
+ React.createElement("path", {
578
+ d: "M13.0001 4V10H4.20718L5.85363 8.35355L5.14652 7.64645L2.64652 10.1464C2.45126 10.3417 2.45126 10.6583 2.64652 10.8536L5.14652 13.3536L5.85363 12.6464L4.20718 11H13.0001C13.5524 11 14.0001 10.5523 14.0001 10V4H13.0001Z",
579
+ fill: "currentColor",
580
+ fillOpacity: "0.9"
581
+ })
582
+ )
583
+ )
584
+ );
585
+ }
586
+ });
587
+
588
+ class MoveableOptionsManager extends EventEmitter {
589
+ mode = Mode.ABSOLUTE;
590
+ container;
591
+ horizontalGuidelines = [];
592
+ verticalGuidelines = [];
593
+ elementGuidelines = [];
594
+ customizedOptions;
595
+ getRootContainer;
596
+ constructor(config) {
597
+ super();
598
+ this.customizedOptions = config.moveableOptions;
599
+ this.container = config.container;
600
+ this.getRootContainer = config.getRootContainer;
601
+ }
602
+ setGuidelines(type, guidelines) {
603
+ if (type === GuidesType.HORIZONTAL) {
604
+ this.horizontalGuidelines = guidelines;
605
+ } else if (type === GuidesType.VERTICAL) {
606
+ this.verticalGuidelines = guidelines;
607
+ }
608
+ this.emit("update-moveable");
609
+ }
610
+ clearGuides() {
611
+ this.horizontalGuidelines = [];
612
+ this.verticalGuidelines = [];
613
+ this.emit("update-moveable");
614
+ }
615
+ setElementGuidelines(selectedElList, allElList) {
616
+ this.elementGuidelines.forEach((node) => {
617
+ node.remove();
618
+ });
619
+ this.elementGuidelines = [];
620
+ if (this.mode === Mode.ABSOLUTE) {
621
+ this.container.append(this.createGuidelineElements(selectedElList, allElList));
622
+ }
623
+ }
624
+ getOptions(isMultiSelect, runtimeOptions = {}) {
625
+ const defaultOptions = this.getDefaultOptions(isMultiSelect);
626
+ const customizedOptions = this.getCustomizeOptions();
627
+ return merge(defaultOptions, customizedOptions, runtimeOptions);
628
+ }
629
+ getDefaultOptions(isMultiSelect) {
630
+ const isSortable = this.mode === Mode.SORTABLE;
631
+ const commonOptions = {
632
+ draggable: true,
633
+ resizable: true,
634
+ rootContainer: this.getRootContainer(),
635
+ zoom: 1,
636
+ throttleDrag: 0,
637
+ snappable: true,
638
+ horizontalGuidelines: this.horizontalGuidelines,
639
+ verticalGuidelines: this.verticalGuidelines,
640
+ elementGuidelines: this.elementGuidelines,
641
+ bounds: {
642
+ top: 0,
643
+ left: -1,
644
+ right: this.container.clientWidth - 1,
645
+ bottom: isSortable ? void 0 : this.container.clientHeight
646
+ }
647
+ };
648
+ const differenceOptions = isMultiSelect ? this.getMultiOptions() : this.getSingleOptions();
649
+ return merge(commonOptions, differenceOptions);
650
+ }
651
+ getSingleOptions() {
652
+ const isAbsolute = this.mode === Mode.ABSOLUTE;
653
+ const isFixed = this.mode === Mode.FIXED;
654
+ return {
655
+ origin: false,
656
+ dragArea: false,
657
+ scalable: false,
658
+ rotatable: false,
659
+ snapGap: isAbsolute || isFixed,
660
+ snapThreshold: 5,
661
+ snapDigit: 0,
662
+ isDisplaySnapDigit: isAbsolute,
663
+ snapDirections: {
664
+ top: isAbsolute,
665
+ right: isAbsolute,
666
+ bottom: isAbsolute,
667
+ left: isAbsolute,
668
+ center: isAbsolute,
669
+ middle: isAbsolute
670
+ },
671
+ elementSnapDirections: {
672
+ top: isAbsolute,
673
+ right: isAbsolute,
674
+ bottom: isAbsolute,
675
+ left: isAbsolute
676
+ },
677
+ isDisplayInnerSnapDigit: true,
678
+ props: {
679
+ selectParent: true
680
+ },
681
+ ables: [selectParentAbles(this.selectParentHandler.bind(this))]
682
+ };
683
+ }
684
+ getMultiOptions() {
685
+ return {
686
+ defaultGroupRotate: 0,
687
+ defaultGroupOrigin: "50% 50%",
688
+ startDragRotate: 0,
689
+ throttleDragRotate: 0,
690
+ origin: true,
691
+ padding: { left: 0, top: 0, right: 0, bottom: 0 }
692
+ };
693
+ }
694
+ getCustomizeOptions() {
695
+ if (typeof this.customizedOptions === "function") {
696
+ return this.customizedOptions();
697
+ }
698
+ return this.customizedOptions;
699
+ }
700
+ selectParentHandler() {
701
+ this.emit("select-parent");
702
+ }
703
+ createGuidelineElements(selectedElList, allElList) {
704
+ const frame = globalThis.document.createDocumentFragment();
705
+ for (const node of allElList) {
706
+ const { width, height } = node.getBoundingClientRect();
707
+ if (this.isInElementList(node, selectedElList))
708
+ continue;
709
+ const { left, top } = getOffset(node);
710
+ const elementGuideline = globalThis.document.createElement("div");
711
+ elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
712
+ this.elementGuidelines.push(elementGuideline);
713
+ frame.append(elementGuideline);
714
+ }
715
+ return frame;
716
+ }
717
+ isInElementList(ele, eleList) {
718
+ for (const eleItem of eleList) {
719
+ if (ele === eleItem)
720
+ return true;
721
+ }
722
+ return false;
723
+ }
724
+ }
725
+
726
+ var ContainerHighlightType = /* @__PURE__ */ ((ContainerHighlightType2) => {
727
+ ContainerHighlightType2["DEFAULT"] = "default";
728
+ ContainerHighlightType2["ALT"] = "alt";
729
+ return ContainerHighlightType2;
730
+ })(ContainerHighlightType || {});
731
+ var SelectStatus = /* @__PURE__ */ ((SelectStatus2) => {
732
+ SelectStatus2["SELECT"] = "select";
733
+ SelectStatus2["MULTI_SELECT"] = "multiSelect";
734
+ return SelectStatus2;
735
+ })(SelectStatus || {});
736
+ var StageDragStatus = /* @__PURE__ */ ((StageDragStatus2) => {
737
+ StageDragStatus2["START"] = "start";
738
+ StageDragStatus2["ING"] = "ing";
739
+ StageDragStatus2["END"] = "end";
740
+ return StageDragStatus2;
741
+ })(StageDragStatus || {});
742
+
743
+ class StageDragResize extends MoveableOptionsManager {
744
+ target;
745
+ moveable;
746
+ dragStatus = StageDragStatus.END;
747
+ dragResizeHelper;
748
+ disabledDragStart;
749
+ getRenderDocument;
750
+ markContainerEnd;
751
+ delayedMarkContainer;
752
+ constructor(config) {
753
+ super(config);
754
+ this.getRenderDocument = config.getRenderDocument;
755
+ this.markContainerEnd = config.markContainerEnd;
756
+ this.delayedMarkContainer = config.delayedMarkContainer;
757
+ this.disabledDragStart = config.disabledDragStart;
758
+ this.dragResizeHelper = new DragResizeHelper({
759
+ container: config.container,
760
+ updateDragEl: config.updateDragEl
761
+ });
762
+ this.on("update-moveable", () => {
763
+ if (this.moveable) {
764
+ this.updateMoveable();
765
+ }
766
+ });
767
+ }
768
+ select(el, event) {
769
+ if (!this.moveable || el !== this.target) {
770
+ this.initMoveable(el);
771
+ } else {
772
+ this.updateMoveable(el);
773
+ }
774
+ if (event && !this.disabledDragStart) {
775
+ this.moveable?.dragStart(event);
776
+ }
777
+ }
778
+ updateMoveable(el = this.target) {
779
+ if (!this.moveable)
780
+ return;
781
+ if (!el)
782
+ throw new Error("\u672A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
783
+ const options = this.init(el);
784
+ Object.entries(options).forEach(([key, value]) => {
785
+ this.moveable[key] = value;
786
+ });
787
+ this.moveable.updateTarget();
788
+ }
789
+ clearSelectStatus() {
790
+ if (!this.moveable)
791
+ return;
792
+ this.dragResizeHelper.destroyShadowEl();
793
+ this.moveable.target = null;
794
+ this.moveable.updateTarget();
795
+ }
796
+ destroy() {
797
+ this.moveable?.destroy();
798
+ this.dragResizeHelper.destroy();
799
+ this.dragStatus = StageDragStatus.END;
800
+ this.removeAllListeners();
801
+ }
802
+ init(el) {
803
+ if (/(auto|scroll)/.test(el.style.overflow)) {
804
+ el.style.overflow = "hidden";
805
+ }
806
+ this.target = el;
807
+ this.mode = getMode(el);
808
+ this.dragResizeHelper.updateShadowEl(el);
809
+ this.dragResizeHelper.setMode(this.mode);
810
+ const elementGuidelines = Array.prototype.slice.call(this.target?.parentElement?.children) || [];
811
+ this.setElementGuidelines([this.target], elementGuidelines);
812
+ return this.getOptions(false, {
813
+ target: this.dragResizeHelper.getShadowEl()
814
+ });
815
+ }
816
+ initMoveable(el) {
817
+ const options = this.init(el);
818
+ this.dragResizeHelper.clear();
819
+ this.moveable?.destroy();
820
+ this.moveable = new Moveable(this.container, {
821
+ ...options
822
+ });
823
+ this.bindResizeEvent();
824
+ this.bindDragEvent();
825
+ this.bindRotateEvent();
826
+ this.bindScaleEvent();
827
+ }
828
+ bindResizeEvent() {
829
+ if (!this.moveable)
830
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
831
+ this.moveable.on("resizeStart", (e) => {
832
+ if (!this.target)
833
+ return;
834
+ this.dragStatus = StageDragStatus.START;
835
+ this.dragResizeHelper.onResizeStart(e);
836
+ }).on("resize", (e) => {
837
+ if (!this.moveable || !this.target || !this.dragResizeHelper.getShadowEl())
838
+ return;
839
+ this.dragStatus = StageDragStatus.ING;
840
+ this.dragResizeHelper.onResize(e);
841
+ }).on("resizeEnd", () => {
842
+ this.dragStatus = StageDragStatus.END;
843
+ this.update(true);
844
+ });
845
+ }
846
+ bindDragEvent() {
847
+ if (!this.moveable)
848
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
849
+ let timeout;
850
+ this.moveable.on("dragStart", (e) => {
851
+ if (!this.target)
852
+ throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
853
+ this.dragStatus = StageDragStatus.START;
854
+ this.dragResizeHelper.onDragStart(e);
855
+ }).on("drag", (e) => {
856
+ if (!this.target || !this.dragResizeHelper.getShadowEl())
857
+ return;
858
+ if (timeout) {
859
+ globalThis.clearTimeout(timeout);
860
+ timeout = void 0;
861
+ }
862
+ timeout = this.delayedMarkContainer(e.inputEvent, [this.target]);
863
+ this.dragStatus = StageDragStatus.ING;
864
+ this.dragResizeHelper.onDrag(e);
865
+ }).on("dragEnd", () => {
866
+ if (timeout) {
867
+ globalThis.clearTimeout(timeout);
868
+ timeout = void 0;
869
+ }
870
+ const parentEl = this.markContainerEnd();
871
+ if (this.dragStatus === StageDragStatus.ING) {
872
+ if (parentEl) {
873
+ this.update(false, parentEl);
874
+ } else {
875
+ switch (this.mode) {
876
+ case Mode.SORTABLE:
877
+ this.sort();
543
878
  break;
544
879
  default:
545
880
  this.update();
@@ -547,7 +882,7 @@ class StageDragResize extends EventEmitter {
547
882
  }
548
883
  }
549
884
  this.dragStatus = StageDragStatus.END;
550
- this.destroyGhostEl();
885
+ this.dragResizeHelper.destroyGhostEl();
551
886
  });
552
887
  }
553
888
  bindRotateEvent() {
@@ -555,17 +890,15 @@ class StageDragResize extends EventEmitter {
555
890
  throw new Error("moveable \u672A\u521D\u59CB\u5316");
556
891
  this.moveable.on("rotateStart", (e) => {
557
892
  this.dragStatus = StageDragStatus.START;
558
- this.moveableHelper?.onRotateStart(e);
893
+ this.dragResizeHelper.onRotateStart(e);
559
894
  }).on("rotate", (e) => {
560
- if (!this.target || !this.dragEl)
895
+ if (!this.target || !this.dragResizeHelper.getShadowEl())
561
896
  return;
562
897
  this.dragStatus = StageDragStatus.ING;
563
- this.moveableHelper?.onRotate(e);
564
- const frame = this.moveableHelper?.getFrame(e.target);
565
- this.target.style.transform = frame?.toCSSObject().transform || "";
898
+ this.dragResizeHelper.onRotate(e);
566
899
  }).on("rotateEnd", (e) => {
567
900
  this.dragStatus = StageDragStatus.END;
568
- const frame = this.moveableHelper?.getFrame(e.target);
901
+ const frame = this.dragResizeHelper?.getFrame(e.target);
569
902
  this.emit("update", {
570
903
  data: [
571
904
  {
@@ -583,17 +916,15 @@ class StageDragResize extends EventEmitter {
583
916
  throw new Error("moveable \u672A\u521D\u59CB\u5316");
584
917
  this.moveable.on("scaleStart", (e) => {
585
918
  this.dragStatus = StageDragStatus.START;
586
- this.moveableHelper?.onScaleStart(e);
919
+ this.dragResizeHelper.onScaleStart(e);
587
920
  }).on("scale", (e) => {
588
- if (!this.target || !this.dragEl)
921
+ if (!this.target || !this.dragResizeHelper.getShadowEl())
589
922
  return;
590
923
  this.dragStatus = StageDragStatus.ING;
591
- this.moveableHelper?.onScale(e);
592
- const frame = this.moveableHelper?.getFrame(e.target);
593
- this.target.style.transform = frame?.toCSSObject().transform || "";
924
+ this.dragResizeHelper.onScale(e);
594
925
  }).on("scaleEnd", (e) => {
595
926
  this.dragStatus = StageDragStatus.END;
596
- const frame = this.moveableHelper?.getFrame(e.target);
927
+ const frame = this.dragResizeHelper.getFrame(e.target);
597
928
  this.emit("update", {
598
929
  data: [
599
930
  {
@@ -607,9 +938,9 @@ class StageDragResize extends EventEmitter {
607
938
  });
608
939
  }
609
940
  sort() {
610
- if (!this.target || !this.ghostEl)
941
+ if (!this.target || !this.dragResizeHelper.getGhostEl())
611
942
  throw new Error("\u672A\u77E5\u9519\u8BEF");
612
- const { top } = this.ghostEl.getBoundingClientRect();
943
+ const { top } = this.dragResizeHelper.getGhostEl().getBoundingClientRect();
613
944
  const { top: oriTop } = this.target.getBoundingClientRect();
614
945
  const deltaTop = top - oriTop;
615
946
  if (Math.abs(deltaTop) >= this.target.clientHeight / 2) {
@@ -628,8 +959,7 @@ class StageDragResize extends EventEmitter {
628
959
  update(isResize = false, parentEl = null) {
629
960
  if (!this.target)
630
961
  return;
631
- const { contentWindow } = this.core.renderer;
632
- const doc = contentWindow?.document;
962
+ const doc = this.getRenderDocument();
633
963
  if (!doc)
634
964
  return;
635
965
  const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
@@ -637,11 +967,16 @@ class StageDragResize extends EventEmitter {
637
967
  let top = calcValueByFontsize(doc, offset.top);
638
968
  const width = calcValueByFontsize(doc, this.target.clientWidth);
639
969
  const height = calcValueByFontsize(doc, this.target.clientHeight);
640
- if (parentEl && this.mode === Mode.ABSOLUTE && this.dragEl) {
641
- const [translateX, translateY] = this.moveableHelper?.getFrame(this.dragEl).properties.transform.translate.value;
970
+ const shadowEl = this.dragResizeHelper.getShadowEl();
971
+ if (parentEl && this.mode === Mode.ABSOLUTE && shadowEl) {
972
+ const targetShadowHtmlEl = shadowEl;
973
+ const targetShadowElOffsetLeft = targetShadowHtmlEl.offsetLeft || 0;
974
+ const targetShadowElOffsetTop = targetShadowHtmlEl.offsetTop || 0;
975
+ const frame = this.dragResizeHelper.getFrame(shadowEl);
976
+ const [translateX, translateY] = frame?.properties.transform.translate.value;
642
977
  const { left: parentLeft, top: parentTop } = getOffset(parentEl);
643
- left = calcValueByFontsize(doc, this.dragEl.offsetLeft) + parseFloat(translateX) - calcValueByFontsize(doc, parentLeft);
644
- top = calcValueByFontsize(doc, this.dragEl.offsetTop) + parseFloat(translateY) - calcValueByFontsize(doc, parentTop);
978
+ left = calcValueByFontsize(doc, targetShadowElOffsetLeft) + parseFloat(translateX) - calcValueByFontsize(doc, parentLeft);
979
+ top = calcValueByFontsize(doc, targetShadowElOffsetTop) + parseFloat(translateY) - calcValueByFontsize(doc, parentTop);
645
980
  }
646
981
  this.emit("update", {
647
982
  data: [
@@ -653,219 +988,517 @@ class StageDragResize extends EventEmitter {
653
988
  parentEl
654
989
  });
655
990
  }
656
- generateGhostEl(el) {
657
- if (this.ghostEl) {
658
- this.destroyGhostEl();
659
- }
660
- const ghostEl = el.cloneNode(true);
661
- this.setGhostElChildrenId(ghostEl);
662
- const { top, left } = getAbsolutePosition(el, getOffset(el));
663
- ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
664
- ghostEl.style.zIndex = ZIndex.GHOST_EL;
665
- ghostEl.style.opacity = ".5";
666
- ghostEl.style.position = "absolute";
667
- ghostEl.style.left = `${left}px`;
668
- ghostEl.style.top = `${top}px`;
669
- el.after(ghostEl);
670
- return ghostEl;
991
+ }
992
+
993
+ class StageHighlight extends EventEmitter$1 {
994
+ container;
995
+ target;
996
+ moveable;
997
+ targetShadow;
998
+ getRootContainer;
999
+ constructor(config) {
1000
+ super();
1001
+ this.container = config.container;
1002
+ this.getRootContainer = config.getRootContainer;
1003
+ this.targetShadow = new TargetShadow({
1004
+ container: config.container,
1005
+ updateDragEl: config.updateDragEl,
1006
+ zIndex: ZIndex.HIGHLIGHT_EL,
1007
+ idPrefix: HIGHLIGHT_EL_ID_PREFIX
1008
+ });
671
1009
  }
672
- setGhostElChildrenId(el) {
673
- for (const child of Array.from(el.children)) {
674
- if (child.id) {
675
- child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
1010
+ highlight(el) {
1011
+ if (!el || el === this.target)
1012
+ return;
1013
+ this.target = el;
1014
+ this.moveable?.destroy();
1015
+ this.moveable = new Moveable(this.container, {
1016
+ target: this.targetShadow.update(el),
1017
+ origin: false,
1018
+ rootContainer: this.getRootContainer(),
1019
+ zoom: 2
1020
+ });
1021
+ }
1022
+ clearHighlight() {
1023
+ if (!this.moveable || !this.target)
1024
+ return;
1025
+ this.target = void 0;
1026
+ this.moveable.target = null;
1027
+ this.moveable.updateTarget();
1028
+ }
1029
+ destroy() {
1030
+ this.moveable?.destroy();
1031
+ this.targetShadow.destroy();
1032
+ }
1033
+ }
1034
+
1035
+ class StageMultiDragResize extends MoveableOptionsManager {
1036
+ container;
1037
+ targetList = [];
1038
+ moveableForMulti;
1039
+ dragStatus = StageDragStatus.END;
1040
+ dragResizeHelper;
1041
+ getRenderDocument;
1042
+ constructor(config) {
1043
+ const moveableOptionsManagerConfig = {
1044
+ container: config.container,
1045
+ moveableOptions: config.multiMoveableOptions,
1046
+ getRootContainer: config.getRootContainer
1047
+ };
1048
+ super(moveableOptionsManagerConfig);
1049
+ this.container = config.container;
1050
+ this.getRenderDocument = config.getRenderDocument;
1051
+ this.dragResizeHelper = new DragResizeHelper({
1052
+ container: config.container,
1053
+ updateDragEl: config.updateDragEl
1054
+ });
1055
+ this.on("update-moveable", () => {
1056
+ if (this.moveableForMulti) {
1057
+ this.updateMoveable();
676
1058
  }
677
- if (child.children.length) {
678
- this.setGhostElChildrenId(child);
1059
+ });
1060
+ }
1061
+ multiSelect(els) {
1062
+ if (els.length === 0) {
1063
+ return;
1064
+ }
1065
+ this.mode = getMode(els[0]);
1066
+ this.targetList = els;
1067
+ this.dragResizeHelper.updateGroup(els);
1068
+ const elementGuidelines = Array.prototype.slice.call(this.targetList[0].parentElement?.children) || [];
1069
+ this.setElementGuidelines(this.targetList, elementGuidelines);
1070
+ this.moveableForMulti?.destroy();
1071
+ this.dragResizeHelper.clear();
1072
+ this.moveableForMulti = new Moveable(
1073
+ this.container,
1074
+ this.getOptions(true, {
1075
+ target: this.dragResizeHelper.getShadowEls()
1076
+ })
1077
+ );
1078
+ this.moveableForMulti.on("resizeGroupStart", (e) => {
1079
+ this.dragResizeHelper.onResizeGroupStart(e);
1080
+ this.dragStatus = StageDragStatus.START;
1081
+ }).on("resizeGroup", (e) => {
1082
+ this.dragResizeHelper.onResizeGroup(e);
1083
+ this.dragStatus = StageDragStatus.ING;
1084
+ }).on("resizeGroupEnd", () => {
1085
+ this.update(true);
1086
+ this.dragStatus = StageDragStatus.END;
1087
+ }).on("dragGroupStart", (e) => {
1088
+ this.dragResizeHelper.onDragGroupStart(e);
1089
+ this.dragStatus = StageDragStatus.START;
1090
+ }).on("dragGroup", (e) => {
1091
+ this.dragResizeHelper.onDragGroup(e);
1092
+ this.dragStatus = StageDragStatus.ING;
1093
+ }).on("dragGroupEnd", () => {
1094
+ this.update();
1095
+ this.dragStatus = StageDragStatus.END;
1096
+ }).on("clickGroup", (e) => {
1097
+ const { inputTarget, targets } = e;
1098
+ if (targets.length > 1 && targets.includes(inputTarget)) {
1099
+ this.emit("change-to-select", inputTarget.id.replace(DRAG_EL_ID_PREFIX, ""));
679
1100
  }
1101
+ });
1102
+ }
1103
+ canSelect(el, selectedEl) {
1104
+ const currentTargetMode = getMode(el);
1105
+ let selectedElMode = "";
1106
+ if (currentTargetMode === Mode.SORTABLE) {
1107
+ return false;
1108
+ }
1109
+ if (this.targetList.length === 0 && selectedEl) {
1110
+ selectedElMode = getMode(selectedEl);
1111
+ } else if (this.targetList.length > 0) {
1112
+ selectedElMode = getMode(this.targetList[0]);
680
1113
  }
1114
+ if (currentTargetMode !== selectedElMode) {
1115
+ return false;
1116
+ }
1117
+ return true;
681
1118
  }
682
- destroyGhostEl() {
683
- this.ghostEl?.remove();
684
- this.ghostEl = void 0;
1119
+ updateMoveable(eleList = this.targetList) {
1120
+ if (!this.moveableForMulti)
1121
+ return;
1122
+ if (!eleList)
1123
+ throw new Error("\u672A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
1124
+ this.targetList = eleList;
1125
+ this.dragResizeHelper.setTargetList(eleList);
1126
+ const options = this.getOptions(true, {
1127
+ target: this.dragResizeHelper.getShadowEls()
1128
+ });
1129
+ Object.entries(options).forEach(([key, value]) => {
1130
+ this.moveableForMulti[key] = value;
1131
+ });
1132
+ this.moveableForMulti.updateTarget();
685
1133
  }
686
- getOptions(options = {}) {
687
- if (!this.target)
688
- return {};
689
- const isAbsolute = this.mode === Mode.ABSOLUTE;
690
- const isFixed = this.mode === Mode.FIXED;
691
- const isSortable = this.mode === Mode.SORTABLE;
692
- let { moveableOptions = {} } = this.core.config;
693
- if (typeof moveableOptions === "function") {
694
- moveableOptions = moveableOptions(this.core);
695
- }
696
- const elementGuidelines = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
697
- this.setElementGuidelines(elementGuidelines);
698
- if (moveableOptions.elementGuidelines) {
699
- delete moveableOptions.elementGuidelines;
1134
+ clearSelectStatus() {
1135
+ if (!this.moveableForMulti)
1136
+ return;
1137
+ this.dragResizeHelper.clearMultiSelectStatus();
1138
+ this.moveableForMulti.target = null;
1139
+ this.moveableForMulti.updateTarget();
1140
+ this.targetList = [];
1141
+ }
1142
+ destroy() {
1143
+ this.moveableForMulti?.destroy();
1144
+ this.dragResizeHelper.destroy();
1145
+ }
1146
+ update(isResize = false) {
1147
+ if (this.targetList.length === 0)
1148
+ return;
1149
+ const doc = this.getRenderDocument();
1150
+ if (!doc)
1151
+ return;
1152
+ const data = this.targetList.map((targetItem) => {
1153
+ const left = calcValueByFontsize(doc, targetItem.offsetLeft);
1154
+ const top = calcValueByFontsize(doc, targetItem.offsetTop);
1155
+ const width = calcValueByFontsize(doc, targetItem.clientWidth);
1156
+ const height = calcValueByFontsize(doc, targetItem.clientHeight);
1157
+ return {
1158
+ el: targetItem,
1159
+ style: isResize ? { left, top, width, height } : { left, top }
1160
+ };
1161
+ });
1162
+ this.emit("update", data, null);
1163
+ }
1164
+ }
1165
+
1166
+ const throttleTime = 100;
1167
+ const defaultContainerHighlightDuration = 800;
1168
+ class ActionManager extends EventEmitter {
1169
+ dr;
1170
+ multiDr;
1171
+ highlightLayer;
1172
+ container;
1173
+ selectedEl;
1174
+ selectedElList = [];
1175
+ highlightedEl;
1176
+ isMultiSelectStatus = false;
1177
+ containerHighlightClassName;
1178
+ containerHighlightDuration;
1179
+ containerHighlightType;
1180
+ isAltKeydown = false;
1181
+ getTargetElement;
1182
+ getElementsFromPoint;
1183
+ canSelect;
1184
+ isContainer;
1185
+ getRenderDocument;
1186
+ mouseMoveHandler = throttle(async (event) => {
1187
+ const el = await this.getElementFromPoint(event);
1188
+ if (!el) {
1189
+ this.clearHighlight();
1190
+ return;
700
1191
  }
701
- return {
702
- origin: false,
703
- rootContainer: this.core.container,
704
- zoom: 1,
705
- dragArea: false,
706
- draggable: true,
707
- resizable: true,
708
- scalable: false,
709
- rotatable: false,
710
- snappable: true,
711
- snapGap: isAbsolute || isFixed,
712
- snapThreshold: 5,
713
- snapDigit: 0,
714
- throttleDrag: 0,
715
- isDisplaySnapDigit: isAbsolute,
716
- snapDirections: {
717
- top: isAbsolute,
718
- right: isAbsolute,
719
- bottom: isAbsolute,
720
- left: isAbsolute,
721
- center: isAbsolute,
722
- middle: isAbsolute
723
- },
724
- elementSnapDirections: {
725
- top: isAbsolute,
726
- right: isAbsolute,
727
- bottom: isAbsolute,
728
- left: isAbsolute
729
- },
730
- isDisplayInnerSnapDigit: true,
731
- horizontalGuidelines: this.horizontalGuidelines,
732
- verticalGuidelines: this.verticalGuidelines,
733
- elementGuidelines: this.elementGuidelines,
734
- bounds: {
735
- top: 0,
736
- left: -1,
737
- right: this.container.clientWidth - 1,
738
- bottom: isSortable ? void 0 : this.container.clientHeight,
739
- ...moveableOptions.bounds || {}
740
- },
741
- props: {
742
- selectParent: true
1192
+ this.highlight(el);
1193
+ }, throttleTime);
1194
+ constructor(config) {
1195
+ super();
1196
+ this.container = config.container;
1197
+ this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS_NAME;
1198
+ this.containerHighlightDuration = config.containerHighlightDuration || defaultContainerHighlightDuration;
1199
+ this.containerHighlightType = config.containerHighlightType;
1200
+ this.getTargetElement = config.getTargetElement;
1201
+ this.getElementsFromPoint = config.getElementsFromPoint;
1202
+ this.canSelect = config.canSelect || ((el) => !!el.id);
1203
+ this.getRenderDocument = config.getRenderDocument;
1204
+ this.isContainer = config.isContainer;
1205
+ this.dr = new StageDragResize({
1206
+ container: config.container,
1207
+ disabledDragStart: config.disabledDragStart,
1208
+ getRootContainer: config.getRootContainer,
1209
+ getRenderDocument: config.getRenderDocument,
1210
+ updateDragEl: config.updateDragEl,
1211
+ markContainerEnd: () => this.markContainerEnd(),
1212
+ delayedMarkContainer: (event, exclude) => {
1213
+ if (this.canAddToContainer()) {
1214
+ return this.delayedMarkContainer(event, exclude);
1215
+ }
1216
+ return void 0;
743
1217
  },
744
- ables: [selectParentAbles(this)],
745
- ...options,
746
- ...moveableOptions
747
- };
1218
+ moveableOptions: this.changeCallback(config.moveableOptions)
1219
+ });
1220
+ this.multiDr = new StageMultiDragResize({
1221
+ container: config.container,
1222
+ multiMoveableOptions: config.multiMoveableOptions,
1223
+ getRootContainer: config.getRootContainer,
1224
+ getRenderDocument: config.getRenderDocument,
1225
+ updateDragEl: config.updateDragEl
1226
+ });
1227
+ this.highlightLayer = new StageHighlight({
1228
+ container: config.container,
1229
+ updateDragEl: config.updateDragEl,
1230
+ getRootContainer: config.getRootContainer
1231
+ });
1232
+ this.initMouseEvent();
1233
+ this.initKeyEvent();
1234
+ this.initActionEvent();
1235
+ }
1236
+ setGuidelines(type, guidelines) {
1237
+ this.dr.setGuidelines(type, guidelines);
1238
+ this.multiDr.setGuidelines(type, guidelines);
1239
+ }
1240
+ clearGuides() {
1241
+ this.dr.clearGuides();
1242
+ this.multiDr.clearGuides();
1243
+ }
1244
+ updateMoveable(el) {
1245
+ this.dr.updateMoveable(el);
1246
+ this.multiDr.updateMoveable();
1247
+ }
1248
+ isSelectedEl(el) {
1249
+ return el.id === this.selectedEl?.id;
1250
+ }
1251
+ setSelectedEl(el) {
1252
+ this.selectedEl = el;
1253
+ }
1254
+ getSelectedEl() {
1255
+ return this.selectedEl;
1256
+ }
1257
+ getSelectedElList() {
1258
+ return this.selectedElList;
1259
+ }
1260
+ async getElementFromPoint(event) {
1261
+ const els = this.getElementsFromPoint(event);
1262
+ let stopped = false;
1263
+ const stop = () => stopped = true;
1264
+ for (const el of els) {
1265
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isElCanSelect(el, event, stop)) {
1266
+ if (stopped)
1267
+ break;
1268
+ return el;
1269
+ }
1270
+ }
1271
+ }
1272
+ async isElCanSelect(el, event, stop) {
1273
+ const canSelectByProp = await this.canSelect(el, event, stop);
1274
+ if (!canSelectByProp)
1275
+ return false;
1276
+ if (this.isMultiSelectStatus) {
1277
+ return this.canMultiSelect(el, stop);
1278
+ }
1279
+ return true;
1280
+ }
1281
+ canMultiSelect(el, stop) {
1282
+ if (el.className.includes(PAGE_CLASS)) {
1283
+ stop();
1284
+ return false;
1285
+ }
1286
+ const selectedEl = this.getSelectedEl();
1287
+ if (selectedEl?.className.includes(PAGE_CLASS)) {
1288
+ return true;
1289
+ }
1290
+ return this.multiDr.canSelect(el, selectedEl);
1291
+ }
1292
+ select(el, event) {
1293
+ this.selectedEl = el;
1294
+ this.clearSelectStatus(SelectStatus.MULTI_SELECT);
1295
+ this.dr.select(el, event);
1296
+ }
1297
+ multiSelect(idOrElList) {
1298
+ this.selectedElList = idOrElList.map((idOrEl) => this.getTargetElement(idOrEl));
1299
+ this.clearSelectStatus(SelectStatus.SELECT);
1300
+ this.multiDr.multiSelect(this.selectedElList);
1301
+ }
1302
+ getHighlightEl() {
1303
+ return this.highlightedEl;
1304
+ }
1305
+ setHighlightEl(el) {
1306
+ this.highlightedEl = el;
1307
+ }
1308
+ highlight(idOrEl) {
1309
+ let el;
1310
+ try {
1311
+ el = this.getTargetElement(idOrEl);
1312
+ } catch (error) {
1313
+ this.clearHighlight();
1314
+ return;
1315
+ }
1316
+ if (el === this.getSelectedEl() || this.multiDr.dragStatus === StageDragStatus.ING) {
1317
+ this.clearHighlight();
1318
+ return;
1319
+ }
1320
+ if (el === this.highlightedEl || !el)
1321
+ return;
1322
+ this.highlightLayer.highlight(el);
1323
+ this.highlightedEl = el;
1324
+ this.emit("highlight", el);
748
1325
  }
749
- canContainerHighlight() {
750
- return this.core.containerHighlightType === ContainerHighlightType.DEFAULT || this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight;
1326
+ clearHighlight() {
1327
+ this.setHighlightEl(void 0);
1328
+ this.highlightLayer.clearHighlight();
751
1329
  }
752
- }
753
-
754
- class TargetCalibrate extends EventEmitter {
755
- parent;
756
- mask;
757
- dr;
758
- core;
759
- operationEl;
760
- constructor(config) {
761
- super();
762
- this.parent = config.parent;
763
- this.mask = config.mask;
764
- this.dr = config.dr;
765
- this.core = config.core;
766
- this.operationEl = globalThis.document.createElement("div");
767
- this.parent.append(this.operationEl);
768
- }
769
- update(el, prefix) {
770
- const { left, top } = this.getOffset(el);
771
- const { transform } = getComputedStyle(el);
772
- this.operationEl.style.cssText = `
773
- position: absolute;
774
- transform: ${transform};
775
- left: ${left}px;
776
- top: ${top}px;
777
- width: ${el.clientWidth}px;
778
- height: ${el.clientHeight}px;
779
- z-index: ${ZIndex.HIGHLIGHT_EL};
780
- `;
781
- this.operationEl.id = `${prefix}${el.id}`;
782
- if (typeof this.core.config.updateDragEl === "function") {
783
- this.core.config.updateDragEl(this.operationEl, el);
1330
+ clearSelectStatus(selectType) {
1331
+ if (selectType === SelectStatus.MULTI_SELECT) {
1332
+ this.multiDr.clearSelectStatus();
1333
+ this.selectedElList = [];
1334
+ } else {
1335
+ this.dr.clearSelectStatus();
1336
+ }
1337
+ }
1338
+ async addContainerHighlightClassName(event, excludeElList) {
1339
+ const doc = this.getRenderDocument();
1340
+ if (!doc)
1341
+ return;
1342
+ const els = this.getElementsFromPoint(event);
1343
+ for (const el of els) {
1344
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isContainer(el) && !excludeElList.includes(el)) {
1345
+ addClassName(el, doc, this.containerHighlightClassName);
1346
+ break;
1347
+ }
784
1348
  }
785
- return this.operationEl;
1349
+ }
1350
+ delayedMarkContainer(event, excludeElList = []) {
1351
+ return globalThis.setTimeout(() => {
1352
+ this.addContainerHighlightClassName(event, excludeElList);
1353
+ }, this.containerHighlightDuration);
786
1354
  }
787
1355
  destroy() {
788
- this.operationEl?.remove();
789
- }
790
- getOffset(el) {
791
- const { offsetParent } = el;
792
- const left = el.offsetLeft;
793
- const top = el.offsetTop;
794
- if (offsetParent) {
795
- const parentOffset = this.getOffset(offsetParent);
796
- return {
797
- left: left + parentOffset.left,
798
- top: top + parentOffset.top
1356
+ this.container.removeEventListener("mousedown", this.mouseDownHandler);
1357
+ this.container.removeEventListener("mousemove", this.mouseMoveHandler);
1358
+ this.container.removeEventListener("mouseleave", this.mouseLeaveHandler);
1359
+ this.container.removeEventListener("wheel", this.mouseWheelHandler);
1360
+ this.dr.destroy();
1361
+ this.multiDr.destroy();
1362
+ this.highlightLayer.destroy();
1363
+ }
1364
+ changeCallback(options) {
1365
+ if (typeof options === "function") {
1366
+ return () => {
1367
+ if (typeof options === "function") {
1368
+ const cfg = {
1369
+ targetElId: this.selectedEl?.id
1370
+ };
1371
+ return options(cfg);
1372
+ }
1373
+ return options;
799
1374
  };
800
1375
  }
801
- if (this.dr.mode === Mode.FIXED) {
802
- if (getMode(el) === Mode.FIXED) {
803
- return {
804
- left,
805
- top
806
- };
807
- }
808
- return {
809
- left: left - this.mask.scrollLeft,
810
- top: top - this.mask.scrollTop
811
- };
1376
+ return options;
1377
+ }
1378
+ async beforeMultiSelect(event) {
1379
+ const el = await this.getElementFromPoint(event);
1380
+ if (!el)
1381
+ return;
1382
+ if (this.selectedEl && !this.selectedEl.className.includes(PAGE_CLASS)) {
1383
+ this.selectedElList.push(this.selectedEl);
1384
+ this.selectedEl = void 0;
812
1385
  }
813
- if (getMode(el) === Mode.FIXED) {
814
- return {
815
- left: left + this.mask.scrollLeft,
816
- top: top + this.mask.scrollTop
817
- };
1386
+ const existIndex = this.selectedElList.findIndex((selectedDom) => selectedDom.id === el.id);
1387
+ if (existIndex !== -1) {
1388
+ this.selectedElList.splice(existIndex, 1);
1389
+ } else {
1390
+ this.selectedElList.push(el);
818
1391
  }
819
- return {
820
- left,
821
- top
822
- };
823
1392
  }
824
- }
825
-
826
- class StageHighlight extends EventEmitter {
827
- core;
828
- container;
829
- target;
830
- moveable;
831
- calibrationTarget;
832
- constructor(config) {
833
- super();
834
- this.core = config.core;
835
- this.container = config.container;
836
- this.calibrationTarget = new TargetCalibrate({
837
- parent: this.core.mask.content,
838
- mask: this.core.mask,
839
- dr: this.core.dr,
840
- core: this.core
1393
+ canAddToContainer() {
1394
+ return this.containerHighlightType === ContainerHighlightType.DEFAULT || this.containerHighlightType === ContainerHighlightType.ALT && this.isAltKeydown;
1395
+ }
1396
+ markContainerEnd() {
1397
+ const doc = this.getRenderDocument();
1398
+ if (doc && this.canAddToContainer()) {
1399
+ return removeClassNameByClassName(doc, this.containerHighlightClassName);
1400
+ }
1401
+ return null;
1402
+ }
1403
+ initMouseEvent() {
1404
+ this.container.addEventListener("mousedown", this.mouseDownHandler);
1405
+ this.container.addEventListener("mousemove", this.mouseMoveHandler);
1406
+ this.container.addEventListener("mouseleave", this.mouseLeaveHandler);
1407
+ this.container.addEventListener("wheel", this.mouseWheelHandler);
1408
+ }
1409
+ initKeyEvent() {
1410
+ const { isMac } = new Env();
1411
+ const ctrl = isMac ? "meta" : "ctrl";
1412
+ KeyController.global.keydown(ctrl, (e) => {
1413
+ e.inputEvent.preventDefault();
1414
+ this.isMultiSelectStatus = true;
1415
+ });
1416
+ KeyController.global.on("blur", () => {
1417
+ this.isMultiSelectStatus = false;
1418
+ });
1419
+ KeyController.global.keyup(ctrl, (e) => {
1420
+ e.inputEvent.preventDefault();
1421
+ this.isMultiSelectStatus = false;
1422
+ });
1423
+ KeyController.global.keydown("alt", (e) => {
1424
+ e.inputEvent.preventDefault();
1425
+ this.isAltKeydown = true;
1426
+ });
1427
+ KeyController.global.keyup("alt", (e) => {
1428
+ e.inputEvent.preventDefault();
1429
+ this.markContainerEnd();
1430
+ this.isAltKeydown = false;
841
1431
  });
842
1432
  }
843
- highlight(el) {
844
- if (!el || el === this.target)
845
- return;
846
- this.target = el;
847
- this.moveable?.destroy();
848
- this.moveable = new Moveable(this.container, {
849
- target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
850
- origin: false,
851
- rootContainer: this.core.container,
852
- zoom: 2
1433
+ initActionEvent() {
1434
+ this.dr.on("update", (data) => {
1435
+ setTimeout(() => this.emit("update", data));
1436
+ }).on("sort", (data) => {
1437
+ setTimeout(() => this.emit("sort", data));
1438
+ }).on("select-parent", () => {
1439
+ this.emit("select-parent");
1440
+ });
1441
+ this.multiDr.on("update", (data, parentEl) => {
1442
+ this.emit("multi-update", data, parentEl);
1443
+ }).on("change-to-select", async (id) => {
1444
+ if (this.isMultiSelectStatus)
1445
+ return false;
1446
+ const el = this.getTargetElement(id);
1447
+ this.emit("change-to-select", el);
853
1448
  });
854
1449
  }
855
- clearHighlight() {
856
- if (!this.moveable)
1450
+ mouseDownHandler = async (event) => {
1451
+ this.clearHighlight();
1452
+ event.stopImmediatePropagation();
1453
+ event.stopPropagation();
1454
+ if (this.isStopTriggerSelect(event))
857
1455
  return;
858
- this.target = void 0;
859
- this.moveable.target = null;
860
- this.moveable.updateTarget();
861
- }
862
- destroy() {
863
- this.moveable?.destroy();
864
- this.calibrationTarget.destroy();
1456
+ this.container.removeEventListener("mousemove", this.mouseMoveHandler);
1457
+ if (this.isMultiSelectStatus) {
1458
+ await this.beforeMultiSelect(event);
1459
+ if (this.selectedElList.length > 0) {
1460
+ this.emit("before-multi-select", this.selectedElList);
1461
+ }
1462
+ } else {
1463
+ const el = await this.getElementFromPoint(event);
1464
+ if (!el)
1465
+ return;
1466
+ this.emit("before-select", el, event);
1467
+ }
1468
+ getDocument().addEventListener("mouseup", this.mouseUpHandler);
1469
+ };
1470
+ isStopTriggerSelect(event) {
1471
+ if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
1472
+ return true;
1473
+ if (!event.target)
1474
+ return true;
1475
+ const targetClassList = event.target.classList;
1476
+ if (!this.isMultiSelectStatus && targetClassList.contains("moveable-area")) {
1477
+ return true;
1478
+ }
1479
+ if (targetClassList.contains("moveable-control") || isMoveableButton(event.target)) {
1480
+ return true;
1481
+ }
1482
+ return false;
865
1483
  }
1484
+ mouseUpHandler = () => {
1485
+ getDocument().removeEventListener("mouseup", this.mouseUpHandler);
1486
+ this.container.addEventListener("mousemove", this.mouseMoveHandler);
1487
+ if (this.isMultiSelectStatus) {
1488
+ this.emit("multi-select", this.selectedElList);
1489
+ } else {
1490
+ this.emit("select", this.selectedEl);
1491
+ }
1492
+ };
1493
+ mouseLeaveHandler = () => {
1494
+ setTimeout(() => this.clearHighlight(), throttleTime);
1495
+ };
1496
+ mouseWheelHandler = () => {
1497
+ this.clearHighlight();
1498
+ };
866
1499
  }
867
1500
 
868
- class Rule extends EventEmitter$1 {
1501
+ class Rule extends EventEmitter {
869
1502
  hGuides;
870
1503
  vGuides;
871
1504
  horizontalGuidelines = [];
@@ -904,11 +1537,11 @@ class Rule extends EventEmitter$1 {
904
1537
  this.vGuides.setState({
905
1538
  defaultGuides: vLines
906
1539
  });
907
- this.emit("changeGuides", {
1540
+ this.emit("change-guides", {
908
1541
  type: GuidesType.HORIZONTAL,
909
1542
  guides: hLines
910
1543
  });
911
- this.emit("changeGuides", {
1544
+ this.emit("change-guides", {
912
1545
  type: GuidesType.VERTICAL,
913
1546
  guides: vLines
914
1547
  });
@@ -967,14 +1600,14 @@ class Rule extends EventEmitter$1 {
967
1600
  });
968
1601
  hGuidesChangeGuidesHandler = (e) => {
969
1602
  this.horizontalGuidelines = e.guides;
970
- this.emit("changeGuides", {
1603
+ this.emit("change-guides", {
971
1604
  type: GuidesType.HORIZONTAL,
972
1605
  guides: this.horizontalGuidelines
973
1606
  });
974
1607
  };
975
1608
  vGuidesChangeGuidesHandler = (e) => {
976
1609
  this.verticalGuidelines = e.guides;
977
- this.emit("changeGuides", {
1610
+ this.emit("change-guides", {
978
1611
  type: GuidesType.VERTICAL,
979
1612
  guides: this.verticalGuidelines
980
1613
  });
@@ -982,9 +1615,8 @@ class Rule extends EventEmitter$1 {
982
1615
  }
983
1616
 
984
1617
  const wrapperClassName = "editor-mask-wrapper";
985
- const throttleTime = 100;
986
1618
  const hideScrollbar = () => {
987
- injectStyle(globalThis.document, `.${wrapperClassName}::-webkit-scrollbar { width: 0 !important; display: none }`);
1619
+ injectStyle(getDocument(), `.${wrapperClassName}::-webkit-scrollbar { width: 0 !important; display: none }`);
988
1620
  };
989
1621
  const createContent = () => createDiv({
990
1622
  className: "editor-mask",
@@ -1023,25 +1655,21 @@ class StageMask extends Rule {
1023
1655
  wrapperWidth = 0;
1024
1656
  maxScrollTop = 0;
1025
1657
  maxScrollLeft = 0;
1026
- isMultiSelectStatus = false;
1027
1658
  mode = Mode.ABSOLUTE;
1028
1659
  pageScrollParent = null;
1029
1660
  intersectionObserver = null;
1030
1661
  wrapperResizeObserver = null;
1031
- highlightHandler = throttle((event) => {
1032
- this.emit("highlight", event);
1033
- }, throttleTime);
1034
1662
  constructor() {
1035
1663
  const wrapper = createWrapper();
1036
1664
  super(wrapper);
1037
1665
  this.wrapper = wrapper;
1038
- this.initContentEventListener();
1666
+ this.content.addEventListener("wheel", this.mouseWheelHandler);
1039
1667
  this.wrapper.appendChild(this.content);
1040
- this.initMultiSelectEvent();
1041
1668
  }
1042
1669
  setMode(mode) {
1043
1670
  this.mode = mode;
1044
1671
  this.scroll();
1672
+ this.content.dataset.mode = mode;
1045
1673
  if (mode === Mode.FIXED) {
1046
1674
  this.content.style.width = `${this.wrapperWidth}px`;
1047
1675
  this.content.style.height = `${this.wrapperHeight}px`;
@@ -1088,30 +1716,8 @@ class StageMask extends Rule {
1088
1716
  this.page = null;
1089
1717
  this.pageScrollParent = null;
1090
1718
  this.wrapperResizeObserver?.disconnect();
1091
- this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
1092
1719
  super.destroy();
1093
1720
  }
1094
- initContentEventListener() {
1095
- this.content.addEventListener("mousedown", this.mouseDownHandler);
1096
- this.content.addEventListener("wheel", this.mouseWheelHandler);
1097
- this.content.addEventListener("mousemove", this.highlightHandler);
1098
- this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
1099
- }
1100
- initMultiSelectEvent() {
1101
- const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
1102
- const ctrl = isMac ? "meta" : "ctrl";
1103
- KeyController.global.keydown(ctrl, (e) => {
1104
- e.inputEvent.preventDefault();
1105
- this.isMultiSelectStatus = true;
1106
- });
1107
- KeyController.global.on("blur", () => {
1108
- this.isMultiSelectStatus = false;
1109
- });
1110
- KeyController.global.keyup(ctrl, (e) => {
1111
- e.inputEvent.preventDefault();
1112
- this.isMultiSelectStatus = false;
1113
- });
1114
- }
1115
1721
  initObserverIntersection() {
1116
1722
  this.pageScrollParent = getScrollParent(this.page) || null;
1117
1723
  this.intersectionObserver?.disconnect();
@@ -1161,317 +1767,78 @@ class StageMask extends Rule {
1161
1767
  scrollLeft = 0;
1162
1768
  scrollTop = 0;
1163
1769
  }
1164
- this.scrollRule(scrollTop);
1165
- this.scrollTo(scrollLeft, scrollTop);
1166
- }
1167
- scrollTo(scrollLeft, scrollTop) {
1168
- this.content.style.transform = `translate3d(${-scrollLeft}px, ${-scrollTop}px, 0)`;
1169
- }
1170
- setHeight(height) {
1171
- this.height = height;
1172
- this.setMaxScrollTop();
1173
- this.content.style.height = `${height}px`;
1174
- }
1175
- setWidth(width) {
1176
- this.width = width;
1177
- this.setMaxScrollLeft();
1178
- this.content.style.width = `${width}px`;
1179
- }
1180
- setMaxScrollLeft() {
1181
- this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
1182
- }
1183
- setMaxScrollTop() {
1184
- this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
1185
- }
1186
- fixScrollValue() {
1187
- if (this.scrollTop < 0)
1188
- this.scrollTop = 0;
1189
- if (this.scrollLeft < 0)
1190
- this.scrollLeft = 0;
1191
- if (this.maxScrollTop < this.scrollTop)
1192
- this.scrollTop = this.maxScrollTop;
1193
- if (this.maxScrollLeft < this.scrollLeft)
1194
- this.scrollLeft = this.maxScrollLeft;
1195
- }
1196
- mouseDownHandler = (event) => {
1197
- this.emit("clearHighlight");
1198
- event.stopImmediatePropagation();
1199
- event.stopPropagation();
1200
- if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
1201
- return;
1202
- if (!event.target)
1203
- return;
1204
- const targetClassList = event.target.classList;
1205
- if (!this.isMultiSelectStatus && targetClassList.contains("moveable-area")) {
1206
- return;
1207
- }
1208
- if (targetClassList.contains("moveable-control") || isMoveableButton(event.target)) {
1209
- return;
1210
- }
1211
- this.content.removeEventListener("mousemove", this.highlightHandler);
1212
- if (this.isMultiSelectStatus) {
1213
- this.emit("beforeMultiSelect", event);
1214
- } else {
1215
- this.emit("beforeSelect", event);
1216
- }
1217
- globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
1218
- };
1219
- mouseUpHandler = () => {
1220
- globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
1221
- this.content.addEventListener("mousemove", this.highlightHandler);
1222
- if (!this.isMultiSelectStatus) {
1223
- this.emit("select");
1224
- }
1225
- };
1226
- mouseWheelHandler = (event) => {
1227
- this.emit("clearHighlight");
1228
- if (!this.page)
1229
- throw new Error("page \u672A\u521D\u59CB\u5316");
1230
- const { deltaY, deltaX } = event;
1231
- if (this.page.clientHeight < this.wrapperHeight && deltaY)
1232
- return;
1233
- if (this.page.clientWidth < this.wrapperWidth && deltaX)
1234
- return;
1235
- if (this.maxScrollTop > 0) {
1236
- this.scrollTop = this.scrollTop + deltaY;
1237
- }
1238
- if (this.maxScrollLeft > 0) {
1239
- this.scrollLeft = this.scrollLeft + deltaX;
1240
- }
1241
- this.scroll();
1242
- this.emit("scroll", event);
1243
- };
1244
- mouseLeaveHandler = () => {
1245
- setTimeout(() => this.emit("clearHighlight"), throttleTime);
1246
- };
1247
- }
1248
-
1249
- class StageMultiDragResize extends EventEmitter {
1250
- core;
1251
- mask;
1252
- container;
1253
- targetList = [];
1254
- dragElList = [];
1255
- moveableForMulti;
1256
- dragStatus = StageDragStatus.END;
1257
- multiMoveableHelper;
1258
- constructor(config) {
1259
- super();
1260
- this.core = config.core;
1261
- this.container = config.container;
1262
- this.mask = config.mask;
1263
- }
1264
- multiSelect(els) {
1265
- this.targetList = els;
1266
- this.core.dr.destroyDragEl();
1267
- this.destroyDragElList();
1268
- this.dragElList = els.map((elItem) => {
1269
- const dragElDiv = globalThis.document.createElement("div");
1270
- this.container.append(dragElDiv);
1271
- dragElDiv.style.cssText = getTargetElStyle(elItem);
1272
- dragElDiv.id = `${DRAG_EL_ID_PREFIX}${elItem.id}`;
1273
- if (typeof this.core.config.updateDragEl === "function") {
1274
- this.core.config.updateDragEl(dragElDiv, elItem);
1275
- }
1276
- return dragElDiv;
1277
- });
1278
- this.moveableForMulti?.destroy();
1279
- this.multiMoveableHelper?.clear();
1280
- this.moveableForMulti = new Moveable(
1281
- this.container,
1282
- this.getOptions({
1283
- target: this.dragElList
1284
- })
1285
- );
1286
- this.multiMoveableHelper = MoveableHelper.create({
1287
- useBeforeRender: true,
1288
- useRender: false,
1289
- createAuto: true
1290
- });
1291
- const frames = [];
1292
- const setFrames = (events) => {
1293
- events.forEach((ev) => {
1294
- const matchEventTarget = this.targetList.find(
1295
- (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
1296
- );
1297
- if (!matchEventTarget)
1298
- return;
1299
- frames.push({
1300
- left: matchEventTarget.offsetLeft,
1301
- top: matchEventTarget.offsetTop,
1302
- id: matchEventTarget.id
1303
- });
1304
- });
1305
- };
1306
- this.moveableForMulti.on("resizeGroupStart", (params) => {
1307
- const { events } = params;
1308
- this.multiMoveableHelper?.onResizeGroupStart(params);
1309
- setFrames(events);
1310
- this.dragStatus = StageDragStatus.START;
1311
- }).on("resizeGroup", (params) => {
1312
- const { events } = params;
1313
- events.forEach((ev) => {
1314
- const { width, height, beforeTranslate } = ev.drag;
1315
- const frameSnapShot = frames.find(
1316
- (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
1317
- );
1318
- if (!frameSnapShot)
1319
- return;
1320
- const targeEl = this.targetList.find(
1321
- (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
1322
- );
1323
- if (!targeEl)
1324
- return;
1325
- const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
1326
- if (!isParentIncluded) {
1327
- targeEl.style.left = `${frameSnapShot.left + beforeTranslate[0]}px`;
1328
- targeEl.style.top = `${frameSnapShot.top + beforeTranslate[1]}px`;
1329
- }
1330
- targeEl.style.width = `${width}px`;
1331
- targeEl.style.height = `${height}px`;
1332
- });
1333
- this.multiMoveableHelper?.onResizeGroup(params);
1334
- this.dragStatus = StageDragStatus.ING;
1335
- }).on("resizeGroupEnd", () => {
1336
- this.update(true);
1337
- this.dragStatus = StageDragStatus.END;
1338
- }).on("dragGroupStart", (params) => {
1339
- const { events } = params;
1340
- this.multiMoveableHelper?.onDragGroupStart(params);
1341
- setFrames(events);
1342
- this.dragStatus = StageDragStatus.START;
1343
- }).on("dragGroup", (params) => {
1344
- const { events } = params;
1345
- events.forEach((ev) => {
1346
- const frameSnapShot = frames.find(
1347
- (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
1348
- );
1349
- if (!frameSnapShot)
1350
- return;
1351
- const targeEl = this.targetList.find(
1352
- (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, "")
1353
- );
1354
- if (!targeEl)
1355
- return;
1356
- const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
1357
- if (!isParentIncluded) {
1358
- targeEl.style.left = `${frameSnapShot.left + ev.beforeTranslate[0]}px`;
1359
- targeEl.style.top = `${frameSnapShot.top + ev.beforeTranslate[1]}px`;
1360
- }
1361
- });
1362
- this.multiMoveableHelper?.onDragGroup(params);
1363
- this.dragStatus = StageDragStatus.ING;
1364
- }).on("dragGroupEnd", () => {
1365
- this.update();
1366
- this.dragStatus = StageDragStatus.END;
1367
- }).on("clickGroup", (params) => {
1368
- const { inputTarget, targets } = params;
1369
- if (!this.mask.isMultiSelectStatus && targets.length > 1 && targets.includes(inputTarget)) {
1370
- this.emit("select", inputTarget.id.replace(DRAG_EL_ID_PREFIX, ""));
1770
+ this.scrollRule(scrollTop);
1771
+ this.scrollTo(scrollLeft, scrollTop);
1772
+ }
1773
+ scrollTo(scrollLeft, scrollTop) {
1774
+ this.content.style.transform = `translate3d(${-scrollLeft}px, ${-scrollTop}px, 0)`;
1775
+ const event = new CustomEvent("customScroll", {
1776
+ detail: {
1777
+ scrollLeft: this.scrollLeft,
1778
+ scrollTop: this.scrollTop
1371
1779
  }
1372
1780
  });
1781
+ this.content.dispatchEvent(event);
1373
1782
  }
1374
- canSelect(el, stop) {
1375
- if (el.className.includes(PAGE_CLASS)) {
1376
- this.core.highlightedDom = void 0;
1377
- this.core.highlightLayer.clearHighlight();
1378
- stop();
1379
- return false;
1380
- }
1381
- const currentTargetMode = getMode(el);
1382
- let selectedDomMode = "";
1383
- if (this.core.selectedDom?.className.includes(PAGE_CLASS)) {
1384
- return true;
1385
- }
1386
- if (this.targetList.length === 0 && this.core.selectedDom) {
1387
- selectedDomMode = getMode(this.core.selectedDom);
1388
- } else if (this.targetList.length > 0) {
1389
- selectedDomMode = getMode(this.targetList[0]);
1390
- }
1391
- if (currentTargetMode !== selectedDomMode) {
1392
- return false;
1393
- }
1394
- return true;
1783
+ setHeight(height) {
1784
+ this.height = height;
1785
+ this.setMaxScrollTop();
1786
+ this.content.style.height = `${height}px`;
1395
1787
  }
1396
- clearSelectStatus() {
1397
- if (!this.moveableForMulti)
1398
- return;
1399
- this.destroyDragElList();
1400
- this.moveableForMulti.target = null;
1401
- this.moveableForMulti.updateTarget();
1402
- this.targetList = [];
1788
+ setWidth(width) {
1789
+ this.width = width;
1790
+ this.setMaxScrollLeft();
1791
+ this.content.style.width = `${width}px`;
1403
1792
  }
1404
- destroy() {
1405
- this.moveableForMulti?.destroy();
1406
- this.destroyDragElList();
1793
+ setMaxScrollLeft() {
1794
+ this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
1407
1795
  }
1408
- destroyDragElList() {
1409
- this.dragElList.forEach((dragElItem) => dragElItem?.remove());
1796
+ setMaxScrollTop() {
1797
+ this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
1410
1798
  }
1411
- update(isResize = false) {
1412
- if (this.targetList.length === 0)
1799
+ fixScrollValue() {
1800
+ if (this.scrollTop < 0)
1801
+ this.scrollTop = 0;
1802
+ if (this.scrollLeft < 0)
1803
+ this.scrollLeft = 0;
1804
+ if (this.maxScrollTop < this.scrollTop)
1805
+ this.scrollTop = this.maxScrollTop;
1806
+ if (this.maxScrollLeft < this.scrollLeft)
1807
+ this.scrollLeft = this.maxScrollLeft;
1808
+ }
1809
+ mouseWheelHandler = (event) => {
1810
+ if (!this.page)
1811
+ throw new Error("page \u672A\u521D\u59CB\u5316");
1812
+ const { deltaY, deltaX } = event;
1813
+ if (this.page.clientHeight < this.wrapperHeight && deltaY)
1413
1814
  return;
1414
- const { contentWindow } = this.core.renderer;
1415
- const doc = contentWindow?.document;
1416
- if (!doc)
1815
+ if (this.page.clientWidth < this.wrapperWidth && deltaX)
1417
1816
  return;
1418
- this.emit("update", {
1419
- data: this.targetList.map((targetItem) => {
1420
- const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop };
1421
- const left = calcValueByFontsize(doc, offset.left);
1422
- const top = calcValueByFontsize(doc, offset.top);
1423
- const width = calcValueByFontsize(doc, targetItem.clientWidth);
1424
- const height = calcValueByFontsize(doc, targetItem.clientHeight);
1425
- return {
1426
- el: targetItem,
1427
- style: isResize ? { left, top, width, height } : { left, top }
1428
- };
1429
- }),
1430
- parentEl: null
1431
- });
1432
- }
1433
- getOptions(options = {}) {
1434
- let { multiMoveableOptions = {} } = this.core.config;
1435
- if (typeof multiMoveableOptions === "function") {
1436
- multiMoveableOptions = multiMoveableOptions(this.core);
1817
+ if (this.maxScrollTop > 0) {
1818
+ this.scrollTop = this.scrollTop + deltaY;
1437
1819
  }
1438
- return {
1439
- defaultGroupRotate: 0,
1440
- defaultGroupOrigin: "50% 50%",
1441
- draggable: true,
1442
- resizable: true,
1443
- throttleDrag: 0,
1444
- startDragRotate: 0,
1445
- throttleDragRotate: 0,
1446
- zoom: 1,
1447
- origin: true,
1448
- padding: { left: 0, top: 0, right: 0, bottom: 0 },
1449
- snappable: true,
1450
- bounds: {
1451
- top: 0,
1452
- left: -1,
1453
- right: this.container.clientWidth - 1,
1454
- bottom: this.container.clientHeight,
1455
- ...multiMoveableOptions.bounds || {}
1456
- },
1457
- ...options,
1458
- ...multiMoveableOptions
1459
- };
1460
- }
1820
+ if (this.maxScrollLeft > 0) {
1821
+ this.scrollLeft = this.scrollLeft + deltaX;
1822
+ }
1823
+ this.scroll();
1824
+ this.emit("scroll", event);
1825
+ };
1461
1826
  }
1462
1827
 
1463
1828
  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\n.magic-ui-container.magic-layout-relative {\n min-height: 50px;\n}\n";
1464
1829
 
1465
- class StageRender extends EventEmitter {
1830
+ class StageRender extends EventEmitter$1 {
1466
1831
  contentWindow = null;
1467
1832
  runtime = null;
1468
1833
  iframe;
1469
1834
  runtimeUrl;
1470
- render;
1471
- constructor({ runtimeUrl, render }) {
1835
+ zoom = DEFAULT_ZOOM;
1836
+ customizedRender;
1837
+ constructor({ runtimeUrl, zoom, customizedRender }) {
1472
1838
  super();
1473
1839
  this.runtimeUrl = runtimeUrl || "";
1474
- this.render = render;
1840
+ this.customizedRender = customizedRender;
1841
+ this.setZoom(zoom);
1475
1842
  this.iframe = globalThis.document.createElement("iframe");
1476
1843
  this.iframe.src = isSameDomain(this.runtimeUrl) ? this.runtimeUrl : "";
1477
1844
  this.iframe.style.cssText = `
@@ -1489,6 +1856,31 @@ class StageRender extends EventEmitter {
1489
1856
  this.emit("runtime-ready", runtime);
1490
1857
  }
1491
1858
  });
1859
+ async add(data) {
1860
+ const runtime = await this.getRuntime();
1861
+ return runtime?.add?.(data);
1862
+ }
1863
+ async remove(data) {
1864
+ const runtime = await this.getRuntime();
1865
+ return runtime?.remove?.(data);
1866
+ }
1867
+ async update(data) {
1868
+ const runtime = await this.getRuntime();
1869
+ runtime?.update?.(data);
1870
+ }
1871
+ async select(els) {
1872
+ const runtime = await this.getRuntime();
1873
+ for (const el of els) {
1874
+ await runtime?.select?.(el.id);
1875
+ if (runtime?.beforeSelect) {
1876
+ await runtime.beforeSelect(el);
1877
+ }
1878
+ this.flagSelectedEl(el);
1879
+ }
1880
+ }
1881
+ setZoom(zoom = DEFAULT_ZOOM) {
1882
+ this.zoom = zoom;
1883
+ }
1492
1884
  async mount(el) {
1493
1885
  if (!this.iframe) {
1494
1886
  throw Error("mount \u5931\u8D25");
@@ -1517,6 +1909,27 @@ class StageRender extends EventEmitter {
1517
1909
  getDocument() {
1518
1910
  return this.contentWindow?.document;
1519
1911
  }
1912
+ getElementsFromPoint(point) {
1913
+ let x = point.clientX;
1914
+ let y = point.clientY;
1915
+ if (this.iframe) {
1916
+ const rect = this.iframe.getClientRects()[0];
1917
+ if (rect) {
1918
+ x = x - rect.left;
1919
+ y = y - rect.top;
1920
+ }
1921
+ }
1922
+ return this.getDocument()?.elementsFromPoint(x / this.zoom, y / this.zoom);
1923
+ }
1924
+ getTargetElement(idOrEl) {
1925
+ if (typeof idOrEl === "string" || typeof idOrEl === "number") {
1926
+ const el = this.getDocument()?.getElementById(`${idOrEl}`);
1927
+ if (!el)
1928
+ throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
1929
+ return el;
1930
+ }
1931
+ return idOrEl;
1932
+ }
1520
1933
  destroy() {
1521
1934
  this.iframe?.removeEventListener("load", this.loadHandler);
1522
1935
  this.contentWindow = null;
@@ -1524,14 +1937,21 @@ class StageRender extends EventEmitter {
1524
1937
  this.iframe = void 0;
1525
1938
  this.removeAllListeners();
1526
1939
  }
1940
+ flagSelectedEl(el) {
1941
+ const doc = this.getDocument();
1942
+ if (doc) {
1943
+ removeSelectedClassName(doc);
1944
+ addSelectedClassName(el, doc);
1945
+ }
1946
+ }
1527
1947
  loadHandler = async () => {
1528
1948
  if (!this.contentWindow?.magic) {
1529
1949
  this.postTmagicRuntimeReady();
1530
1950
  }
1531
1951
  if (!this.contentWindow)
1532
1952
  return;
1533
- if (this.render) {
1534
- const el = await this.render();
1953
+ if (this.customizedRender) {
1954
+ const el = await this.customizedRender();
1535
1955
  if (el) {
1536
1956
  this.contentWindow.document?.body?.appendChild(el);
1537
1957
  }
@@ -1551,211 +1971,81 @@ class StageRender extends EventEmitter {
1551
1971
  }
1552
1972
  }
1553
1973
 
1554
- class StageCore extends EventEmitter {
1974
+ class StageCore extends EventEmitter$1 {
1555
1975
  container;
1556
- selectedDom;
1557
- selectedDomList = [];
1558
- highlightedDom;
1559
1976
  renderer;
1560
1977
  mask;
1561
- dr;
1562
- multiDr;
1563
- highlightLayer;
1564
- config;
1565
- zoom = DEFAULT_ZOOM;
1566
- containerHighlightClassName;
1567
- containerHighlightDuration;
1568
- containerHighlightType;
1569
- isContainer;
1570
- canSelect;
1978
+ actionManager;
1571
1979
  pageResizeObserver = null;
1980
+ autoScrollIntoView;
1981
+ customizedRender;
1572
1982
  constructor(config) {
1573
1983
  super();
1574
- this.config = config;
1575
- this.setZoom(config.zoom);
1576
- this.canSelect = config.canSelect || ((el) => !!el.id);
1577
- this.isContainer = config.isContainer;
1578
- this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
1579
- this.containerHighlightDuration = config.containerHighlightDuration || 800;
1580
- this.containerHighlightType = config.containerHighlightType;
1581
- this.renderer = new StageRender({ runtimeUrl: config.runtimeUrl, render: this.render.bind(this) });
1582
- this.mask = new StageMask();
1583
- this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
1584
- this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
1585
- this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
1586
- this.renderer.on("runtime-ready", (runtime) => {
1587
- this.emit("runtime-ready", runtime);
1588
- });
1589
- this.renderer.on("page-el-update", (el) => {
1590
- this.mask?.observe(el);
1591
- this.observePageResize(el);
1592
- });
1593
- this.mask.on("beforeSelect", async (event) => {
1594
- this.clearSelectStatus("multiSelect");
1595
- const el = await this.getElementFromPoint(event);
1596
- if (!el)
1597
- return;
1598
- this.select(el, event);
1599
- }).on("select", () => {
1600
- this.emit("select", this.selectedDom);
1601
- }).on("changeGuides", (data) => {
1602
- this.dr.setGuidelines(data.type, data.guides);
1603
- this.emit("changeGuides", data);
1604
- }).on("highlight", async (event) => {
1605
- const el = await this.getElementFromPoint(event);
1606
- if (!el)
1607
- return;
1608
- if (this.multiDr.dragStatus === StageDragStatus.ING)
1609
- return;
1610
- await this.highlight(el);
1611
- if (this.highlightedDom === this.selectedDom) {
1612
- this.highlightLayer.clearHighlight();
1613
- return;
1614
- }
1615
- this.emit("highlight", this.highlightedDom);
1616
- }).on("clearHighlight", async () => {
1617
- this.highlightLayer.clearHighlight();
1618
- }).on("beforeMultiSelect", async (event) => {
1619
- const el = await this.getElementFromPoint(event);
1620
- if (!el)
1621
- return;
1622
- if (this.selectedDom && !this.selectedDom.className.includes(PAGE_CLASS)) {
1623
- this.selectedDomList.push(this.selectedDom);
1624
- this.selectedDom = void 0;
1625
- }
1626
- const existIndex = this.selectedDomList.findIndex((selectedDom) => selectedDom.id === el.id);
1627
- if (existIndex !== -1) {
1628
- this.selectedDomList.splice(existIndex, 1);
1629
- } else {
1630
- this.selectedDomList.push(el);
1984
+ this.autoScrollIntoView = config.autoScrollIntoView;
1985
+ this.customizedRender = config.render;
1986
+ this.renderer = new StageRender({
1987
+ runtimeUrl: config.runtimeUrl,
1988
+ zoom: config.zoom,
1989
+ customizedRender: async () => {
1990
+ if (this?.customizedRender) {
1991
+ return await this.customizedRender(this);
1992
+ }
1993
+ return null;
1631
1994
  }
1632
- this.multiSelect(this.selectedDomList);
1633
- this.emit("multiSelect", this.selectedDomList);
1634
- });
1635
- this.dr.on("update", (data) => {
1636
- setTimeout(() => this.emit("update", data));
1637
- }).on("sort", (data) => {
1638
- setTimeout(() => this.emit("sort", data));
1639
- }).on("select-parent", () => {
1640
- this.emit("select-parent");
1641
- });
1642
- this.multiDr.on("update", (data) => {
1643
- setTimeout(() => this.emit("update", data));
1644
- }).on("select", async (id) => {
1645
- const el = await this.getTargetElement(id);
1646
- this.select(el);
1647
- setTimeout(() => this.emit("select", el));
1648
1995
  });
1649
- }
1650
- getElementsFromPoint(event) {
1651
- const { renderer, zoom } = this;
1652
- let x = event.clientX;
1653
- let y = event.clientY;
1654
- if (renderer.iframe) {
1655
- const rect = renderer.iframe.getClientRects()[0];
1656
- if (rect) {
1657
- x = x - rect.left;
1658
- y = y - rect.top;
1659
- }
1660
- }
1661
- return renderer.getDocument()?.elementsFromPoint(x / zoom, y / zoom);
1662
- }
1663
- async getElementFromPoint(event) {
1664
- const els = this.getElementsFromPoint(event);
1665
- let stopped = false;
1666
- const stop = () => stopped = true;
1667
- for (const el of els) {
1668
- if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isElCanSelect(el, event, stop)) {
1669
- if (stopped)
1670
- break;
1671
- return el;
1672
- }
1673
- }
1674
- }
1675
- async isElCanSelect(el, event, stop) {
1676
- const canSelectByProp = await this.canSelect(el, event, stop);
1677
- if (!canSelectByProp)
1678
- return false;
1679
- if (this.mask.isMultiSelectStatus) {
1680
- return this.multiDr.canSelect(el, stop);
1681
- }
1682
- return true;
1996
+ this.mask = new StageMask();
1997
+ this.actionManager = new ActionManager(this.getActionManagerConfig(config));
1998
+ this.initRenderEvent();
1999
+ this.initActionEvent();
2000
+ this.initMaskEvent();
1683
2001
  }
1684
2002
  async select(idOrEl, event) {
1685
- this.clearSelectStatus("multiSelect");
1686
- const el = await this.getTargetElement(idOrEl);
1687
- if (el === this.selectedDom)
2003
+ const el = this.renderer.getTargetElement(idOrEl);
2004
+ if (el === this.actionManager.getSelectedEl())
1688
2005
  return;
1689
- const runtime = await this.renderer.getRuntime();
1690
- await runtime?.select?.(el.id);
1691
- if (runtime?.beforeSelect) {
1692
- await runtime.beforeSelect(el);
1693
- }
2006
+ await this.renderer.select([el]);
1694
2007
  this.mask.setLayout(el);
1695
- this.dr.select(el, event);
1696
- if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
2008
+ this.actionManager.select(el, event);
2009
+ if (this.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1697
2010
  this.mask.observerIntersection(el);
1698
2011
  }
1699
- this.selectedDom = el;
1700
- const doc = this.renderer.getDocument();
1701
- if (doc) {
1702
- removeSelectedClassName(doc);
1703
- if (this.selectedDom) {
1704
- addSelectedClassName(this.selectedDom, doc);
1705
- }
1706
- }
1707
2012
  }
1708
2013
  async multiSelect(idOrElList) {
1709
- this.clearSelectStatus("select");
1710
- this.selectedDomList = await Promise.all(idOrElList.map(async (idOrEl) => await this.getTargetElement(idOrEl)));
1711
- this.multiDr.multiSelect(this.selectedDomList);
1712
- }
1713
- update(data) {
1714
- const { config } = data;
1715
- return this.renderer?.getRuntime().then((runtime) => {
1716
- runtime?.update?.(data);
1717
- setTimeout(() => {
1718
- const el = this.renderer.getDocument()?.getElementById(`${config.id}`);
1719
- if (el && el.id === this.selectedDom?.id) {
1720
- this.selectedDom = el;
1721
- this.mask.setLayout(el);
1722
- this.dr.updateMoveable(el);
1723
- }
1724
- }, 0);
1725
- });
1726
- }
1727
- async highlight(idOrEl) {
1728
- let el;
1729
- try {
1730
- el = await this.getTargetElement(idOrEl);
1731
- } catch (error) {
1732
- this.highlightLayer.clearHighlight();
2014
+ const els = idOrElList.map((idOrEl) => this.renderer.getTargetElement(idOrEl));
2015
+ if (els.length === 0)
1733
2016
  return;
2017
+ const lastEl = els[els.length - 1];
2018
+ const isReduceSelect = els.length < this.actionManager.getSelectedElList().length;
2019
+ await this.renderer.select(els);
2020
+ this.mask.setLayout(lastEl);
2021
+ this.actionManager.multiSelect(idOrElList);
2022
+ if ((this.autoScrollIntoView || lastEl.dataset.autoScrollIntoView) && !isReduceSelect) {
2023
+ this.mask.observerIntersection(lastEl);
1734
2024
  }
1735
- if (el === this.highlightedDom || !el)
1736
- return;
1737
- this.highlightLayer.highlight(el);
1738
- this.highlightedDom = el;
1739
2025
  }
1740
- sortNode(data) {
1741
- return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
2026
+ highlight(idOrEl) {
2027
+ this.actionManager.highlight(idOrEl);
1742
2028
  }
1743
- add(data) {
1744
- return this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
2029
+ async update(data) {
2030
+ const { config } = data;
2031
+ await this.renderer.update(data);
2032
+ setTimeout(() => {
2033
+ const el = this.renderer.getTargetElement(`${config.id}`);
2034
+ if (el && this.actionManager.isSelectedEl(el)) {
2035
+ this.mask.setLayout(el);
2036
+ this.actionManager.setSelectedEl(el);
2037
+ this.actionManager.updateMoveable(el);
2038
+ }
2039
+ });
1745
2040
  }
1746
- remove(data) {
1747
- return this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
2041
+ async add(data) {
2042
+ return await this.renderer.add(data);
1748
2043
  }
1749
- setZoom(zoom = DEFAULT_ZOOM) {
1750
- this.zoom = zoom;
2044
+ async remove(data) {
2045
+ return await this.renderer.remove(data);
1751
2046
  }
1752
- clearSelectStatus(selectType) {
1753
- if (selectType === "multiSelect") {
1754
- this.multiDr.clearSelectStatus();
1755
- this.selectedDomList = [];
1756
- } else {
1757
- this.dr.clearSelectStatus();
1758
- }
2047
+ setZoom(zoom = DEFAULT_ZOOM) {
2048
+ this.renderer.setZoom(zoom);
1759
2049
  }
1760
2050
  async mount(el) {
1761
2051
  this.container = el;
@@ -1766,32 +2056,19 @@ class StageCore extends EventEmitter {
1766
2056
  }
1767
2057
  clearGuides() {
1768
2058
  this.mask.clearGuides();
1769
- this.dr.clearGuides();
2059
+ this.actionManager.clearGuides();
1770
2060
  }
1771
- async addContainerHighlightClassName(event, exclude) {
1772
- const els = this.getElementsFromPoint(event);
1773
- const { renderer } = this;
1774
- const doc = renderer.getDocument();
1775
- if (!doc)
1776
- return;
1777
- for (const el of els) {
1778
- if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isContainer(el) && !exclude.includes(el)) {
1779
- addClassName(el, doc, this.containerHighlightClassName);
1780
- break;
1781
- }
1782
- }
2061
+ getAddContainerHighlightClassNameTimeout(event, excludeElList = []) {
2062
+ return this.delayedMarkContainer(event, excludeElList);
1783
2063
  }
1784
- getAddContainerHighlightClassNameTimeout(event, exclude = []) {
1785
- return globalThis.setTimeout(() => {
1786
- this.addContainerHighlightClassName(event, exclude);
1787
- }, this.containerHighlightDuration);
2064
+ delayedMarkContainer(event, excludeElList = []) {
2065
+ return this.actionManager.delayedMarkContainer(event, excludeElList);
1788
2066
  }
1789
2067
  destroy() {
1790
- const { mask, renderer, dr, highlightLayer, pageResizeObserver } = this;
2068
+ const { mask, renderer, actionManager, pageResizeObserver } = this;
1791
2069
  renderer.destroy();
1792
2070
  mask.destroy();
1793
- dr.destroy();
1794
- highlightLayer.destroy();
2071
+ actionManager.destroy();
1795
2072
  pageResizeObserver?.disconnect();
1796
2073
  this.removeAllListeners();
1797
2074
  this.container = void 0;
@@ -1800,29 +2077,85 @@ class StageCore extends EventEmitter {
1800
2077
  if (typeof ResizeObserver !== "undefined") {
1801
2078
  this.pageResizeObserver = new ResizeObserver((entries) => {
1802
2079
  this.mask.pageResize(entries);
1803
- if (this.dr.moveable) {
1804
- this.dr.updateMoveable();
1805
- }
2080
+ this.actionManager.updateMoveable();
1806
2081
  });
1807
2082
  this.pageResizeObserver.observe(page);
1808
2083
  }
1809
2084
  }
1810
- async render() {
1811
- if (this.config?.render) {
1812
- return await this.config.render(this);
1813
- }
1814
- return null;
2085
+ getActionManagerConfig(config) {
2086
+ const actionManagerConfig = {
2087
+ containerHighlightClassName: config.containerHighlightClassName,
2088
+ containerHighlightDuration: config.containerHighlightDuration,
2089
+ containerHighlightType: config.containerHighlightType,
2090
+ moveableOptions: config.moveableOptions,
2091
+ multiMoveableOptions: config.multiMoveableOptions,
2092
+ container: this.mask.content,
2093
+ disabledDragStart: config.disabledDragStart,
2094
+ canSelect: config.canSelect,
2095
+ isContainer: config.isContainer,
2096
+ updateDragEl: config.updateDragEl,
2097
+ getRootContainer: () => this.container,
2098
+ getRenderDocument: () => this.renderer.getDocument(),
2099
+ getTargetElement: (idOrEl) => this.renderer.getTargetElement(idOrEl),
2100
+ getElementsFromPoint: (point) => this.renderer.getElementsFromPoint(point)
2101
+ };
2102
+ return actionManagerConfig;
1815
2103
  }
1816
- async getTargetElement(idOrEl) {
1817
- if (typeof idOrEl === "string" || typeof idOrEl === "number") {
1818
- const el = this.renderer.getDocument()?.getElementById(`${idOrEl}`);
1819
- if (!el)
1820
- throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
1821
- return el;
1822
- }
1823
- return idOrEl;
2104
+ initRenderEvent() {
2105
+ this.renderer.on("runtime-ready", (runtime) => {
2106
+ this.emit("runtime-ready", runtime);
2107
+ });
2108
+ this.renderer.on("page-el-update", (el) => {
2109
+ this.mask?.observe(el);
2110
+ this.observePageResize(el);
2111
+ });
2112
+ }
2113
+ initMaskEvent() {
2114
+ this.mask.on("change-guides", (data) => {
2115
+ this.actionManager.setGuidelines(data.type, data.guides);
2116
+ this.emit("change-guides", data);
2117
+ });
2118
+ }
2119
+ initActionEvent() {
2120
+ this.initActionManagerEvent();
2121
+ this.initDrEvent();
2122
+ this.initMulDrEvent();
2123
+ this.initHighlightEvent();
2124
+ }
2125
+ initActionManagerEvent() {
2126
+ this.actionManager.on("before-select", (idOrEl, event) => {
2127
+ this.select(idOrEl, event);
2128
+ }).on("select", (selectedEl) => {
2129
+ this.emit("select", selectedEl);
2130
+ }).on("before-multi-select", (idOrElList) => {
2131
+ this.multiSelect(idOrElList);
2132
+ }).on("multi-select", (selectedElList) => {
2133
+ this.emit("multi-select", selectedElList);
2134
+ });
2135
+ }
2136
+ initDrEvent() {
2137
+ this.actionManager.on("update", (data) => {
2138
+ this.emit("update", data);
2139
+ }).on("sort", (data) => {
2140
+ this.emit("sort", data);
2141
+ }).on("select-parent", () => {
2142
+ this.emit("select-parent");
2143
+ });
2144
+ }
2145
+ initMulDrEvent() {
2146
+ this.actionManager.on("change-to-select", (el) => {
2147
+ this.select(el);
2148
+ setTimeout(() => this.emit("select", el));
2149
+ }).on("multi-update", (data, parentEl) => {
2150
+ this.emit("update", { data, parentEl });
2151
+ });
2152
+ }
2153
+ initHighlightEvent() {
2154
+ this.actionManager.on("highlight", async (highlightEl) => {
2155
+ this.emit("highlight", highlightEl);
2156
+ });
1824
2157
  }
1825
2158
  }
1826
2159
 
1827
- 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, isMoveableButton, isRelative, isStatic, removeSelectedClassName, up };
1828
- //# sourceMappingURL=tmagic-stage.mjs.map
2160
+ export { CONTAINER_HIGHLIGHT_CLASS_NAME, ContainerHighlightType, DEFAULT_ZOOM, DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, HIGHLIGHT_EL_ID_PREFIX, Mode, MouseButton, PAGE_CLASS, SELECTED_CLASS, SelectStatus, StageDragResize, StageDragStatus, StageMask, StageRender, ZIndex, addSelectedClassName, calcValueByFontsize, StageCore as default, down, getAbsolutePosition, getMode, getOffset, getScrollParent, getTargetElStyle, isAbsolute, isFixed, isFixedParent, isMoveableButton, isRelative, isStatic, removeSelectedClassName, up };
2161
+ //# sourceMappingURL=tmagic-stage.js.map