@tmagic/stage 1.0.0-rc.1 → 1.0.0-rc.10

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.
@@ -16,6 +16,8 @@ var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
16
16
  var ZIndex = /* @__PURE__ */ ((ZIndex2) => {
17
17
  ZIndex2["MASK"] = "99999";
18
18
  ZIndex2["SELECTED_EL"] = "666";
19
+ ZIndex2["GHOST_EL"] = "700";
20
+ ZIndex2["DRAG_EL"] = "9";
19
21
  return ZIndex2;
20
22
  })(ZIndex || {});
21
23
  var MouseButton = /* @__PURE__ */ ((MouseButton2) => {
@@ -31,31 +33,22 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
31
33
  return Mode2;
32
34
  })(Mode || {});
33
35
  const SELECTED_CLASS = "tmagic-stage-selected-area";
36
+ const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
37
+ const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
34
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
+ };
35
48
  const getOffset = (el) => {
36
- const { transform } = getComputedStyle(el);
37
49
  const { offsetParent } = el;
38
- let left = el.offsetLeft;
39
- let top = el.offsetTop;
40
- if (transform.indexOf("matrix") > -1) {
41
- let a = 1;
42
- let b = 1;
43
- let c = 1;
44
- let d = 1;
45
- let e = 0;
46
- let f = 0;
47
- transform.replace(/matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/, ($0, $1, $2, $3, $4, $5, $6) => {
48
- a = +$1;
49
- b = +$2;
50
- c = +$3;
51
- d = +$4;
52
- e = +$5;
53
- f = +$6;
54
- return transform;
55
- });
56
- left = a * left + c * top + e;
57
- top = b * left + d * top + f;
58
- }
50
+ const left = el.offsetLeft;
51
+ const top = el.offsetTop;
59
52
  if (offsetParent) {
60
53
  const parentOffset = getOffset(offsetParent);
61
54
  return {
@@ -156,18 +149,41 @@ const removeSelectedClassName = (doc) => {
156
149
  if (oldEl) {
157
150
  oldEl.classList.remove(SELECTED_CLASS);
158
151
  oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
152
+ doc.querySelectorAll(`.${SELECTED_CLASS}-parents`).forEach((item) => {
153
+ item.classList.remove(`${SELECTED_CLASS}-parents`);
154
+ });
159
155
  }
160
156
  };
161
- const addSelectedClassName = (el) => {
157
+ const addSelectedClassName = (el, doc) => {
162
158
  el.classList.add(SELECTED_CLASS);
163
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 [];
164
180
  };
165
181
 
166
182
  class StageDragResize extends EventEmitter {
167
183
  constructor(config) {
168
184
  super();
169
- this.horizontalGuidelines = [];
170
- this.verticalGuidelines = [];
185
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
186
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
171
187
  this.elementGuidelines = [];
172
188
  this.mode = Mode.ABSOLUTE;
173
189
  this.moveableOptions = {};
@@ -180,8 +196,8 @@ class StageDragResize extends EventEmitter {
180
196
  select(el, event) {
181
197
  const oldTarget = this.target;
182
198
  this.target = el;
183
- this.init(el);
184
199
  if (!this.moveable || this.target !== oldTarget) {
200
+ this.init(el);
185
201
  this.moveableHelper = MoveableHelper.create({
186
202
  useBeforeRender: true,
187
203
  useRender: false,
@@ -242,6 +258,26 @@ class StageDragResize extends EventEmitter {
242
258
  target: this.dragEl
243
259
  });
244
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
+ }
245
281
  initMoveable() {
246
282
  this.moveable?.destroy();
247
283
  this.moveable = new Moveable(this.container, {
@@ -249,35 +285,38 @@ class StageDragResize extends EventEmitter {
249
285
  });
250
286
  this.bindResizeEvent();
251
287
  this.bindDragEvent();
288
+ this.bindRotateEvent();
289
+ this.bindScaleEvent();
252
290
  }
253
291
  bindResizeEvent() {
254
292
  if (!this.moveable)
255
293
  throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
294
+ const frame = {
295
+ left: 0,
296
+ top: 0
297
+ };
256
298
  this.moveable.on("resizeStart", (e) => {
257
- if (e.dragStart) {
258
- const rect = this.moveable.getRect();
259
- const offset = getAbsolutePosition(e.target, rect);
260
- e.dragStart.set([offset.left, offset.top]);
261
- }
262
- }).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;
263
307
  if (!this.moveable || !this.target || !this.dragEl)
264
308
  return;
265
309
  const { beforeTranslate } = drag;
266
310
  this.dragStatus = "ing" /* ING */;
267
- this.target.style.width = `${width}px`;
268
- this.target.style.height = `${height}px`;
269
- this.dragEl.style.width = `${width}px`;
270
- this.dragEl.style.height = `${height}px`;
311
+ this.moveableHelper?.onResize(e);
271
312
  if (this.mode === Mode.SORTABLE) {
272
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
273
- this.target.style.top = `0px`;
274
- 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`;
275
317
  }
276
- this.dragEl.style.left = `${beforeTranslate[0]}px`;
277
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
278
- const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
279
- this.target.style.left = `${offset.left}px`;
280
- this.target.style.top = `${offset.top}px`;
318
+ this.target.style.width = `${width}px`;
319
+ this.target.style.height = `${height}px`;
281
320
  }).on("resizeEnd", () => {
282
321
  this.dragStatus = "end" /* END */;
283
322
  this.update(true);
@@ -286,7 +325,10 @@ class StageDragResize extends EventEmitter {
286
325
  bindDragEvent() {
287
326
  if (!this.moveable)
288
327
  throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
289
- let offset = null;
328
+ const frame = {
329
+ left: 0,
330
+ top: 0
331
+ };
290
332
  this.moveable.on("dragStart", (e) => {
291
333
  if (!this.target)
292
334
  throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
@@ -295,22 +337,19 @@ class StageDragResize extends EventEmitter {
295
337
  if (this.mode === Mode.SORTABLE) {
296
338
  this.ghostEl = this.generateGhostEl(this.target);
297
339
  }
340
+ frame.top = this.target.offsetTop;
341
+ frame.left = this.target.offsetLeft;
298
342
  }).on("drag", (e) => {
299
343
  if (!this.target || !this.dragEl)
300
344
  return;
301
- if (!offset) {
302
- offset = getAbsolutePosition(this.target, { left: 0, top: 0 });
303
- }
304
345
  this.dragStatus = "ing" /* ING */;
305
- const { left, top } = e;
306
346
  if (this.ghostEl) {
307
- this.dragEl.style.top = `${top}px`;
308
- this.ghostEl.style.top = `${top + offset.top}px`;
347
+ this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
309
348
  return;
310
349
  }
311
350
  this.moveableHelper?.onDrag(e);
312
- this.target.style.left = `${left + offset.left}px`;
313
- 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`;
314
353
  }).on("dragEnd", () => {
315
354
  if (this.dragStatus === "ing" /* ING */) {
316
355
  switch (this.mode) {
@@ -321,18 +360,57 @@ class StageDragResize extends EventEmitter {
321
360
  this.update();
322
361
  }
323
362
  }
324
- offset = null;
325
363
  this.dragStatus = "end" /* END */;
326
364
  this.destroyGhostEl();
327
365
  });
328
366
  }
329
- getSnapElements(runtime, el) {
330
- const { renderer, mask } = this.core;
331
- const getSnapElements = runtime?.getSnapElements || (() => {
332
- const doc = renderer.contentWindow?.document;
333
- 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
+ });
334
413
  });
335
- return getSnapElements(el).filter((element) => element !== this.target && !this.target?.contains(element) && element !== mask.page);
336
414
  }
337
415
  sort() {
338
416
  if (!this.target || !this.ghostEl)
@@ -354,12 +432,13 @@ class StageDragResize extends EventEmitter {
354
432
  }
355
433
  }
356
434
  update(isResize = false) {
357
- const rect = this.moveable.getRect();
358
- 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 };
359
438
  const left = this.calcValueByFontsize(offset.left);
360
439
  const top = this.calcValueByFontsize(offset.top);
361
- const width = this.calcValueByFontsize(rect.width);
362
- const height = this.calcValueByFontsize(rect.height);
440
+ const width = this.calcValueByFontsize(this.target.clientWidth);
441
+ const height = this.calcValueByFontsize(this.target.clientHeight);
363
442
  this.emit("update", {
364
443
  el: this.target,
365
444
  style: isResize ? { left, top, width, height } : { left, top }
@@ -372,7 +451,7 @@ class StageDragResize extends EventEmitter {
372
451
  const ghostEl = el.cloneNode(true);
373
452
  const { top, left } = getAbsolutePosition(el, getOffset(el));
374
453
  ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
375
- ghostEl.style.zIndex = "5";
454
+ ghostEl.style.zIndex = ZIndex.GHOST_EL;
376
455
  ghostEl.style.opacity = ".5";
377
456
  ghostEl.style.position = "absolute";
378
457
  ghostEl.style.left = `${left}px`;
@@ -385,17 +464,21 @@ class StageDragResize extends EventEmitter {
385
464
  this.ghostEl = void 0;
386
465
  }
387
466
  updateDragEl(el) {
388
- const { width, height } = el.getBoundingClientRect();
389
467
  const offset = getOffset(el);
468
+ const { transform } = getComputedStyle(el);
390
469
  this.dragEl.style.cssText = `
391
470
  position: absolute;
471
+ transform: ${transform};
392
472
  left: ${offset.left}px;
393
473
  top: ${offset.top}px;
394
- width: ${width}px;
395
- height: ${height}px;
396
- z-index: 9;
474
+ width: ${el.clientWidth}px;
475
+ height: ${el.clientHeight}px;
476
+ z-index: ${ZIndex.DRAG_EL};
397
477
  `;
398
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
+ }
399
482
  }
400
483
  destroyDragEl() {
401
484
  this.dragEl?.remove();
@@ -409,6 +492,11 @@ class StageDragResize extends EventEmitter {
409
492
  if (typeof moveableOptions === "function") {
410
493
  moveableOptions = moveableOptions(this.core);
411
494
  }
495
+ const elementGuidelines = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
496
+ this.setElementGuidelines(elementGuidelines);
497
+ if (moveableOptions.elementGuidelines) {
498
+ delete moveableOptions.elementGuidelines;
499
+ }
412
500
  return {
413
501
  origin: false,
414
502
  rootContainer: this.core.container,
@@ -416,6 +504,8 @@ class StageDragResize extends EventEmitter {
416
504
  dragArea: false,
417
505
  draggable: true,
418
506
  resizable: true,
507
+ scalable: false,
508
+ rotatable: false,
419
509
  snappable: isAbsolute || isFixed,
420
510
  snapGap: isAbsolute || isFixed,
421
511
  snapThreshold: 5,
@@ -514,49 +604,34 @@ class TargetCalibrate extends EventEmitter {
514
604
  this.parent = config.parent;
515
605
  this.mask = config.mask;
516
606
  this.dr = config.dr;
607
+ this.core = config.core;
517
608
  this.operationEl = globalThis.document.createElement("div");
518
609
  this.parent.append(this.operationEl);
519
610
  }
520
611
  update(el, prefix) {
521
- const { width, height } = el.getBoundingClientRect();
522
612
  const { left, top } = this.getOffset(el);
613
+ const { transform } = getComputedStyle(el);
523
614
  this.operationEl.style.cssText = `
524
615
  position: absolute;
616
+ transform: ${transform};
525
617
  left: ${left}px;
526
618
  top: ${top}px;
527
- width: ${width}px;
528
- height: ${height}px;
619
+ width: ${el.clientWidth}px;
620
+ height: ${el.clientHeight}px;
529
621
  `;
530
622
  this.operationEl.id = `${prefix}${el.id}`;
623
+ if (typeof this.core.config.updateDragEl === "function") {
624
+ this.core.config.updateDragEl(this.operationEl, el);
625
+ }
531
626
  return this.operationEl;
532
627
  }
533
628
  destroy() {
534
629
  this.operationEl?.remove();
535
630
  }
536
631
  getOffset(el) {
537
- const { transform } = getComputedStyle(el);
538
632
  const { offsetParent } = el;
539
- let left = el.offsetLeft;
540
- let top = el.offsetTop;
541
- if (transform.indexOf("matrix") > -1) {
542
- let a = 1;
543
- let b = 1;
544
- let c = 1;
545
- let d = 1;
546
- let e = 0;
547
- let f = 0;
548
- transform.replace(/matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/, ($0, $1, $2, $3, $4, $5, $6) => {
549
- a = +$1;
550
- b = +$2;
551
- c = +$3;
552
- d = +$4;
553
- e = +$5;
554
- f = +$6;
555
- return transform;
556
- });
557
- left = a * left + c * top + e;
558
- top = b * left + d * top + f;
559
- }
633
+ const left = el.offsetLeft;
634
+ const top = el.offsetTop;
560
635
  if (offsetParent) {
561
636
  const parentOffset = this.getOffset(offsetParent);
562
637
  return {
@@ -597,7 +672,8 @@ class StageHighlight extends EventEmitter {
597
672
  this.calibrationTarget = new TargetCalibrate({
598
673
  parent: this.core.mask.content,
599
674
  mask: this.core.mask,
600
- dr: this.core.dr
675
+ dr: this.core.dr,
676
+ core: this.core
601
677
  });
602
678
  }
603
679
  highlight(el) {
@@ -628,8 +704,8 @@ class StageHighlight extends EventEmitter {
628
704
  class Rule extends EventEmitter$1 {
629
705
  constructor(container) {
630
706
  super();
631
- this.horizontalGuidelines = [];
632
- this.verticalGuidelines = [];
707
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
708
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
633
709
  this.getGuidesStyle = (type) => ({
634
710
  position: "fixed",
635
711
  zIndex: 1,
@@ -653,6 +729,7 @@ class Rule extends EventEmitter$1 {
653
729
  type: GuidesType.HORIZONTAL,
654
730
  guides: this.horizontalGuidelines
655
731
  });
732
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
656
733
  };
657
734
  this.vGuidesChangeGuidesHandler = (e) => {
658
735
  this.verticalGuidelines = e.guides;
@@ -660,10 +737,11 @@ class Rule extends EventEmitter$1 {
660
737
  type: GuidesType.VERTICAL,
661
738
  guides: this.verticalGuidelines
662
739
  });
740
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
663
741
  };
664
742
  this.container = container;
665
- this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
666
- this.vGuides = this.createGuides(GuidesType.VERTICAL);
743
+ this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
744
+ this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
667
745
  this.hGuides.on("changeGuides", this.hGuidesChangeGuidesHandler);
668
746
  this.vGuides.on("changeGuides", this.vGuidesChangeGuidesHandler);
669
747
  this.containerResizeObserver = new ResizeObserver(() => {
@@ -697,6 +775,8 @@ class Rule extends EventEmitter$1 {
697
775
  type: GuidesType.HORIZONTAL,
698
776
  guides: []
699
777
  });
778
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, "[]");
779
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, "[]");
700
780
  }
701
781
  showRule(show = true) {
702
782
  if (show) {
@@ -780,6 +860,7 @@ class StageMask extends Rule {
780
860
  this.wrapperWidth = 0;
781
861
  this.maxScrollTop = 0;
782
862
  this.maxScrollLeft = 0;
863
+ this.intersectionObserver = null;
783
864
  this.mode = Mode.ABSOLUTE;
784
865
  this.pageResizeObserver = null;
785
866
  this.wrapperResizeObserver = null;
@@ -819,7 +900,6 @@ class StageMask extends Rule {
819
900
  if (this.maxScrollLeft > 0) {
820
901
  this.scrollLeft = this.scrollLeft + deltaX;
821
902
  }
822
- this.fixScrollValue();
823
903
  this.scroll();
824
904
  this.emit("scroll", event);
825
905
  };
@@ -851,15 +931,33 @@ class StageMask extends Rule {
851
931
  this.page = page;
852
932
  this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
853
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
+ }
854
951
  if (typeof ResizeObserver !== "undefined") {
855
952
  this.pageResizeObserver = new ResizeObserver((entries) => {
856
953
  const [entry] = entries;
857
954
  const { clientHeight, clientWidth } = entry.target;
858
955
  this.setHeight(clientHeight);
859
956
  this.setWidth(clientWidth);
860
- this.fixScrollValue();
861
957
  this.scroll();
862
- this.core.dr.updateMoveable();
958
+ if (this.core.dr.moveable) {
959
+ this.core.dr.updateMoveable();
960
+ }
863
961
  });
864
962
  this.pageResizeObserver.observe(page);
865
963
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
@@ -881,6 +979,14 @@ class StageMask extends Rule {
881
979
  setLayout(el) {
882
980
  this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
883
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
+ }
884
990
  destroy() {
885
991
  this.content?.remove();
886
992
  this.page = null;
@@ -891,6 +997,7 @@ class StageMask extends Rule {
891
997
  super.destroy();
892
998
  }
893
999
  scroll() {
1000
+ this.fixScrollValue();
894
1001
  let { scrollLeft, scrollTop } = this;
895
1002
  if (this.pageScrollParent) {
896
1003
  this.pageScrollParent.scrollTo({
@@ -919,10 +1026,10 @@ class StageMask extends Rule {
919
1026
  this.content.style.width = `${width}px`;
920
1027
  }
921
1028
  setMaxScrollLeft() {
922
- this.maxScrollLeft = this.width - this.wrapperWidth;
1029
+ this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
923
1030
  }
924
1031
  setMaxScrollTop() {
925
- this.maxScrollTop = this.height - this.wrapperHeight;
1032
+ this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
926
1033
  }
927
1034
  fixScrollValue() {
928
1035
  if (this.scrollTop < 0)
@@ -968,16 +1075,6 @@ class StageRender extends EventEmitter {
968
1075
  this.iframe?.contentDocument?.body?.appendChild(el);
969
1076
  }
970
1077
  }
971
- if (this.contentWindow) {
972
- const style = this.contentWindow.document.createElement("style");
973
- style.id = "tmagic-stage-render";
974
- style.innerHTML = `
975
- .${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
976
- z-index: ${ZIndex.SELECTED_EL};
977
- }
978
- `;
979
- this.contentWindow.document.head.appendChild(style);
980
- }
981
1078
  };
982
1079
  this.core = core;
983
1080
  this.runtimeUrl = core.config.runtimeUrl || "";
@@ -1096,11 +1193,14 @@ class StageCore extends EventEmitter {
1096
1193
  }
1097
1194
  this.mask.setLayout(el);
1098
1195
  this.dr.select(el, event);
1196
+ if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1197
+ this.mask.intersectionObserver?.observe(el);
1198
+ }
1099
1199
  this.selectedDom = el;
1100
1200
  if (this.renderer.contentWindow) {
1101
1201
  removeSelectedClassName(this.renderer.contentWindow.document);
1102
1202
  if (this.selectedDom) {
1103
- addSelectedClassName(this.selectedDom);
1203
+ addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
1104
1204
  }
1105
1205
  }
1106
1206
  }