@tmagic/stage 1.2.0-beta.17 → 1.2.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,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,251 +213,665 @@ 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:
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
+ getRenderDocument;
749
+ markContainerEnd;
750
+ delayedMarkContainer;
751
+ constructor(config) {
752
+ super(config);
753
+ this.getRenderDocument = config.getRenderDocument;
754
+ this.markContainerEnd = config.markContainerEnd;
755
+ this.delayedMarkContainer = config.delayedMarkContainer;
756
+ this.dragResizeHelper = new DragResizeHelper({
757
+ container: config.container,
758
+ updateDragEl: config.updateDragEl
759
+ });
760
+ this.on("update-moveable", () => {
761
+ if (this.moveable) {
762
+ this.updateMoveable();
763
+ }
764
+ });
765
+ }
766
+ select(el, event) {
767
+ if (!this.moveable || el !== this.target) {
768
+ this.initMoveable(el);
769
+ } else {
770
+ this.updateMoveable(el);
771
+ }
772
+ if (event) {
773
+ this.moveable?.dragStart(event);
774
+ }
775
+ }
776
+ updateMoveable(el = this.target) {
777
+ if (!this.moveable)
778
+ return;
779
+ if (!el)
780
+ throw new Error("\u672A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
781
+ const options = this.init(el);
782
+ Object.entries(options).forEach(([key, value]) => {
783
+ this.moveable[key] = value;
784
+ });
785
+ this.moveable.updateTarget();
786
+ }
787
+ clearSelectStatus() {
788
+ if (!this.moveable)
789
+ return;
790
+ this.dragResizeHelper.destroyShadowEl();
791
+ this.moveable.target = null;
792
+ this.moveable.updateTarget();
793
+ }
794
+ destroy() {
795
+ this.moveable?.destroy();
796
+ this.dragResizeHelper.destroy();
797
+ this.dragStatus = StageDragStatus.END;
798
+ this.removeAllListeners();
799
+ }
800
+ init(el) {
801
+ if (/(auto|scroll)/.test(el.style.overflow)) {
802
+ el.style.overflow = "hidden";
803
+ }
804
+ this.target = el;
805
+ this.mode = getMode(el);
806
+ this.dragResizeHelper.updateShadowEl(el);
807
+ this.dragResizeHelper.setMode(this.mode);
808
+ const elementGuidelines = Array.prototype.slice.call(this.target?.parentElement?.children) || [];
809
+ this.setElementGuidelines([this.target], elementGuidelines);
810
+ return this.getOptions(false, {
811
+ target: this.dragResizeHelper.getShadowEl()
812
+ });
813
+ }
814
+ initMoveable(el) {
815
+ const options = this.init(el);
816
+ this.dragResizeHelper.clear();
817
+ this.moveable?.destroy();
818
+ this.moveable = new Moveable(this.container, {
819
+ ...options
820
+ });
821
+ this.bindResizeEvent();
822
+ this.bindDragEvent();
823
+ this.bindRotateEvent();
824
+ this.bindScaleEvent();
825
+ }
826
+ bindResizeEvent() {
827
+ if (!this.moveable)
828
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
829
+ this.moveable.on("resizeStart", (e) => {
830
+ if (!this.target)
831
+ return;
832
+ this.dragStatus = StageDragStatus.START;
833
+ this.dragResizeHelper.onResizeStart(e);
834
+ }).on("resize", (e) => {
835
+ if (!this.moveable || !this.target || !this.dragResizeHelper.getShadowEl())
836
+ return;
837
+ this.dragStatus = StageDragStatus.ING;
838
+ this.dragResizeHelper.onResize(e);
839
+ }).on("resizeEnd", () => {
840
+ this.dragStatus = StageDragStatus.END;
841
+ this.update(true);
842
+ });
843
+ }
844
+ bindDragEvent() {
845
+ if (!this.moveable)
846
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
847
+ let timeout;
848
+ this.moveable.on("dragStart", (e) => {
849
+ if (!this.target)
850
+ throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
851
+ this.dragStatus = StageDragStatus.START;
852
+ this.dragResizeHelper.onDragStart(e);
853
+ }).on("drag", (e) => {
854
+ if (!this.target || !this.dragResizeHelper.getShadowEl())
855
+ return;
856
+ if (timeout) {
857
+ globalThis.clearTimeout(timeout);
858
+ timeout = void 0;
859
+ }
860
+ timeout = this.delayedMarkContainer(e.inputEvent, [this.target]);
861
+ this.dragStatus = StageDragStatus.ING;
862
+ this.dragResizeHelper.onDrag(e);
863
+ }).on("dragEnd", () => {
864
+ if (timeout) {
865
+ globalThis.clearTimeout(timeout);
866
+ timeout = void 0;
867
+ }
868
+ const parentEl = this.markContainerEnd();
869
+ if (this.dragStatus === StageDragStatus.ING) {
870
+ if (parentEl) {
871
+ this.update(false, parentEl);
872
+ } else {
873
+ switch (this.mode) {
874
+ case Mode.SORTABLE:
542
875
  this.sort();
543
876
  break;
544
877
  default:
@@ -547,7 +880,7 @@ class StageDragResize extends EventEmitter {
547
880
  }
548
881
  }
549
882
  this.dragStatus = StageDragStatus.END;
550
- this.destroyGhostEl();
883
+ this.dragResizeHelper.destroyGhostEl();
551
884
  });
552
885
  }
553
886
  bindRotateEvent() {
@@ -555,17 +888,15 @@ class StageDragResize extends EventEmitter {
555
888
  throw new Error("moveable \u672A\u521D\u59CB\u5316");
556
889
  this.moveable.on("rotateStart", (e) => {
557
890
  this.dragStatus = StageDragStatus.START;
558
- this.moveableHelper?.onRotateStart(e);
891
+ this.dragResizeHelper.onRotateStart(e);
559
892
  }).on("rotate", (e) => {
560
- if (!this.target || !this.dragEl)
893
+ if (!this.target || !this.dragResizeHelper.getShadowEl())
561
894
  return;
562
895
  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 || "";
896
+ this.dragResizeHelper.onRotate(e);
566
897
  }).on("rotateEnd", (e) => {
567
898
  this.dragStatus = StageDragStatus.END;
568
- const frame = this.moveableHelper?.getFrame(e.target);
899
+ const frame = this.dragResizeHelper?.getFrame(e.target);
569
900
  this.emit("update", {
570
901
  data: [
571
902
  {
@@ -583,17 +914,15 @@ class StageDragResize extends EventEmitter {
583
914
  throw new Error("moveable \u672A\u521D\u59CB\u5316");
584
915
  this.moveable.on("scaleStart", (e) => {
585
916
  this.dragStatus = StageDragStatus.START;
586
- this.moveableHelper?.onScaleStart(e);
917
+ this.dragResizeHelper.onScaleStart(e);
587
918
  }).on("scale", (e) => {
588
- if (!this.target || !this.dragEl)
919
+ if (!this.target || !this.dragResizeHelper.getShadowEl())
589
920
  return;
590
921
  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 || "";
922
+ this.dragResizeHelper.onScale(e);
594
923
  }).on("scaleEnd", (e) => {
595
924
  this.dragStatus = StageDragStatus.END;
596
- const frame = this.moveableHelper?.getFrame(e.target);
925
+ const frame = this.dragResizeHelper.getFrame(e.target);
597
926
  this.emit("update", {
598
927
  data: [
599
928
  {
@@ -607,9 +936,9 @@ class StageDragResize extends EventEmitter {
607
936
  });
608
937
  }
609
938
  sort() {
610
- if (!this.target || !this.ghostEl)
939
+ if (!this.target || !this.dragResizeHelper.getGhostEl())
611
940
  throw new Error("\u672A\u77E5\u9519\u8BEF");
612
- const { top } = this.ghostEl.getBoundingClientRect();
941
+ const { top } = this.dragResizeHelper.getGhostEl().getBoundingClientRect();
613
942
  const { top: oriTop } = this.target.getBoundingClientRect();
614
943
  const deltaTop = top - oriTop;
615
944
  if (Math.abs(deltaTop) >= this.target.clientHeight / 2) {
@@ -628,8 +957,7 @@ class StageDragResize extends EventEmitter {
628
957
  update(isResize = false, parentEl = null) {
629
958
  if (!this.target)
630
959
  return;
631
- const { contentWindow } = this.core.renderer;
632
- const doc = contentWindow?.document;
960
+ const doc = this.getRenderDocument();
633
961
  if (!doc)
634
962
  return;
635
963
  const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
@@ -637,11 +965,16 @@ class StageDragResize extends EventEmitter {
637
965
  let top = calcValueByFontsize(doc, offset.top);
638
966
  const width = calcValueByFontsize(doc, this.target.clientWidth);
639
967
  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;
968
+ const shadowEl = this.dragResizeHelper.getShadowEl();
969
+ if (parentEl && this.mode === Mode.ABSOLUTE && shadowEl) {
970
+ const targetShadowHtmlEl = shadowEl;
971
+ const targetShadowElOffsetLeft = targetShadowHtmlEl.offsetLeft || 0;
972
+ const targetShadowElOffsetTop = targetShadowHtmlEl.offsetTop || 0;
973
+ const frame = this.dragResizeHelper.getFrame(shadowEl);
974
+ const [translateX, translateY] = frame?.properties.transform.translate.value;
642
975
  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);
976
+ left = calcValueByFontsize(doc, targetShadowElOffsetLeft) + parseFloat(translateX) - calcValueByFontsize(doc, parentLeft);
977
+ top = calcValueByFontsize(doc, targetShadowElOffsetTop) + parseFloat(translateY) - calcValueByFontsize(doc, parentTop);
645
978
  }
646
979
  this.emit("update", {
647
980
  data: [
@@ -653,219 +986,516 @@ class StageDragResize extends EventEmitter {
653
986
  parentEl
654
987
  });
655
988
  }
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;
989
+ }
990
+
991
+ class StageHighlight extends EventEmitter$1 {
992
+ container;
993
+ target;
994
+ moveable;
995
+ targetShadow;
996
+ getRootContainer;
997
+ constructor(config) {
998
+ super();
999
+ this.container = config.container;
1000
+ this.getRootContainer = config.getRootContainer;
1001
+ this.targetShadow = new TargetShadow({
1002
+ container: config.container,
1003
+ updateDragEl: config.updateDragEl,
1004
+ zIndex: ZIndex.HIGHLIGHT_EL,
1005
+ idPrefix: HIGHLIGHT_EL_ID_PREFIX
1006
+ });
671
1007
  }
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}`;
1008
+ highlight(el) {
1009
+ if (!el || el === this.target)
1010
+ return;
1011
+ this.target = el;
1012
+ this.moveable?.destroy();
1013
+ this.moveable = new Moveable(this.container, {
1014
+ target: this.targetShadow.update(el),
1015
+ origin: false,
1016
+ rootContainer: this.getRootContainer(),
1017
+ zoom: 2
1018
+ });
1019
+ }
1020
+ clearHighlight() {
1021
+ if (!this.moveable || !this.target)
1022
+ return;
1023
+ this.target = void 0;
1024
+ this.moveable.target = null;
1025
+ this.moveable.updateTarget();
1026
+ }
1027
+ destroy() {
1028
+ this.moveable?.destroy();
1029
+ this.targetShadow.destroy();
1030
+ }
1031
+ }
1032
+
1033
+ class StageMultiDragResize extends MoveableOptionsManager {
1034
+ container;
1035
+ targetList = [];
1036
+ moveableForMulti;
1037
+ dragStatus = StageDragStatus.END;
1038
+ dragResizeHelper;
1039
+ getRenderDocument;
1040
+ constructor(config) {
1041
+ const moveableOptionsManagerConfig = {
1042
+ container: config.container,
1043
+ moveableOptions: config.multiMoveableOptions,
1044
+ getRootContainer: config.getRootContainer
1045
+ };
1046
+ super(moveableOptionsManagerConfig);
1047
+ this.container = config.container;
1048
+ this.getRenderDocument = config.getRenderDocument;
1049
+ this.dragResizeHelper = new DragResizeHelper({
1050
+ container: config.container,
1051
+ updateDragEl: config.updateDragEl
1052
+ });
1053
+ this.on("update-moveable", () => {
1054
+ if (this.moveableForMulti) {
1055
+ this.updateMoveable();
676
1056
  }
677
- if (child.children.length) {
678
- this.setGhostElChildrenId(child);
1057
+ });
1058
+ }
1059
+ multiSelect(els) {
1060
+ if (els.length === 0) {
1061
+ return;
1062
+ }
1063
+ this.mode = getMode(els[0]);
1064
+ this.targetList = els;
1065
+ this.dragResizeHelper.updateGroup(els);
1066
+ const elementGuidelines = Array.prototype.slice.call(this.targetList[0].parentElement?.children) || [];
1067
+ this.setElementGuidelines(this.targetList, elementGuidelines);
1068
+ this.moveableForMulti?.destroy();
1069
+ this.dragResizeHelper.clear();
1070
+ this.moveableForMulti = new Moveable(
1071
+ this.container,
1072
+ this.getOptions(true, {
1073
+ target: this.dragResizeHelper.getShadowEls()
1074
+ })
1075
+ );
1076
+ this.moveableForMulti.on("resizeGroupStart", (e) => {
1077
+ this.dragResizeHelper.onResizeGroupStart(e);
1078
+ this.dragStatus = StageDragStatus.START;
1079
+ }).on("resizeGroup", (e) => {
1080
+ this.dragResizeHelper.onResizeGroup(e);
1081
+ this.dragStatus = StageDragStatus.ING;
1082
+ }).on("resizeGroupEnd", () => {
1083
+ this.update(true);
1084
+ this.dragStatus = StageDragStatus.END;
1085
+ }).on("dragGroupStart", (e) => {
1086
+ this.dragResizeHelper.onDragGroupStart(e);
1087
+ this.dragStatus = StageDragStatus.START;
1088
+ }).on("dragGroup", (e) => {
1089
+ this.dragResizeHelper.onDragGroup(e);
1090
+ this.dragStatus = StageDragStatus.ING;
1091
+ }).on("dragGroupEnd", () => {
1092
+ this.update();
1093
+ this.dragStatus = StageDragStatus.END;
1094
+ }).on("clickGroup", (e) => {
1095
+ const { inputTarget, targets } = e;
1096
+ if (targets.length > 1 && targets.includes(inputTarget)) {
1097
+ this.emit("change-to-select", inputTarget.id.replace(DRAG_EL_ID_PREFIX, ""));
679
1098
  }
1099
+ });
1100
+ }
1101
+ canSelect(el, selectedEl) {
1102
+ const currentTargetMode = getMode(el);
1103
+ let selectedElMode = "";
1104
+ if (currentTargetMode === Mode.SORTABLE) {
1105
+ return false;
1106
+ }
1107
+ if (this.targetList.length === 0 && selectedEl) {
1108
+ selectedElMode = getMode(selectedEl);
1109
+ } else if (this.targetList.length > 0) {
1110
+ selectedElMode = getMode(this.targetList[0]);
680
1111
  }
1112
+ if (currentTargetMode !== selectedElMode) {
1113
+ return false;
1114
+ }
1115
+ return true;
681
1116
  }
682
- destroyGhostEl() {
683
- this.ghostEl?.remove();
684
- this.ghostEl = void 0;
1117
+ updateMoveable(eleList = this.targetList) {
1118
+ if (!this.moveableForMulti)
1119
+ return;
1120
+ if (!eleList)
1121
+ throw new Error("\u672A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
1122
+ this.targetList = eleList;
1123
+ this.dragResizeHelper.setTargetList(eleList);
1124
+ const options = this.getOptions(true, {
1125
+ target: this.dragResizeHelper.getShadowEls()
1126
+ });
1127
+ Object.entries(options).forEach(([key, value]) => {
1128
+ this.moveableForMulti[key] = value;
1129
+ });
1130
+ this.moveableForMulti.updateTarget();
685
1131
  }
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;
1132
+ clearSelectStatus() {
1133
+ if (!this.moveableForMulti)
1134
+ return;
1135
+ this.dragResizeHelper.clearMultiSelectStatus();
1136
+ this.moveableForMulti.target = null;
1137
+ this.moveableForMulti.updateTarget();
1138
+ this.targetList = [];
1139
+ }
1140
+ destroy() {
1141
+ this.moveableForMulti?.destroy();
1142
+ this.dragResizeHelper.destroy();
1143
+ }
1144
+ update(isResize = false) {
1145
+ if (this.targetList.length === 0)
1146
+ return;
1147
+ const doc = this.getRenderDocument();
1148
+ if (!doc)
1149
+ return;
1150
+ const data = this.targetList.map((targetItem) => {
1151
+ const left = calcValueByFontsize(doc, targetItem.offsetLeft);
1152
+ const top = calcValueByFontsize(doc, targetItem.offsetTop);
1153
+ const width = calcValueByFontsize(doc, targetItem.clientWidth);
1154
+ const height = calcValueByFontsize(doc, targetItem.clientHeight);
1155
+ return {
1156
+ el: targetItem,
1157
+ style: isResize ? { left, top, width, height } : { left, top }
1158
+ };
1159
+ });
1160
+ this.emit("update", data, null);
1161
+ }
1162
+ }
1163
+
1164
+ const throttleTime = 100;
1165
+ const defaultContainerHighlightDuration = 800;
1166
+ class ActionManager extends EventEmitter {
1167
+ dr;
1168
+ multiDr;
1169
+ highlightLayer;
1170
+ container;
1171
+ selectedEl;
1172
+ selectedElList = [];
1173
+ highlightedEl;
1174
+ isMultiSelectStatus = false;
1175
+ containerHighlightClassName;
1176
+ containerHighlightDuration;
1177
+ containerHighlightType;
1178
+ isAltKeydown = false;
1179
+ getTargetElement;
1180
+ getElementsFromPoint;
1181
+ canSelect;
1182
+ isContainer;
1183
+ getRenderDocument;
1184
+ mouseMoveHandler = throttle(async (event) => {
1185
+ const el = await this.getElementFromPoint(event);
1186
+ if (!el) {
1187
+ this.clearHighlight();
1188
+ return;
700
1189
  }
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
1190
+ this.highlight(el);
1191
+ }, throttleTime);
1192
+ constructor(config) {
1193
+ super();
1194
+ this.container = config.container;
1195
+ this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS_NAME;
1196
+ this.containerHighlightDuration = config.containerHighlightDuration || defaultContainerHighlightDuration;
1197
+ this.containerHighlightType = config.containerHighlightType;
1198
+ this.getTargetElement = config.getTargetElement;
1199
+ this.getElementsFromPoint = config.getElementsFromPoint;
1200
+ this.canSelect = config.canSelect || ((el) => !!el.id);
1201
+ this.getRenderDocument = config.getRenderDocument;
1202
+ this.isContainer = config.isContainer;
1203
+ this.dr = new StageDragResize({
1204
+ container: config.container,
1205
+ getRootContainer: config.getRootContainer,
1206
+ getRenderDocument: config.getRenderDocument,
1207
+ updateDragEl: config.updateDragEl,
1208
+ markContainerEnd: () => this.markContainerEnd(),
1209
+ delayedMarkContainer: (event, exclude) => {
1210
+ if (this.canAddToContainer()) {
1211
+ return this.delayedMarkContainer(event, exclude);
1212
+ }
1213
+ return void 0;
743
1214
  },
744
- ables: [selectParentAbles(this)],
745
- ...options,
746
- ...moveableOptions
747
- };
1215
+ moveableOptions: this.changeCallback(config.moveableOptions)
1216
+ });
1217
+ this.multiDr = new StageMultiDragResize({
1218
+ container: config.container,
1219
+ multiMoveableOptions: config.multiMoveableOptions,
1220
+ getRootContainer: config.getRootContainer,
1221
+ getRenderDocument: config.getRenderDocument,
1222
+ updateDragEl: config.updateDragEl
1223
+ });
1224
+ this.highlightLayer = new StageHighlight({
1225
+ container: config.container,
1226
+ updateDragEl: config.updateDragEl,
1227
+ getRootContainer: config.getRootContainer
1228
+ });
1229
+ this.initMouseEvent();
1230
+ this.initKeyEvent();
1231
+ this.initActionEvent();
1232
+ }
1233
+ setGuidelines(type, guidelines) {
1234
+ this.dr.setGuidelines(type, guidelines);
1235
+ this.multiDr.setGuidelines(type, guidelines);
1236
+ }
1237
+ clearGuides() {
1238
+ this.dr.clearGuides();
1239
+ this.multiDr.clearGuides();
1240
+ }
1241
+ updateMoveable(el) {
1242
+ this.dr.updateMoveable(el);
1243
+ this.multiDr.updateMoveable();
1244
+ }
1245
+ isSelectedEl(el) {
1246
+ return el.id === this.selectedEl?.id;
1247
+ }
1248
+ setSelectedEl(el) {
1249
+ this.selectedEl = el;
1250
+ }
1251
+ getSelectedEl() {
1252
+ return this.selectedEl;
1253
+ }
1254
+ getSelectedElList() {
1255
+ return this.selectedElList;
1256
+ }
1257
+ async getElementFromPoint(event) {
1258
+ const els = this.getElementsFromPoint(event);
1259
+ let stopped = false;
1260
+ const stop = () => stopped = true;
1261
+ for (const el of els) {
1262
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isElCanSelect(el, event, stop)) {
1263
+ if (stopped)
1264
+ break;
1265
+ return el;
1266
+ }
1267
+ }
1268
+ }
1269
+ async isElCanSelect(el, event, stop) {
1270
+ const canSelectByProp = await this.canSelect(el, event, stop);
1271
+ if (!canSelectByProp)
1272
+ return false;
1273
+ if (this.isMultiSelectStatus) {
1274
+ return this.canMultiSelect(el, stop);
1275
+ }
1276
+ return true;
1277
+ }
1278
+ canMultiSelect(el, stop) {
1279
+ if (el.className.includes(PAGE_CLASS)) {
1280
+ stop();
1281
+ return false;
1282
+ }
1283
+ const selectedEl = this.getSelectedEl();
1284
+ if (selectedEl?.className.includes(PAGE_CLASS)) {
1285
+ return true;
1286
+ }
1287
+ return this.multiDr.canSelect(el, selectedEl);
1288
+ }
1289
+ select(el, event) {
1290
+ this.selectedEl = el;
1291
+ this.clearSelectStatus(SelectStatus.MULTI_SELECT);
1292
+ this.dr.select(el, event);
1293
+ }
1294
+ multiSelect(idOrElList) {
1295
+ this.selectedElList = idOrElList.map((idOrEl) => this.getTargetElement(idOrEl));
1296
+ this.clearSelectStatus(SelectStatus.SELECT);
1297
+ this.multiDr.multiSelect(this.selectedElList);
1298
+ }
1299
+ getHighlightEl() {
1300
+ return this.highlightedEl;
1301
+ }
1302
+ setHighlightEl(el) {
1303
+ this.highlightedEl = el;
1304
+ }
1305
+ highlight(idOrEl) {
1306
+ let el;
1307
+ try {
1308
+ el = this.getTargetElement(idOrEl);
1309
+ } catch (error) {
1310
+ this.clearHighlight();
1311
+ return;
1312
+ }
1313
+ if (el === this.getSelectedEl() || this.multiDr.dragStatus === StageDragStatus.ING) {
1314
+ this.clearHighlight();
1315
+ return;
1316
+ }
1317
+ if (el === this.highlightedEl || !el)
1318
+ return;
1319
+ this.highlightLayer.highlight(el);
1320
+ this.highlightedEl = el;
1321
+ this.emit("highlight", el);
748
1322
  }
749
- canContainerHighlight() {
750
- return this.core.containerHighlightType === ContainerHighlightType.DEFAULT || this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight;
1323
+ clearHighlight() {
1324
+ this.setHighlightEl(void 0);
1325
+ this.highlightLayer.clearHighlight();
751
1326
  }
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);
1327
+ clearSelectStatus(selectType) {
1328
+ if (selectType === SelectStatus.MULTI_SELECT) {
1329
+ this.multiDr.clearSelectStatus();
1330
+ this.selectedElList = [];
1331
+ } else {
1332
+ this.dr.clearSelectStatus();
1333
+ }
1334
+ }
1335
+ async addContainerHighlightClassName(event, excludeElList) {
1336
+ const doc = this.getRenderDocument();
1337
+ if (!doc)
1338
+ return;
1339
+ const els = this.getElementsFromPoint(event);
1340
+ for (const el of els) {
1341
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.isContainer(el) && !excludeElList.includes(el)) {
1342
+ addClassName(el, doc, this.containerHighlightClassName);
1343
+ break;
1344
+ }
784
1345
  }
785
- return this.operationEl;
1346
+ }
1347
+ delayedMarkContainer(event, excludeElList = []) {
1348
+ return globalThis.setTimeout(() => {
1349
+ this.addContainerHighlightClassName(event, excludeElList);
1350
+ }, this.containerHighlightDuration);
786
1351
  }
787
1352
  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
1353
+ this.container.removeEventListener("mousedown", this.mouseDownHandler);
1354
+ this.container.removeEventListener("mousemove", this.mouseMoveHandler);
1355
+ this.container.removeEventListener("mouseleave", this.mouseLeaveHandler);
1356
+ this.container.removeEventListener("wheel", this.mouseWheelHandler);
1357
+ this.dr.destroy();
1358
+ this.multiDr.destroy();
1359
+ this.highlightLayer.destroy();
1360
+ }
1361
+ changeCallback(options) {
1362
+ if (typeof options === "function") {
1363
+ return () => {
1364
+ if (typeof options === "function") {
1365
+ const cfg = {
1366
+ targetElId: this.selectedEl?.id
1367
+ };
1368
+ return options(cfg);
1369
+ }
1370
+ return options;
799
1371
  };
800
1372
  }
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
- };
1373
+ return options;
1374
+ }
1375
+ async beforeMultiSelect(event) {
1376
+ const el = await this.getElementFromPoint(event);
1377
+ if (!el)
1378
+ return;
1379
+ if (this.selectedEl && !this.selectedEl.className.includes(PAGE_CLASS)) {
1380
+ this.selectedElList.push(this.selectedEl);
1381
+ this.selectedEl = void 0;
812
1382
  }
813
- if (getMode(el) === Mode.FIXED) {
814
- return {
815
- left: left + this.mask.scrollLeft,
816
- top: top + this.mask.scrollTop
817
- };
1383
+ const existIndex = this.selectedElList.findIndex((selectedDom) => selectedDom.id === el.id);
1384
+ if (existIndex !== -1) {
1385
+ this.selectedElList.splice(existIndex, 1);
1386
+ } else {
1387
+ this.selectedElList.push(el);
818
1388
  }
819
- return {
820
- left,
821
- top
822
- };
823
1389
  }
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
1390
+ canAddToContainer() {
1391
+ return this.containerHighlightType === ContainerHighlightType.DEFAULT || this.containerHighlightType === ContainerHighlightType.ALT && this.isAltKeydown;
1392
+ }
1393
+ markContainerEnd() {
1394
+ const doc = this.getRenderDocument();
1395
+ if (doc && this.canAddToContainer()) {
1396
+ return removeClassNameByClassName(doc, this.containerHighlightClassName);
1397
+ }
1398
+ return null;
1399
+ }
1400
+ initMouseEvent() {
1401
+ this.container.addEventListener("mousedown", this.mouseDownHandler);
1402
+ this.container.addEventListener("mousemove", this.mouseMoveHandler);
1403
+ this.container.addEventListener("mouseleave", this.mouseLeaveHandler);
1404
+ this.container.addEventListener("wheel", this.mouseWheelHandler);
1405
+ }
1406
+ initKeyEvent() {
1407
+ const { isMac } = new Env();
1408
+ const ctrl = isMac ? "meta" : "ctrl";
1409
+ KeyController.global.keydown(ctrl, (e) => {
1410
+ e.inputEvent.preventDefault();
1411
+ this.isMultiSelectStatus = true;
1412
+ });
1413
+ KeyController.global.on("blur", () => {
1414
+ this.isMultiSelectStatus = false;
1415
+ });
1416
+ KeyController.global.keyup(ctrl, (e) => {
1417
+ e.inputEvent.preventDefault();
1418
+ this.isMultiSelectStatus = false;
1419
+ });
1420
+ KeyController.global.keydown("alt", (e) => {
1421
+ e.inputEvent.preventDefault();
1422
+ this.isAltKeydown = true;
1423
+ });
1424
+ KeyController.global.keyup("alt", (e) => {
1425
+ e.inputEvent.preventDefault();
1426
+ this.markContainerEnd();
1427
+ this.isAltKeydown = false;
841
1428
  });
842
1429
  }
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
1430
+ initActionEvent() {
1431
+ this.dr.on("update", (data) => {
1432
+ setTimeout(() => this.emit("update", data));
1433
+ }).on("sort", (data) => {
1434
+ setTimeout(() => this.emit("sort", data));
1435
+ }).on("select-parent", () => {
1436
+ this.emit("select-parent");
1437
+ });
1438
+ this.multiDr.on("update", (data, parentEl) => {
1439
+ this.emit("multi-update", data, parentEl);
1440
+ }).on("change-to-select", async (id) => {
1441
+ if (this.isMultiSelectStatus)
1442
+ return false;
1443
+ const el = this.getTargetElement(id);
1444
+ this.emit("change-to-select", el);
853
1445
  });
854
1446
  }
855
- clearHighlight() {
856
- if (!this.moveable)
1447
+ mouseDownHandler = async (event) => {
1448
+ this.clearHighlight();
1449
+ event.stopImmediatePropagation();
1450
+ event.stopPropagation();
1451
+ if (this.isStopTriggerSelect(event))
857
1452
  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();
1453
+ this.container.removeEventListener("mousemove", this.mouseMoveHandler);
1454
+ if (this.isMultiSelectStatus) {
1455
+ await this.beforeMultiSelect(event);
1456
+ if (this.selectedElList.length > 0) {
1457
+ this.emit("before-multi-select", this.selectedElList);
1458
+ }
1459
+ } else {
1460
+ const el = await this.getElementFromPoint(event);
1461
+ if (!el)
1462
+ return;
1463
+ this.emit("before-select", el, event);
1464
+ }
1465
+ getDocument().addEventListener("mouseup", this.mouseUpHandler);
1466
+ };
1467
+ isStopTriggerSelect(event) {
1468
+ if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
1469
+ return true;
1470
+ if (!event.target)
1471
+ return true;
1472
+ const targetClassList = event.target.classList;
1473
+ if (!this.isMultiSelectStatus && targetClassList.contains("moveable-area")) {
1474
+ return true;
1475
+ }
1476
+ if (targetClassList.contains("moveable-control") || isMoveableButton(event.target)) {
1477
+ return true;
1478
+ }
1479
+ return false;
865
1480
  }
1481
+ mouseUpHandler = () => {
1482
+ getDocument().removeEventListener("mouseup", this.mouseUpHandler);
1483
+ this.container.addEventListener("mousemove", this.mouseMoveHandler);
1484
+ if (this.isMultiSelectStatus) {
1485
+ this.emit("multi-select", this.selectedElList);
1486
+ } else {
1487
+ this.emit("select", this.selectedEl);
1488
+ }
1489
+ };
1490
+ mouseLeaveHandler = () => {
1491
+ setTimeout(() => this.clearHighlight(), throttleTime);
1492
+ };
1493
+ mouseWheelHandler = () => {
1494
+ this.clearHighlight();
1495
+ };
866
1496
  }
867
1497
 
868
- class Rule extends EventEmitter$1 {
1498
+ class Rule extends EventEmitter {
869
1499
  hGuides;
870
1500
  vGuides;
871
1501
  horizontalGuidelines = [];
@@ -904,11 +1534,11 @@ class Rule extends EventEmitter$1 {
904
1534
  this.vGuides.setState({
905
1535
  defaultGuides: vLines
906
1536
  });
907
- this.emit("changeGuides", {
1537
+ this.emit("change-guides", {
908
1538
  type: GuidesType.HORIZONTAL,
909
1539
  guides: hLines
910
1540
  });
911
- this.emit("changeGuides", {
1541
+ this.emit("change-guides", {
912
1542
  type: GuidesType.VERTICAL,
913
1543
  guides: vLines
914
1544
  });
@@ -967,14 +1597,14 @@ class Rule extends EventEmitter$1 {
967
1597
  });
968
1598
  hGuidesChangeGuidesHandler = (e) => {
969
1599
  this.horizontalGuidelines = e.guides;
970
- this.emit("changeGuides", {
1600
+ this.emit("change-guides", {
971
1601
  type: GuidesType.HORIZONTAL,
972
1602
  guides: this.horizontalGuidelines
973
1603
  });
974
1604
  };
975
1605
  vGuidesChangeGuidesHandler = (e) => {
976
1606
  this.verticalGuidelines = e.guides;
977
- this.emit("changeGuides", {
1607
+ this.emit("change-guides", {
978
1608
  type: GuidesType.VERTICAL,
979
1609
  guides: this.verticalGuidelines
980
1610
  });
@@ -982,9 +1612,8 @@ class Rule extends EventEmitter$1 {
982
1612
  }
983
1613
 
984
1614
  const wrapperClassName = "editor-mask-wrapper";
985
- const throttleTime = 100;
986
1615
  const hideScrollbar = () => {
987
- injectStyle(globalThis.document, `.${wrapperClassName}::-webkit-scrollbar { width: 0 !important; display: none }`);
1616
+ injectStyle(getDocument(), `.${wrapperClassName}::-webkit-scrollbar { width: 0 !important; display: none }`);
988
1617
  };
989
1618
  const createContent = () => createDiv({
990
1619
  className: "editor-mask",
@@ -1023,25 +1652,21 @@ class StageMask extends Rule {
1023
1652
  wrapperWidth = 0;
1024
1653
  maxScrollTop = 0;
1025
1654
  maxScrollLeft = 0;
1026
- isMultiSelectStatus = false;
1027
1655
  mode = Mode.ABSOLUTE;
1028
1656
  pageScrollParent = null;
1029
1657
  intersectionObserver = null;
1030
1658
  wrapperResizeObserver = null;
1031
- highlightHandler = throttle((event) => {
1032
- this.emit("highlight", event);
1033
- }, throttleTime);
1034
1659
  constructor() {
1035
1660
  const wrapper = createWrapper();
1036
1661
  super(wrapper);
1037
1662
  this.wrapper = wrapper;
1038
- this.initContentEventListener();
1663
+ this.content.addEventListener("wheel", this.mouseWheelHandler);
1039
1664
  this.wrapper.appendChild(this.content);
1040
- this.initMultiSelectEvent();
1041
1665
  }
1042
1666
  setMode(mode) {
1043
1667
  this.mode = mode;
1044
1668
  this.scroll();
1669
+ this.content.dataset.mode = mode;
1045
1670
  if (mode === Mode.FIXED) {
1046
1671
  this.content.style.width = `${this.wrapperWidth}px`;
1047
1672
  this.content.style.height = `${this.wrapperHeight}px`;
@@ -1088,30 +1713,8 @@ class StageMask extends Rule {
1088
1713
  this.page = null;
1089
1714
  this.pageScrollParent = null;
1090
1715
  this.wrapperResizeObserver?.disconnect();
1091
- this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
1092
1716
  super.destroy();
1093
1717
  }
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
1718
  initObserverIntersection() {
1116
1719
  this.pageScrollParent = getScrollParent(this.page) || null;
1117
1720
  this.intersectionObserver?.disconnect();
@@ -1161,317 +1764,78 @@ class StageMask extends Rule {
1161
1764
  scrollLeft = 0;
1162
1765
  scrollTop = 0;
1163
1766
  }
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, ""));
1767
+ this.scrollRule(scrollTop);
1768
+ this.scrollTo(scrollLeft, scrollTop);
1769
+ }
1770
+ scrollTo(scrollLeft, scrollTop) {
1771
+ this.content.style.transform = `translate3d(${-scrollLeft}px, ${-scrollTop}px, 0)`;
1772
+ const event = new CustomEvent("customScroll", {
1773
+ detail: {
1774
+ scrollLeft: this.scrollLeft,
1775
+ scrollTop: this.scrollTop
1371
1776
  }
1372
1777
  });
1778
+ this.content.dispatchEvent(event);
1373
1779
  }
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;
1780
+ setHeight(height) {
1781
+ this.height = height;
1782
+ this.setMaxScrollTop();
1783
+ this.content.style.height = `${height}px`;
1395
1784
  }
1396
- clearSelectStatus() {
1397
- if (!this.moveableForMulti)
1398
- return;
1399
- this.destroyDragElList();
1400
- this.moveableForMulti.target = null;
1401
- this.moveableForMulti.updateTarget();
1402
- this.targetList = [];
1785
+ setWidth(width) {
1786
+ this.width = width;
1787
+ this.setMaxScrollLeft();
1788
+ this.content.style.width = `${width}px`;
1403
1789
  }
1404
- destroy() {
1405
- this.moveableForMulti?.destroy();
1406
- this.destroyDragElList();
1790
+ setMaxScrollLeft() {
1791
+ this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
1407
1792
  }
1408
- destroyDragElList() {
1409
- this.dragElList.forEach((dragElItem) => dragElItem?.remove());
1793
+ setMaxScrollTop() {
1794
+ this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
1410
1795
  }
1411
- update(isResize = false) {
1412
- if (this.targetList.length === 0)
1796
+ fixScrollValue() {
1797
+ if (this.scrollTop < 0)
1798
+ this.scrollTop = 0;
1799
+ if (this.scrollLeft < 0)
1800
+ this.scrollLeft = 0;
1801
+ if (this.maxScrollTop < this.scrollTop)
1802
+ this.scrollTop = this.maxScrollTop;
1803
+ if (this.maxScrollLeft < this.scrollLeft)
1804
+ this.scrollLeft = this.maxScrollLeft;
1805
+ }
1806
+ mouseWheelHandler = (event) => {
1807
+ if (!this.page)
1808
+ throw new Error("page \u672A\u521D\u59CB\u5316");
1809
+ const { deltaY, deltaX } = event;
1810
+ if (this.page.clientHeight < this.wrapperHeight && deltaY)
1413
1811
  return;
1414
- const { contentWindow } = this.core.renderer;
1415
- const doc = contentWindow?.document;
1416
- if (!doc)
1812
+ if (this.page.clientWidth < this.wrapperWidth && deltaX)
1417
1813
  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);
1814
+ if (this.maxScrollTop > 0) {
1815
+ this.scrollTop = this.scrollTop + deltaY;
1437
1816
  }
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
- }
1817
+ if (this.maxScrollLeft > 0) {
1818
+ this.scrollLeft = this.scrollLeft + deltaX;
1819
+ }
1820
+ this.scroll();
1821
+ this.emit("scroll", event);
1822
+ };
1461
1823
  }
1462
1824
 
1463
1825
  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
1826
 
1465
- class StageRender extends EventEmitter {
1827
+ class StageRender extends EventEmitter$1 {
1466
1828
  contentWindow = null;
1467
1829
  runtime = null;
1468
1830
  iframe;
1469
1831
  runtimeUrl;
1470
- render;
1471
- constructor({ runtimeUrl, render }) {
1832
+ zoom = DEFAULT_ZOOM;
1833
+ customizedRender;
1834
+ constructor({ runtimeUrl, zoom, customizedRender }) {
1472
1835
  super();
1473
1836
  this.runtimeUrl = runtimeUrl || "";
1474
- this.render = render;
1837
+ this.customizedRender = customizedRender;
1838
+ this.setZoom(zoom);
1475
1839
  this.iframe = globalThis.document.createElement("iframe");
1476
1840
  this.iframe.src = isSameDomain(this.runtimeUrl) ? this.runtimeUrl : "";
1477
1841
  this.iframe.style.cssText = `
@@ -1489,6 +1853,31 @@ class StageRender extends EventEmitter {
1489
1853
  this.emit("runtime-ready", runtime);
1490
1854
  }
1491
1855
  });
1856
+ async add(data) {
1857
+ const runtime = await this.getRuntime();
1858
+ return runtime?.add?.(data);
1859
+ }
1860
+ async remove(data) {
1861
+ const runtime = await this.getRuntime();
1862
+ return runtime?.remove?.(data);
1863
+ }
1864
+ async update(data) {
1865
+ const runtime = await this.getRuntime();
1866
+ runtime?.update?.(data);
1867
+ }
1868
+ async select(els) {
1869
+ const runtime = await this.getRuntime();
1870
+ for (const el of els) {
1871
+ await runtime?.select?.(el.id);
1872
+ if (runtime?.beforeSelect) {
1873
+ await runtime.beforeSelect(el);
1874
+ }
1875
+ this.flagSelectedEl(el);
1876
+ }
1877
+ }
1878
+ setZoom(zoom = DEFAULT_ZOOM) {
1879
+ this.zoom = zoom;
1880
+ }
1492
1881
  async mount(el) {
1493
1882
  if (!this.iframe) {
1494
1883
  throw Error("mount \u5931\u8D25");
@@ -1517,6 +1906,27 @@ class StageRender extends EventEmitter {
1517
1906
  getDocument() {
1518
1907
  return this.contentWindow?.document;
1519
1908
  }
1909
+ getElementsFromPoint(point) {
1910
+ let x = point.clientX;
1911
+ let y = point.clientY;
1912
+ if (this.iframe) {
1913
+ const rect = this.iframe.getClientRects()[0];
1914
+ if (rect) {
1915
+ x = x - rect.left;
1916
+ y = y - rect.top;
1917
+ }
1918
+ }
1919
+ return this.getDocument()?.elementsFromPoint(x / this.zoom, y / this.zoom);
1920
+ }
1921
+ getTargetElement(idOrEl) {
1922
+ if (typeof idOrEl === "string" || typeof idOrEl === "number") {
1923
+ const el = this.getDocument()?.getElementById(`${idOrEl}`);
1924
+ if (!el)
1925
+ throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
1926
+ return el;
1927
+ }
1928
+ return idOrEl;
1929
+ }
1520
1930
  destroy() {
1521
1931
  this.iframe?.removeEventListener("load", this.loadHandler);
1522
1932
  this.contentWindow = null;
@@ -1524,14 +1934,21 @@ class StageRender extends EventEmitter {
1524
1934
  this.iframe = void 0;
1525
1935
  this.removeAllListeners();
1526
1936
  }
1937
+ flagSelectedEl(el) {
1938
+ const doc = this.getDocument();
1939
+ if (doc) {
1940
+ removeSelectedClassName(doc);
1941
+ addSelectedClassName(el, doc);
1942
+ }
1943
+ }
1527
1944
  loadHandler = async () => {
1528
1945
  if (!this.contentWindow?.magic) {
1529
1946
  this.postTmagicRuntimeReady();
1530
1947
  }
1531
1948
  if (!this.contentWindow)
1532
1949
  return;
1533
- if (this.render) {
1534
- const el = await this.render();
1950
+ if (this.customizedRender) {
1951
+ const el = await this.customizedRender();
1535
1952
  if (el) {
1536
1953
  this.contentWindow.document?.body?.appendChild(el);
1537
1954
  }
@@ -1551,211 +1968,81 @@ class StageRender extends EventEmitter {
1551
1968
  }
1552
1969
  }
1553
1970
 
1554
- class StageCore extends EventEmitter {
1971
+ class StageCore extends EventEmitter$1 {
1555
1972
  container;
1556
- selectedDom;
1557
- selectedDomList = [];
1558
- highlightedDom;
1559
1973
  renderer;
1560
1974
  mask;
1561
- dr;
1562
- multiDr;
1563
- highlightLayer;
1564
- config;
1565
- zoom = DEFAULT_ZOOM;
1566
- containerHighlightClassName;
1567
- containerHighlightDuration;
1568
- containerHighlightType;
1569
- isContainer;
1570
- canSelect;
1975
+ actionManager;
1571
1976
  pageResizeObserver = null;
1977
+ autoScrollIntoView;
1978
+ customizedRender;
1572
1979
  constructor(config) {
1573
1980
  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);
1981
+ this.autoScrollIntoView = config.autoScrollIntoView;
1982
+ this.customizedRender = config.render;
1983
+ this.renderer = new StageRender({
1984
+ runtimeUrl: config.runtimeUrl,
1985
+ zoom: config.zoom,
1986
+ customizedRender: async () => {
1987
+ if (this?.customizedRender) {
1988
+ return await this.customizedRender(this);
1989
+ }
1990
+ return null;
1631
1991
  }
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
1992
  });
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;
1993
+ this.mask = new StageMask();
1994
+ this.actionManager = new ActionManager(this.getActionManagerConfig(config));
1995
+ this.initRenderEvent();
1996
+ this.initActionEvent();
1997
+ this.initMaskEvent();
1683
1998
  }
1684
1999
  async select(idOrEl, event) {
1685
- this.clearSelectStatus("multiSelect");
1686
- const el = await this.getTargetElement(idOrEl);
1687
- if (el === this.selectedDom)
2000
+ const el = this.renderer.getTargetElement(idOrEl);
2001
+ if (el === this.actionManager.getSelectedEl())
1688
2002
  return;
1689
- const runtime = await this.renderer.getRuntime();
1690
- await runtime?.select?.(el.id);
1691
- if (runtime?.beforeSelect) {
1692
- await runtime.beforeSelect(el);
1693
- }
2003
+ await this.renderer.select([el]);
1694
2004
  this.mask.setLayout(el);
1695
- this.dr.select(el, event);
1696
- if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
2005
+ this.actionManager.select(el, event);
2006
+ if (this.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1697
2007
  this.mask.observerIntersection(el);
1698
2008
  }
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
2009
  }
1708
2010
  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();
2011
+ const els = idOrElList.map((idOrEl) => this.renderer.getTargetElement(idOrEl));
2012
+ if (els.length === 0)
1733
2013
  return;
2014
+ const lastEl = els[els.length - 1];
2015
+ const isReduceSelect = els.length < this.actionManager.getSelectedElList().length;
2016
+ await this.renderer.select(els);
2017
+ this.mask.setLayout(lastEl);
2018
+ this.actionManager.multiSelect(idOrElList);
2019
+ if ((this.autoScrollIntoView || lastEl.dataset.autoScrollIntoView) && !isReduceSelect) {
2020
+ this.mask.observerIntersection(lastEl);
1734
2021
  }
1735
- if (el === this.highlightedDom || !el)
1736
- return;
1737
- this.highlightLayer.highlight(el);
1738
- this.highlightedDom = el;
1739
2022
  }
1740
- sortNode(data) {
1741
- return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
2023
+ highlight(idOrEl) {
2024
+ this.actionManager.highlight(idOrEl);
1742
2025
  }
1743
- add(data) {
1744
- return this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
2026
+ async update(data) {
2027
+ const { config } = data;
2028
+ await this.renderer.update(data);
2029
+ setTimeout(() => {
2030
+ const el = this.renderer.getTargetElement(`${config.id}`);
2031
+ if (el && this.actionManager.isSelectedEl(el)) {
2032
+ this.mask.setLayout(el);
2033
+ this.actionManager.setSelectedEl(el);
2034
+ this.actionManager.updateMoveable(el);
2035
+ }
2036
+ });
1745
2037
  }
1746
- remove(data) {
1747
- return this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
2038
+ async add(data) {
2039
+ return await this.renderer.add(data);
1748
2040
  }
1749
- setZoom(zoom = DEFAULT_ZOOM) {
1750
- this.zoom = zoom;
2041
+ async remove(data) {
2042
+ return await this.renderer.remove(data);
1751
2043
  }
1752
- clearSelectStatus(selectType) {
1753
- if (selectType === "multiSelect") {
1754
- this.multiDr.clearSelectStatus();
1755
- this.selectedDomList = [];
1756
- } else {
1757
- this.dr.clearSelectStatus();
1758
- }
2044
+ setZoom(zoom = DEFAULT_ZOOM) {
2045
+ this.renderer.setZoom(zoom);
1759
2046
  }
1760
2047
  async mount(el) {
1761
2048
  this.container = el;
@@ -1766,32 +2053,19 @@ class StageCore extends EventEmitter {
1766
2053
  }
1767
2054
  clearGuides() {
1768
2055
  this.mask.clearGuides();
1769
- this.dr.clearGuides();
2056
+ this.actionManager.clearGuides();
1770
2057
  }
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
- }
2058
+ getAddContainerHighlightClassNameTimeout(event, excludeElList = []) {
2059
+ return this.delayedMarkContainer(event, excludeElList);
1783
2060
  }
1784
- getAddContainerHighlightClassNameTimeout(event, exclude = []) {
1785
- return globalThis.setTimeout(() => {
1786
- this.addContainerHighlightClassName(event, exclude);
1787
- }, this.containerHighlightDuration);
2061
+ delayedMarkContainer(event, excludeElList = []) {
2062
+ return this.actionManager.delayedMarkContainer(event, excludeElList);
1788
2063
  }
1789
2064
  destroy() {
1790
- const { mask, renderer, dr, highlightLayer, pageResizeObserver } = this;
2065
+ const { mask, renderer, actionManager, pageResizeObserver } = this;
1791
2066
  renderer.destroy();
1792
2067
  mask.destroy();
1793
- dr.destroy();
1794
- highlightLayer.destroy();
2068
+ actionManager.destroy();
1795
2069
  pageResizeObserver?.disconnect();
1796
2070
  this.removeAllListeners();
1797
2071
  this.container = void 0;
@@ -1800,29 +2074,84 @@ class StageCore extends EventEmitter {
1800
2074
  if (typeof ResizeObserver !== "undefined") {
1801
2075
  this.pageResizeObserver = new ResizeObserver((entries) => {
1802
2076
  this.mask.pageResize(entries);
1803
- if (this.dr.moveable) {
1804
- this.dr.updateMoveable();
1805
- }
2077
+ this.actionManager.updateMoveable();
1806
2078
  });
1807
2079
  this.pageResizeObserver.observe(page);
1808
2080
  }
1809
2081
  }
1810
- async render() {
1811
- if (this.config?.render) {
1812
- return await this.config.render(this);
1813
- }
1814
- return null;
2082
+ getActionManagerConfig(config) {
2083
+ const actionManagerConfig = {
2084
+ containerHighlightClassName: config.containerHighlightClassName,
2085
+ containerHighlightDuration: config.containerHighlightDuration,
2086
+ containerHighlightType: config.containerHighlightType,
2087
+ moveableOptions: config.moveableOptions,
2088
+ multiMoveableOptions: config.multiMoveableOptions,
2089
+ container: this.mask.content,
2090
+ canSelect: config.canSelect,
2091
+ isContainer: config.isContainer,
2092
+ updateDragEl: config.updateDragEl,
2093
+ getRootContainer: () => this.container,
2094
+ getRenderDocument: () => this.renderer.getDocument(),
2095
+ getTargetElement: (idOrEl) => this.renderer.getTargetElement(idOrEl),
2096
+ getElementsFromPoint: (point) => this.renderer.getElementsFromPoint(point)
2097
+ };
2098
+ return actionManagerConfig;
1815
2099
  }
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;
2100
+ initRenderEvent() {
2101
+ this.renderer.on("runtime-ready", (runtime) => {
2102
+ this.emit("runtime-ready", runtime);
2103
+ });
2104
+ this.renderer.on("page-el-update", (el) => {
2105
+ this.mask?.observe(el);
2106
+ this.observePageResize(el);
2107
+ });
2108
+ }
2109
+ initMaskEvent() {
2110
+ this.mask.on("change-guides", (data) => {
2111
+ this.actionManager.setGuidelines(data.type, data.guides);
2112
+ this.emit("change-guides", data);
2113
+ });
2114
+ }
2115
+ initActionEvent() {
2116
+ this.initActionManagerEvent();
2117
+ this.initDrEvent();
2118
+ this.initMulDrEvent();
2119
+ this.initHighlightEvent();
2120
+ }
2121
+ initActionManagerEvent() {
2122
+ this.actionManager.on("before-select", (idOrEl, event) => {
2123
+ this.select(idOrEl, event);
2124
+ }).on("select", (selectedEl) => {
2125
+ this.emit("select", selectedEl);
2126
+ }).on("before-multi-select", (idOrElList) => {
2127
+ this.multiSelect(idOrElList);
2128
+ }).on("multi-select", (selectedElList) => {
2129
+ this.emit("multi-select", selectedElList);
2130
+ });
2131
+ }
2132
+ initDrEvent() {
2133
+ this.actionManager.on("update", (data) => {
2134
+ this.emit("update", data);
2135
+ }).on("sort", (data) => {
2136
+ this.emit("sort", data);
2137
+ }).on("select-parent", () => {
2138
+ this.emit("select-parent");
2139
+ });
2140
+ }
2141
+ initMulDrEvent() {
2142
+ this.actionManager.on("change-to-select", (el) => {
2143
+ this.select(el);
2144
+ setTimeout(() => this.emit("select", el));
2145
+ }).on("multi-update", (data, parentEl) => {
2146
+ this.emit("update", { data, parentEl });
2147
+ });
2148
+ }
2149
+ initHighlightEvent() {
2150
+ this.actionManager.on("highlight", async (highlightEl) => {
2151
+ this.emit("highlight", highlightEl);
2152
+ });
1824
2153
  }
1825
2154
  }
1826
2155
 
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 };
2156
+ 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 };
1828
2157
  //# sourceMappingURL=tmagic-stage.mjs.map