@tmagic/editor 1.3.11 → 1.3.12

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.
@@ -13,7 +13,7 @@ import Gesto from 'gesto';
13
13
  import Moveable from 'moveable';
14
14
  import { Watcher, DepTargetType, createRelatedCompTarget, createCodeBlockTarget, createDataSourceTarget, createDataSourceMethodTarget, createDataSourceCondTarget } from '@tmagic/dep';
15
15
  export { DepTargetType } from '@tmagic/dep';
16
- import StageCore, { GuidesType, getOffset, calcValueByFontsize, CONTAINER_HIGHLIGHT_CLASS_NAME, ContainerHighlightType, RenderType } from '@tmagic/stage';
16
+ import StageCore, { GuidesType, getOffset, calcValueByFontsize, RenderType, CONTAINER_HIGHLIGHT_CLASS_NAME, ContainerHighlightType } from '@tmagic/stage';
17
17
  import { EventEmitter } from 'events';
18
18
  import { DEFAULT_EVENTS, DEFAULT_METHODS } from '@tmagic/core';
19
19
  import KeyController from 'keycon';
@@ -1850,6 +1850,197 @@ class Dep extends BaseService {
1850
1850
  }
1851
1851
  const depService = new Dep();
1852
1852
 
1853
+ class Props extends BaseService {
1854
+ state = reactive({
1855
+ propsConfigMap: {},
1856
+ propsValueMap: {},
1857
+ relateIdMap: {}
1858
+ });
1859
+ constructor() {
1860
+ super([
1861
+ { name: "setPropsConfig", isAsync: true },
1862
+ { name: "getPropsConfig", isAsync: true },
1863
+ { name: "setPropsValue", isAsync: true },
1864
+ { name: "getPropsValue", isAsync: true },
1865
+ { name: "createId", isAsync: false },
1866
+ { name: "setNewItemId", isAsync: true },
1867
+ { name: "fillConfig", isAsync: true },
1868
+ { name: "getDefaultPropsValue", isAsync: true }
1869
+ ]);
1870
+ }
1871
+ setPropsConfigs(configs) {
1872
+ Object.keys(configs).forEach((type) => {
1873
+ this.setPropsConfig(toLine(type), configs[type]);
1874
+ });
1875
+ this.emit("props-configs-change");
1876
+ }
1877
+ async fillConfig(config) {
1878
+ return fillConfig(config);
1879
+ }
1880
+ /**
1881
+ * 为指定类型组件设置组件属性表单配置
1882
+ * @param type 组件类型
1883
+ * @param config 组件属性表单配置
1884
+ */
1885
+ async setPropsConfig(type, config) {
1886
+ this.state.propsConfigMap[type] = await this.fillConfig(Array.isArray(config) ? config : [config]);
1887
+ }
1888
+ /**
1889
+ * 获取指点类型的组件属性表单配置
1890
+ * @param type 组件类型
1891
+ * @returns 组件属性表单配置
1892
+ */
1893
+ async getPropsConfig(type) {
1894
+ if (type === "area") {
1895
+ return await this.getPropsConfig("button");
1896
+ }
1897
+ return cloneDeep(this.state.propsConfigMap[type] || await this.fillConfig([]));
1898
+ }
1899
+ setPropsValues(values) {
1900
+ Object.keys(values).forEach((type) => {
1901
+ this.setPropsValue(toLine(type), values[type]);
1902
+ });
1903
+ }
1904
+ /**
1905
+ * 为指点类型组件设置组件初始值
1906
+ * @param type 组件类型
1907
+ * @param value 组件初始值
1908
+ */
1909
+ async setPropsValue(type, value) {
1910
+ this.state.propsValueMap[type] = value;
1911
+ }
1912
+ /**
1913
+ * 获取指定类型的组件初始值
1914
+ * @param type 组件类型
1915
+ * @returns 组件初始值
1916
+ */
1917
+ async getPropsValue(type, { inputEvent, ...defaultValue } = {}) {
1918
+ if (type === "area") {
1919
+ const value = await this.getPropsValue("button");
1920
+ value.className = "action-area";
1921
+ value.text = "";
1922
+ if (value.style) {
1923
+ value.style.backgroundColor = "rgba(255, 255, 255, 0)";
1924
+ }
1925
+ return value;
1926
+ }
1927
+ const [id, defaultPropsValue, data] = await Promise.all([
1928
+ this.createId(type),
1929
+ this.getDefaultPropsValue(type),
1930
+ this.setNewItemId(
1931
+ cloneDeep({
1932
+ type,
1933
+ ...defaultValue
1934
+ })
1935
+ )
1936
+ ]);
1937
+ return {
1938
+ id,
1939
+ ...defaultPropsValue,
1940
+ ...mergeWith({}, cloneDeep(this.state.propsValueMap[type] || {}), data)
1941
+ };
1942
+ }
1943
+ async createId(type) {
1944
+ return `${type}_${guid()}`;
1945
+ }
1946
+ /**
1947
+ * 将组件与组件的子元素配置中的id都设置成一个新的ID
1948
+ * 如果没有相同ID并且force为false则保持不变
1949
+ * @param {Object} config 组件配置
1950
+ * @param {Boolean} force 是否强制设置新的ID
1951
+ */
1952
+ /* eslint no-param-reassign: ["error", { "props": false }] */
1953
+ async setNewItemId(config, force = true) {
1954
+ if (force || editorService.getNodeById(config.id)) {
1955
+ const newId = await this.createId(config.type || "component");
1956
+ this.setRelateId(config.id, newId);
1957
+ config.id = newId;
1958
+ }
1959
+ if (config.items && Array.isArray(config.items)) {
1960
+ for (const item of config.items) {
1961
+ await this.setNewItemId(item);
1962
+ }
1963
+ }
1964
+ return config;
1965
+ }
1966
+ /**
1967
+ * 获取默认属性配置
1968
+ * @param type 组件类型
1969
+ * @returns Object
1970
+ */
1971
+ async getDefaultPropsValue(type) {
1972
+ return ["page", "container"].includes(type) ? {
1973
+ type,
1974
+ layout: "absolute",
1975
+ style: {},
1976
+ name: type,
1977
+ items: []
1978
+ } : {
1979
+ type,
1980
+ style: {},
1981
+ name: type
1982
+ };
1983
+ }
1984
+ resetState() {
1985
+ this.state.propsConfigMap = {};
1986
+ this.state.propsValueMap = {};
1987
+ }
1988
+ /**
1989
+ * 替换关联ID
1990
+ * @param originConfigs 原组件配置
1991
+ * @param targetConfigs 待替换的组件配置
1992
+ */
1993
+ replaceRelateId(originConfigs, targetConfigs) {
1994
+ const relateIdMap = this.getRelateIdMap();
1995
+ if (Object.keys(relateIdMap).length === 0)
1996
+ return;
1997
+ const target = depService.getTarget(DepTargetType.RELATED_COMP_WHEN_COPY, DepTargetType.RELATED_COMP_WHEN_COPY);
1998
+ if (!target)
1999
+ return;
2000
+ originConfigs.forEach((config) => {
2001
+ const newId = relateIdMap[config.id];
2002
+ const targetConfig = targetConfigs.find((targetConfig2) => targetConfig2.id === newId);
2003
+ if (!targetConfig)
2004
+ return;
2005
+ target.deps[config.id]?.keys?.forEach((fullKey) => {
2006
+ const relateOriginId = getValueByKeyPath(fullKey, config);
2007
+ const relateTargetId = relateIdMap[relateOriginId];
2008
+ if (!relateTargetId)
2009
+ return;
2010
+ setValueByKeyPath(fullKey, relateTargetId, targetConfig);
2011
+ });
2012
+ });
2013
+ }
2014
+ /**
2015
+ * 清除setNewItemId前后映射关系
2016
+ */
2017
+ clearRelateId() {
2018
+ this.state.relateIdMap = {};
2019
+ }
2020
+ destroy() {
2021
+ this.resetState();
2022
+ this.removeAllListeners();
2023
+ this.removeAllPlugins();
2024
+ }
2025
+ /**
2026
+ * 获取setNewItemId前后映射关系
2027
+ * @param oldId 原组件ID
2028
+ * @returns 新旧ID映射
2029
+ */
2030
+ getRelateIdMap() {
2031
+ return this.state.relateIdMap;
2032
+ }
2033
+ /**
2034
+ * 记录setNewItemId前后映射关系
2035
+ * @param oldId 原组件ID
2036
+ * @param newId 分配的新ID
2037
+ */
2038
+ setRelateId(oldId, newId) {
2039
+ this.state.relateIdMap[oldId] = newId;
2040
+ }
2041
+ }
2042
+ const propsService = new Props();
2043
+
1853
2044
  class UndoRedo {
1854
2045
  elementList;
1855
2046
  listCursor;
@@ -2104,197 +2295,6 @@ class WebStorage extends BaseService {
2104
2295
  }
2105
2296
  const storageService = new WebStorage();
2106
2297
 
2107
- class Props extends BaseService {
2108
- state = reactive({
2109
- propsConfigMap: {},
2110
- propsValueMap: {},
2111
- relateIdMap: {}
2112
- });
2113
- constructor() {
2114
- super([
2115
- { name: "setPropsConfig", isAsync: true },
2116
- { name: "getPropsConfig", isAsync: true },
2117
- { name: "setPropsValue", isAsync: true },
2118
- { name: "getPropsValue", isAsync: true },
2119
- { name: "createId", isAsync: false },
2120
- { name: "setNewItemId", isAsync: true },
2121
- { name: "fillConfig", isAsync: true },
2122
- { name: "getDefaultPropsValue", isAsync: true }
2123
- ]);
2124
- }
2125
- setPropsConfigs(configs) {
2126
- Object.keys(configs).forEach((type) => {
2127
- this.setPropsConfig(toLine(type), configs[type]);
2128
- });
2129
- this.emit("props-configs-change");
2130
- }
2131
- async fillConfig(config) {
2132
- return fillConfig(config);
2133
- }
2134
- /**
2135
- * 为指定类型组件设置组件属性表单配置
2136
- * @param type 组件类型
2137
- * @param config 组件属性表单配置
2138
- */
2139
- async setPropsConfig(type, config) {
2140
- this.state.propsConfigMap[type] = await this.fillConfig(Array.isArray(config) ? config : [config]);
2141
- }
2142
- /**
2143
- * 获取指点类型的组件属性表单配置
2144
- * @param type 组件类型
2145
- * @returns 组件属性表单配置
2146
- */
2147
- async getPropsConfig(type) {
2148
- if (type === "area") {
2149
- return await this.getPropsConfig("button");
2150
- }
2151
- return cloneDeep(this.state.propsConfigMap[type] || await this.fillConfig([]));
2152
- }
2153
- setPropsValues(values) {
2154
- Object.keys(values).forEach((type) => {
2155
- this.setPropsValue(toLine(type), values[type]);
2156
- });
2157
- }
2158
- /**
2159
- * 为指点类型组件设置组件初始值
2160
- * @param type 组件类型
2161
- * @param value 组件初始值
2162
- */
2163
- async setPropsValue(type, value) {
2164
- this.state.propsValueMap[type] = value;
2165
- }
2166
- /**
2167
- * 获取指定类型的组件初始值
2168
- * @param type 组件类型
2169
- * @returns 组件初始值
2170
- */
2171
- async getPropsValue(type, { inputEvent, ...defaultValue } = {}) {
2172
- if (type === "area") {
2173
- const value = await this.getPropsValue("button");
2174
- value.className = "action-area";
2175
- value.text = "";
2176
- if (value.style) {
2177
- value.style.backgroundColor = "rgba(255, 255, 255, 0)";
2178
- }
2179
- return value;
2180
- }
2181
- const [id, defaultPropsValue, data] = await Promise.all([
2182
- this.createId(type),
2183
- this.getDefaultPropsValue(type),
2184
- this.setNewItemId(
2185
- cloneDeep({
2186
- type,
2187
- ...defaultValue
2188
- })
2189
- )
2190
- ]);
2191
- return {
2192
- id,
2193
- ...defaultPropsValue,
2194
- ...mergeWith({}, cloneDeep(this.state.propsValueMap[type] || {}), data)
2195
- };
2196
- }
2197
- async createId(type) {
2198
- return `${type}_${guid()}`;
2199
- }
2200
- /**
2201
- * 将组件与组件的子元素配置中的id都设置成一个新的ID
2202
- * 如果没有相同ID并且force为false则保持不变
2203
- * @param {Object} config 组件配置
2204
- * @param {Boolean} force 是否强制设置新的ID
2205
- */
2206
- /* eslint no-param-reassign: ["error", { "props": false }] */
2207
- async setNewItemId(config, force = true) {
2208
- if (force || editorService.getNodeById(config.id)) {
2209
- const newId = await this.createId(config.type || "component");
2210
- this.setRelateId(config.id, newId);
2211
- config.id = newId;
2212
- }
2213
- if (config.items && Array.isArray(config.items)) {
2214
- for (const item of config.items) {
2215
- await this.setNewItemId(item);
2216
- }
2217
- }
2218
- return config;
2219
- }
2220
- /**
2221
- * 获取默认属性配置
2222
- * @param type 组件类型
2223
- * @returns Object
2224
- */
2225
- async getDefaultPropsValue(type) {
2226
- return ["page", "container"].includes(type) ? {
2227
- type,
2228
- layout: "absolute",
2229
- style: {},
2230
- name: type,
2231
- items: []
2232
- } : {
2233
- type,
2234
- style: {},
2235
- name: type
2236
- };
2237
- }
2238
- resetState() {
2239
- this.state.propsConfigMap = {};
2240
- this.state.propsValueMap = {};
2241
- }
2242
- /**
2243
- * 替换关联ID
2244
- * @param originConfigs 原组件配置
2245
- * @param targetConfigs 待替换的组件配置
2246
- */
2247
- replaceRelateId(originConfigs, targetConfigs) {
2248
- const relateIdMap = this.getRelateIdMap();
2249
- if (Object.keys(relateIdMap).length === 0)
2250
- return;
2251
- const target = depService.getTarget(DepTargetType.RELATED_COMP_WHEN_COPY, DepTargetType.RELATED_COMP_WHEN_COPY);
2252
- if (!target)
2253
- return;
2254
- originConfigs.forEach((config) => {
2255
- const newId = relateIdMap[config.id];
2256
- const targetConfig = targetConfigs.find((targetConfig2) => targetConfig2.id === newId);
2257
- if (!targetConfig)
2258
- return;
2259
- target.deps[config.id]?.keys?.forEach((fullKey) => {
2260
- const relateOriginId = getValueByKeyPath(fullKey, config);
2261
- const relateTargetId = relateIdMap[relateOriginId];
2262
- if (!relateTargetId)
2263
- return;
2264
- setValueByKeyPath(fullKey, relateTargetId, targetConfig);
2265
- });
2266
- });
2267
- }
2268
- /**
2269
- * 清除setNewItemId前后映射关系
2270
- */
2271
- clearRelateId() {
2272
- this.state.relateIdMap = {};
2273
- }
2274
- destroy() {
2275
- this.resetState();
2276
- this.removeAllListeners();
2277
- this.removeAllPlugins();
2278
- }
2279
- /**
2280
- * 获取setNewItemId前后映射关系
2281
- * @param oldId 原组件ID
2282
- * @returns 新旧ID映射
2283
- */
2284
- getRelateIdMap() {
2285
- return this.state.relateIdMap;
2286
- }
2287
- /**
2288
- * 记录setNewItemId前后映射关系
2289
- * @param oldId 原组件ID
2290
- * @param newId 分配的新ID
2291
- */
2292
- setRelateId(oldId, newId) {
2293
- this.state.relateIdMap[oldId] = newId;
2294
- }
2295
- }
2296
- const propsService = new Props();
2297
-
2298
2298
  class Editor extends BaseService {
2299
2299
  state = reactive({
2300
2300
  root: null,
@@ -2930,14 +2930,14 @@ class Editor extends BaseService {
2930
2930
  * @param targetId 容器ID
2931
2931
  */
2932
2932
  async moveToContainer(config, targetId) {
2933
- const root = cloneDeep(this.get("root"));
2933
+ const root = this.get("root");
2934
2934
  const { node, parent } = this.getNodeInfo(config.id, false);
2935
2935
  const target = this.getNodeById(targetId, false);
2936
2936
  const stage = this.get("stage");
2937
2937
  if (root && node && parent && stage) {
2938
2938
  const index = getNodeIndex(node.id, parent);
2939
2939
  parent.items?.splice(index, 1);
2940
- await stage.remove({ id: node.id, parentId: parent.id, root });
2940
+ await stage.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
2941
2941
  const layout = await this.getLayout(target);
2942
2942
  const newConfig = mergeWith(cloneDeep(node), config, (objValue, srcValue) => {
2943
2943
  if (Array.isArray(srcValue)) {
@@ -2948,7 +2948,7 @@ class Editor extends BaseService {
2948
2948
  target.items.push(newConfig);
2949
2949
  await stage.select(targetId);
2950
2950
  const targetParent = this.getParentById(target.id);
2951
- await stage.update({ config: cloneDeep(target), parentId: targetParent?.id, root });
2951
+ await stage.update({ config: cloneDeep(target), parentId: targetParent?.id, root: cloneDeep(root) });
2952
2952
  await this.select(newConfig);
2953
2953
  stage.select(newConfig.id);
2954
2954
  this.addModifiedNodeId(target.id);
@@ -5365,7 +5365,7 @@ const _sfc_main$A = /* @__PURE__ */ defineComponent({
5365
5365
 
5366
5366
  const _sfc_main$z = /* @__PURE__ */ defineComponent({
5367
5367
  ...{
5368
- name: "MEditorLayout"
5368
+ name: "MEditorSplitView"
5369
5369
  },
5370
5370
  __name: "SplitView",
5371
5371
  props: {
@@ -8468,8 +8468,8 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
8468
8468
  globalThis.clearTimeout(timeout);
8469
8469
  timeout = void 0;
8470
8470
  }
8471
- const doc = stage.value?.renderer.contentWindow?.document;
8472
- if (doc && stageOptions) {
8471
+ const doc = stage.value?.renderer.getDocument();
8472
+ if (doc && stageOptions?.containerHighlightClassName) {
8473
8473
  removeClassNameByClassName(doc, stageOptions.containerHighlightClassName);
8474
8474
  }
8475
8475
  clientX = 0;
@@ -9277,7 +9277,9 @@ const useStage = (stageOptions) => {
9277
9277
  disabledDragStart: stageOptions.disabledDragStart,
9278
9278
  renderType: stageOptions.renderType,
9279
9279
  canSelect: (el, event, stop) => {
9280
- const elCanSelect = stageOptions.canSelect(el);
9280
+ if (!stageOptions.canSelect)
9281
+ return true;
9282
+ const elCanSelect = stageOptions.canSelect?.(el);
9281
9283
  if (uiSelectMode.value && elCanSelect && event.type === "mousedown") {
9282
9284
  document.dispatchEvent(new CustomEvent(UI_SELECT_MODE_EVENT_NAME, { detail: el }));
9283
9285
  return stop();
@@ -9572,152 +9574,71 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
9572
9574
  }
9573
9575
  });
9574
9576
 
9575
- const useStageOverlay = () => {
9576
- const services = inject("services");
9577
- const stageOptions = inject("stageOptions");
9578
- const wrapWidth = ref(0);
9579
- const wrapHeight = ref(0);
9580
- const stageOverlayVisible = ref(false);
9581
- const stageOverlay = ref();
9582
- const stage = computed(() => services?.editorService.get("stage"));
9583
- let subStage = null;
9584
- const div = document.createElement("div");
9585
- let selectEl = null;
9586
- const render = () => {
9587
- if (!selectEl)
9588
- return;
9589
- const content = selectEl.cloneNode(true);
9590
- content.style.position = "static";
9591
- Array.from(div.children).forEach((element) => {
9592
- element.remove();
9593
- });
9594
- div.appendChild(content);
9595
- subStage?.renderer.contentWindow?.magic.onPageElUpdate(div);
9596
- subStage?.select(content);
9597
- };
9598
- const copyDocumentElement = () => {
9599
- const doc = subStage?.renderer.getDocument();
9600
- const documentElement = stage.value?.renderer.getDocument()?.documentElement;
9601
- if (doc && documentElement) {
9602
- doc.replaceChild(documentElement.cloneNode(true), doc.documentElement);
9603
- }
9604
- };
9605
- const updateOverlay = () => {
9606
- if (!selectEl)
9607
- return;
9608
- const { scrollWidth, scrollHeight } = selectEl;
9609
- stageOverlay.value.style.width = `${scrollWidth}px`;
9610
- stageOverlay.value.style.height = `${scrollHeight}px`;
9611
- wrapWidth.value = scrollWidth;
9612
- wrapHeight.value = scrollHeight;
9613
- };
9614
- const updateHandler = () => {
9615
- render();
9616
- updateOverlay();
9617
- };
9618
- const addHandler = () => {
9619
- render();
9620
- updateOverlay();
9621
- };
9622
- const removeHandler = () => {
9623
- render();
9624
- updateOverlay();
9625
- };
9626
- const openOverlay = async (el) => {
9627
- selectEl = el;
9628
- stageOverlayVisible.value = true;
9629
- if (!stageOverlay.value) {
9630
- await nextTick();
9631
- }
9632
- if (!stageOptions) {
9633
- return;
9634
- }
9635
- subStage = useStage({
9636
- ...stageOptions,
9637
- runtimeUrl: "",
9638
- autoScrollIntoView: false,
9639
- render(stage2) {
9640
- copyDocumentElement();
9641
- const rootEl = stage2.renderer.getDocument()?.getElementById("app");
9642
- if (rootEl) {
9643
- rootEl.remove();
9644
- }
9645
- div.style.cssText = `
9646
- width: ${el.scrollWidth}px;
9647
- height: ${el.scrollHeight}px;
9648
- background-color: #fff;
9649
- `;
9650
- render();
9651
- return div;
9652
- }
9653
- });
9654
- subStage.mount(stageOverlay.value);
9655
- const { mask, renderer } = subStage;
9656
- const { contentWindow } = renderer;
9657
- mask.showRule(false);
9658
- updateOverlay();
9659
- contentWindow?.magic.onRuntimeReady({});
9660
- services?.editorService.on("update", updateHandler);
9661
- services?.editorService.on("add", addHandler);
9662
- services?.editorService.on("remove", removeHandler);
9663
- };
9664
- const closeOverlay = () => {
9665
- stageOverlayVisible.value = false;
9666
- subStage?.destroy();
9667
- subStage = null;
9668
- services?.editorService.off("update", updateHandler);
9669
- services?.editorService.off("add", addHandler);
9670
- services?.editorService.off("remove", removeHandler);
9671
- };
9672
- watch(stage, (stage2) => {
9673
- if (stage2) {
9674
- stage2.on("dblclick", async (event) => {
9675
- const el = await stage2.actionManager.getElementFromPoint(event);
9676
- if (el) {
9677
- openOverlay(el);
9678
- }
9679
- });
9680
- } else if (subStage) {
9681
- closeOverlay();
9682
- }
9683
- });
9684
- return {
9685
- wrapWidth,
9686
- wrapHeight,
9687
- stageOverlayVisible,
9688
- stageOverlay,
9689
- closeOverlay
9690
- };
9691
- };
9692
-
9693
9577
  const _sfc_main$6 = /* @__PURE__ */ defineComponent({
9694
9578
  __name: "StageOverlay",
9695
9579
  setup(__props) {
9696
- const { stageOverlayVisible, stageOverlay, closeOverlay } = useStageOverlay();
9580
+ const services = inject("services");
9581
+ const stageOptions = inject("stageOptions");
9582
+ const stageOverlay = ref();
9583
+ const stageOverlayVisible = computed(() => services?.stageOverlayService.get("stageOverlayVisible"));
9584
+ const wrapWidth = computed(() => services?.stageOverlayService.get("wrapWidth") || 0);
9585
+ const wrapHeight = computed(() => services?.stageOverlayService.get("wrapHeight") || 0);
9586
+ const stage = computed(() => services?.editorService.get("stage"));
9587
+ const style = computed(() => ({
9588
+ width: `${wrapWidth.value}px`,
9589
+ height: `${wrapHeight.value}px`
9590
+ }));
9591
+ watch(stage, (stage2) => {
9592
+ if (stage2) {
9593
+ stage2.on("dblclick", async (event) => {
9594
+ const el = await stage2.actionManager.getElementFromPoint(event);
9595
+ services?.stageOverlayService.openOverlay(el);
9596
+ });
9597
+ } else {
9598
+ services?.stageOverlayService.closeOverlay();
9599
+ }
9600
+ });
9601
+ watch(stageOverlay, (stageOverlay2) => {
9602
+ if (!services)
9603
+ return;
9604
+ const subStage = services.stageOverlayService.createStage(stageOptions);
9605
+ services?.stageOverlayService.set("stage", subStage);
9606
+ if (stageOverlay2 && subStage) {
9607
+ subStage.mount(stageOverlay2);
9608
+ const { mask, renderer } = subStage;
9609
+ const { contentWindow } = renderer;
9610
+ mask.showRule(false);
9611
+ services?.stageOverlayService.updateOverlay();
9612
+ contentWindow?.magic.onRuntimeReady({});
9613
+ }
9614
+ });
9615
+ const closeOverlayHandler = () => {
9616
+ services?.stageOverlayService.closeOverlay();
9617
+ };
9697
9618
  return (_ctx, _cache) => {
9698
- return unref(stageOverlayVisible) ? (openBlock(), createElementBlock("div", {
9619
+ return stageOverlayVisible.value ? (openBlock(), createElementBlock("div", {
9699
9620
  key: 0,
9700
9621
  class: "m-editor-stage-overlay",
9701
- onClick: _cache[1] || (_cache[1] = //@ts-ignore
9702
- (...args) => unref(closeOverlay) && unref(closeOverlay)(...args))
9622
+ onClick: closeOverlayHandler
9703
9623
  }, [
9704
9624
  createVNode(unref(TMagicIcon), {
9705
9625
  class: "m-editor-stage-overlay-close",
9706
9626
  size: 20,
9707
- onClick: unref(closeOverlay)
9627
+ onClick: closeOverlayHandler
9708
9628
  }, {
9709
9629
  default: withCtx(() => [
9710
9630
  createVNode(unref(CloseBold))
9711
9631
  ]),
9712
9632
  _: 1
9713
- }, 8, ["onClick"]),
9633
+ }),
9714
9634
  createElementVNode("div", {
9715
9635
  ref_key: "stageOverlay",
9716
9636
  ref: stageOverlay,
9717
9637
  class: "m-editor-stage-overlay-container",
9638
+ style: normalizeStyle(style.value),
9718
9639
  onClick: _cache[0] || (_cache[0] = withModifiers(() => {
9719
9640
  }, ["stop"]))
9720
- }, null, 512)
9641
+ }, null, 4)
9721
9642
  ])) : createCommentVNode("", true);
9722
9643
  };
9723
9644
  }
@@ -9904,7 +9825,8 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
9904
9825
  __name: "Stage",
9905
9826
  props: {
9906
9827
  stageContentMenu: {},
9907
- customContentMenu: { type: Function }
9828
+ disabledStageOverlay: { type: Boolean, default: false },
9829
+ customContentMenu: {}
9908
9830
  },
9909
9831
  setup(__props) {
9910
9832
  let stage = null;
@@ -10065,7 +9987,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
10065
9987
  onClick: _cache[0] || (_cache[0] = ($event) => stageWrap.value?.container?.focus())
10066
9988
  }, {
10067
9989
  content: withCtx(() => [
10068
- createVNode(_sfc_main$6),
9990
+ !_ctx.disabledStageOverlay ? (openBlock(), createBlock(_sfc_main$6, { key: 0 })) : createCommentVNode("", true),
10069
9991
  (openBlock(), createBlock(Teleport, { to: "body" }, [
10070
9992
  createVNode(_sfc_main$4, {
10071
9993
  ref_key: "menu",
@@ -10147,7 +10069,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
10147
10069
  __name: "Workspace",
10148
10070
  props: {
10149
10071
  stageContentMenu: {},
10150
- customContentMenu: { type: Function }
10072
+ disabledStageOverlay: { type: Boolean, default: false },
10073
+ customContentMenu: {}
10151
10074
  },
10152
10075
  setup(__props) {
10153
10076
  const services = inject("services");
@@ -10158,9 +10081,10 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
10158
10081
  renderSlot(_ctx.$slots, "stage", {}, () => [
10159
10082
  page.value ? (openBlock(), createBlock(_sfc_main$3, {
10160
10083
  key: 0,
10084
+ "disabled-stage-overlay": _ctx.disabledStageOverlay,
10161
10085
  "stage-content-menu": _ctx.stageContentMenu,
10162
10086
  "custom-content-menu": _ctx.customContentMenu
10163
- }, null, 8, ["stage-content-menu", "custom-content-menu"])) : createCommentVNode("", true)
10087
+ }, null, 8, ["disabled-stage-overlay", "stage-content-menu", "custom-content-menu"])) : createCommentVNode("", true)
10164
10088
  ]),
10165
10089
  renderSlot(_ctx.$slots, "workspace-content")
10166
10090
  ]);
@@ -10619,7 +10543,152 @@ class Keybinding extends BaseService {
10619
10543
  }
10620
10544
  const keybindingService = new Keybinding();
10621
10545
 
10546
+ class StageOverlay extends BaseService {
10547
+ state = reactive({
10548
+ wrapDiv: document.createElement("div"),
10549
+ sourceEl: null,
10550
+ contentEl: null,
10551
+ stage: null,
10552
+ stageOptions: null,
10553
+ wrapWidth: 0,
10554
+ wrapHeight: 0,
10555
+ stageOverlayVisible: false
10556
+ });
10557
+ constructor() {
10558
+ super([
10559
+ { name: "openOverlay", isAsync: false },
10560
+ { name: "closeOverlay", isAsync: false },
10561
+ { name: "updateOverlay", isAsync: false },
10562
+ { name: "createStage", isAsync: false }
10563
+ ]);
10564
+ this.get("wrapDiv").classList.add("tmagic-editor-sub-stage-wrap");
10565
+ }
10566
+ get(name) {
10567
+ return this.state[name];
10568
+ }
10569
+ set(name, value) {
10570
+ this.state[name] = value;
10571
+ }
10572
+ openOverlay(el) {
10573
+ const stageOptions = this.get("stageOptions");
10574
+ if (!el || !stageOptions)
10575
+ return;
10576
+ this.set("sourceEl", el);
10577
+ this.createContentEl();
10578
+ this.set("stageOverlayVisible", true);
10579
+ editorService.on("update", this.updateHandler);
10580
+ editorService.on("add", this.addHandler);
10581
+ editorService.on("remove", this.removeHandler);
10582
+ }
10583
+ closeOverlay() {
10584
+ this.set("stageOverlayVisible", false);
10585
+ const subStage = this.get("stage");
10586
+ const wrapDiv = this.get("wrapDiv");
10587
+ subStage?.destroy();
10588
+ wrapDiv.remove();
10589
+ this.set("stage", null);
10590
+ this.set("sourceEl", null);
10591
+ this.set("contentEl", null);
10592
+ editorService.off("update", this.updateHandler);
10593
+ editorService.off("add", this.addHandler);
10594
+ editorService.off("remove", this.removeHandler);
10595
+ }
10596
+ updateOverlay() {
10597
+ const sourceEl = this.get("sourceEl");
10598
+ if (!sourceEl)
10599
+ return;
10600
+ const { scrollWidth, scrollHeight } = sourceEl;
10601
+ this.set("wrapWidth", scrollWidth);
10602
+ this.set("wrapHeight", scrollHeight);
10603
+ }
10604
+ createStage(stageOptions = {}) {
10605
+ return useStage({
10606
+ ...stageOptions,
10607
+ runtimeUrl: "",
10608
+ autoScrollIntoView: false,
10609
+ render: async (stage) => {
10610
+ this.copyDocumentElement();
10611
+ const rootEls = stage.renderer.getDocument()?.body.children;
10612
+ if (rootEls) {
10613
+ Array.from(rootEls).forEach((element) => {
10614
+ if (["SCRIPT", "STYLE"].includes(element.tagName)) {
10615
+ return;
10616
+ }
10617
+ element.remove();
10618
+ });
10619
+ }
10620
+ const wrapDiv = this.get("wrapDiv");
10621
+ const sourceEl = this.get("sourceEl");
10622
+ wrapDiv.style.cssText = `
10623
+ width: ${sourceEl?.scrollWidth}px;
10624
+ height: ${sourceEl?.scrollHeight}px;
10625
+ background-color: #fff;
10626
+ `;
10627
+ await this.render();
10628
+ return wrapDiv;
10629
+ }
10630
+ });
10631
+ }
10632
+ createContentEl() {
10633
+ const sourceEl = this.get("sourceEl");
10634
+ if (!sourceEl)
10635
+ return;
10636
+ const contentEl = sourceEl.cloneNode(true);
10637
+ this.set("contentEl", contentEl);
10638
+ contentEl.style.position = "static";
10639
+ contentEl.style.overflow = "visible";
10640
+ }
10641
+ copyDocumentElement() {
10642
+ const subStage = this.get("stage");
10643
+ const stage = editorService.get("stage");
10644
+ const doc = subStage?.renderer.getDocument();
10645
+ const documentElement = stage?.renderer.getDocument()?.documentElement;
10646
+ if (doc && documentElement) {
10647
+ doc.replaceChild(documentElement.cloneNode(true), doc.documentElement);
10648
+ }
10649
+ }
10650
+ async render() {
10651
+ this.createContentEl();
10652
+ const contentEl = this.get("contentEl");
10653
+ const wrapDiv = this.get("wrapDiv");
10654
+ const subStage = this.get("stage");
10655
+ const stageOptions = this.get("stageOptions");
10656
+ if (!contentEl)
10657
+ return;
10658
+ Array.from(wrapDiv.children).forEach((element) => {
10659
+ element.remove();
10660
+ });
10661
+ wrapDiv.appendChild(contentEl);
10662
+ setTimeout(() => {
10663
+ subStage?.renderer.contentWindow?.magic.onPageElUpdate(wrapDiv);
10664
+ });
10665
+ if (await stageOptions?.canSelect?.(contentEl)) {
10666
+ subStage?.select(contentEl);
10667
+ }
10668
+ }
10669
+ updateHandler = () => {
10670
+ this.render();
10671
+ this.updateOverlay();
10672
+ };
10673
+ addHandler = () => {
10674
+ this.render();
10675
+ this.updateOverlay();
10676
+ };
10677
+ removeHandler = () => {
10678
+ this.render();
10679
+ this.updateOverlay();
10680
+ };
10681
+ }
10682
+ const stageOverlayService = new StageOverlay();
10683
+
10622
10684
  const defaultEditorProps = {
10685
+ renderType: RenderType.IFRAME,
10686
+ disabledMultiSelect: false,
10687
+ disabledPageFragment: false,
10688
+ disabledStageOverlay: false,
10689
+ containerHighlightClassName: CONTAINER_HIGHLIGHT_CLASS_NAME,
10690
+ containerHighlightDuration: 800,
10691
+ containerHighlightType: ContainerHighlightType.DEFAULT,
10623
10692
  componentGroupList: () => [],
10624
10693
  datasourceList: () => [],
10625
10694
  menu: () => ({ left: [], right: [] }),
@@ -10632,13 +10701,7 @@ const defaultEditorProps = {
10632
10701
  datasourceConfigs: () => ({}),
10633
10702
  canSelect: (el) => Boolean(el.id),
10634
10703
  isContainer: (el) => el.classList.contains("magic-ui-container"),
10635
- containerHighlightClassName: CONTAINER_HIGHLIGHT_CLASS_NAME,
10636
- containerHighlightDuration: 800,
10637
- containerHighlightType: ContainerHighlightType.DEFAULT,
10638
- codeOptions: () => ({}),
10639
- renderType: RenderType.IFRAME,
10640
- disabledMultiSelect: false,
10641
- disabledPageFragment: false
10704
+ codeOptions: () => ({})
10642
10705
  };
10643
10706
 
10644
10707
  const initServiceState = (props, {
@@ -10985,7 +11048,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10985
11048
  menu: {},
10986
11049
  layerContentMenu: {},
10987
11050
  stageContentMenu: {},
10988
- render: { type: Function },
10989
11051
  runtimeUrl: {},
10990
11052
  renderType: {},
10991
11053
  autoScrollIntoView: { type: Boolean },
@@ -10997,21 +11059,23 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10997
11059
  datasourceEventMethodList: {},
10998
11060
  moveableOptions: { type: Function },
10999
11061
  defaultSelected: {},
11000
- canSelect: { type: Function },
11001
- isContainer: { type: Function },
11002
11062
  containerHighlightClassName: {},
11003
11063
  containerHighlightDuration: {},
11004
11064
  containerHighlightType: {},
11005
11065
  stageRect: {},
11006
11066
  codeOptions: {},
11007
- updateDragEl: { type: Function },
11008
11067
  disabledDragStart: { type: Boolean },
11009
- extendFormState: { type: Function },
11010
11068
  collectorOptions: {},
11011
11069
  guidesOptions: {},
11012
11070
  disabledMultiSelect: { type: Boolean },
11013
11071
  disabledPageFragment: { type: Boolean },
11014
- customContentMenu: { type: Function }
11072
+ disabledStageOverlay: { type: Boolean },
11073
+ render: { type: Function },
11074
+ updateDragEl: { type: Function },
11075
+ canSelect: { type: Function },
11076
+ isContainer: { type: Function },
11077
+ customContentMenu: { type: Function },
11078
+ extendFormState: { type: Function }
11015
11079
  }, defaultEditorProps),
11016
11080
  emits: ["props-panel-mounted", "update:modelValue", "props-form-error", "props-submit-error"],
11017
11081
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -11028,33 +11092,33 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
11028
11092
  codeBlockService,
11029
11093
  depService,
11030
11094
  dataSourceService,
11031
- keybindingService
11095
+ keybindingService,
11096
+ stageOverlayService
11032
11097
  };
11033
11098
  initServiceEvents(props, emit, services);
11034
11099
  initServiceState(props, services);
11035
11100
  keybindingService.register(keybindingConfig);
11036
11101
  keybindingService.registerEl("global");
11102
+ const stageOptions = {
11103
+ runtimeUrl: props.runtimeUrl,
11104
+ autoScrollIntoView: props.autoScrollIntoView,
11105
+ render: props.render,
11106
+ moveableOptions: props.moveableOptions,
11107
+ canSelect: props.canSelect,
11108
+ updateDragEl: props.updateDragEl,
11109
+ isContainer: props.isContainer,
11110
+ containerHighlightClassName: props.containerHighlightClassName,
11111
+ containerHighlightDuration: props.containerHighlightDuration,
11112
+ containerHighlightType: props.containerHighlightType,
11113
+ disabledDragStart: props.disabledDragStart,
11114
+ renderType: props.renderType,
11115
+ guidesOptions: props.guidesOptions,
11116
+ disabledMultiSelect: props.disabledMultiSelect
11117
+ };
11118
+ stageOverlayService.set("stageOptions", stageOptions);
11037
11119
  provide("services", services);
11038
11120
  provide("codeOptions", props.codeOptions);
11039
- provide(
11040
- "stageOptions",
11041
- reactive({
11042
- runtimeUrl: props.runtimeUrl,
11043
- autoScrollIntoView: props.autoScrollIntoView,
11044
- render: props.render,
11045
- moveableOptions: props.moveableOptions,
11046
- canSelect: props.canSelect,
11047
- updateDragEl: props.updateDragEl,
11048
- isContainer: props.isContainer,
11049
- containerHighlightClassName: props.containerHighlightClassName,
11050
- containerHighlightDuration: props.containerHighlightDuration,
11051
- containerHighlightType: props.containerHighlightType,
11052
- disabledDragStart: props.disabledDragStart,
11053
- renderType: props.renderType,
11054
- guidesOptions: props.guidesOptions,
11055
- disabledMultiSelect: props.disabledMultiSelect
11056
- })
11057
- );
11121
+ provide("stageOptions", stageOptions);
11058
11122
  __expose(services);
11059
11123
  return (_ctx, _cache) => {
11060
11124
  return openBlock(), createBlock(_sfc_main$s, { "disabled-page-fragment": _ctx.disabledPageFragment }, {
@@ -11116,6 +11180,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
11116
11180
  workspace: withCtx(() => [
11117
11181
  renderSlot(_ctx.$slots, "workspace", { editorService: unref(editorService) }, () => [
11118
11182
  createVNode(_sfc_main$1, {
11183
+ "disabled-stage-overlay": _ctx.disabledStageOverlay,
11119
11184
  "stage-content-menu": _ctx.stageContentMenu,
11120
11185
  "custom-content-menu": _ctx.customContentMenu
11121
11186
  }, {
@@ -11126,7 +11191,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
11126
11191
  renderSlot(_ctx.$slots, "workspace-content", { editorService: unref(editorService) })
11127
11192
  ]),
11128
11193
  _: 3
11129
- }, 8, ["stage-content-menu", "custom-content-menu"])
11194
+ }, 8, ["disabled-stage-overlay", "stage-content-menu", "custom-content-menu"])
11130
11195
  ])
11131
11196
  ]),
11132
11197
  "props-panel": withCtx(() => [
@@ -11197,4 +11262,4 @@ const index = {
11197
11262
  }
11198
11263
  };
11199
11264
 
11200
- export { CODE_DRAFT_STORAGE_KEY, COPY_STORAGE_KEY, _sfc_main$Q as CodeBlockEditor, _sfc_main$m as CodeBlockList, _sfc_main$l as CodeBlockListPanel, CodeDeleteErrorType, _sfc_main$R as CodeSelect, _sfc_main$N as CodeSelectCol, ColumnLayout, _sfc_main$c as ComponentListPanel, _sfc_main$h as ContentMenu, _sfc_main$L as DataSourceFieldSelect, _sfc_main$M as DataSourceFields, _sfc_main$K as DataSourceInput, _sfc_main$I as DataSourceMethodSelect, _sfc_main$J as DataSourceMethods, _sfc_main$H as DataSourceMocks, _sfc_main$G as DataSourceSelect, DragType, _sfc_main$F as EventSelect, Fixed2Other, H_GUIDE_LINE_STORAGE_KEY, _sfc_main$O as Icon, KeyBindingCommand, _sfc_main$D as KeyValue, Keys, LayerOffset, _sfc_main$d as LayerPanel, Layout, _sfc_main$z as LayoutContainer, _sfc_main$C as PageFragmentSelect, _sfc_main$q as PropsPanel, _sfc_main$A as Resizer, _sfc_main$z as SplitView, _sfc_main$U as TMagicCodeEditor, _sfc_main as TMagicEditor, _sfc_main$y as ToolButton, UI_SELECT_MODE_EVENT_NAME, V_GUIDE_LINE_STORAGE_KEY, advancedTabConfig, beforePaste, change2Fixed, codeBlockService, dataSourceService, debug, index as default, depService, displayTabConfig, editorService, error, eventTabConfig, eventsService, fillConfig, fixNodeLeft, fixNodePosition, generatePageName, generatePageNameByApp, getAddParent, getConfig, getDefaultConfig, getDisplayField, getFormConfig, getFormValue, getGuideLineFromCache, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, getPageNameList, getPositionInContainer, getRelativeStyle, historyService, info, isFixed, log, propsService, serializeConfig, setChildrenLayout, setConfig, setLayout, storageService, styleTabConfig, traverseNode, uiService, useCodeBlockEdit, useDataSourceMethod, useFloatBox, useStage, warn };
11265
+ export { CODE_DRAFT_STORAGE_KEY, COPY_STORAGE_KEY, _sfc_main$Q as CodeBlockEditor, _sfc_main$m as CodeBlockList, _sfc_main$l as CodeBlockListPanel, CodeDeleteErrorType, _sfc_main$R as CodeSelect, _sfc_main$N as CodeSelectCol, ColumnLayout, _sfc_main$c as ComponentListPanel, _sfc_main$h as ContentMenu, _sfc_main$L as DataSourceFieldSelect, _sfc_main$M as DataSourceFields, _sfc_main$K as DataSourceInput, _sfc_main$I as DataSourceMethodSelect, _sfc_main$J as DataSourceMethods, _sfc_main$H as DataSourceMocks, _sfc_main$G as DataSourceSelect, DragType, _sfc_main$F as EventSelect, Fixed2Other, H_GUIDE_LINE_STORAGE_KEY, _sfc_main$O as Icon, KeyBindingCommand, _sfc_main$D as KeyValue, Keys, LayerOffset, _sfc_main$d as LayerPanel, Layout, _sfc_main$z as LayoutContainer, _sfc_main$C as PageFragmentSelect, _sfc_main$q as PropsPanel, _sfc_main$A as Resizer, _sfc_main$z as SplitView, _sfc_main$U as TMagicCodeEditor, _sfc_main as TMagicEditor, _sfc_main$y as ToolButton, UI_SELECT_MODE_EVENT_NAME, V_GUIDE_LINE_STORAGE_KEY, advancedTabConfig, beforePaste, change2Fixed, codeBlockService, dataSourceService, debug, index as default, depService, displayTabConfig, editorService, error, eventTabConfig, eventsService, fillConfig, fixNodeLeft, fixNodePosition, generatePageName, generatePageNameByApp, getAddParent, getConfig, getDefaultConfig, getDisplayField, getFormConfig, getFormValue, getGuideLineFromCache, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, getPageNameList, getPositionInContainer, getRelativeStyle, historyService, info, isFixed, log, propsService, serializeConfig, setChildrenLayout, setConfig, setLayout, stageOverlayService, storageService, styleTabConfig, traverseNode, uiService, useCodeBlockEdit, useDataSourceMethod, useFloatBox, useStage, warn };