@tmagic/stage 1.2.0-beta.8 → 1.2.0

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