@tmagic/stage 1.0.0-beta.10 → 1.0.0-beta.13

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.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # [文档](https://tencent.github.io/tmagic-editor/docs/)
@@ -163,21 +163,14 @@ const addSelectedClassName = (el) => {
163
163
  };
164
164
 
165
165
  class StageDragResize extends EventEmitter {
166
- core;
167
- container;
168
- target;
169
- dragEl;
170
- moveable;
171
- horizontalGuidelines = [];
172
- verticalGuidelines = [];
173
- elementGuidelines = [];
174
- moveableOptions = {};
175
- dragStatus = "end" /* END */;
176
- ghostEl;
177
- mode = Mode.ABSOLUTE;
178
- moveableHelper;
179
166
  constructor(config) {
180
167
  super();
168
+ this.horizontalGuidelines = [];
169
+ this.verticalGuidelines = [];
170
+ this.elementGuidelines = [];
171
+ this.moveableOptions = {};
172
+ this.dragStatus = "end" /* END */;
173
+ this.mode = Mode.ABSOLUTE;
181
174
  this.core = config.core;
182
175
  this.container = config.container;
183
176
  this.dragEl = globalThis.document.createElement("div");
@@ -409,6 +402,7 @@ class StageDragResize extends EventEmitter {
409
402
  if (!this.target)
410
403
  return {};
411
404
  const isAbsolute = this.mode === Mode.ABSOLUTE;
405
+ const isFixed = this.mode === Mode.FIXED;
412
406
  let { moveableOptions = {} } = this.core.config;
413
407
  if (typeof moveableOptions === "function") {
414
408
  moveableOptions = moveableOptions(this.core);
@@ -420,8 +414,8 @@ class StageDragResize extends EventEmitter {
420
414
  dragArea: false,
421
415
  draggable: true,
422
416
  resizable: true,
423
- snappable: isAbsolute,
424
- snapGap: isAbsolute,
417
+ snappable: isAbsolute || isFixed,
418
+ snapGap: isAbsolute || isFixed,
425
419
  snapThreshold: 5,
426
420
  snapDigit: 0,
427
421
  throttleDrag: 0,
@@ -513,10 +507,6 @@ const up = (deltaTop, target) => {
513
507
  };
514
508
 
515
509
  class StageHighlight extends EventEmitter {
516
- core;
517
- container;
518
- target;
519
- moveable;
520
510
  constructor(config) {
521
511
  super();
522
512
  this.core = config.core;
@@ -536,6 +526,7 @@ class StageHighlight extends EventEmitter {
536
526
  clearHighlight() {
537
527
  if (!this.moveable)
538
528
  return;
529
+ this.target = void 0;
539
530
  this.moveable.target = null;
540
531
  this.moveable.updateTarget();
541
532
  }
@@ -545,14 +536,41 @@ class StageHighlight extends EventEmitter {
545
536
  }
546
537
 
547
538
  class Rule extends EventEmitter$1 {
548
- hGuides;
549
- vGuides;
550
- horizontalGuidelines = [];
551
- verticalGuidelines = [];
552
- container;
553
- containerResizeObserver;
554
539
  constructor(container) {
555
540
  super();
541
+ this.horizontalGuidelines = [];
542
+ this.verticalGuidelines = [];
543
+ this.getGuidesStyle = (type) => ({
544
+ position: "fixed",
545
+ zIndex: 1,
546
+ left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
547
+ top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
548
+ width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
549
+ height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
550
+ });
551
+ this.createGuides = (type, defaultGuides = []) => new Guides(this.container, {
552
+ type,
553
+ defaultGuides,
554
+ displayDragPos: true,
555
+ backgroundColor: "#fff",
556
+ lineColor: "#000",
557
+ textColor: "#000",
558
+ style: this.getGuidesStyle(type)
559
+ });
560
+ this.hGuidesChangeGuidesHandler = (e) => {
561
+ this.horizontalGuidelines = e.guides;
562
+ this.emit("changeGuides", {
563
+ type: GuidesType.HORIZONTAL,
564
+ guides: this.horizontalGuidelines
565
+ });
566
+ };
567
+ this.vGuidesChangeGuidesHandler = (e) => {
568
+ this.verticalGuidelines = e.guides;
569
+ this.emit("changeGuides", {
570
+ type: GuidesType.VERTICAL,
571
+ guides: this.verticalGuidelines
572
+ });
573
+ };
556
574
  this.container = container;
557
575
  this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
558
576
  this.vGuides = this.createGuides(GuidesType.VERTICAL);
@@ -621,41 +639,10 @@ class Rule extends EventEmitter$1 {
621
639
  this.containerResizeObserver.disconnect();
622
640
  this.removeAllListeners();
623
641
  }
624
- getGuidesStyle = (type) => ({
625
- position: "fixed",
626
- zIndex: 1,
627
- left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
628
- top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
629
- width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
630
- height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
631
- });
632
- createGuides = (type, defaultGuides = []) => new Guides(this.container, {
633
- type,
634
- defaultGuides,
635
- displayDragPos: true,
636
- backgroundColor: "#fff",
637
- lineColor: "#000",
638
- textColor: "#000",
639
- style: this.getGuidesStyle(type)
640
- });
641
- hGuidesChangeGuidesHandler = (e) => {
642
- this.horizontalGuidelines = e.guides;
643
- this.emit("changeGuides", {
644
- type: GuidesType.HORIZONTAL,
645
- guides: this.horizontalGuidelines
646
- });
647
- };
648
- vGuidesChangeGuidesHandler = (e) => {
649
- this.verticalGuidelines = e.guides;
650
- this.emit("changeGuides", {
651
- type: GuidesType.VERTICAL,
652
- guides: this.verticalGuidelines
653
- });
654
- };
655
642
  }
656
643
 
657
644
  const wrapperClassName = "editor-mask-wrapper";
658
- const throttleTime = 300;
645
+ const throttleTime = 100;
659
646
  const hideScrollbar = () => {
660
647
  const style = globalThis.document.createElement("style");
661
648
  style.innerHTML = `
@@ -689,32 +676,73 @@ const createWrapper = () => {
689
676
  return el;
690
677
  };
691
678
  class StageMask extends Rule {
692
- content = createContent();
693
- wrapper;
694
- core;
695
- page = null;
696
- pageScrollParent = null;
697
- scrollTop = 0;
698
- scrollLeft = 0;
699
- width = 0;
700
- height = 0;
701
- wrapperHeight = 0;
702
- wrapperWidth = 0;
703
- mode = Mode.ABSOLUTE;
704
- pageResizeObserver = null;
705
- wrapperResizeObserver = null;
706
- highlightHandler = throttle((event) => {
707
- this.emit("highlight", event);
708
- }, throttleTime);
709
679
  constructor(config) {
710
680
  const wrapper = createWrapper();
711
681
  super(wrapper);
682
+ this.content = createContent();
683
+ this.page = null;
684
+ this.pageScrollParent = null;
685
+ this.scrollTop = 0;
686
+ this.scrollLeft = 0;
687
+ this.width = 0;
688
+ this.height = 0;
689
+ this.wrapperHeight = 0;
690
+ this.wrapperWidth = 0;
691
+ this.maxScrollTop = 0;
692
+ this.maxScrollLeft = 0;
693
+ this.mode = Mode.ABSOLUTE;
694
+ this.pageResizeObserver = null;
695
+ this.wrapperResizeObserver = null;
696
+ this.highlightHandler = throttle((event) => {
697
+ this.emit("highlight", event);
698
+ }, throttleTime);
699
+ this.mouseDownHandler = (event) => {
700
+ this.emit("clearHighlight");
701
+ event.stopImmediatePropagation();
702
+ event.stopPropagation();
703
+ if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
704
+ return;
705
+ if (event.target.className.indexOf("moveable-control") !== -1) {
706
+ return;
707
+ }
708
+ this.content.removeEventListener("mousemove", this.highlightHandler);
709
+ this.emit("beforeSelect", event);
710
+ globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
711
+ };
712
+ this.mouseUpHandler = () => {
713
+ globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
714
+ this.content.addEventListener("mousemove", this.highlightHandler);
715
+ this.emit("select");
716
+ };
717
+ this.mouseWheelHandler = (event) => {
718
+ this.emit("clearHighlight");
719
+ if (!this.page)
720
+ throw new Error("page \u672A\u521D\u59CB\u5316");
721
+ const { deltaY, deltaX } = event;
722
+ if (this.page.clientHeight < this.wrapperHeight && deltaY)
723
+ return;
724
+ if (this.page.clientWidth < this.wrapperWidth && deltaX)
725
+ return;
726
+ if (this.maxScrollTop > 0) {
727
+ this.scrollTop = this.scrollTop + deltaY;
728
+ }
729
+ if (this.maxScrollLeft > 0) {
730
+ this.scrollLeft = this.scrollLeft + deltaX;
731
+ }
732
+ this.fixScrollValue();
733
+ this.scroll();
734
+ this.emit("scroll", event);
735
+ };
736
+ this.mouseLeaveHandler = () => {
737
+ setTimeout(() => this.emit("clearHighlight"), throttleTime);
738
+ };
712
739
  this.wrapper = wrapper;
713
740
  this.core = config.core;
714
741
  this.content.addEventListener("mousedown", this.mouseDownHandler);
715
742
  this.wrapper.appendChild(this.content);
716
743
  this.content.addEventListener("wheel", this.mouseWheelHandler);
717
744
  this.content.addEventListener("mousemove", this.highlightHandler);
745
+ this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
718
746
  }
719
747
  setMode(mode) {
720
748
  this.mode = mode;
@@ -739,6 +767,9 @@ class StageMask extends Rule {
739
767
  const { clientHeight, clientWidth } = entry.target;
740
768
  this.setHeight(clientHeight);
741
769
  this.setWidth(clientWidth);
770
+ this.fixScrollValue();
771
+ this.scroll();
772
+ this.core.dr.updateMoveable();
742
773
  });
743
774
  this.pageResizeObserver.observe(page);
744
775
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
@@ -746,6 +777,8 @@ class StageMask extends Rule {
746
777
  const { clientHeight, clientWidth } = entry.target;
747
778
  this.wrapperHeight = clientHeight;
748
779
  this.wrapperWidth = clientWidth;
780
+ this.setMaxScrollLeft();
781
+ this.setMaxScrollTop();
749
782
  });
750
783
  this.wrapperResizeObserver.observe(this.wrapper);
751
784
  }
@@ -764,10 +797,17 @@ class StageMask extends Rule {
764
797
  this.pageScrollParent = null;
765
798
  this.pageResizeObserver?.disconnect();
766
799
  this.wrapperResizeObserver?.disconnect();
800
+ this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
767
801
  super.destroy();
768
802
  }
769
803
  scroll() {
770
804
  let { scrollLeft, scrollTop } = this;
805
+ if (this.pageScrollParent) {
806
+ this.pageScrollParent.scrollTo({
807
+ top: scrollTop,
808
+ left: scrollLeft
809
+ });
810
+ }
771
811
  if (this.mode === Mode.FIXED) {
772
812
  scrollLeft = 0;
773
813
  scrollTop = 0;
@@ -780,75 +820,75 @@ class StageMask extends Rule {
780
820
  }
781
821
  setHeight(height) {
782
822
  this.height = height;
823
+ this.setMaxScrollTop();
783
824
  this.content.style.height = `${height}px`;
784
825
  }
785
826
  setWidth(width) {
786
827
  this.width = width;
828
+ this.setMaxScrollLeft();
787
829
  this.content.style.width = `${width}px`;
788
830
  }
789
- mouseDownHandler = (event) => {
790
- this.emit("clearHighlight");
791
- event.stopImmediatePropagation();
792
- event.stopPropagation();
793
- if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
794
- return;
795
- if (event.target.className.indexOf("moveable-control") !== -1) {
796
- return;
797
- }
798
- this.content.removeEventListener("mousemove", this.highlightHandler);
799
- this.emit("beforeSelect", event);
800
- globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
801
- };
802
- mouseUpHandler = () => {
803
- globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
804
- this.content.addEventListener("mousemove", this.highlightHandler);
805
- this.emit("select");
806
- };
807
- mouseWheelHandler = (event) => {
808
- this.emit("clearHighlight");
809
- if (!this.page)
810
- throw new Error("page \u672A\u521D\u59CB\u5316");
811
- const { deltaY, deltaX } = event;
812
- const { height, wrapperHeight, width, wrapperWidth } = this;
813
- const maxScrollTop = height - wrapperHeight;
814
- const maxScrollLeft = width - wrapperWidth;
815
- if (maxScrollTop > 0) {
816
- if (deltaY > 0) {
817
- this.scrollTop = this.scrollTop + Math.min(maxScrollTop - this.scrollTop, deltaY);
818
- } else {
819
- this.scrollTop = Math.max(this.scrollTop + deltaY, 0);
820
- }
821
- }
822
- if (width > wrapperWidth) {
823
- if (deltaX > 0) {
824
- this.scrollLeft = this.scrollLeft + Math.min(maxScrollLeft - this.scrollLeft, deltaX);
825
- } else {
826
- this.scrollLeft = Math.max(this.scrollLeft + deltaX, 0);
827
- }
828
- }
829
- if (this.mode !== Mode.FIXED) {
830
- this.scrollTo(this.scrollLeft, this.scrollTop);
831
- }
832
- if (this.pageScrollParent) {
833
- this.pageScrollParent.scrollTo({
834
- top: this.scrollTop,
835
- left: this.scrollLeft
836
- });
837
- }
838
- this.scroll();
839
- this.emit("scroll", event);
840
- };
831
+ setMaxScrollLeft() {
832
+ this.maxScrollLeft = this.width - this.wrapperWidth;
833
+ }
834
+ setMaxScrollTop() {
835
+ this.maxScrollTop = this.height - this.wrapperHeight;
836
+ }
837
+ fixScrollValue() {
838
+ if (this.scrollTop < 0)
839
+ this.scrollTop = 0;
840
+ if (this.scrollLeft < 0)
841
+ this.scrollLeft = 0;
842
+ if (this.maxScrollTop < this.scrollTop)
843
+ this.scrollTop = this.maxScrollTop;
844
+ if (this.maxScrollLeft < this.scrollLeft)
845
+ this.scrollLeft = this.maxScrollLeft;
846
+ }
841
847
  }
842
848
 
843
849
  class StageRender extends EventEmitter {
844
- contentWindow = null;
845
- runtime = null;
846
- iframe;
847
- runtimeUrl;
848
- core;
849
- render;
850
850
  constructor({ core }) {
851
851
  super();
852
+ this.contentWindow = null;
853
+ this.runtime = null;
854
+ this.getMagicApi = () => ({
855
+ onPageElUpdate: (el) => this.emit("page-el-update", el),
856
+ onRuntimeReady: (runtime) => {
857
+ this.runtime = runtime;
858
+ globalThis.runtime = runtime;
859
+ this.emit("runtime-ready", runtime);
860
+ }
861
+ });
862
+ this.getRuntime = () => {
863
+ if (this.runtime)
864
+ return Promise.resolve(this.runtime);
865
+ return new Promise((resolve) => {
866
+ const listener = (runtime) => {
867
+ this.off("runtime-ready", listener);
868
+ resolve(runtime);
869
+ };
870
+ this.on("runtime-ready", listener);
871
+ });
872
+ };
873
+ this.loadHandler = async () => {
874
+ this.emit("onload");
875
+ if (this.render) {
876
+ const el = await this.render(this.core);
877
+ if (el) {
878
+ this.iframe?.contentDocument?.body?.appendChild(el);
879
+ }
880
+ }
881
+ if (this.contentWindow) {
882
+ const style = this.contentWindow.document.createElement("style");
883
+ style.id = "tmagic-stage-render";
884
+ style.innerHTML = `
885
+ .${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
886
+ z-index: ${ZIndex.SELECTED_EL};
887
+ }
888
+ `;
889
+ this.contentWindow.document.head.appendChild(style);
890
+ }
891
+ };
852
892
  this.core = core;
853
893
  this.runtimeUrl = core.config.runtimeUrl || "";
854
894
  this.render = core.config.render;
@@ -861,14 +901,6 @@ class StageRender extends EventEmitter {
861
901
  `;
862
902
  this.iframe.addEventListener("load", this.loadHandler);
863
903
  }
864
- getMagicApi = () => ({
865
- onPageElUpdate: (el) => this.emit("page-el-update", el),
866
- onRuntimeReady: (runtime) => {
867
- this.runtime = runtime;
868
- globalThis.runtime = runtime;
869
- this.emit("runtime-ready", runtime);
870
- }
871
- });
872
904
  async mount(el) {
873
905
  if (this.iframe) {
874
906
  if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
@@ -885,17 +917,6 @@ class StageRender extends EventEmitter {
885
917
  throw Error("mount \u5931\u8D25");
886
918
  }
887
919
  }
888
- getRuntime = () => {
889
- if (this.runtime)
890
- return Promise.resolve(this.runtime);
891
- return new Promise((resolve) => {
892
- const listener = (runtime) => {
893
- this.off("runtime-ready", listener);
894
- resolve(runtime);
895
- };
896
- this.on("runtime-ready", listener);
897
- });
898
- };
899
920
  destroy() {
900
921
  this.iframe?.removeEventListener("load", this.loadHandler);
901
922
  this.contentWindow = null;
@@ -903,40 +924,12 @@ class StageRender extends EventEmitter {
903
924
  this.iframe = void 0;
904
925
  this.removeAllListeners();
905
926
  }
906
- loadHandler = async () => {
907
- this.emit("onload");
908
- if (this.render) {
909
- const el = await this.render(this.core);
910
- if (el) {
911
- this.iframe?.contentDocument?.body?.appendChild(el);
912
- }
913
- }
914
- if (this.contentWindow) {
915
- const style = this.contentWindow.document.createElement("style");
916
- style.id = "tmagic-stage-render";
917
- style.innerHTML = `
918
- .${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
919
- z-index: ${ZIndex.SELECTED_EL};
920
- }
921
- `;
922
- this.contentWindow.document.head.appendChild(style);
923
- }
924
- };
925
927
  }
926
928
 
927
929
  class StageCore extends EventEmitter {
928
- selectedDom;
929
- highlightedDom;
930
- renderer;
931
- mask;
932
- dr;
933
- highlightLayer;
934
- config;
935
- zoom = DEFAULT_ZOOM;
936
- container;
937
- canSelect;
938
930
  constructor(config) {
939
931
  super();
932
+ this.zoom = DEFAULT_ZOOM;
940
933
  this.config = config;
941
934
  this.setZoom(config.zoom);
942
935
  this.canSelect = config.canSelect || ((el) => !!el.id);
@@ -1023,7 +1016,7 @@ class StageCore extends EventEmitter {
1023
1016
  }
1024
1017
  update(data) {
1025
1018
  const { config } = data;
1026
- this.renderer?.getRuntime().then((runtime) => {
1019
+ return this.renderer?.getRuntime().then((runtime) => {
1027
1020
  runtime?.update?.(data);
1028
1021
  setTimeout(() => {
1029
1022
  const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
@@ -1049,13 +1042,13 @@ class StageCore extends EventEmitter {
1049
1042
  this.highlightedDom = el;
1050
1043
  }
1051
1044
  sortNode(data) {
1052
- this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
1045
+ return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
1053
1046
  }
1054
1047
  add(data) {
1055
- this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
1048
+ return this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
1056
1049
  }
1057
1050
  remove(data) {
1058
- this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
1051
+ return this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
1059
1052
  }
1060
1053
  setZoom(zoom = DEFAULT_ZOOM) {
1061
1054
  this.zoom = zoom;