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

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.
@@ -23,6 +23,8 @@
23
23
  var ZIndex = /* @__PURE__ */ ((ZIndex2) => {
24
24
  ZIndex2["MASK"] = "99999";
25
25
  ZIndex2["SELECTED_EL"] = "666";
26
+ ZIndex2["GHOST_EL"] = "700";
27
+ ZIndex2["DRAG_EL"] = "9";
26
28
  return ZIndex2;
27
29
  })(ZIndex || {});
28
30
  var MouseButton = /* @__PURE__ */ ((MouseButton2) => {
@@ -38,31 +40,22 @@
38
40
  return Mode2;
39
41
  })(Mode || {});
40
42
  const SELECTED_CLASS = "tmagic-stage-selected-area";
43
+ const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
44
+ const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
41
45
 
46
+ const getParents = (el, relative) => {
47
+ let cur = el.parentElement;
48
+ const parents = [];
49
+ while (cur && cur !== relative) {
50
+ parents.push(cur);
51
+ cur = cur.parentElement;
52
+ }
53
+ return parents;
54
+ };
42
55
  const getOffset = (el) => {
43
- const { transform } = getComputedStyle(el);
44
56
  const { offsetParent } = el;
45
- let left = el.offsetLeft;
46
- let top = el.offsetTop;
47
- if (transform.indexOf("matrix") > -1) {
48
- let a = 1;
49
- let b = 1;
50
- let c = 1;
51
- let d = 1;
52
- let e = 0;
53
- let f = 0;
54
- transform.replace(/matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/, ($0, $1, $2, $3, $4, $5, $6) => {
55
- a = +$1;
56
- b = +$2;
57
- c = +$3;
58
- d = +$4;
59
- e = +$5;
60
- f = +$6;
61
- return transform;
62
- });
63
- left = a * left + c * top + e;
64
- top = b * left + d * top + f;
65
- }
57
+ const left = el.offsetLeft;
58
+ const top = el.offsetTop;
66
59
  if (offsetParent) {
67
60
  const parentOffset = getOffset(offsetParent);
68
61
  return {
@@ -93,11 +86,6 @@
93
86
  return true;
94
87
  return getHost(targetUrl) === source;
95
88
  };
96
- const isAbsolute = (el) => {
97
- if (!el)
98
- return false;
99
- return getComputedStyle(el).position === "absolute";
100
- };
101
89
  const isRelative = (el) => {
102
90
  if (!el)
103
91
  return false;
@@ -138,15 +126,15 @@
138
126
  };
139
127
  const getScrollParent = (element, includeHidden = false) => {
140
128
  let style = getComputedStyle(element);
129
+ const excludeStaticParent = style.position === "absolute";
141
130
  const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
142
- if (isFixed(element))
131
+ if (style.position === "fixed")
143
132
  return null;
144
133
  for (let parent = element; parent.parentElement; ) {
145
134
  parent = parent.parentElement;
146
135
  style = getComputedStyle(parent);
147
- if (isAbsolute(element) && isStatic(element)) {
136
+ if (excludeStaticParent && style.position === "static")
148
137
  continue;
149
- }
150
138
  if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX))
151
139
  return parent;
152
140
  }
@@ -163,18 +151,41 @@
163
151
  if (oldEl) {
164
152
  oldEl.classList.remove(SELECTED_CLASS);
165
153
  oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
154
+ doc.querySelectorAll(`.${SELECTED_CLASS}-parents`).forEach((item) => {
155
+ item.classList.remove(`${SELECTED_CLASS}-parents`);
156
+ });
166
157
  }
167
158
  };
