@tmagic/stage 1.1.6 → 1.2.0-beta.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.
@@ -45,6 +45,77 @@
45
45
  })(Mode || {});
46
46
  const SELECTED_CLASS = "tmagic-stage-selected-area";
47
47
 
48
+ const selectParentAbles = (dr) => ({
49
+ name: "selectParent",
50
+ props: {},
51
+ events: {},
52
+ render(moveable, React) {
53
+ const rect = moveable.getRect();
54
+ const { pos2 } = moveable.state;
55
+ const editableViewer = moveable.useCSS(
56
+ "div",
57
+ `
58
+ {
59
+ position: absolute;
60
+ left: 0px;
61
+ top: 0px;
62
+ will-change: transform;
63
+ transform-origin: 0px 0px;
64
+ display: flex;
65
+ }
66
+ .moveable-button {
67
+ width: 20px;
68
+ height: 20px;
69
+ background: #4af;
70
+ border-radius: 4px;
71
+ appearance: none;
72
+ border: 0;
73
+ color: white;
74
+ font-size: 12px;
75
+ font-weight: bold;
76
+ }
77
+ `
78
+ );
79
+ return React.createElement(
80
+ editableViewer,
81
+ {
82
+ className: "moveable-editable",
83
+ style: {
84
+ transform: `translate(${pos2[0] - 25}px, ${pos2[1] - 30}px) rotate(${rect.rotation}deg) translate(10px)`
85
+ }
86
+ },
87
+ React.createElement(
88
+ "button",
89
+ {
90
+ className: "moveable-button",
91
+ title: "\u9009\u4E2D\u7236\u7EC4\u4EF6",
92
+ onClick: () => {
93
+ dr.emit("select-parent");
94
+ }
95
+ },
96
+ React.createElement(
97
+ "svg",
98
+ {
99
+ width: "1em",
100
+ height: "1em",
101
+ viewBox: "0 0 16 16",
102
+ fill: "none",
103
+ xmlns: "http://www.w3.org/2000/svg",
104
+ style: {
105
+ transform: "rotate(90deg)"
106
+ }
107
+ },
108
+ React.createElement("path", {
109
+ d: "M13.0001 4V10H4.20718L5.85363 8.35355L5.14652 7.64645L2.64652 10.1464C2.45126 10.3417 2.45126 10.6583 2.64652 10.8536L5.14652 13.3536L5.85363 12.6464L4.20718 11H13.0001C13.5524 11 14.0001 10.5523 14.0001 10V4H13.0001Z",
110
+ fill: "currentColor",
111
+ fillOpacity: "0.9"
112
+ })
113
+ )
114
+ )
115
+ );
116
+ }
117
+ });
118
+
48
119
  var ContainerHighlightType = /* @__PURE__ */ ((ContainerHighlightType2) => {
49
120
  ContainerHighlightType2["DEFAULT"] = "default";
50
121
  ContainerHighlightType2["ALT"] = "alt";
@@ -141,6 +212,8 @@
141
212
  return null;
142
213
  for (let parent = element; parent.parentElement; ) {
143
214
  parent = parent.parentElement;
215
+ if (parent.tagName === "HTML")
216
+ return parent;
144
217
  style = getComputedStyle(parent);
145
218
  if (isAbsolute(style) && isStatic(style))
146
219
  continue;
@@ -225,6 +298,7 @@
225
298
  dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
226
299
  };
227
300
  };
301
+ const isMoveableButton = (target) => target.classList.contains("moveable-button") || target.parentElement?.classList.contains("moveable-button");
228
302
 
229
303
  class StageDragResize extends EventEmitter.EventEmitter {
230
304
  core;
@@ -499,10 +573,14 @@
499
573
  this.dragStatus = StageDragStatus.END;
500
574
  const frame = this.moveableHelper?.getFrame(e.target);
501
575
  this.emit("update", {
502
- el: this.target,
503
- style: {
504
- transform: frame?.get("transform")
505
- }
576
+ data: [
577
+ {
578
+ el: this.target,
579
+ style: {
580
+ transform: frame?.get("transform")
581
+ }
582
+ }
583
+ ]
506
584
  });
507
585
  });
