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