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

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.
@@ -31,7 +31,18 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
31
31
  return Mode2;
32
32
  })(Mode || {});
33
33
  const SELECTED_CLASS = "tmagic-stage-selected-area";
34
+ const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
35
+ const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
34
36
 
37
+ const getParents = (el, relative) => {
38
+ let cur = el.parentElement;
39
+ const parents = [];
40
+ while (cur && cur !== relative) {
41
+ parents.push(cur);
42
+ cur = cur.parentElement;
43
+ }
44
+ return parents;
45
+ };
35
46
  const getOffset = (el) => {
36
47
  const { transform } = getComputedStyle(el);
37
48
  const { offsetParent } = el;
@@ -156,18 +167,41 @@ const removeSelectedClassName = (doc) => {
156
167
  if (oldEl) {
157
168
  oldEl.classList.remove(SELECTED_CLASS);
158
169
  oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
170
+ doc.querySelectorAll(`.${SELECTED_CLASS}-parents`).forEach((item) => {
171
+ item.classList.remove(`${SELECTED_CLASS}-parents`);
172
+ });
159
173
  }
160
174
  };
161
- const addSelectedClassName = (el) => {
175
+ const addSelectedClassName = (el, doc) => {
162
176
  el.classList.add(SELECTED_CLASS);
163
177
  el.parentNode?.classList.add(`${SELECTED_CLASS}-parent`);
178
+ getParents(el, doc.body).forEach((item) => {
179
+ item.classList.add(`${SELECTED_CLASS}-parents`);
180
+ });
181
+ };
182
+ const getGuideLineFromCache = (type) => {
183
+ const key = {
184
+ [GuidesType.HORIZONTAL]: H_GUIDE_LINE_STORAGE_KEY,
185
+ [GuidesType.VERTICAL]: V_GUIDE_LINE_STORAGE_KEY
186
+ }[type];
187
+ if (!key)
188
+ return [];
189
+ const guideLineCacheData = globalThis.localStorage.getItem(key);
190
+ if (guideLineCacheData) {
191
+ try {
192
+ return JSON.parse(guideLineCacheData) || [];
193
+ } catch (e) {
194
+ console.error(e);
195
+ }
196
+ }
197
+ return [];
164
198
  };
165
199
 
166
200
  class StageDragResize extends EventEmitter {
167
201
  constructor(config) {
168
202
  super();
169
- this.horizontalGuidelines = [];
170
- this.verticalGuidelines = [];
203
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
204
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
171
205
  this.elementGuidelines = [];
172
206
  this.mode = Mode.ABSOLUTE;
173
207
  this.moveableOptions = {};
@@ -238,10 +272,32 @@ class StageDragResize extends EventEmitter {
238
272
  this.mode = getMode(el);
239
273
  this.destroyGhostEl();
240
274
  this.updateDragEl(el);
275
+ this.setElementGuidelines(el);
241
276
  this.moveableOptions = this.getOptions({
242
277
  target: this.dragEl
243
278
  });
244
279
  }
280
+ setElementGuidelines(el) {
281
+ const nodes = el.parentElement?.children || [];
282
+ this.elementGuidelines.forEach((node) => {
283
+ node.remove();
284
+ });
285
+ this.elementGuidelines = [];
286
+ if (this.mode === Mode.ABSOLUTE) {
287
+ const frame = document.createDocumentFragment();
288
+ for (const node of nodes) {
289
+ const { width, height } = node.getBoundingClientRect();
290
+ if (node === el)
291
+ continue;
292
+ const { left, top } = getOffset(node);
293
+ const elementGuideline = document.createElement("div");
294
+ elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
295
+ this.elementGuidelines.push(elementGuideline);
296
+ frame.append(elementGuideline);
297
+ }
298
+ this.container.append(frame);
299
+ }
300
+ }
245
301
  initMoveable() {
246
302
  this.moveable?.destroy();
247
303
  this.moveable = new Moveable(this.container, {
@@ -326,14 +382,6 @@ class StageDragResize extends EventEmitter {
326
382
  this.destroyGhostEl();
327
383
  });
328
384
  }
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]")) : [];
334
- });
335
- return getSnapElements(el).filter((element) => element !== this.target && !this.target?.contains(element) && element !== mask.page);
336
- }
337
385
  sort() {
338
386
  if (!this.target || !this.ghostEl)
339
387
  throw new Error("\u672A\u77E5\u9519\u8BEF");
@@ -628,8 +676,8 @@ class StageHighlight extends EventEmitter {
628
676
  class Rule extends EventEmitter$1 {
629
677
  constructor(container) {
630
678
  super();
631
- this.horizontalGuidelines = [];
632
- this.verticalGuidelines = [];
679
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
680
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
633
681
  this.getGuidesStyle = (type) => ({
634
682
  position: "fixed",
635
683
  zIndex: 1,
@@ -653,6 +701,7 @@ class Rule extends EventEmitter$1 {
653
701
  type: GuidesType.HORIZONTAL,
654
702
  guides: this.horizontalGuidelines
655
703
  });
704
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
656
705
  };
657
706
  this.vGuidesChangeGuidesHandler = (e) => {
658
707
  this.verticalGuidelines = e.guides;
@@ -660,10 +709,11 @@ class Rule extends EventEmitter$1 {
660
709
  type: GuidesType.VERTICAL,
661
710
  guides: this.verticalGuidelines
662
711
  });
712
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
663
713
  };
664
714
  this.container = container;
665
- this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
666
- this.vGuides = this.createGuides(GuidesType.VERTICAL);
715
+ this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
716
+ this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
667
717
  this.hGuides.on("changeGuides", this.hGuidesChangeGuidesHandler);
668
718
  this.vGuides.on("changeGuides", this.vGuidesChangeGuidesHandler);
669
719
  this.containerResizeObserver = new ResizeObserver(() => {
@@ -697,6 +747,8 @@ class Rule extends EventEmitter$1 {
697
747
  type: GuidesType.HORIZONTAL,
698
748
  guides: []
699
749
  });
750
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, "[]");
751
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, "[]");
700
752
  }
701
753
  showRule(show = true) {
702
754
  if (show) {
@@ -780,6 +832,7 @@ class StageMask extends Rule {
780
832
  this.wrapperWidth = 0;
781
833
  this.maxScrollTop = 0;
782
834
  this.maxScrollLeft = 0;
835
+ this.intersectionObserver = null;
783
836
  this.mode = Mode.ABSOLUTE;
784
837
  this.pageResizeObserver = null;
785
838
  this.wrapperResizeObserver = null;
@@ -819,7 +872,6 @@ class StageMask extends Rule {
819
872
  if (this.maxScrollLeft > 0) {
820
873
  this.scrollLeft = this.scrollLeft + deltaX;
821
874
  }
822
- this.fixScrollValue();
823
875
  this.scroll();
824
876
  this.emit("scroll", event);
825
877
  };
@@ -851,15 +903,33 @@ class StageMask extends Rule {
851
903
  this.page = page;
852
904
  this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
853
905
  this.pageResizeObserver?.disconnect();
906
+ this.wrapperResizeObserver?.disconnect();
907
+ this.intersectionObserver?.disconnect();
908
+ if (typeof IntersectionObserver !== "undefined") {
909
+ this.intersectionObserver = new IntersectionObserver((entries) => {
910
+ entries.forEach((entry) => {
911
+ const { target, intersectionRatio } = entry;
912
+ if (intersectionRatio <= 0) {
913
+ this.scrollIntoView(target);
914
+ }
915
+ this.intersectionObserver?.unobserve(target);
916
+ });
917
+ }, {
918
+ root: this.pageScrollParent,
919
+ rootMargin: "0px",
920
+ threshold: 1
921
+ });
922
+ }
854
923
  if (typeof ResizeObserver !== "undefined") {
855
924
  this.pageResizeObserver = new ResizeObserver((entries) => {
856
925
  const [entry] = entries;
857
926
  const { clientHeight, clientWidth } = entry.target;
858
927
  this.setHeight(clientHeight);
859
928
  this.setWidth(clientWidth);
860
- this.fixScrollValue();
861
929
  this.scroll();
862
- this.core.dr.updateMoveable();
930
+ if (this.core.dr.moveable) {
931
+ this.core.dr.updateMoveable();
932
+ }
863
933
  });
864
934
  this.pageResizeObserver.observe(page);
865
935
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
@@ -881,6 +951,14 @@ class StageMask extends Rule {
881
951
  setLayout(el) {
882
952
  this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
883
953
  }
954
+ scrollIntoView(el) {
955
+ el.scrollIntoView();
956
+ if (!this.pageScrollParent)
957
+ return;
958
+ this.scrollLeft = this.pageScrollParent.scrollLeft;
959
+ this.scrollTop = this.pageScrollParent.scrollTop;
960
+ this.scroll();
961
+ }
884
962
  destroy() {
885
963
  this.content?.remove();
886
964
  this.page = null;
@@ -891,6 +969,7 @@ class StageMask extends Rule {
891
969
  super.destroy();
892
970
  }
893
971
  scroll() {
972
+ this.fixScrollValue();
894
973
  let { scrollLeft, scrollTop } = this;
895
974
  if (this.pageScrollParent) {
896
975
  this.pageScrollParent.scrollTo({
@@ -919,10 +998,10 @@ class StageMask extends Rule {
919
998
  this.content.style.width = `${width}px`;
920
999
  }
921
1000
  setMaxScrollLeft() {
922
- this.maxScrollLeft = this.width - this.wrapperWidth;
1001
+ this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
923
1002
  }
924
1003
  setMaxScrollTop() {
925
- this.maxScrollTop = this.height - this.wrapperHeight;
1004
+ this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
926
1005
  }
927
1006
  fixScrollValue() {
928
1007
  if (this.scrollTop < 0)
@@ -1096,11 +1175,14 @@ class StageCore extends EventEmitter {
1096
1175
  }
1097
1176
  this.mask.setLayout(el);
1098
1177
  this.dr.select(el, event);
1178
+ if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1179
+ this.mask.intersectionObserver?.observe(el);
1180
+ }
1099
1181
  this.selectedDom = el;
1100
1182
  if (this.renderer.contentWindow) {
1101
1183
  removeSelectedClassName(this.renderer.contentWindow.document);
1102
1184
  if (this.selectedDom) {
1103
- addSelectedClassName(this.selectedDom);
1185
+ addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
1104
1186
  }
1105
1187
  }
1106
1188
  }