@tmagic/stage 1.0.0-beta.9 → 1.0.0-rc.11

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.
@@ -5,6 +5,8 @@ import { throttle } from 'lodash-es';
5
5
  import Guides from '@scena/guides';
6
6
 
7
7
  const GHOST_EL_ID_PREFIX = "ghost_el_";
8
+ const DRAG_EL_ID_PREFIX = "drag_el_";
9
+ const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
8
10
  const DEFAULT_ZOOM = 1;
9
11
  var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
10
12
  GuidesType2["HORIZONTAL"] = "horizontal";
@@ -14,6 +16,8 @@ var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
14
16
  var ZIndex = /* @__PURE__ */ ((ZIndex2) => {
15
17
  ZIndex2["MASK"] = "99999";
16
18
  ZIndex2["SELECTED_EL"] = "666";
19
+ ZIndex2["GHOST_EL"] = "700";
20
+ ZIndex2["DRAG_EL"] = "9";
17
21
  return ZIndex2;
18
22
  })(ZIndex || {});
19
23
  var MouseButton = /* @__PURE__ */ ((MouseButton2) => {
@@ -29,31 +33,22 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
29
33
  return Mode2;
30
34
  })(Mode || {});
31
35
  const SELECTED_CLASS = "tmagic-stage-selected-area";
36
+ const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
37
+ const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
32
38
 
