@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.
@@ -38,7 +38,18 @@
38
38
  return Mode2;
39
39
  })(Mode || {});
40
40
  const SELECTED_CLASS = "tmagic-stage-selected-area";
41
+ const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
42
+ const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
41
43
 
44
+ const getParents = (el, relative) => {
45
+ let cur = el.parentElement;
46
+ const parents = [];
47
+ while (cur && cur !== relative) {
48
+ parents.push(cur);
49
+ cur = cur.parentElement;
50
+ }
51
+ return parents;
52
+ };
42
53
  const getOffset = (el) => {
43
54
  const { transform } = getComputedStyle(el);
44
55
  const { offsetParent } = el;
@@ -163,18 +174,41 @@
163
174
  if (oldEl) {
164
175
  oldEl.classList.remove(SELECTED_CLASS);
165
176
  oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
177
+ doc.querySelectorAll(`.${SELECTED_CLASS}-parents`).forEach((item) => {
178
+ item.classList.remove(`${SELECTED_CLASS}-parents`);
179
+ });
166
180
  }
167
181
  };
168
- const addSelectedClassName = (el) => {
182
+ const addSelectedClassName = (el, doc) => {
169
183
  el.classList.add(SELECTED_CLASS);
170
184
  el.parentNode?.classList.add(`${SELECTED_CLASS}-parent`);
185
+ getParents(el, doc.body).forEach((item) => {
186
+ item.classList.add(`${SELECTED_CLASS}-parents`);
187
+ });
188
+ };
189
+ const getGuideLineFromCache = (type) => {
190
+ const key = {
191
+ [GuidesType.HORIZONTAL]: H_GUIDE_LINE_STORAGE_KEY,
192
+ [GuidesType.VERTICAL]: V_GUIDE_LINE_STORAGE_KEY
193
+ }[type];
194
+ if (!key)
195
+ return [];
196
+ const guideLineCacheData = globalThis.localStorage.getItem(key);
197
+ if (guideLineCacheData) {
198
+ try {
199
+ return JSON.parse(guideLineCacheData) || [];
200
+ } catch (e) {
201
+ console.error(e);
202
+ }
203
+ }
204
+ return [];
171
205
  };
172
206
 
173
207
  class StageDragResize extends EventEmitter.EventEmitter {
174
208
  constructor(config) {
175
209
  super();
176
- this.horizontalGuidelines = [];
177
- this.verticalGuidelines = [];
210
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
211
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
178
212
  this.elementGuidelines = [];
179
213
  this.mode = Mode.ABSOLUTE;
180
214
  this.moveableOptions = {};
@@ -245,10 +279,32 @@
245
279
  this.mode = getMode(el);
246
280
  this.destroyGhostEl();
247
281
  this.updateDragEl(el);
282
+ this.setElementGuidelines(el);
248
283
  this.moveableOptions = this.getOptions({
249
284
  target: this.dragEl
250
285
  });
251
286
  }
287
+ setElementGuidelines(el) {
288
+ const nodes = el.parentElement?.children || [];
289
+ this.elementGuidelines.forEach((node) => {
290
+ node.remove();
291
+ });
292
+ this.elementGuidelines = [];
293
+ if (this.mode === Mode.ABSOLUTE) {
294
+ const frame = document.createDocumentFragment();
295
+ for (const node of nodes) {
296
+ const { width, height } = node.getBoundingClientRect();
297
+ if (node === el)
298
+ continue;
299
+ const { left, top } = getOffset(node);
300
+ const elementGuideline = document.createElement("div");
301
+ elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
302
+ this.elementGuidelines.push(elementGuideline);
303
+ frame.append(elementGuideline);
304
+ }
305
+ this.container.append(frame);
306
+ }
307
+ }
252
308
  initMoveable() {
253
309
  this.moveable?.destroy();
254
310
  this.moveable = new Moveable__default["default"](this.container, {
@@ -333,14 +389,6 @@
333
389
  this.destroyGhostEl();
334
390
  });
335
391
  }
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]")) : [];
341
- });
342
- return getSnapElements(el).filter((element) => element !== this.target && !this.target?.contains(element) && element !== mask.page);
343
- }
344
392
  sort() {
345
393
  if (!this.target || !this.ghostEl)
346
394
  throw new Error("\u672A\u77E5\u9519\u8BEF");
@@ -635,8 +683,8 @@
635
683
  class Rule extends EventEmitter__default["default"] {
636
684
  constructor(container) {
637
685
  super();
638
- this.horizontalGuidelines = [];
639
- this.verticalGuidelines = [];
686
+ this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
687
+ this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
640
688
  this.getGuidesStyle = (type) => ({
641
689
  position: "fixed",
642
690
  zIndex: 1,
@@ -660,6 +708,7 @@
660
708
  type: GuidesType.HORIZONTAL,
661
709
  guides: this.horizontalGuidelines
662
710
  });
711
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
663
712
  };
664
713
  this.vGuidesChangeGuidesHandler = (e) => {
665
714
  this.verticalGuidelines = e.guides;
@@ -667,10 +716,11 @@
667
716
  type: GuidesType.VERTICAL,
668
717
  guides: this.verticalGuidelines
669
718
  });
719
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
670
720
  };
