@tmagic/stage 1.2.0-beta.6 → 1.2.0-beta.8

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.
@@ -39,6 +39,77 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
39
39
  })(Mode || {});
40
40
  const SELECTED_CLASS = "tmagic-stage-selected-area";
41
41
 
42
+ const selectParentAbles = (dr) => ({
43
+ name: "selectParent",
44
+ props: {},
45
+ events: {},
46
+ render(moveable, React) {
47
+ const rect = moveable.getRect();
48
+ const { pos2 } = moveable.state;
49
+ const editableViewer = moveable.useCSS(
50
+ "div",
51
+ `
52
+ {
53
+ position: absolute;
54
+ left: 0px;
55
+ top: 0px;
56
+ will-change: transform;
57
+ transform-origin: 0px 0px;
58
+ display: flex;
59
+ }
60
+ .moveable-button {
61
+ width: 20px;
62
+ height: 20px;
63
+ background: #4af;
64
+ border-radius: 4px;
65
+ appearance: none;
66
+ border: 0;
67
+ color: white;
68
+ font-size: 12px;
69
+ font-weight: bold;
70
+ }
71
+ `
72
+ );
73
+ return React.createElement(
74
+ editableViewer,
75
+ {
76
+ className: "moveable-editable",
77
+ style: {
78
+ transform: `translate(${pos2[0] - 25}px, ${pos2[1] - 30}px) rotate(${rect.rotation}deg) translate(10px)`
79
+ }
80
+ },
81
+ React.createElement(
82
+ "button",
83
+ {
84
+ className: "moveable-button",
85
+ title: "\u9009\u4E2D\u7236\u7EC4\u4EF6",
86
+ onClick: () => {
87
+ dr.emit("select-parent");
88
+ }
89
+ },
90
+ React.createElement(
91
+ "svg",
92
+ {
93
+ width: "1em",
94
+ height: "1em",
95
+ viewBox: "0 0 16 16",
96
+ fill: "none",
97
+ xmlns: "http://www.w3.org/2000/svg",
98
+ style: {
99
+ transform: "rotate(90deg)"
100
+ }
101
+ },
102
+ React.createElement("path", {
103
+ 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",
104
+ fill: "currentColor",
105
+ fillOpacity: "0.9"
106
+ })
107
+ )
108
+ )
109
+ );
110
+ }
111
+ });
112
+
42
113
  var ContainerHighlightType = /* @__PURE__ */ ((ContainerHighlightType2) => {
43
114
  ContainerHighlightType2["DEFAULT"] = "default";
44
115
  ContainerHighlightType2["ALT"] = "alt";
@@ -135,6 +206,8 @@ const getScrollParent = (element, includeHidden = false) => {
135
206
  return null;
136
207
  for (let parent = element; parent.parentElement; ) {
137
208
  parent = parent.parentElement;
209
+ if (parent.tagName === "HTML")
210
+ return parent;
138
211
  style = getComputedStyle(parent);
139
212
  if (isAbsolute(style) && isStatic(style))
140
213
  continue;
@@ -219,6 +292,7 @@ const up = (deltaTop, target) => {
219
292
  dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id
220
293
  };
221
294
  };
295
+ const isMoveableButton = (target) => target.classList.contains("moveable-button") || target.parentElement?.classList.contains("moveable-button");
222
296
 
223
297
  class StageDragResize extends EventEmitter {
224
298
  core;
@@ -664,6 +738,10 @@ class StageDragResize extends EventEmitter {
664
738
  bottom: isSortable ? void 0 : this.container.clientHeight,
665
739
  ...moveableOptions.bounds || {}
666
740
  },
741
+ props: {
742
+ selectParent: true
743
+ },
744
+ ables: [selectParentAbles(this)],
667
745
  ...options,
668
746
  ...moveableOptions
669
747
  };
@@ -794,6 +872,7 @@ class Rule extends EventEmitter$1 {
794
872
  verticalGuidelines = [];
795
873
  container;
796
874
  containerResizeObserver;
875
+ isShowGuides = true;
797
876
  constructor(container) {
798
877
  super();
799
878
  this.container = container;
@@ -807,12 +886,13 @@ class Rule extends EventEmitter$1 {
807
886
  });
808
887
  this.containerResizeObserver.observe(this.container);
809
888
  }
810
- showGuides(show = true) {
889
+ showGuides(isShowGuides = true) {
890
+ this.isShowGuides = isShowGuides;
811
891
  this.hGuides.setState({
812
- showGuides: show
892
+ showGuides: isShowGuides
813
893
  });
814
894
  this.vGuides.setState({
815
- showGuides: show
895
+ showGuides: isShowGuides
816
896
  });
817
897
  }
818
898
  setGuides([hLines, vLines]) {
@@ -882,7 +962,8 @@ class Rule extends EventEmitter$1 {
882
962
  backgroundColor: "#fff",
883
963
  lineColor: "#000",
884
964
  textColor: "#000",
885
- style: this.getGuidesStyle(type)
965
+ style: this.getGuidesStyle(type),
966
+ showGuides: this.isShowGuides
886
967
  });
887
968
  hGuidesChangeGuidesHandler = (e) => {
888
969
  this.horizontalGuidelines = e.guides;
@@ -933,9 +1014,7 @@ const createWrapper = () => {
933
1014
  class StageMask extends Rule {
934
1015
  content = createContent();
935
1016
  wrapper;
936
- core;
937
1017
  page = null;
938
- pageScrollParent = null;
939
1018
  scrollTop = 0;
940
1019
  scrollLeft = 0;
941
1020
  width = 0;
@@ -944,37 +1023,21 @@ class StageMask extends Rule {
944
1023
  wrapperWidth = 0;
945
1024
  maxScrollTop = 0;
946
1025
  maxScrollLeft = 0;
947
- intersectionObserver = null;
948
1026
  isMultiSelectStatus = false;
949
1027
  mode = Mode.ABSOLUTE;
950
- pageResizeObserver = null;
1028
+ pageScrollParent = null;
1029
+ intersectionObserver = null;
951
1030
  wrapperResizeObserver = null;
952
1031
  highlightHandler = throttle((event) => {
953
1032
  this.emit("highlight", event);
954
1033
  }, throttleTime);
955
- constructor(config) {
1034
+ constructor() {
956
1035
  const wrapper = createWrapper();
957
1036
  super(wrapper);
958
1037
  this.wrapper = wrapper;
959
- this.core = config.core;
960
- this.content.addEventListener("mousedown", this.mouseDownHandler);
1038
+ this.initContentEventListener();
961
1039
  this.wrapper.appendChild(this.content);
962
- this.content.addEventListener("wheel", this.mouseWheelHandler);
963
- this.content.addEventListener("mousemove", this.highlightHandler);
964
- this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
965
- const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
966
- const ctrl = isMac ? "meta" : "ctrl";
967
- KeyController.global.keydown(ctrl, (e) => {
968
- e.inputEvent.preventDefault();
969
- this.isMultiSelectStatus = true;
970
- });
971
- KeyController.global.on("blur", () => {
972
- this.isMultiSelectStatus = false;
973
- });
974
- KeyController.global.keyup(ctrl, (e) => {
975
- e.inputEvent.preventDefault();
976
- this.isMultiSelectStatus = false;
977
- });
1040
+ this.initMultiSelectEvent();
978
1041
  }
979
1042
  setMode(mode) {
980
1043
  this.mode = mode;
@@ -991,9 +1054,66 @@ class StageMask extends Rule {
991
1054
  if (!page)
992
1055
  return;
993
1056
  this.page = page;
994
- this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
995
- this.pageResizeObserver?.disconnect();
1057
+ this.initObserverIntersection();
1058
+ this.initObserverWrapper();
1059
+ }
1060
+ pageResize(entries) {
1061
+ const [entry] = entries;
1062
+ const { clientHeight, clientWidth } = entry.target;
1063
+ this.setHeight(clientHeight);
1064
+ this.setWidth(clientWidth);
1065
+ this.scroll();
1066
+ }
1067
+ observerIntersection(el) {
1068
+ this.intersectionObserver?.observe(el);
1069
+ }
1070
+ mount(el) {
1071
+ if (!this.content)
1072
+ throw new Error("content \u4E0D\u5B58\u5728");
1073
+ el.appendChild(this.wrapper);
1074
+ }
1075
+ setLayout(el) {
1076
+ this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
1077
+ }
1078
+ scrollIntoView(el) {
1079
+ el.scrollIntoView();
1080
+ if (!this.pageScrollParent)
1081
+ return;
1082
+ this.scrollLeft = this.pageScrollParent.scrollLeft;
1083
+ this.scrollTop = this.pageScrollParent.scrollTop;
1084
+ this.scroll();
1085
+ }
1086
+ destroy() {
1087
+ this.content?.remove();
1088
+ this.page = null;
1089
+ this.pageScrollParent = null;
996
1090
  this.wrapperResizeObserver?.disconnect();
1091
+ this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
1092
+ super.destroy();
1093
+ }
1094
+ initContentEventListener() {
1095
+ this.content.addEventListener("mousedown", this.mouseDownHandler);
1096
+ this.content.addEventListener("wheel", this.mouseWheelHandler);
1097
+ this.content.addEventListener("mousemove", this.highlightHandler);
1098
+ this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
1099
+ }
1100
+ initMultiSelectEvent() {
1101
+ const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
1102
+ const ctrl = isMac ? "meta" : "ctrl";
1103
+ KeyController.global.keydown(ctrl, (e) => {
1104
+ e.inputEvent.preventDefault();
1105
+ this.isMultiSelectStatus = true;
1106
+ });
1107
+ KeyController.global.on("blur", () => {
1108
+ this.isMultiSelectStatus = false;
1109
+ });
1110
+ KeyController.global.keyup(ctrl, (e) => {
1111
+ e.inputEvent.preventDefault();
1112
+ this.isMultiSelectStatus = false;
1113
+ });
1114
+ }
1115
+ initObserverIntersection() {
1116
+ this.pageScrollParent = getScrollParent(this.page) || null;
997
1117
  this.intersectionObserver?.disconnect();
998
1118
  if (typeof IntersectionObserver !== "undefined") {
999
1119
  this.intersectionObserver = new IntersectionObserver(
@@ -1013,18 +1133,10 @@ class StageMask extends Rule {
1013
1133
  }
1014
1134
  );
1015
1135
  }
1136
+ }
1137
+ initObserverWrapper() {
1138
+ this.wrapperResizeObserver?.disconnect();
1016
1139
  if (typeof ResizeObserver !== "undefined") {
1017
- this.pageResizeObserver = new ResizeObserver((entries) => {
1018
- const [entry] = entries;
1019
- const { clientHeight, clientWidth } = entry.target;
1020
- this.setHeight(clientHeight);
1021
- this.setWidth(clientWidth);
1022
- this.scroll();
1023
- if (this.core.dr.moveable) {
1024
- this.core.dr.updateMoveable();
1025
- }
1026
- });
1027
- this.pageResizeObserver.observe(page);
1028
1140
  this.wrapperResizeObserver = new ResizeObserver((entries) => {
1029
1141
  const [entry] = entries;
1030
1142
  const { clientHeight, clientWidth } = entry.target;
@@ -1036,31 +1148,6 @@ class StageMask extends Rule {
1036
1148
  this.wrapperResizeObserver.observe(this.wrapper);
1037
1149
  }
1038
1150
  }
1039
- mount(el) {
1040
- if (!this.content)
1041
- throw new Error("content \u4E0D\u5B58\u5728");
1042
- el.appendChild(this.wrapper);
1043
- }
1044
- setLayout(el) {
1045
- this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
1046
- }
1047
- scrollIntoView(el) {
1048
- el.scrollIntoView();
1049
- if (!this.pageScrollParent)
1050
- return;
1051
- this.scrollLeft = this.pageScrollParent.scrollLeft;
1052
- this.scrollTop = this.pageScrollParent.scrollTop;
1053
- this.scroll();
1054
- }
1055
- destroy() {
1056
- this.content?.remove();
1057
- this.page = null;
1058
- this.pageScrollParent = null;
1059
- this.pageResizeObserver?.disconnect();
1060
- this.wrapperResizeObserver?.disconnect();
1061
- this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
1062
- super.destroy();
1063
- }
1064
1151
  scroll() {
1065
1152
  this.fixScrollValue();
1066
1153
  let { scrollLeft, scrollTop } = this;
@@ -1112,10 +1199,13 @@ class StageMask extends Rule {
1112
1199
  event.stopPropagation();
1113
1200
  if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
1114
1201
  return;
1115
- if (!this.isMultiSelectStatus && event.target.className.indexOf("moveable-area") !== -1) {
1202
+ if (!event.target)
1203
+ return;
1204
+ const targetClassList = event.target.classList;
1205
+ if (!this.isMultiSelectStatus && targetClassList.contains("moveable-area")) {
1116
1206
  return;
1117
1207
  }
1118
- if (event.target.className.indexOf("moveable-control") !== -1) {
1208
+ if (targetClassList.contains("moveable-control") || isMoveableButton(event.target)) {
1119
1209
  return;
1120
1210
  }
1121
1211
  this.content.removeEventListener("mousemove", this.highlightHandler);
@@ -1377,13 +1467,11 @@ class StageRender extends EventEmitter {
1377
1467
  runtime = null;
1378
1468
  iframe;
1379
1469
  runtimeUrl;
1380
- core;
1381
1470
  render;
1382
- constructor({ core }) {
1471
+ constructor({ runtimeUrl, render }) {
1383
1472
  super();
1384
- this.core = core;
1385
- this.runtimeUrl = core.config.runtimeUrl || "";
1386
- this.render = core.config.render;
1473
+ this.runtimeUrl = runtimeUrl || "";
1474
+ this.render = render;
1387
1475
  this.iframe = globalThis.document.createElement("iframe");
1388
1476
  this.iframe.src = isSameDomain(this.runtimeUrl) ? this.runtimeUrl : "";
1389
1477
  this.iframe.style.cssText = `
@@ -1426,6 +1514,9 @@ class StageRender extends EventEmitter {
1426
1514
  this.on("runtime-ready", listener);
1427
1515
  });
1428
1516
  };
1517
+ getDocument() {
1518
+ return this.contentWindow?.document;
1519
+ }
1429
1520
  destroy() {
1430
1521
  this.iframe?.removeEventListener("load", this.loadHandler);
1431
1522
  this.contentWindow = null;
@@ -1440,7 +1531,7 @@ class StageRender extends EventEmitter {
1440
1531
  if (!this.contentWindow)
1441
1532
  return;
1442
1533
  if (this.render) {
1443
- const el = await this.render(this.core);
1534
+ const el = await this.render();
1444
1535
  if (el) {
1445
1536
  this.contentWindow.document?.body?.appendChild(el);
1446
1537
  }
@@ -1477,6 +1568,7 @@ class StageCore extends EventEmitter {
1477
1568
  containerHighlightType;
1478
1569
  isContainer;
1479
1570
  canSelect;
1571
+ pageResizeObserver = null;
1480
1572
  constructor(config) {
1481
1573
  super();
1482
1574
  this.config = config;
@@ -1486,8 +1578,8 @@ class StageCore extends EventEmitter {
1486
1578
  this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
1487
1579
  this.containerHighlightDuration = config.containerHighlightDuration || 800;
1488
1580
  this.containerHighlightType = config.containerHighlightType;
1489
- this.renderer = new StageRender({ core: this });
1490
- this.mask = new StageMask({ core: this });
1581
+ this.renderer = new StageRender({ runtimeUrl: config.runtimeUrl, render: this.render.bind(this) });
1582
+ this.mask = new StageMask();
1491
1583
  this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
1492
1584
  this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
1493
1585
  this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
@@ -1496,6 +1588,7 @@ class StageCore extends EventEmitter {
1496
1588
  });
1497
1589
  this.renderer.on("page-el-update", (el) => {
1498
1590
  this.mask?.observe(el);
1591
+ this.observePageResize(el);
1499
1592
  });
1500
1593
  this.mask.on("beforeSelect", async (event) => {
1501
1594
  this.clearSelectStatus("multiSelect");
@@ -1543,6 +1636,8 @@ class StageCore extends EventEmitter {
1543
1636
  setTimeout(() => this.emit("update", data));
1544
1637
  }).on("sort", (data) => {
1545
1638
  setTimeout(() => this.emit("sort", data));
1639
+ }).on("select-parent", () => {
1640
+ this.emit("select-parent");
1546
1641
  });
1547
1642
  this.multiDr.on("update", (data) => {
1548
1643
  setTimeout(() => this.emit("update", data));
@@ -1554,7 +1649,6 @@ class StageCore extends EventEmitter {
1554
1649
  }
1555
1650
  getElementsFromPoint(event) {
1556
1651
  const { renderer, zoom } = this;
1557
- const doc = renderer.contentWindow?.document;
1558
1652
  let x = event.clientX;
1559
1653
  let y = event.clientY;
1560
1654
  if (renderer.iframe) {
@@ -1564,7 +1658,7 @@ class StageCore extends EventEmitter {
1564
1658
  y = y - rect.top;
1565
1659
  }
1566
1660
  }
1567
- return doc?.elementsFromPoint(x / zoom, y / zoom);
1661
+ return renderer.getDocument()?.elementsFromPoint(x / zoom, y / zoom);
1568
1662
  }
1569
1663
  async getElementFromPoint(event) {
1570
1664
  const els = this.getElementsFromPoint(event);
@@ -1600,13 +1694,14 @@ class StageCore extends EventEmitter {
1600
1694
  this.mask.setLayout(el);
1601
1695
  this.dr.select(el, event);
1602
1696
  if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
1603
- this.mask.intersectionObserver?.observe(el);
1697
+ this.mask.observerIntersection(el);
1604
1698
  }
1605
1699
  this.selectedDom = el;
1606
- if (this.renderer.contentWindow) {
1607
- removeSelectedClassName(this.renderer.contentWindow.document);
1700
+ const doc = this.renderer.getDocument();
1701
+ if (doc) {
1702
+ removeSelectedClassName(doc);
1608
1703
  if (this.selectedDom) {
1609
- addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
1704
+ addSelectedClassName(this.selectedDom, doc);
1610
1705
  }
1611
1706
  }
1612
1707
  }
@@ -1620,7 +1715,7 @@ class StageCore extends EventEmitter {
1620
1715
  return this.renderer?.getRuntime().then((runtime) => {
1621
1716
  runtime?.update?.(data);
1622
1717
  setTimeout(() => {
1623
- const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
1718
+ const el = this.renderer.getDocument()?.getElementById(`${config.id}`);
1624
1719
  if (el && el.id === this.selectedDom?.id) {
1625
1720
  this.selectedDom = el;
1626
1721
  this.mask.setLayout(el);
@@ -1676,7 +1771,7 @@ class StageCore extends EventEmitter {
1676
1771
  async addContainerHighlightClassName(event, exclude) {
1677
1772
  const els = this.getElementsFromPoint(event);
1678
1773
  const { renderer } = this;
1679
- const doc = renderer.contentWindow?.document;
1774
+ const doc = renderer.getDocument();
1680
1775
  if (!doc)
1681
1776
  return;
1682
1777
  for (const el of els) {
@@ -1692,17 +1787,35 @@ class StageCore extends EventEmitter {
1692
1787
  }, this.containerHighlightDuration);
1693
1788
  }
1694
1789
  destroy() {
1695
- const { mask, renderer, dr, highlightLayer } = this;
1790
+ const { mask, renderer, dr, highlightLayer, pageResizeObserver } = this;
1696
1791
  renderer.destroy();
1697
1792
  mask.destroy();
1698
1793
  dr.destroy();
1699
1794
  highlightLayer.destroy();
1795
+ pageResizeObserver?.disconnect();
1700
1796
  this.removeAllListeners();
1701
1797
  this.container = void 0;
1702
1798
  }
1799
+ observePageResize(page) {
1800
+ if (typeof ResizeObserver !== "undefined") {
1801
+ this.pageResizeObserver = new ResizeObserver((entries) => {
1802
+ this.mask.pageResize(entries);
1803
+ if (this.dr.moveable) {
1804
+ this.dr.updateMoveable();
1805
+ }
1806
+ });
1807
+ this.pageResizeObserver.observe(page);
1808
+ }
1809
+ }
1810
+ async render() {
1811
+ if (this.config?.render) {
1812
+ return await this.config.render(this);
1813
+ }
1814
+ return null;
1815
+ }
1703
1816
  async getTargetElement(idOrEl) {
1704
1817
  if (typeof idOrEl === "string" || typeof idOrEl === "number") {
1705
- const el = this.renderer.contentWindow?.document.getElementById(`${idOrEl}`);
1818
+ const el = this.renderer.getDocument()?.getElementById(`${idOrEl}`);
1706
1819
  if (!el)
1707
1820
  throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
1708
1821
  return el;
@@ -1711,5 +1824,5 @@ class StageCore extends EventEmitter {
1711
1824
  }
1712
1825
  }
1713
1826
 
1714
- export { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, DEFAULT_ZOOM, DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, HIGHLIGHT_EL_ID_PREFIX, Mode, MouseButton, PAGE_CLASS, SELECTED_CLASS, StageDragResize, StageDragStatus, StageMask, StageRender, ZIndex, addSelectedClassName, calcValueByFontsize, StageCore as default, down, getAbsolutePosition, getMode, getOffset, getScrollParent, getTargetElStyle, isAbsolute, isFixed, isFixedParent, isRelative, isStatic, removeSelectedClassName, up };
1827
+ export { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, DEFAULT_ZOOM, DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, HIGHLIGHT_EL_ID_PREFIX, Mode, MouseButton, PAGE_CLASS, SELECTED_CLASS, StageDragResize, StageDragStatus, StageMask, StageRender, ZIndex, addSelectedClassName, calcValueByFontsize, StageCore as default, down, getAbsolutePosition, getMode, getOffset, getScrollParent, getTargetElStyle, isAbsolute, isFixed, isFixedParent, isMoveableButton, isRelative, isStatic, removeSelectedClassName, up };
1715
1828
  //# sourceMappingURL=tmagic-stage.mjs.map