508
586
  }
@@ -523,10 +601,14 @@
523
601
  this.dragStatus = StageDragStatus.END;
524
602
  const frame = this.moveableHelper?.getFrame(e.target);
525
603
  this.emit("update", {
526
- el: this.target,
527
- style: {
528
- transform: frame?.get("transform")
529
- }
604
+ data: [
605
+ {
606
+ el: this.target,
607
+ style: {
608
+ transform: frame?.get("transform")
609
+ }
610
+ }
611
+ ]
530
612
  });
531
613
  });
532
614
  }
@@ -631,7 +713,7 @@
631
713
  resizable: true,
632
714
  scalable: false,
633
715
  rotatable: false,
634
- snappable: isAbsolute || isFixed,
716
+ snappable: true,
635
717
  snapGap: isAbsolute || isFixed,
636
718
  snapThreshold: 5,
637
719
  snapDigit: 0,
@@ -662,6 +744,10 @@
662
744
  bottom: isSortable ? void 0 : this.container.clientHeight,
663
745
  ...moveableOptions.bounds || {}
664
746
  },
747
+ props: {
748
+ selectParent: true
749
+ },
750
+ ables: [selectParentAbles(this)],
665
751
  ...options,
666
752
  ...moveableOptions
667
753
  };
@@ -792,6 +878,7 @@
792
878
  verticalGuidelines = [];
793
879
  container;
794
880
  containerResizeObserver;
881
+ isShowGuides = true;
795
882
  constructor(container) {
796
883
  super();
797
884
  this.container = container;
@@ -805,12 +892,13 @@
805
892
  });
806
893
  this.containerResizeObserver.observe(this.container);
807
894
  }
808
- showGuides(show = true) {
895
+ showGuides(isShowGuides = true) {
896
+ this.isShowGuides = isShowGuides;
809
897
  this.hGuides.setState({
810
- showGuides: show
898
+ showGuides: isShowGuides
811
899
  });
812
900
  this.vGuides.setState({
813
- showGuides: show
901
+ showGuides: isShowGuides
814
902
  });
815
903
  }
816
904
  setGuides([hLines, vLines]) {
@@ -880,7 +968,8 @@
880
968
  backgroundColor: "#fff",
881
969
  lineColor: "#000",
882
970
  textColor: "#000",
883
- style: this.getGuidesStyle(type)
971
+ style: this.getGuidesStyle(type),
972
+ showGuides: this.isShowGuides
884
973
  });