168
- const addSelectedClassName = (el) => {
159
+ const addSelectedClassName = (el, doc) => {
169
160
  el.classList.add(SELECTED_CLASS);
170
161
  el.parentNode?.classList.add(`${SELECTED_CLASS}-parent`);
162
+ getParents(el, doc.body).forEach((item) => {
163
+ item.classList.add(`${SELECTED_CLASS}-parents`);
164
+ });
165
+ };
166
+ const getGuideLineFromCache = (type) => {
167
+ const key = {
168
+ [GuidesType.HORIZONTAL]: H_GUIDE_LINE_STORAGE_KEY,
169
+ [GuidesType.VERTICAL]: V_GUIDE_LINE_STORAGE_KEY
170
+ }[type];
171
+ if (!key)
172
+ return [];
173
+ const guideLineCacheData = globalThis.localStorage.getItem(key);
174
+ if (guideLineCacheData) {
175
+ try {
176
+ return JSON.parse(guideLineCacheData) || [];
177
+ } catch (e) {
178
+ console.error(e);
179
+ }
180
+ }
181
+ return [];
171
182
  };
172
183
 
173
184
  class StageDragResize extends EventEmitter.EventEmitter {
174
185
  constructor(config) {
175
186
  super();
176
- this.horizontalGuidelines = [];
177
- this.verticalGuidelines = [];
187
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
188
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
178
189
  this.elementGuidelines = [];
179
190
  this.mode = Mode.ABSOLUTE;
180
191
  this.moveableOptions = {};
@@ -187,8 +198,8 @@
187
198
  select(el, event) {
188
199
  const oldTarget = this.target;
189
200
  this.target = el;
190
- this.init(el);
191
201
  if (!this.moveable || this.target !== oldTarget) {
202
+ this.init(el);
192
203
  this.moveableHelper = MoveableHelper__default["default"].create({
193
204
  useBeforeRender: true,
194
205
  useRender: false,
@@ -206,7 +217,7 @@
206
217
  if (!this.moveable)
207
218
  throw new Error("\u672A\u521D\u59CB\u5316moveable");
208
219
  if (!el)
209
- throw new Error("\u4E3A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
220
+ throw new Error("\u672A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
210
221
  this.target = el;
211
222
  this.init(el);
212
223
  Object.entries(this.moveableOptions).forEach(([key, value]) => {
@@ -249,6 +260,26 @@
249
260
  target: this.dragEl
250
261
  });
251
262
  }
263
+ setElementGuidelines(nodes) {
264
+ this.elementGuidelines.forEach((node) => {
265
+ node.remove();
266
+ });
267
+ this.elementGuidelines = [];
268
+ if (this.mode === Mode.ABSOLUTE) {
269
+ const frame = document.createDocumentFragment();
270
+ for (const node of nodes) {
271
+ const { width, height } = node.getBoundingClientRect();
272
+ if (node === this.target)
273
+ continue;
274
+ const { left, top } = getOffset(node);
275
+ const elementGuideline = document.createElement("div");
276
+ elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
277
+ this.elementGuidelines.push(elementGuideline);
278
+ frame.append(elementGuideline);
279
+ }
280
+ this.container.append(frame);
281
+ }
282
+ }
252
283
  initMoveable() {
253
284
  this.moveable?.destroy();
254
285
  this.moveable = new Moveable__default["default"](this.container, {
@@ -256,35 +287,38 @@
256
287
  });
257
288
  this.bindResizeEvent();
258
289
  this.bindDragEvent();
290
+ this.bindRotateEvent();
291
+ this.bindScaleEvent();
259
292
  }
260
293
  bindResizeEvent() {
261
294
  if (!this.moveable)
262
- throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
295
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
296
+ const frame = {
297
+ left: 0,
298
+ top: 0
299
+ };
263
300
  this.moveable.on("resizeStart", (e) => {
264
- if (e.dragStart) {
265
- const rect = this.moveable.getRect();
266
- const offset = getAbsolutePosition(e.target, rect);
267
- e.dragStart.set([offset.left, offset.top]);
268
- }
269
- }).on("resize", ({ width, height, drag }) => {
301
+ if (!this.target)
302
+ return;
303
+ this.dragStatus = "start" /* START */;
304
+ this.moveableHelper?.onResizeStart(e);
305
+ frame.top = this.target.offsetTop;
306
+ frame.left = this.target.offsetLeft;
307
+ }).on("resize", (e) => {
308
+ const { width, height, drag } = e;
270
309
  if (!this.moveable || !this.target || !this.dragEl)
271
310
  return;
272
311
  const { beforeTranslate } = drag;
273
312
  this.dragStatus = "ing" /* ING */;
274
- this.target.style.width = `${width}px`;
275
- this.target.style.height = `${height}px`;
276
- this.dragEl.style.width = `${width}px`;
277
- this.dragEl.style.height = `${height}px`;
313
+ this.moveableHelper?.onResize(e);
278
314
  if (this.mode === Mode.SORTABLE) {
279
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
280
- this.target.style.top = `0px`;
281
- return;
315
+ this.target.style.top = "0px";
316
+ } else {
317
+ this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
318
+ this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
282
319
  }
283
- this.dragEl.style.left = `${beforeTranslate[0]}px`;
284
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
285
- const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
286
- this.target.style.left = `${offset.left}px`;
287
- this.target.style.top = `${offset.top}px`;
320
+ this.target.style.width = `${width}px`;
321
+ this.target.style.height = `${height}px`;
288
322
  }).on("resizeEnd", () => {
289
323
  this.dragStatus = "end" /* END */;
290
324
  this.update(true);
@@ -292,8 +326,11 @@
292
326
  }
293
327
  bindDragEvent() {
294
328
  if (!this.moveable)
295
- throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
296
- let offset = null;
329
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
330
+ const frame = {
331
+ left: 0,
332
+ top: 0
333
+ };
297
334
  this.moveable.on("dragStart", (e) => {
298
335
  if (!this.target)
299
336
  throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
@@ -302,22 +339,19 @@
302
339
  if (this.mode === Mode.SORTABLE) {
303
340
  this.ghostEl = this.generateGhostEl(this.target);
304
341
  }
342
+ frame.top = this.target.offsetTop;
343
+ frame.left = this.target.offsetLeft;
305
344
  }).on("drag", (e) => {
306
345
  if (!this.target || !this.dragEl)
307
346
  return;
308
- if (!offset) {
309
- offset = getAbsolutePosition(this.target, { left: 0, top: 0 });
310
- }
311
347
  this.dragStatus = "ing" /* ING */;
312
- const { left, top } = e;
313
348
  if (this.ghostEl) {
314
- this.dragEl.style.top = `${top}px`;
315
- this.ghostEl.style.top = `${top + offset.top}px`;
349
+ this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
316
350
  return;
317
351
  }
318
352
  this.moveableHelper?.onDrag(e);
319
- this.target.style.left = `${left + offset.left}px`;
320
- this.target.style.top = `${top + offset.top}px`;
353
+ this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
354
+ this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
321
355
  }).on("dragEnd", () => {
322
356
  if (this.dragStatus === "ing" /* ING */) {
323
357
  switch (this.mode) {
@@ -328,18 +362,57 @@
328
362
  this.update();
329
363
  }
330
364
  }
331
- offset = null;
332
365
  this.dragStatus = "end" /* END */;
333
366
  this.destroyGhostEl();
334
367
  });
335
368
  }
336
- getSnapElements(runtime, el) {
337
- const { renderer, mask } = this.core;
338
- const getSnapElements = runtime?.getSnapElements || (() => {
339
- const doc = renderer.contentWindow?.document;
340
- return doc ? Array.from(doc.querySelectorAll("[id]")) : [];
369
+ bindRotateEvent() {
370
+ if (!this.moveable)
371
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
372
+ this.moveable.on("rotateStart", (e) => {
373
+ this.dragStatus = "start" /* START */;
374
+ this.moveableHelper?.onRotateStart(e);
375
+ }).on("rotate", (e) => {
376
+ if (!this.target || !this.dragEl)
377
+ return;
378
+ this.dragStatus = "ing" /* ING */;
379
+ this.moveableHelper?.onRotate(e);
380
+ const frame = this.moveableHelper?.getFrame(e.target);
381
+ this.target.style.transform = frame?.toCSSObject().transform || "";
382
+ }).on("rotateEnd", (e) => {
383
+ this.dragStatus = "end" /* END */;
384
+ const frame = this.moveableHelper?.getFrame(e.target);
385
+ this.emit("update", {
386
+ el: this.target,
387
+ style: {
388
+ transform: frame?.get("transform")
389
+ }
390
+ });
391
+ });
392
+ }
393
+ bindScaleEvent() {
394
+ if (!this.moveable)
395
+ throw new Error("moveable \u672A\u521D\u59CB\u5316");
396
+ this.moveable.on("scaleStart", (e) => {
397
+ this.dragStatus = "start" /* START */;
398
+ this.moveableHelper?.onScaleStart(e);
399
+ }).on("scale", (e) => {
400
+ if (!this.target || !this.dragEl)
401
+ return;
402
+ this.dragStatus = "ing" /* ING */;
403
+ this.moveableHelper?.onScale(e);
404
+ const frame = this.moveableHelper?.getFrame(e.target);
405
+ this.target.style.transform = frame?.toCSSObject().transform || "";
406
+ }).on("scaleEnd", (e) => {
407
+ this.dragStatus = "end" /* END */;
408
+ const frame = this.moveableHelper?.getFrame(e.target);
409
+ this.emit("update", {
410
+ el: this.target,
411
+ style: {
412
+ transform: frame?.get("transform")
413
+ }
414
+ });
341
415
  });
342
- return getSnapElements(el).filter((element) => element !== this.target && !this.target?.contains(element) && element !== mask.page);
343
416
  }
344
417
  sort() {
345
418
  if (!this.target || !this.ghostEl)
@@ -361,12 +434,13 @@
361
434
  }
362
435
  }
363
436
  update(isResize = false) {
364
- const rect = this.moveable.getRect();
365
- const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : getAbsolutePosition(this.target, rect);
437
+ if (!this.target)
438
+ return;
439
+ const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
366
440
  const left = this.calcValueByFontsize(offset.left);
367
441
  const top = this.calcValueByFontsize(offset.top);
368
- const width = this.calcValueByFontsize(rect.width);
369
- const height = this.calcValueByFontsize(rect.height);
442
+ const width = this.calcValueByFontsize(this.target.clientWidth);
443
+ const height = this.calcValueByFontsize(this.target.clientHeight);
370
444
  this.emit("update", {
371
445
  el: this.target,
372
446
  style: isResize ? { left, top, width, height } : { left, top }
@@ -379,7 +453,7 @@
379
453
  const ghostEl = el.cloneNode(true);
380
454
  const { top, left } = getAbsolutePosition(el, getOffset(el));
381
455
  ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
382
- ghostEl.style.zIndex = "5";
456
+ ghostEl.style.zIndex = ZIndex.GHOST_EL;
383
457
  ghostEl.style.opacity = ".5";
384
458
  ghostEl.style.position = "absolute";
385
459
  ghostEl.style.left = `${left}px`;
@@ -392,17 +466,21 @@
392
466
  this.ghostEl = void 0;
393
467
  }
394
468
  updateDragEl(el) {
395
- const { width, height } = el.getBoundingClientRect();
396
469
  const offset = getOffset(el);
470
+ const { transform } = getComputedStyle(el);
397
471
  this.dragEl.style.cssText = `
398
472
  position: absolute;
473
+ transform: ${transform};
399
474
  left: ${offset.left}px;
400
475
  top: ${offset.top}px;
401
- width: ${width}px;
402
- height: ${height}px;
403
- z-index: 9;
476
+ width: ${el.clientWidth}px;
477
+ height: ${el.clientHeight}px;
478
+ z-index: ${ZIndex.DRAG_EL};
404
479
  `;
405
480
  this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
481
+ if (typeof this.core.config.updateDragEl === "function") {
482
+ this.core.config.updateDragEl(this.dragEl, el);
483
+ }
406
484
  }
407
485
  destroyDragEl() {
408
486
  this.dragEl?.remove();
@@ -416,6 +494,11 @@
416
494
  if (typeof moveableOptions === "function") {
417
495
  moveableOptions = moveableOptions(this.core);
418
496
  }
497
+ const elementGuidelines = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
498
+ this.setElementGuidelines(elementGuidelines);
499
+ if (moveableOptions.elementGuidelines) {
500
+ delete moveableOptions.elementGuidelines;
501
+ }
419
502
  return {
420
503
  origin: false,
421
504
  rootContainer: this.core.container,
@@ -423,6 +506,8 @@
423
506
  dragArea: false,
424
507
  draggable: true,
425
508
  resizable: true,
509
+ scalable: false,
510
+ rotatable: false,
426
511
  snappable: isAbsolute || isFixed,
427
512
  snapGap: isAbsolute || isFixed,
428
513
  snapThreshold: 5,
@@ -521,49 +606,34 @@
521
606
  this.parent = config.parent;
522
607
  this.mask = config.mask;
523
608
  this.dr = config.dr;
609
+ this.core = config.core;
524
610
  this.operationEl = globalThis.document.createElement("div");
525
611
  this.parent.append(this.operationEl);
526
612
  }
527
613
  update(el, prefix) {
528
- const { width, height } = el.getBoundingClientRect();
529
614
  const { left, top } = this.getOffset(el);
615
+ const { transform } = getComputedStyle(el);
530
616
  this.operationEl.style.cssText = `
531
617
  position: absolute;
618
+ transform: ${transform};
532
619
  left: ${left}px;
533
620
  top: ${top}px;
534
- width: ${width}px;
535
- height: ${height}px;
621
+ width: ${el.clientWidth}px;
622
+ height: ${el.clientHeight}px;
536
623
  `;
537
624
  this.operationEl.id = `${prefix}${el.id}`;
625
+ if (typeof this.core.config.updateDragEl === "function") {
626
+ this.core.config.updateDragEl(this.operationEl, el);
627
+ }
538
628
  return this.operationEl;
539
629
  }
540
630
  destroy() {
541
631
  this.operationEl?.remove();
542
632
  }
543
633
  getOffset(el) {
544
- const { transform } = getComputedStyle(el);
545
634
  const { offsetParent } = el;
546
- let left = el.offsetLeft;
547
- let top = el.offsetTop;
548
- if (transform.indexOf("matrix") > -1) {
549
- let a = 1;
550
- let b = 1;
551
- let c = 1;
552
- let d = 1;
553
- let e = 0;
554
- let f = 0;
555
- transform.replace(/matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/, ($0, $1, $2, $3, $4, $5, $6) => {
556
- a = +$1;
557
- b = +$2;
558
- c = +$3;
559
- d = +$4;
560
- e = +$5;
561
- f = +$6;
562
- return transform;
563
- });
564
- left = a * left + c * top + e;
565
- top = b * left + d * top + f;
566
- }
635
+ const left = el.offsetLeft;
636
+ const top = el.offsetTop;
567
637
  if (offsetParent) {
568
638
  const parentOffset = this.getOffset(offsetParent);
569
639
  return {
@@ -604,7 +674,8 @@
604
674
  this.calibrationTarget = new TargetCalibrate({
605
675
  parent: this.core.mask.content,
606
676
  mask: this.core.mask,
607
- dr: this.core.dr
677
+ dr: this.core.dr,
678
+ core: this.core
608
679
  });
609
680
  }
610
681
  highlight(el) {
@@ -635,8 +706,8 @@
635
706
  class Rule extends EventEmitter__default["default"] {
636
707
  constructor(container) {
637
708
  super();
638
- this.horizontalGuidelines = [];
639
- this.verticalGuidelines = [];
709
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
710
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
640
711
  this.getGuidesStyle = (type) => ({
641
712
  position: "fixed",
642
713
  zIndex: 1,
@@ -660,6 +731,7 @@
660
731
  type: GuidesType.HORIZONTAL,
661
732
  guides: this.horizontalGuidelines
662
733
  });
734
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
663
735
  };
664
736
  this.vGuidesChangeGuidesHandler = (e) => {
665
737
  this.verticalGuidelines = e.guides;
@@ -667,10 +739,11 @@
667
739
  type: GuidesType.VERTICAL,
668
740
  guides: this.verticalGuidelines
669
741
  });
742
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
670
743
  };
671
744
  this.container = container;
672
- this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
673
- this.vGuides = this.createGuides(GuidesType.VERTICAL);
745
+ this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
746
+ this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
674
747
  this.hGuides.on("changeGuides", this.hGuidesChangeGuidesHandler);
675
748
  this.vGuides.on("changeGuides", this.vGuidesChangeGuidesHandler);
676
749
  this.containerResizeObserver = new ResizeObserver(() => {
@@ -704,6 +777,8 @@
704
777
  type: GuidesType.HORIZONTAL,
705
778
  guides: []
706
779
  });
780
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, "[]");
781
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, "[]");
707
782
  }
708
783
  showRule(show = true) {
709
784
  if (show) {
@@ -787,6 +862,7 @@
787
862
  this.wrapperWidth = 0;
788
863
  this.maxScrollTop = 0;
789
864
  this.maxScrollLeft = 0;
865
+ this.intersectionObserver = null;
790
866
  this.mode = Mode.ABSOLUTE;
791
867
  this.pageResizeObserver = null;
792
868
  this.wrapperResizeObserver = null;
@@ -826,7 +902,6 @@
826
902
  if (this.maxScrollLeft > 0) {
827
903
  this.scrollLeft = this.scrollLeft + deltaX;
828
904
  }
829
- this.fixScrollValue();
830
905
  this.scroll();
831
906
  this.emit("scroll", event);
832
907
  };
@@ -858,15 +933,33 @@
858
933
  this.page = page;
859
934
  this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
860
935
  this.pageResizeObserver?.disconnect();
936
+ this.wrapperResizeObserver?.disconnect();
937
+ this.intersectionObserver?.disconnect();
938
+ if (typeof IntersectionObserver !== "undefined") {
939
+ this.intersectionObserver = new IntersectionObserver((entries) => {
940
+ entries.forEach((entry) => {
941
+ const { target, intersectionRatio } = entry;
942
+ if (intersectionRatio <= 0) {
943
+ this.scrollIntoView(target);
944
+ }
945
+ this.intersectionObserver?.unobserve(target);
946
+ });
947
+ }, {
948
+ root: this.pageScrollParent,
949
+ rootMargin: "0px",
950
+ threshold: 1
951
+ });
952
+ }
861
953
  if (typeof ResizeObserver !== "undefined") {
862
954
  this.pageResizeObserver = new ResizeObserver((entries) => {
863
955
  const [entry] = entries;
864
956
  const { clientHeight, clientWidth } = entry.target;
865
957
  this.setHeight(clientHeight);
866
958
  this.setWidth(clientWidth);
867
- this.fixScrollValue();
868
959
  this.scroll();
869
- this.core.dr.updateMoveable();
960
+ if (this.core.dr.moveable) {
961
+ this.core.dr.updateMoveable();
962
+ }
870
963
  });
871
964
  this.pageResizeObserver.observe(page);
872
965
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
@@ -888,6 +981,14 @@
888
981
  setLayout(el) {
889
982
  this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
890
983
  }
984
+ scrollIntoView(el) {
985
+ el.scrollIntoView();
986
+ if (!this.pageScrollParent)
987
+ return;
988
+ this.scrollLeft = this.pageScrollParent.scrollLeft;
989
+ this.scrollTop = this.pageScrollParent.scrollTop;
990
+ this.scroll();
991
+ }
891
992
  destroy() {
892
993
  this.content?.remove();
893
994
  this.page = null;
@@ -898,6 +999,7 @@
898
999
  super.destroy();
899
1000
  }
900
1001
  scroll() {
1002
+ this.fixScrollValue();
901
1003
  let { scrollLeft, scrollTop } = this;
902
1004
  if (this.pageScrollParent) {
903
1005
  this.pageScrollParent.scrollTo({
@@ -926,10 +1028,10 @@
926
1028
  this.content.style.width = `${width}px`;
927
1029
  }
928
1030
  setMaxScrollLeft() {
929
- this.maxScrollLeft = this.width - this.wrapperWidth;
1031
+ this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
930
1032
  }
931
1033
  setMaxScrollTop() {
932
- this.maxScrollTop = this.height - this.wrapperHeight;
1034
+ this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
933
1035
  }
934
1036
  fixScrollValue() {
935
1037
  if (this.scrollTop < 0)
@@ -968,23 +1070,18 @@
968
1070
  });
969
1071
  };
970
1072
  this.loadHandler = async () => {
971
- this.emit("onload");
1073
+ this.contentWindow = this.iframe?.contentWindow;
1074
+ this.contentWindow.magic = this.getMagicApi();
972
1075
  if (this.render) {
973
1076
  const el = await this.render(this.core);
974
1077
  if (el) {
975
1078
  this.iframe?.contentDocument?.body?.appendChild(el);
976
1079
  }
977
1080
  }
978
- if (this.contentWindow) {
979
- const style = this.contentWindow.document.createElement("style");
980
- style.id = "tmagic-stage-render";
981
- style.innerHTML = `
982
- .${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
983
- z-index: ${ZIndex.SELECTED_EL};
984
- }
985
- `;
986
- this.contentWindow.document.head.appendChild(style);
987
- }
1081
+ this.emit("onload");
1082
+ this.contentWindow.postMessage({
1083
+ tmagicRuntimeReady: true
1084
+ }, "*");
988
1085
  };
989
1086
  this.core = core;
990
1087
  this.runtimeUrl = core.config.runtimeUrl || "";
@@ -1008,8 +1105,6 @@
1008
1105
  this.iframe.srcdoc = html;
1009
1106
  }
1010
1107
  el.appendChild(this.iframe);
1011
- this.contentWindow = this.iframe?.contentWindow;
1012
- this.contentWindow.magic = this.getMagicApi();
1013
1108
  } else {
1014
1109
  throw Error("mount \u5931\u8D25");
1015
1110
  }
@@ -1103,11 +1198,14 @@
1103
1198
  }
1104
1199
  this.mask.setLayout(el);
1105
1200
  this.dr.select(el, event);
1201
+ if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1202
+ this.mask.intersectionObserver?.observe(el);
1203
+ }
1106
1204
  this.selectedDom = el;
1107
1205
  if (this.renderer.contentWindow) {
1108
1206
  removeSelectedClassName(this.renderer.contentWindow.document);
1109
1207
  if (this.selectedDom) {
1110
- addSelectedClassName(this.selectedDom);
1208
+ addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
1111
1209
  }
1112
1210
  }
1113
1211
  }
@@ -1150,10 +1248,10 @@
1150
1248
  setZoom(zoom = DEFAULT_ZOOM) {
1151
1249
  this.zoom = zoom;
1152
1250
  }
1153
- mount(el) {
1251
+ async mount(el) {
1154
1252
  this.container = el;
1155
1253
  const { mask, renderer } = this;
1156
- renderer.mount(el);
1254
+ await renderer.mount(el);
1157
1255
  mask.mount(el);
1158
1256
  this.emit("mounted");
1159
1257
  }