@tmagic/stage 1.2.0-beta.2 → 1.2.0-beta.21

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