671
721
  this.container = container;
672
- this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
673
- this.vGuides = this.createGuides(GuidesType.VERTICAL);
722
+ this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
723
+ this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
674
724
  this.hGuides.on("changeGuides", this.hGuidesChangeGuidesHandler);
675
725
  this.vGuides.on("changeGuides", this.vGuidesChangeGuidesHandler);
676
726
  this.containerResizeObserver = new ResizeObserver(() => {
@@ -704,6 +754,8 @@
704
754
  type: GuidesType.HORIZONTAL,
705
755
  guides: []
706
756
  });
757
+ globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, "[]");
758
+ globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, "[]");
707
759
  }
708
760
  showRule(show = true) {
709
761
  if (show) {
@@ -787,6 +839,7 @@
787
839
  this.wrapperWidth = 0;
788
840
  this.maxScrollTop = 0;
789
841
  this.maxScrollLeft = 0;
842
+ this.intersectionObserver = null;
790
843
  this.mode = Mode.ABSOLUTE;
791
844
  this.pageResizeObserver = null;
792
845
  this.wrapperResizeObserver = null;
@@ -826,7 +879,6 @@
826
879
  if (this.maxScrollLeft > 0) {
827
880
  this.scrollLeft = this.scrollLeft + deltaX;
828
881
  }
829
- this.fixScrollValue();
830
882
  this.scroll();
831
883
  this.emit("scroll", event);
832
884
  };
@@ -858,15 +910,33 @@
858
910
  this.page = page;
859
911
  this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
860
912
  this.pageResizeObserver?.disconnect();
913
+ this.wrapperResizeObserver?.disconnect();
914
+ this.intersectionObserver?.disconnect();
915
+ if (typeof IntersectionObserver !== "undefined") {
916
+ this.intersectionObserver = new IntersectionObserver((entries) => {
917
+ entries.forEach((entry) => {
918
+ const { target, intersectionRatio } = entry;
919
+ if (intersectionRatio <= 0) {
920
+ this.scrollIntoView(target);
921
+ }
922
+ this.intersectionObserver?.unobserve(target);
923
+ });
924
+ }, {
925
+ root: this.pageScrollParent,
926
+ rootMargin: "0px",
927
+ threshold: 1
928
+ });
929
+ }
861
930
  if (typeof ResizeObserver !== "undefined") {
862
931
  this.pageResizeObserver = new ResizeObserver((entries) => {
863
932
  const [entry] = entries;
864
933
  const { clientHeight, clientWidth } = entry.target;
865
934
  this.setHeight(clientHeight);
866
935
  this.setWidth(clientWidth);
867
- this.fixScrollValue();
868
936
  this.scroll();
869
- this.core.dr.updateMoveable();
937
+ if (this.core.dr.moveable) {
938
+ this.core.dr.updateMoveable();
939
+ }
870
940
  });
871
941
  this.pageResizeObserver.observe(page);
872
942
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
@@ -888,6 +958,14 @@
888
958
  setLayout(el) {
889
959
  this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
890
960
  }
961
+ scrollIntoView(el) {
962
+ el.scrollIntoView();
963
+ if (!this.pageScrollParent)
964
+ return;
965
+ this.scrollLeft = this.pageScrollParent.scrollLeft;
966
+ this.scrollTop = this.pageScrollParent.scrollTop;
967
+ this.scroll();
968
+ }
891
969
  destroy() {
892
970
  this.content?.remove();
893
971
  this.page = null;
@@ -898,6 +976,7 @@
898
976
  super.destroy();
899
977
  }
900
978
  scroll() {
979
+ this.fixScrollValue();
901
980
  let { scrollLeft, scrollTop } = this;
902
981
  if (this.pageScrollParent) {
903
982
  this.pageScrollParent.scrollTo({
@@ -926,10 +1005,10 @@
926
1005
  this.content.style.width = `${width}px`;
927
1006
  }
928
1007
  setMaxScrollLeft() {
929
- this.maxScrollLeft = this.width - this.wrapperWidth;
1008
+ this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
930
1009
  }
931
1010
  setMaxScrollTop() {
932
- this.maxScrollTop = this.height - this.wrapperHeight;
1011
+ this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
933
1012
  }
934
1013
  fixScrollValue() {
935
1014
  if (this.scrollTop < 0)
@@ -1103,11 +1182,14 @@
1103
1182
  }
1104
1183
  this.mask.setLayout(el);
1105
1184
  this.dr.select(el, event);
1185
+ if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1186
+ this.mask.intersectionObserver?.observe(el);
1187
+ }
1106
1188
  this.selectedDom = el;
1107
1189
  if (this.renderer.contentWindow) {
1108
1190
  removeSelectedClassName(this.renderer.contentWindow.document);
1109
1191
  if (this.selectedDom) {
1110
- addSelectedClassName(this.selectedDom);
1192
+ addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
1111
1193
  }
1112
1194
  }
1113
1195
  }