39
+ const getParents = (el, relative) => {
40
+ let cur = el.parentElement;
41
+ const parents = [];
42
+ while (cur && cur !== relative) {
43
+ parents.push(cur);
44
+ cur = cur.parentElement;
45
+ }
46
+ return parents;
47
+ };
33
48
  const getOffset = (el) => {
34
- const { transform } = getComputedStyle(el);
35
49
  const { offsetParent } = el;
36
- let left = el.offsetLeft;
37
- let top = el.offsetTop;
38
- if (transform.indexOf("matrix") > -1) {
39
- let a = 1;
40
- let b = 1;
41
- let c = 1;
42
- let d = 1;
43
- let e = 0;
44
- let f = 0;
45
- transform.replace(/matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/, ($0, $1, $2, $3, $4, $5, $6) => {
46
- a = +$1;
47
- b = +$2;
48
- c = +$3;
49
- d = +$4;
50
- e = +$5;
51
- f = +$6;
52
- return transform;
53
- });
54
- left = a * left + c * top + e;
55
- top = b * left + d * top + f;
56
- }
50
+ const left = el.offsetLeft;
51
+ const top = el.offsetTop;
57
52
  if (offsetParent) {
58
53
  const parentOffset = getOffset(offsetParent);
59
54
  return {
@@ -154,58 +149,76 @@ const removeSelectedClassName = (doc) => {
154
149
  if (oldEl) {
155
150
  oldEl.classList.remove(SELECTED_CLASS);
156
151
  oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
152
+ doc.querySelectorAll(`.${SELECTED_CLASS}-parents`).forEach((item) => {
153
+ item.classList.remove(`${SELECTED_CLASS}-parents`);
154
+ });
157
155
  }
158
156
  };
159
- const addSelectedClassName = (el) => {
157
+ const addSelectedClassName = (el, doc) => {
160
158
  el.classList.add(SELECTED_CLASS);
161
159
  el.parentNode?.classList.add(`${SELECTED_CLASS}-parent`);
160
+ getParents(el, doc.body).forEach((item) => {
161
+ item.classList.add(`${SELECTED_CLASS}-parents`);
162
+ });
163
+ };
164
+ const getGuideLineFromCache = (type) => {
165
+ const key = {
166
+ [GuidesType.HORIZONTAL]: H_GUIDE_LINE_STORAGE_KEY,
167
+ [GuidesType.VERTICAL]: V_GUIDE_LINE_STORAGE_KEY
168
+ }[type];
169
+ if (!key)
170
+ return [];
171
+ const guideLineCacheData = globalThis.localStorage.getItem(key);
172
+ if (guideLineCacheData) {
173
+ try {
174
+ return JSON.parse(guideLineCacheData) || [];
175
+ } catch (e) {
176
+ console.error(e);
177
+ }
178
+ }
179
+ return [];
162
180
  };
163
181
 
164
182
  class StageDragResize extends EventEmitter {
165
- core;
166
- container;
167
- target;
168
- dragEl;
169
- moveable;
170
- horizontalGuidelines = [];
171
- verticalGuidelines = [];
172
- moveableOptions = {};
173
- dragStatus = "end" /* END */;
174
- ghostEl;
175
- mode = Mode.ABSOLUTE;
176
- moveableHelper;
177
183
  constructor(config) {
178
184
  super();
185
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
186
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
187
+ this.elementGuidelines = [];
188
+ this.mode = Mode.ABSOLUTE;
189
+ this.moveableOptions = {};
190
+ this.dragStatus = "end" /* END */;
179
191
  this.core = config.core;
180
192
  this.container = config.container;
193
+ this.dragEl = globalThis.document.createElement("div");
194
+ this.container.append(this.dragEl);
181
195
  }
182
- async select(el, event) {
196
+ select(el, event) {
197
+ const oldTarget = this.target;
183
198
  this.target = el;
184
- if (/(auto|scroll)/.test(this.target.style.overflow)) {
185
- this.target.style.overflow = "hidden";
199
+ if (!this.moveable || this.target !== oldTarget) {
200
+ this.init(el);
201
+ this.moveableHelper = MoveableHelper.create({
202
+ useBeforeRender: true,
203
+ useRender: false,
204
+ createAuto: true
205
+ });
206
+ this.initMoveable();
207
+ } else {
208
+ this.updateMoveable();
186
209
  }
187
- this.mode = getMode(el);
188
- this.destroyDragEl();
189
- this.destroyGhostEl();
190
- this.dragEl = this.generateDragEl(el);
191
- this.moveableOptions = await this.getOptions({
192
- target: this.dragEl || this.target
193
- });
194
- this.moveableHelper = MoveableHelper.create({
195
- useBeforeRender: true,
196
- useRender: false,
197
- createAuto: true
198
- });
199
- this.initMoveable();
200
210
  if (event) {
201
211
  this.moveable?.dragStart(event);
202
212
  }
203
213
  }
204
- async refresh() {
214
+ updateMoveable(el = this.target) {
205
215
  if (!this.moveable)
206
216
  throw new Error("\u672A\u521D\u59CB\u5316moveable");
207
- const options = await this.getOptions();
208
- Object.entries(options).forEach(([key, value]) => {
217
+ if (!el)
218
+ throw new Error("\u4E3A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
219
+ this.target = el;
220
+ this.init(el);
221
+ Object.entries(this.moveableOptions).forEach(([key, value]) => {
209
222
  this.moveable[key] = value;
210
223
  });
211
224
  this.moveable.updateTarget();
@@ -213,15 +226,19 @@ class StageDragResize extends EventEmitter {
213
226
  setGuidelines(type, guidelines) {
214
227
  if (type === GuidesType.HORIZONTAL) {
215
228
  this.horizontalGuidelines = guidelines;
229
+ this.moveableOptions.horizontalGuidelines = guidelines;
216
230
  } else if (type === GuidesType.VERTICAL) {
217
231
  this.verticalGuidelines = guidelines;
232
+ this.moveableOptions.verticalGuidelines = guidelines;
218
233
  }
219
- this.refresh();
234
+ this.updateMoveable();
220
235
  }
221
236
  clearGuides() {
222
- this.verticalGuidelines = [];
223
237
  this.horizontalGuidelines = [];
224
- this.refresh();
238
+ this.verticalGuidelines = [];
239
+ this.moveableOptions.horizontalGuidelines = [];
240
+ this.moveableOptions.verticalGuidelines = [];
241
+ this.updateMoveable();
225
242
  }
226
243
  destroy() {
227
244
  this.moveable?.destroy();
@@ -230,6 +247,37 @@ class StageDragResize extends EventEmitter {
230
247
  this.dragStatus = "end" /* END */;
231
248
  this.removeAllListeners();
232
249
  }
250
+ init(el) {
251
+ if (/(auto|scroll)/.test(el.style.overflow)) {
252
+ el.style.overflow = "hidden";
253
+ }
254
+ this.mode = getMode(el);
255
+ this.destroyGhostEl();
256
+ this.updateDragEl(el);
257
+ this.moveableOptions = this.getOptions({
258
+ target: this.dragEl
259
+ });
260
+ }
261
+ setElementGuidelines(nodes) {
262
+ this.elementGuidelines.forEach((node) => {
263
+ node.remove();
264
+ });
265
+ this.elementGuidelines = [];
266
+ if (this.mode === Mode.ABSOLUTE) {
267
+ const frame = document.createDocumentFragment();
268
+ for (const node of nodes) {
269
+ const { width, height } = node.getBoundingClientRect();
270
+ if (node === this.target)
271
+ continue;
272
+ const { left, top } = getOffset(node);
273
+ const elementGuideline = document.createElement("div");
274
+ elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
275
+ this.elementGuidelines.push(elementGuideline);
276
+ frame.append(elementGuideline);
277
+ }
278
+ this.container.append(frame);
279
+ }
280
+ }
233
281
  initMoveable() {
234
282
  this.moveable?.destroy();
235
283
  this.moveable = new Moveable(this.container, {
@@ -237,35 +285,38 @@ class StageDragResize extends EventEmitter {
237
285
  });
238
286
  this.bindResizeEvent();
239
287
  this.bindDragEvent();
288
+ this.bindRotateEvent();
289
+ this.bindScaleEvent();
240
290
  }
241
291
  bindResizeEvent() {
242
292
  if (!this.moveable)
243
293
  throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
294
+ const frame = {
295
+ left: 0,
296
+ top: 0
297
+ };
244
298
  this.moveable.on("resizeStart", (e) => {
245
- if (e.dragStart) {
246
- const rect = this.moveable.getRect();
247
- const offset = getAbsolutePosition(e.target, rect);
248
- e.dragStart.set([offset.left, offset.top]);
249
- }
250
- }).on("resize", ({ width, height, drag }) => {
299
+ if (!this.target)
300
+ return;
301
+ this.dragStatus = "start" /* START */;
302
+ this.moveableHelper?.onResizeStart(e);
303
+ frame.top = this.target.offsetTop;
304
+ frame.left = this.target.offsetLeft;
305
+ }).on("resize", (e) => {
306
+ const { width, height, drag } = e;
251
307
  if (!this.moveable || !this.target || !this.dragEl)
252
308
  return;
253
309
  const { beforeTranslate } = drag;
254
310
  this.dragStatus = "ing" /* ING */;
255
- this.target.style.width = `${width}px`;
256
- this.target.style.height = `${height}px`;
257
- this.dragEl.style.width = `${width}px`;
258
- this.dragEl.style.height = `${height}px`;
311
+ this.moveableHelper?.onResize(e);
259
312
  if (this.mode === Mode.SORTABLE) {
260
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
261
- this.target.style.top = `0px`;
262
- return;
313
+ this.target.style.top = "0px";
314
+ } else {
315
+ this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
316
+ this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
263
317
  }
264
- this.dragEl.style.left = `${beforeTranslate[0]}px`;
265
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
266
- const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
267
- this.target.style.left = `${offset.left}px`;
268
- this.target.style.top = `${offset.top}px`;
318
+ this.target.style.width = `${width}px`;
319
+ this.target.style.height = `${height}px`;
269
320
  }).on("resizeEnd", () => {
270
321
  this.dragStatus = "end" /* END */;
271
322
  this.update(true);
@@ -274,7 +325,7 @@ class StageDragResize extends EventEmitter {
274
325
  bindDragEvent() {
275
326
  if (!this.moveable)
276
327
  throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
277
- let offset = {
328
+ const frame = {
278
329
  left: 0,
279
330
  top: 0
280
331
  };
@@ -283,23 +334,22 @@ class StageDragResize extends EventEmitter {
283
334
  throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
284
335
  this.dragStatus = "start" /* START */;
285
336
  this.moveableHelper?.onDragStart(e);
286
- offset = getAbsolutePosition(this.target, { left: 0, top: 0 });
287
337
  if (this.mode === Mode.SORTABLE) {
288
338
  this.ghostEl = this.generateGhostEl(this.target);
289
339
  }
340
+ frame.top = this.target.offsetTop;
341
+ frame.left = this.target.offsetLeft;
290
342
  }).on("drag", (e) => {
291
343
  if (!this.target || !this.dragEl)
292
344
  return;
293
345
  this.dragStatus = "ing" /* ING */;
294
- const { left, top } = e;
295
346
  if (this.ghostEl) {
296
- this.dragEl.style.top = `${top}px`;
297
- this.ghostEl.style.top = `${top + offset.top}px`;
347
+ this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
298
348
  return;
299
349
  }
300
350
  this.moveableHelper?.onDrag(e);
301
- this.target.style.left = `${left + offset.left}px`;
302
- this.target.style.top = `${top + offset.top}px`;
351
+ this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
352
+ this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
303
353
  }).on("dragEnd", () => {
304
354
  if (this.dragStatus === "ing" /* ING */) {
305
355
  switch (this.mode) {
@@ -314,13 +364,53 @@ class StageDragResize extends EventEmitter {
314
364
  this.destroyGhostEl();
315
365
  });
316
366
  }
317
- async getSnapElements(el) {
318
- const { renderer } = this.core;
319
- const getSnapElements = (await renderer.getRuntime())?.getSnapElements || (() => {
320
- const doc = renderer.contentWindow?.document;
321
- return doc ? Array.from(doc.querySelectorAll("[id]")) : [];
367
+ bindRotateEvent() {
368
+ if (!this.moveable)
369
+ throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
370
+ this.moveable.on("rotateStart", (e) => {
371
+ this.dragStatus = "start" /* START */;
372
+ this.moveableHelper?.onRotateStart(e);
373
+ }).on("rotate", (e) => {
374
+ if (!this.target || !this.dragEl)
375
+ return;
376
+ this.dragStatus = "ing" /* ING */;
377
+ this.moveableHelper?.onRotate(e);
378
+ const frame = this.moveableHelper?.getFrame(e.target);
379
+ this.target.style.transform = frame?.toCSSObject().transform || "";
380
+ }).on("rotateEnd", (e) => {
381
+ this.dragStatus = "end" /* END */;
382
+ const frame = this.moveableHelper?.getFrame(e.target);
383
+ this.emit("update", {
384
+ el: this.target,
385
+ style: {
386
+ transform: frame?.get("transform")
387
+ }
388
+ });
389
+ });
390
+ }
391
+ bindScaleEvent() {
392
+ if (!this.moveable)
393
+ throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
394
+ this.moveable.on("scaleStart", (e) => {
395
+ this.dragStatus = "start" /* START */;
396
+ this.moveableHelper?.onScaleStart(e);
397
+ }).on("scale", (e) => {
398
+ if (!this.target || !this.dragEl)
399
+ return;
400
+ this.dragStatus = "ing" /* ING */;
401
+ this.moveableHelper?.onScale(e);
402
+ const frame = this.moveableHelper?.getFrame(e.target);
403
+ this.target.style.transform = frame?.toCSSObject().transform || "";
404
+ }).on("scaleEnd", (e) => {
405
+ this.dragStatus = "end" /* END */;
406
+ const frame = this.moveableHelper?.getFrame(e.target);
407
+ this.emit("update", {
408
+ el: this.target,
409
+ style: {
410
+ transform: frame?.get("transform")
411
+ }
412
+ });
322
413
  });
323
- return getSnapElements(el).filter((element) => element !== this.target && !this.target?.contains(element));
324
414
  }
325
415
  sort() {
326
416
  if (!this.target || !this.ghostEl)
@@ -342,12 +432,13 @@ class StageDragResize extends EventEmitter {
342
432
  }
343
433
  }
344
434
  update(isResize = false) {
345
- const rect = this.moveable.getRect();
346
- const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : getAbsolutePosition(this.target, rect);
435
+ if (!this.target)
436
+ return;
437
+ const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
347
438
  const left = this.calcValueByFontsize(offset.left);
348
439
  const top = this.calcValueByFontsize(offset.top);
349
- const width = this.calcValueByFontsize(rect.width);
350
- const height = this.calcValueByFontsize(rect.height);
440
+ const width = this.calcValueByFontsize(this.target.clientWidth);
441
+ const height = this.calcValueByFontsize(this.target.clientHeight);
351
442
  this.emit("update", {
352
443
  el: this.target,
353
444
  style: isResize ? { left, top, width, height } : { left, top }
@@ -359,8 +450,8 @@ class StageDragResize extends EventEmitter {
359
450
  }
360
451
  const ghostEl = el.cloneNode(true);
361
452
  const { top, left } = getAbsolutePosition(el, getOffset(el));
362
- ghostEl.id = `${GHOST_EL_ID_PREFIX}${ghostEl.id}`;
363
- ghostEl.style.zIndex = "5";
453
+ ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
454
+ ghostEl.style.zIndex = ZIndex.GHOST_EL;
364
455
  ghostEl.style.opacity = ".5";
365
456
  ghostEl.style.position = "absolute";
366
457
  ghostEl.style.left = `${left}px`;
@@ -372,44 +463,51 @@ class StageDragResize extends EventEmitter {
372
463
  this.ghostEl?.remove();
373
464
  this.ghostEl = void 0;
374
465
  }
375
- generateDragEl(el) {
376
- if (this.dragEl) {
377
- this.destroyDragEl();
378
- }
379
- const { width, height } = el.getBoundingClientRect();
466
+ updateDragEl(el) {
380
467
  const offset = getOffset(el);
381
- const dragEl = globalThis.document.createElement("div");
382
- dragEl.style.cssText = `
468
+ const { transform } = getComputedStyle(el);
469
+ this.dragEl.style.cssText = `
383
470
  position: absolute;
471
+ transform: ${transform};
384
472
  left: ${offset.left}px;
385
473
  top: ${offset.top}px;
386
- width: ${width}px;
387
- height: ${height}px;
474
+ width: ${el.clientWidth}px;
475
+ height: ${el.clientHeight}px;
476
+ z-index: ${ZIndex.DRAG_EL};
388
477
  `;
389
- this.container.append(dragEl);
390
- return dragEl;
478
+ this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
479
+ if (typeof this.core.config.updateDragEl === "function") {
480
+ this.core.config.updateDragEl(this.dragEl, el);
481
+ }
391
482
  }
392
483
  destroyDragEl() {
393
484
  this.dragEl?.remove();
394
- this.dragEl = void 0;
395
485
  }
396
- async getOptions(options = {}) {
486
+ getOptions(options = {}) {
397
487
  if (!this.target)
398
488
  return {};
399
489
  const isAbsolute = this.mode === Mode.ABSOLUTE;
490
+ const isFixed = this.mode === Mode.FIXED;
400
491
  let { moveableOptions = {} } = this.core.config;
401
492
  if (typeof moveableOptions === "function") {
402
493
  moveableOptions = moveableOptions(this.core);
403
494
  }
495
+ const elementGuidelines = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
496
+ this.setElementGuidelines(elementGuidelines);
497
+ if (moveableOptions.elementGuidelines) {
498
+ delete moveableOptions.elementGuidelines;
499
+ }
404
500
  return {
405
- origin: true,
501
+ origin: false,
406
502
  rootContainer: this.core.container,
407
503
  zoom: 1,
408
504
  dragArea: false,
409
505
  draggable: true,
410
506
  resizable: true,
411
- snappable: isAbsolute,
412
- snapGap: isAbsolute,
507
+ scalable: false,
508
+ rotatable: false,
509
+ snappable: isAbsolute || isFixed,
510
+ snapGap: isAbsolute || isFixed,
413
511
  snapThreshold: 5,
414
512
  snapDigit: 0,
415
513
  throttleDrag: 0,
@@ -422,8 +520,16 @@ class StageDragResize extends EventEmitter {
422
520
  center: isAbsolute,
423
521
  middle: isAbsolute
424
522
  },
523
+ elementSnapDirections: {
524
+ top: isAbsolute,
525
+ right: isAbsolute,
526
+ bottom: isAbsolute,
527
+ left: isAbsolute
528
+ },
529
+ isDisplayInnerSnapDigit: true,
425
530
  horizontalGuidelines: this.horizontalGuidelines,
426
531
  verticalGuidelines: this.verticalGuidelines,
532
+ elementGuidelines: this.elementGuidelines,
427
533
  bounds: {
428
534
  top: 0,
429
535
  left: 0,
@@ -492,15 +598,83 @@ const up = (deltaTop, target) => {
492
598
  };
493
599
  };
494
600
 
601
+ class TargetCalibrate extends EventEmitter {
602
+ constructor(config) {
603
+ super();
604
+ this.parent = config.parent;
605
+ this.mask = config.mask;
606
+ this.dr = config.dr;
607
+ this.core = config.core;
608
+ this.operationEl = globalThis.document.createElement("div");
609
+ this.parent.append(this.operationEl);
610
+ }
611
+ update(el, prefix) {
612
+ const { left, top } = this.getOffset(el);
613
+ const { transform } = getComputedStyle(el);
614
+ this.operationEl.style.cssText = `
615
+ position: absolute;
616
+ transform: ${transform};
617
+ left: ${left}px;
618
+ top: ${top}px;
619
+ width: ${el.clientWidth}px;
620
+ height: ${el.clientHeight}px;
621
+ `;
622
+ this.operationEl.id = `${prefix}${el.id}`;
623
+ if (typeof this.core.config.updateDragEl === "function") {
624
+ this.core.config.updateDragEl(this.operationEl, el);
625
+ }
626
+ return this.operationEl;
627
+ }
628
+ destroy() {
629
+ this.operationEl?.remove();
630
+ }
631
+ getOffset(el) {
632
+ const { offsetParent } = el;
633
+ const left = el.offsetLeft;
634
+ const top = el.offsetTop;
635
+ if (offsetParent) {
636
+ const parentOffset = this.getOffset(offsetParent);
637
+ return {
638
+ left: left + parentOffset.left,
639
+ top: top + parentOffset.top
640
+ };
641
+ }
642
+ if (this.dr.mode === Mode.FIXED) {
643
+ if (getMode(el) === Mode.FIXED) {
644
+ return {
645
+ left,
646
+ top
647
+ };
648
+ }
649
+ return {
650
+ left: left - this.mask.scrollLeft,
651
+ top: top - this.mask.scrollTop
652
+ };
653
+ }
654
+ if (getMode(el) === Mode.FIXED) {
655
+ return {
656
+ left: left + this.mask.scrollLeft,
657
+ top: top + this.mask.scrollTop
658
+ };
659
+ }
660
+ return {
661
+ left,
662
+ top
663
+ };
664
+ }
665
+ }
666
+
495
667
  class StageHighlight extends EventEmitter {
496
- core;
497
- container;
498
- target;
499
- moveable;
500
668
  constructor(config) {
501
669
  super();
502
670
  this.core = config.core;
503
671
  this.container = config.container;
672
+ this.calibrationTarget = new TargetCalibrate({
673
+ parent: this.core.mask.content,
674
+ mask: this.core.mask,
675
+ dr: this.core.dr,
676
+ core: this.core
677
+ });
504
678
  }
505
679
  highlight(el) {
506
680
  if (!el || el === this.target)
@@ -508,32 +682,66 @@ class StageHighlight extends EventEmitter {
508
682
  this.target = el;
509
683
  this.moveable?.destroy();
510
684
  this.moveable = new Moveable(this.container, {
511
- target: this.target
685
+ target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
686
+ origin: false,
687
+ rootContainer: this.core.container,
688
+ zoom: 1
512
689
  });
513
690
  }
514
691
  clearHighlight() {
515
692
  if (!this.moveable)
516
693
  return;
694
+ this.target = void 0;
517
695
  this.moveable.target = null;
518
696
  this.moveable.updateTarget();
519
697
  }
520
698
  destroy() {
521
699
  this.moveable?.destroy();
700
+ this.calibrationTarget.destroy();
522
701
  }
523
702
  }
524
703
 
525
704
  class Rule extends EventEmitter$1 {
526
- hGuides;
527
- vGuides;
528
- horizontalGuidelines = [];
529
- verticalGuidelines = [];
530
- container;
531
- containerResizeObserver;
532
705
  constructor(container) {
533
706
  super();
707
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
708
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
709
+ this.getGuidesStyle = (type) => ({
710
+ position: "fixed",
711
+ zIndex: 1,
712
+ left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
713
+ top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
714
+ width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
715
+ height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
716
+ });
717
+ this.createGuides = (type, defaultGuides = []) => new Guides(this.container, {
718
+ type,
719
+ defaultGuides,
720
+ displayDragPos: true,
721
+ backgroundColor: "#fff",
722
+ lineColor: "#000",
723
+ textColor: "#000",
724
+ style: this.getGuidesStyle(type)
725
+ });
726
+ this.hGuidesChangeGuidesHandler = (e) => {
727
+ this.horizontalGuidelines = e.guides;
728
+ this.emit("changeGuides", {
729
+ type: GuidesType.HORIZONTAL,
730
+ guides: this.horizontalGuidelines
731
+ });
732
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
733
+ };
734
+ this.vGuidesChangeGuidesHandler = (e) => {
735
+ this.verticalGuidelines = e.guides;
736
+ this.emit("changeGuides", {
737
+ type: GuidesType.VERTICAL,
738
+ guides: this.verticalGuidelines
739
+ });
740
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
741
+ };
534
742
  this.container = container;
535
- this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
536
- this.vGuides = this.createGuides(GuidesType.VERTICAL);
743
+ this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
744
+ this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
537
745
  this.hGuides.on("changeGuides", this.hGuidesChangeGuidesHandler);
538
746
  this.vGuides.on("changeGuides", this.vGuidesChangeGuidesHandler);
539
747
  this.containerResizeObserver = new ResizeObserver(() => {
@@ -567,6 +775,8 @@ class Rule extends EventEmitter$1 {
567
775
  type: GuidesType.HORIZONTAL,
568
776
  guides: []
569
777
  });
778
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, "[]");
779
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, "[]");
570
780
  }
571
781
  showRule(show = true) {
572
782
  if (show) {
@@ -599,37 +809,6 @@ class Rule extends EventEmitter$1 {
599
809
  this.containerResizeObserver.disconnect();
600
810
  this.removeAllListeners();
601
811
  }
602
- getGuidesStyle = (type) => ({
603
- position: "fixed",
604
- zIndex: 1,
605
- left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
606
- top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
607
- width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
608
- height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
609
- });
610
- createGuides = (type, defaultGuides = []) => new Guides(this.container, {
611
- type,
612
- defaultGuides,
613
- displayDragPos: true,
614
- backgroundColor: "#fff",
615
- lineColor: "#000",
616
- textColor: "#000",
617
- style: this.getGuidesStyle(type)
618
- });
619
- hGuidesChangeGuidesHandler = (e) => {
620
- this.horizontalGuidelines = e.guides;
621
- this.emit("changeGuides", {
622
- type: GuidesType.HORIZONTAL,
623
- guides: this.horizontalGuidelines
624
- });
625
- };
626
- vGuidesChangeGuidesHandler = (e) => {
627
- this.verticalGuidelines = e.guides;
628
- this.emit("changeGuides", {
629
- type: GuidesType.VERTICAL,
630
- guides: this.verticalGuidelines
631
- });
632
- };
633
812
  }
634
813
 
635
814
  const wrapperClassName = "editor-mask-wrapper";
@@ -667,32 +846,73 @@ const createWrapper = () => {
667
846
  return el;
668
847
  };
669
848
  class StageMask extends Rule {
670
- content = createContent();
671
- wrapper;
672
- core;
673
- page = null;
674
- pageScrollParent = null;
675
- scrollTop = 0;
676
- scrollLeft = 0;
677
- width = 0;
678
- height = 0;
679
- wrapperHeight = 0;
680
- wrapperWidth = 0;
681
- mode = Mode.ABSOLUTE;
682
- pageResizeObserver = null;
683
- wrapperResizeObserver = null;
684
- highlightHandler = throttle((event) => {
685
- this.emit("highlight", event);
686
- }, throttleTime);
687
849
  constructor(config) {
688
850
  const wrapper = createWrapper();
689
851
  super(wrapper);
852
+ this.content = createContent();
853
+ this.page = null;
854
+ this.pageScrollParent = null;
855
+ this.scrollTop = 0;
856
+ this.scrollLeft = 0;
857
+ this.width = 0;
858
+ this.height = 0;
859
+ this.wrapperHeight = 0;
860
+ this.wrapperWidth = 0;
861
+ this.maxScrollTop = 0;
862
+ this.maxScrollLeft = 0;
863
+ this.intersectionObserver = null;
864
+ this.mode = Mode.ABSOLUTE;
865
+ this.pageResizeObserver = null;
866
+ this.wrapperResizeObserver = null;
867
+ this.highlightHandler = throttle((event) => {
868
+ this.emit("highlight", event);
869
+ }, throttleTime);
870
+ this.mouseDownHandler = (event) => {
871
+ this.emit("clearHighlight");
872
+ event.stopImmediatePropagation();
873
+ event.stopPropagation();
874
+ if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
875
+ return;
876
+ if (event.target.className.indexOf("moveable-control") !== -1) {
877
+ return;
878
+ }
879
+ this.content.removeEventListener("mousemove", this.highlightHandler);
880
+ this.emit("beforeSelect", event);
881
+ globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
882
+ };
883
+ this.mouseUpHandler = () => {
884
+ globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
885
+ this.content.addEventListener("mousemove", this.highlightHandler);
886
+ this.emit("select");
887
+ };
888
+ this.mouseWheelHandler = (event) => {
889
+ this.emit("clearHighlight");
890
+ if (!this.page)
891
+ throw new Error("page \u672A\u521D\u59CB\u5316");
892
+ const { deltaY, deltaX } = event;
893
+ if (this.page.clientHeight < this.wrapperHeight && deltaY)
894
+ return;
895
+ if (this.page.clientWidth < this.wrapperWidth && deltaX)
896
+ return;
897
+ if (this.maxScrollTop > 0) {
898
+ this.scrollTop = this.scrollTop + deltaY;
899
+ }
900
+ if (this.maxScrollLeft > 0) {
901
+ this.scrollLeft = this.scrollLeft + deltaX;
902
+ }
903
+ this.scroll();
904
+ this.emit("scroll", event);
905
+ };
906
+ this.mouseLeaveHandler = () => {
907
+ setTimeout(() => this.emit("clearHighlight"), throttleTime);
908
+ };
690
909
  this.wrapper = wrapper;
691
910
  this.core = config.core;
692
911
  this.content.addEventListener("mousedown", this.mouseDownHandler);
693
912
  this.wrapper.appendChild(this.content);
694
913
  this.content.addEventListener("wheel", this.mouseWheelHandler);
695
914
  this.content.addEventListener("mousemove", this.highlightHandler);
915
+ this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
696
916
  }
697
917
  setMode(mode) {
698
918
  this.mode = mode;
@@ -711,12 +931,33 @@ class StageMask extends Rule {
711
931
  this.page = page;
712
932
  this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
713
933
  this.pageResizeObserver?.disconnect();
934
+ this.wrapperResizeObserver?.disconnect();
935
+ this.intersectionObserver?.disconnect();
936
+ if (typeof IntersectionObserver !== "undefined") {
937
+ this.intersectionObserver = new IntersectionObserver((entries) => {
938
+ entries.forEach((entry) => {
939
+ const { target, intersectionRatio } = entry;
940
+ if (intersectionRatio <= 0) {
941
+ this.scrollIntoView(target);
942
+ }
943
+ this.intersectionObserver?.unobserve(target);
944
+ });
945
+ }, {
946
+ root: this.pageScrollParent,
947
+ rootMargin: "0px",
948
+ threshold: 1
949
+ });
950
+ }
714
951
  if (typeof ResizeObserver !== "undefined") {
715
952
  this.pageResizeObserver = new ResizeObserver((entries) => {
716
953
  const [entry] = entries;
717
954
  const { clientHeight, clientWidth } = entry.target;
718
955
  this.setHeight(clientHeight);
719
956
  this.setWidth(clientWidth);
957
+ this.scroll();
958
+ if (this.core.dr.moveable) {
959
+ this.core.dr.updateMoveable();
960
+ }
720
961
  });
721
962
  this.pageResizeObserver.observe(page);
722
963
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
@@ -724,6 +965,8 @@ class StageMask extends Rule {
724
965
  const { clientHeight, clientWidth } = entry.target;
725
966
  this.wrapperHeight = clientHeight;
726
967
  this.wrapperWidth = clientWidth;
968
+ this.setMaxScrollLeft();
969
+ this.setMaxScrollTop();
727
970
  });
728
971
  this.wrapperResizeObserver.observe(this.wrapper);
729
972
  }
@@ -736,16 +979,32 @@ class StageMask extends Rule {
736
979
  setLayout(el) {
737
980
  this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
738
981
  }
982
+ scrollIntoView(el) {
983
+ el.scrollIntoView();
984
+ if (!this.pageScrollParent)
985
+ return;
986
+ this.scrollLeft = this.pageScrollParent.scrollLeft;
987
+ this.scrollTop = this.pageScrollParent.scrollTop;
988
+ this.scroll();
989
+ }
739
990
  destroy() {
740
991
  this.content?.remove();
741
992
  this.page = null;
742
993
  this.pageScrollParent = null;
743
994
  this.pageResizeObserver?.disconnect();
744
995
  this.wrapperResizeObserver?.disconnect();
996
+ this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
745
997
  super.destroy();
746
998
  }
747
999
  scroll() {
1000
+ this.fixScrollValue();
748
1001
  let { scrollLeft, scrollTop } = this;
1002
+ if (this.pageScrollParent) {
1003
+ this.pageScrollParent.scrollTo({
1004
+ top: scrollTop,
1005
+ left: scrollLeft
1006
+ });
1007
+ }
749
1008
  if (this.mode === Mode.FIXED) {
750
1009
  scrollLeft = 0;
751
1010
  scrollTop = 0;
@@ -758,74 +1017,67 @@ class StageMask extends Rule {
758
1017
  }
759
1018
  setHeight(height) {
760
1019
  this.height = height;
1020
+ this.setMaxScrollTop();
761
1021
  this.content.style.height = `${height}px`;
762
1022
  }
763
1023
  setWidth(width) {
764
1024
  this.width = width;
1025
+ this.setMaxScrollLeft();
765
1026
  this.content.style.width = `${width}px`;
766
1027
  }
767
- mouseDownHandler = (event) => {
768
- event.stopImmediatePropagation();
769
- event.stopPropagation();
770
- if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
771
- return;
772
- if (event.target.className.indexOf("moveable-control") !== -1) {
773
- return;
774
- }
775
- this.emit("beforeSelect", event);
776
- globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
777
- this.content.removeEventListener("mousemove", this.highlightHandler);
778
- this.emit("clearHighlight");
779
- };
780
- mouseUpHandler = () => {
781
- globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
782
- this.content.addEventListener("mousemove", this.highlightHandler);
783
- this.emit("select");
784
- };
785
- mouseWheelHandler = (event) => {
786
- if (!this.page)
787
- throw new Error("page \u672A\u521D\u59CB\u5316");
788
- const { deltaY, deltaX } = event;
789
- const { height, wrapperHeight, width, wrapperWidth } = this;
790
- const maxScrollTop = height - wrapperHeight;
791
- const maxScrollLeft = width - wrapperWidth;
792
- if (maxScrollTop > 0) {
793
- if (deltaY > 0) {
794
- this.scrollTop = this.scrollTop + Math.min(maxScrollTop - this.scrollTop, deltaY);
795
- } else {
796
- this.scrollTop = Math.max(this.scrollTop + deltaY, 0);
797
- }
798
- }
799
- if (width > wrapperWidth) {
800
- if (deltaX > 0) {
801
- this.scrollLeft = this.scrollLeft + Math.min(maxScrollLeft - this.scrollLeft, deltaX);
802
- } else {
803
- this.scrollLeft = Math.max(this.scrollLeft + deltaX, 0);
804
- }
805
- }
806
- if (this.mode !== Mode.FIXED) {
807
- this.scrollTo(this.scrollLeft, this.scrollTop);
808
- }
809
- if (this.pageScrollParent) {
810
- this.pageScrollParent.scrollTo({
811
- top: this.scrollTop,
812
- left: this.scrollLeft
813
- });
814
- }
815
- this.scroll();
816
- this.emit("scroll", event);
817
- };
1028
+ setMaxScrollLeft() {
1029
+ this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
1030
+ }
1031
+ setMaxScrollTop() {
1032
+ this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
1033
+ }
1034
+ fixScrollValue() {
1035
+ if (this.scrollTop < 0)
1036
+ this.scrollTop = 0;
1037
+ if (this.scrollLeft < 0)
1038
+ this.scrollLeft = 0;
1039
+ if (this.maxScrollTop < this.scrollTop)
1040
+ this.scrollTop = this.maxScrollTop;
1041
+ if (this.maxScrollLeft < this.scrollLeft)
1042
+ this.scrollLeft = this.maxScrollLeft;
1043
+ }
818
1044
  }
819
1045
 
820
1046
  class StageRender extends EventEmitter {
821
- contentWindow = null;
822
- runtime = null;
823
- iframe;
824
- runtimeUrl;
825
- core;
826
- render;
827
1047
  constructor({ core }) {
828
1048
  super();
1049
+ this.contentWindow = null;
1050
+ this.runtime = null;
1051
+ this.getMagicApi = () => ({
1052
+ onPageElUpdate: (el) => this.emit("page-el-update", el),
1053
+ onRuntimeReady: (runtime) => {
1054
+ this.runtime = runtime;
1055
+ globalThis.runtime = runtime;
1056
+ this.emit("runtime-ready", runtime);
1057
+ }
1058
+ });
1059
+ this.getRuntime = () => {
1060
+ if (this.runtime)
1061
+ return Promise.resolve(this.runtime);
1062
+ return new Promise((resolve) => {
1063
+ const listener = (runtime) => {
1064
+ this.off("runtime-ready", listener);
1065
+ resolve(runtime);
1066
+ };
1067
+ this.on("runtime-ready", listener);
1068
+ });
1069
+ };
1070
+ this.loadHandler = async () => {
1071
+ this.contentWindow = this.iframe?.contentWindow;
1072
+ this.contentWindow.magic = this.getMagicApi();
1073
+ if (this.render) {
1074
+ const el = await this.render(this.core);
1075
+ if (el) {
1076
+ this.iframe?.contentDocument?.body?.appendChild(el);
1077
+ }
1078
+ }
1079
+ this.emit("onload");
1080
+ };
829
1081
  this.core = core;
830
1082
  this.runtimeUrl = core.config.runtimeUrl || "";
831
1083
  this.render = core.config.render;
@@ -838,14 +1090,6 @@ class StageRender extends EventEmitter {
838
1090
  `;
839
1091
  this.iframe.addEventListener("load", this.loadHandler);
840
1092
  }
841
- getMagicApi = () => ({
842
- onPageElUpdate: (el) => this.emit("page-el-update", el),
843
- onRuntimeReady: (runtime) => {
844
- this.runtime = runtime;
845
- globalThis.runtime = runtime;
846
- this.emit("runtime-ready", runtime);
847
- }
848
- });
849
1093
  async mount(el) {
850
1094
  if (this.iframe) {
851
1095
  if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
@@ -856,23 +1100,10 @@ class StageRender extends EventEmitter {
856
1100
  this.iframe.srcdoc = html;
857
1101
  }
858
1102
  el.appendChild(this.iframe);
859
- this.contentWindow = this.iframe?.contentWindow;
860
- this.contentWindow.magic = this.getMagicApi();
861
1103
  } else {
862
1104
  throw Error("mount \u5931\u8D25");
863
1105
  }
864
1106
  }
865
- getRuntime = () => {
866
- if (this.runtime)
867
- return Promise.resolve(this.runtime);
868
- return new Promise((resolve) => {
869
- const listener = (runtime) => {
870
- this.off("runtime-ready", listener);
871
- resolve(runtime);
872
- };
873
- this.on("runtime-ready", listener);
874
- });
875
- };
876
1107
  destroy() {
877
1108
  this.iframe?.removeEventListener("load", this.loadHandler);
878
1109
  this.contentWindow = null;
@@ -880,49 +1111,25 @@ class StageRender extends EventEmitter {
880
1111
  this.iframe = void 0;
881
1112
  this.removeAllListeners();
882
1113
  }
883
- loadHandler = async () => {
884
- this.emit("onload");
885
- if (this.render) {
886
- const el = await this.render(this.core);
887
- if (el) {
888
- this.iframe?.contentDocument?.body?.appendChild(el);
889
- }
890
- }
891
- if (this.contentWindow) {
892
- const style = this.contentWindow.document.createElement("style");
893
- style.id = "tmagic-stage-render";
894
- style.innerHTML = `
895
- .${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
896
- z-index: ${ZIndex.SELECTED_EL};
897
- }
898
- `;
899
- this.contentWindow.document.head.appendChild(style);
900
- }
901
- };
902
1114
  }
903
1115
 
904
1116
  class StageCore extends EventEmitter {
905
- selectedDom;
906
- highlightedDom;
907
- renderer;
908
- mask;
909
- dr;
910
- highlightLayer;
911
- config;
912
- zoom = DEFAULT_ZOOM;
913
- container;
914
- canSelect;
915
1117
  constructor(config) {
916
1118
  super();
1119
+ this.zoom = DEFAULT_ZOOM;
917
1120
  this.config = config;
918
1121
  this.setZoom(config.zoom);
919
1122
  this.canSelect = config.canSelect || ((el) => !!el.id);
920
1123
  this.renderer = new StageRender({ core: this });
921
1124
  this.mask = new StageMask({ core: this });
922
1125
  this.dr = new StageDragResize({ core: this, container: this.mask.content });
923
- this.highlightLayer = new StageHighlight({ core: this, container: this.mask.content });
924
- this.renderer.on("runtime-ready", (runtime) => this.emit("runtime-ready", runtime));
925
- this.renderer.on("page-el-update", (el) => this.mask?.observe(el));
1126
+ this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
1127
+ this.renderer.on("runtime-ready", (runtime) => {
1128
+ this.emit("runtime-ready", runtime);
1129
+ });
1130
+ this.renderer.on("page-el-update", (el) => {
1131
+ this.mask?.observe(el);
1132
+ });
926
1133
  this.mask.on("beforeSelect", (event) => {
927
1134
  this.setElementFromPoint(event);
928
1135
  }).on("select", () => {
@@ -932,6 +1139,10 @@ class StageCore extends EventEmitter {
932
1139
  this.emit("changeGuides", data);
933
1140
  }).on("highlight", async (event) => {
934
1141
  await this.setElementFromPoint(event);
1142
+ if (this.highlightedDom === this.selectedDom) {
1143
+ this.highlightLayer.clearHighlight();
1144
+ return;
1145
+ }
935
1146
  this.highlightLayer.highlight(this.highlightedDom);
936
1147
  this.emit("highlight", this.highlightedDom);
937
1148
  }).on("clearHighlight", async () => {
@@ -959,7 +1170,7 @@ class StageCore extends EventEmitter {
959
1170
  let stopped = false;
960
1171
  const stop = () => stopped = true;
961
1172
  for (const el of els) {
962
- if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, stop)) {
1173
+ if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, event, stop)) {
963
1174
  if (stopped)
964
1175
  break;
965
1176
  if (event.type === "mousemove") {
@@ -976,47 +1187,58 @@ class StageCore extends EventEmitter {
976
1187
  if (el === this.selectedDom)
977
1188
  return;
978
1189
  const runtime = await this.renderer.getRuntime();
1190
+ await runtime?.select?.(el.id);
979
1191
  if (runtime?.beforeSelect) {
980
1192
  await runtime.beforeSelect(el);
981
1193
  }
982
1194
  this.mask.setLayout(el);
983
- this.dr?.select(el, event);
1195
+ this.dr.select(el, event);
1196
+ if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1197
+ this.mask.intersectionObserver?.observe(el);
1198
+ }
984
1199
  this.selectedDom = el;
985
1200
  if (this.renderer.contentWindow) {
986
1201
  removeSelectedClassName(this.renderer.contentWindow.document);
987
1202
  if (this.selectedDom) {
988
- addSelectedClassName(this.selectedDom);
1203
+ addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
989
1204
  }
990
1205
  }
991
1206
  }
992
1207
  update(data) {
993
1208
  const { config } = data;
994
- this.renderer?.getRuntime().then((runtime) => {
1209
+ return this.renderer?.getRuntime().then((runtime) => {
995
1210
  runtime?.update?.(data);
996
1211
  setTimeout(() => {
997
1212
  const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
998
- if (el) {
1213
+ if (el && el.id === this.selectedDom?.id) {
1214
+ this.selectedDom = el;
999
1215
  this.mask.setLayout(el);
1000
- this.dr?.select(el);
1216
+ this.dr.updateMoveable(el);
1001
1217
  }
1002
1218
  }, 0);
1003
1219
  });
1004
1220
  }
1005
1221
  async highlight(idOrEl) {
1006
- const el = await this.getTargetElement(idOrEl);
1222
+ let el;
1223
+ try {
1224
+ el = await this.getTargetElement(idOrEl);
1225
+ } catch (error) {
1226
+ this.highlightLayer.clearHighlight();
1227
+ return;
1228
+ }
1007
1229
  if (el === this.highlightedDom)
1008
1230
  return;
1009
1231
  this.highlightLayer.highlight(el);
1010
1232
  this.highlightedDom = el;
1011
1233
  }
1012
1234
  sortNode(data) {
1013
- this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
1235
+ return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
1014
1236
  }
1015
1237
  add(data) {
1016
- this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
1238
+ return this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
1017
1239
  }
1018
1240
  remove(data) {
1019
- this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
1241
+ return this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
1020
1242
  }
1021
1243
  setZoom(zoom = DEFAULT_ZOOM) {
1022
1244
  this.zoom = zoom;
@@ -1042,16 +1264,13 @@ class StageCore extends EventEmitter {
1042
1264
  this.container = void 0;
1043
1265
  }
1044
1266
  async getTargetElement(idOrEl) {
1045
- let el;
1046
1267
  if (typeof idOrEl === "string" || typeof idOrEl === "number") {
1047
- const runtime = await this.renderer?.getRuntime();
1048
- el = await runtime?.select?.(`${idOrEl}`);
1268
+ const el = this.renderer.contentWindow?.document.getElementById(`${idOrEl}`);
1049
1269
  if (!el)
1050
1270
  throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
1051
- } else {
1052
- el = idOrEl;
1271
+ return el;
1053
1272
  }
1054
- return el;
1273
+ return idOrEl;
1055
1274
  }
1056
1275
  }
1057
1276