885
974
  hGuidesChangeGuidesHandler = (e) => {
886
975
  this.horizontalGuidelines = e.guides;
@@ -931,9 +1020,7 @@
931
1020
  class StageMask extends Rule {
932
1021
  content = createContent();
933
1022
  wrapper;
934
- core;
935
1023
  page = null;
936
- pageScrollParent = null;
937
1024
  scrollTop = 0;
938
1025
  scrollLeft = 0;
939
1026
  width = 0;
@@ -942,34 +1029,21 @@
942
1029
  wrapperWidth = 0;
943
1030
  maxScrollTop = 0;
944
1031
  maxScrollLeft = 0;
945
- intersectionObserver = null;
946
1032
  isMultiSelectStatus = false;
947
1033
  mode = Mode.ABSOLUTE;
948
- pageResizeObserver = null;
1034
+ pageScrollParent = null;
1035
+ intersectionObserver = null;
949
1036
  wrapperResizeObserver = null;
950
1037
  highlightHandler = lodashEs.throttle((event) => {
951
1038
  this.emit("highlight", event);
952
1039
  }, throttleTime);
953
- constructor(config) {
1040
+ constructor() {
954
1041
  const wrapper = createWrapper();
955
1042
  super(wrapper);
956
1043
  this.wrapper = wrapper;
957
- this.core = config.core;
958
- this.content.addEventListener("mousedown", this.mouseDownHandler);
1044
+ this.initContentEventListener();
959
1045
  this.wrapper.appendChild(this.content);
960
- this.content.addEventListener("wheel", this.mouseWheelHandler);
961
- this.content.addEventListener("mousemove", this.highlightHandler);
962
- this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
963
- const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
964
- const ctrl = isMac ? "meta" : "ctrl";
965
- KeyController__default.default.global.keydown(ctrl, (e) => {
966
- e.inputEvent.preventDefault();
967
- this.isMultiSelectStatus = true;
968
- });
969
- KeyController__default.default.global.keyup(ctrl, (e) => {
970
- e.inputEvent.preventDefault();
971
- this.isMultiSelectStatus = false;
972
- });
1046
+ this.initMultiSelectEvent();
973
1047
  }
974
1048
  setMode(mode) {
975
1049
  this.mode = mode;
@@ -986,9 +1060,66 @@
986
1060
  if (!page)
987
1061
  return;
988
1062
  this.page = page;
989
- this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
990
- this.pageResizeObserver?.disconnect();
1063
+ this.initObserverIntersection();
1064
+ this.initObserverWrapper();
1065
+ }
1066
+ pageResize(entries) {
1067
+ const [entry] = entries;
1068
+ const { clientHeight, clientWidth } = entry.target;
1069
+ this.setHeight(clientHeight);
1070
+ this.setWidth(clientWidth);
1071
+ this.scroll();
1072
+ }
1073
+ observerIntersection(el) {
1074
+ this.intersectionObserver?.observe(el);
1075
+ }
1076
+ mount(el) {
1077
+ if (!this.content)
1078
+ throw new Error("content \u4E0D\u5B58\u5728");
1079
+ el.appendChild(this.wrapper);
1080
+ }
1081
+ setLayout(el) {
1082
+ this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
1083
+ }
1084
+ scrollIntoView(el) {
1085
+ el.scrollIntoView();
1086
+ if (!this.pageScrollParent)
1087
+ return;
1088
+ this.scrollLeft = this.pageScrollParent.scrollLeft;
1089
+ this.scrollTop = this.pageScrollParent.scrollTop;
1090
+ this.scroll();
1091
+ }
1092
+ destroy() {
1093
+ this.content?.remove();
1094
+ this.page = null;
1095
+ this.pageScrollParent = null;
991
1096
  this.wrapperResizeObserver?.disconnect();
1097
+ this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
1098
+ super.destroy();
1099
+ }
1100
+ initContentEventListener() {
1101
+ this.content.addEventListener("mousedown", this.mouseDownHandler);
1102
+ this.content.addEventListener("wheel", this.mouseWheelHandler);
1103
+ this.content.addEventListener("mousemove", this.highlightHandler);
1104
+ this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
1105
+ }
1106
+ initMultiSelectEvent() {
1107
+ const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
1108
+ const ctrl = isMac ? "meta" : "ctrl";
1109
+ KeyController__default.default.global.keydown(ctrl, (e) => {
1110
+ e.inputEvent.preventDefault();
1111
+ this.isMultiSelectStatus = true;
1112
+ });
1113
+ KeyController__default.default.global.on("blur", () => {
1114
+ this.isMultiSelectStatus = false;
1115
+ });
1116
+ KeyController__default.default.global.keyup(ctrl, (e) => {
1117
+ e.inputEvent.preventDefault();
1118
+ this.isMultiSelectStatus = false;
1119
+ });
1120
+ }
1121
+ initObserverIntersection() {
1122
+ this.pageScrollParent = getScrollParent(this.page) || null;
992
1123
  this.intersectionObserver?.disconnect();
993
1124
  if (typeof IntersectionObserver !== "undefined") {
994
1125
  this.intersectionObserver = new IntersectionObserver(
@@ -1008,18 +1139,10 @@
1008
1139
  }
1009
1140
  );
1010
1141
  }
1142
+ }
1143
+ initObserverWrapper() {
1144
+ this.wrapperResizeObserver?.disconnect();
1011
1145
  if (typeof ResizeObserver !== "undefined") {
1012
- this.pageResizeObserver = new ResizeObserver((entries) => {
1013
- const [entry] = entries;
1014
- const { clientHeight, clientWidth } = entry.target;
1015
- this.setHeight(clientHeight);
1016
- this.setWidth(clientWidth);
1017
- this.scroll();
1018
- if (this.core.dr.moveable) {
1019
- this.core.dr.updateMoveable();
1020
- }
1021
- });
1022
- this.pageResizeObserver.observe(page);
1023
1146
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
1024
1147
  const [entry] = entries;
1025
1148
  const { clientHeight, clientWidth } = entry.target;
@@ -1031,31 +1154,6 @@
1031
1154
  this.wrapperResizeObserver.observe(this.wrapper);
1032
1155
  }
1033
1156
  }
1034
- mount(el) {
1035
- if (!this.content)
1036
- throw new Error("content \u4E0D\u5B58\u5728");
1037
- el.appendChild(this.wrapper);
1038
- }
1039
- setLayout(el) {
1040
- this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
1041
- }
1042
- scrollIntoView(el) {
1043
- el.scrollIntoView();
1044
- if (!this.pageScrollParent)
1045
- return;
1046
- this.scrollLeft = this.pageScrollParent.scrollLeft;
1047
- this.scrollTop = this.pageScrollParent.scrollTop;
1048
- this.scroll();
1049
- }
1050
- destroy() {
1051
- this.content?.remove();
1052
- this.page = null;
1053
- this.pageScrollParent = null;
1054
- this.pageResizeObserver?.disconnect();
1055
- this.wrapperResizeObserver?.disconnect();
1056
- this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
1057
- super.destroy();
1058
- }
1059
1157
  scroll() {
1060
1158
  this.fixScrollValue();
1061
1159
  let { scrollLeft, scrollTop } = this;
@@ -1107,10 +1205,13 @@
1107
1205
  event.stopPropagation();
1108
1206
  if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
1109
1207
  return;
1110
- if (!this.isMultiSelectStatus && event.target.className.indexOf("moveable-area") !== -1) {
1208
+ if (!event.target)
1209
+ return;
1210
+ const targetClassList = event.target.classList;
1211
+ if (!this.isMultiSelectStatus && targetClassList.contains("moveable-area")) {
1111
1212
  return;
1112
1213
  }
1113
- if (event.target.className.indexOf("moveable-control") !== -1) {
1214
+ if (targetClassList.contains("moveable-control") || isMoveableButton(event.target)) {
1114
1215
  return;
1115
1216
  }
1116
1217
  this.content.removeEventListener("mousemove", this.highlightHandler);
@@ -1372,13 +1473,11 @@
1372
1473
  runtime = null;
1373
1474
  iframe;
1374
1475
  runtimeUrl;
1375
- core;
1376
1476
  render;
1377
- constructor({ core }) {
1477
+ constructor({ runtimeUrl, render }) {
1378
1478
  super();
1379
- this.core = core;
1380
- this.runtimeUrl = core.config.runtimeUrl || "";
1381
- this.render = core.config.render;
1479
+ this.runtimeUrl = runtimeUrl || "";
1480
+ this.render = render;
1382
1481
  this.iframe = globalThis.document.createElement("iframe");
1383
1482
  this.iframe.src = utils.isSameDomain(this.runtimeUrl) ? this.runtimeUrl : "";
1384
1483
  this.iframe.style.cssText = `
@@ -1421,6 +1520,9 @@
1421
1520
  this.on("runtime-ready", listener);
1422
1521
  });
1423
1522
  };
1523
+ getDocument() {
1524
+ return this.contentWindow?.document;
1525
+ }
1424
1526
  destroy() {
1425
1527
  this.iframe?.removeEventListener("load", this.loadHandler);
1426
1528
  this.contentWindow = null;
@@ -1435,7 +1537,7 @@
1435
1537
  if (!this.contentWindow)
1436
1538
  return;
1437
1539
  if (this.render) {
1438
- const el = await this.render(this.core);
1540
+ const el = await this.render();
1439
1541
  if (el) {
1440
1542
  this.contentWindow.document?.body?.appendChild(el);
1441
1543
  }
@@ -1472,6 +1574,7 @@
1472
1574
  containerHighlightType;
1473
1575
  isContainer;
1474
1576
  canSelect;
1577
+ pageResizeObserver = null;
1475
1578
  constructor(config) {
1476
1579
  super();
1477
1580
  this.config = config;
@@ -1481,8 +1584,8 @@
1481
1584
  this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
1482
1585
  this.containerHighlightDuration = config.containerHighlightDuration || 800;
1483
1586
  this.containerHighlightType = config.containerHighlightType;
1484
- this.renderer = new StageRender({ core: this });
1485
- this.mask = new StageMask({ core: this });
1587
+ this.renderer = new StageRender({ runtimeUrl: config.runtimeUrl, render: this.render.bind(this) });
1588
+ this.mask = new StageMask();
1486
1589
  this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
1487
1590
  this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
1488
1591
  this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
@@ -1491,6 +1594,7 @@
1491
1594
  });
1492
1595
  this.renderer.on("page-el-update", (el) => {
1493
1596
  this.mask?.observe(el);
1597
+ this.observePageResize(el);
1494
1598
  });
1495
1599
  this.mask.on("beforeSelect", async (event) => {
1496
1600
  this.clearSelectStatus("multiSelect");
@@ -1532,11 +1636,14 @@
1532
1636
  this.selectedDomList.push(el);
1533
1637
  }
1534
1638
  this.multiSelect(this.selectedDomList);
1639
+ this.emit("multiSelect", this.selectedDomList);
1535
1640
  });
1536
1641
  this.dr.on("update", (data) => {
1537
1642
  setTimeout(() => this.emit("update", data));
1538
1643
  }).on("sort", (data) => {
1539
1644
  setTimeout(() => this.emit("sort", data));
1645
+ }).on("select-parent", () => {
1646
+ this.emit("select-parent");
1540
1647
  });
1541
1648
  this.multiDr.on("update", (data) => {
1542
1649
  setTimeout(() => this.emit("update", data));
@@ -1548,7 +1655,6 @@
1548
1655
  }
1549
1656
  getElementsFromPoint(event) {
1550
1657
  const { renderer, zoom } = this;
1551
- const doc = renderer.contentWindow?.document;
1552
1658
  let x = event.clientX;
1553
1659
  let y = event.clientY;
1554
1660
  if (renderer.iframe) {
@@ -1558,7 +1664,7 @@
1558
1664
  y = y - rect.top;
1559
1665
  }
1560
1666
  }
1561
- return doc?.elementsFromPoint(x / zoom, y / zoom);
1667
+ return renderer.getDocument()?.elementsFromPoint(x / zoom, y / zoom);
1562
1668
  }
1563
1669
  async getElementFromPoint(event) {
1564
1670
  const els = this.getElementsFromPoint(event);
@@ -1594,28 +1700,28 @@
1594
1700
  this.mask.setLayout(el);
1595
1701
  this.dr.select(el, event);
1596
1702
  if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1597
- this.mask.intersectionObserver?.observe(el);
1703
+ this.mask.observerIntersection(el);
1598
1704
  }
1599
1705
  this.selectedDom = el;
1600
- if (this.renderer.contentWindow) {
1601
- removeSelectedClassName(this.renderer.contentWindow.document);
1706
+ const doc = this.renderer.getDocument();
1707
+ if (doc) {
1708
+ removeSelectedClassName(doc);
1602
1709
  if (this.selectedDom) {
1603
- addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
1710
+ addSelectedClassName(this.selectedDom, doc);
1604
1711
  }
1605
1712
  }
1606
1713
  }
1607
1714
  async multiSelect(idOrElList) {
1608
1715
  this.clearSelectStatus("select");
1609
- const elList = await Promise.all(idOrElList.map(async (idOrEl) => await this.getTargetElement(idOrEl)));
1610
- this.multiDr.multiSelect(elList);
1611
- this.emit("multiSelect", elList);
1716
+ this.selectedDomList = await Promise.all(idOrElList.map(async (idOrEl) => await this.getTargetElement(idOrEl)));
1717
+ this.multiDr.multiSelect(this.selectedDomList);
1612
1718
  }
1613
1719
  update(data) {
1614
1720
  const { config } = data;
1615
1721
  return this.renderer?.getRuntime().then((runtime) => {
1616
1722
  runtime?.update?.(data);
1617
1723
  setTimeout(() => {
1618
- const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
1724
+ const el = this.renderer.getDocument()?.getElementById(`${config.id}`);
1619
1725
  if (el && el.id === this.selectedDom?.id) {
1620
1726
  this.selectedDom = el;
1621
1727
  this.mask.setLayout(el);
@@ -1671,7 +1777,7 @@
1671
1777
  async addContainerHighlightClassName(event, exclude) {
1672
1778
  const els = this.getElementsFromPoint(event);
1673
1779
  const { renderer } = this;
1674
- const doc = renderer.contentWindow?.document;
1780
+ const doc = renderer.getDocument();
1675
1781
  if (!doc)
1676
1782
  return;
1677
1783
  for (const el of els) {
@@ -1687,17 +1793,35 @@
1687
1793
  }, this.containerHighlightDuration);
1688
1794
  }
1689
1795
  destroy() {
1690
- const { mask, renderer, dr, highlightLayer } = this;
1796
+ const { mask, renderer, dr, highlightLayer, pageResizeObserver } = this;
1691
1797
  renderer.destroy();
1692
1798
  mask.destroy();
1693
1799
  dr.destroy();
1694
1800
  highlightLayer.destroy();
1801
+ pageResizeObserver?.disconnect();
1695
1802
  this.removeAllListeners();
1696
1803
  this.container = void 0;
1697
1804
  }
1805
+ observePageResize(page) {
1806
+ if (typeof ResizeObserver !== "undefined") {
1807
+ this.pageResizeObserver = new ResizeObserver((entries) => {
1808
+ this.mask.pageResize(entries);
1809
+ if (this.dr.moveable) {
1810
+ this.dr.updateMoveable();
1811
+ }
1812
+ });
1813
+ this.pageResizeObserver.observe(page);
1814
+ }
1815
+ }
1816
+ async render() {
1817
+ if (this.config?.render) {
1818
+ return await this.config.render(this);
1819
+ }
1820
+ return null;
1821
+ }
1698
1822
  async getTargetElement(idOrEl) {
1699
1823
  if (typeof idOrEl === "string" || typeof idOrEl === "number") {
1700
- const el = this.renderer.contentWindow?.document.getElementById(`${idOrEl}`);
1824
+ const el = this.renderer.getDocument()?.getElementById(`${idOrEl}`);
1701
1825
  if (!el)
1702
1826
  throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
1703
1827
  return el;
@@ -1734,6 +1858,7 @@
1734
1858
  exports.isAbsolute = isAbsolute;
1735
1859
  exports.isFixed = isFixed;
1736
1860
  exports.isFixedParent = isFixedParent;
1861
+ exports.isMoveableButton = isMoveableButton;
1737
1862
  exports.isRelative = isRelative;
1738
1863
  exports.isStatic = isStatic;
1739
1864
  exports.removeSelectedClassName = removeSelectedClassName;