@tmagic/editor 1.3.11 → 1.3.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.
@@ -1855,6 +1855,197 @@
1855
1855
  }
1856
1856
  const depService = new Dep();
1857
1857
 
1858
+ class Props extends BaseService {
1859
+ state = vue.reactive({
1860
+ propsConfigMap: {},
1861
+ propsValueMap: {},
1862
+ relateIdMap: {}
1863
+ });
1864
+ constructor() {
1865
+ super([
1866
+ { name: "setPropsConfig", isAsync: true },
1867
+ { name: "getPropsConfig", isAsync: true },
1868
+ { name: "setPropsValue", isAsync: true },
1869
+ { name: "getPropsValue", isAsync: true },
1870
+ { name: "createId", isAsync: false },
1871
+ { name: "setNewItemId", isAsync: true },
1872
+ { name: "fillConfig", isAsync: true },
1873
+ { name: "getDefaultPropsValue", isAsync: true }
1874
+ ]);
1875
+ }
1876
+ setPropsConfigs(configs) {
1877
+ Object.keys(configs).forEach((type) => {
1878
+ this.setPropsConfig(utils.toLine(type), configs[type]);
1879
+ });
1880
+ this.emit("props-configs-change");
1881
+ }
1882
+ async fillConfig(config) {
1883
+ return fillConfig(config);
1884
+ }
1885
+ /**
1886
+ * 为指定类型组件设置组件属性表单配置
1887
+ * @param type 组件类型
1888
+ * @param config 组件属性表单配置
1889
+ */
1890
+ async setPropsConfig(type, config) {
1891
+ this.state.propsConfigMap[type] = await this.fillConfig(Array.isArray(config) ? config : [config]);
1892
+ }
1893
+ /**
1894
+ * 获取指点类型的组件属性表单配置
1895
+ * @param type 组件类型
1896
+ * @returns 组件属性表单配置
1897
+ */
1898
+ async getPropsConfig(type) {
1899
+ if (type === "area") {
1900
+ return await this.getPropsConfig("button");
1901
+ }
1902
+ return lodashEs.cloneDeep(this.state.propsConfigMap[type] || await this.fillConfig([]));
1903
+ }
1904
+ setPropsValues(values) {
1905
+ Object.keys(values).forEach((type) => {
1906
+ this.setPropsValue(utils.toLine(type), values[type]);
1907
+ });
1908
+ }
1909
+ /**
1910
+ * 为指点类型组件设置组件初始值
1911
+ * @param type 组件类型
1912
+ * @param value 组件初始值
1913
+ */
1914
+ async setPropsValue(type, value) {
1915
+ this.state.propsValueMap[type] = value;
1916
+ }
1917
+ /**
1918
+ * 获取指定类型的组件初始值
1919
+ * @param type 组件类型
1920
+ * @returns 组件初始值
1921
+ */
1922
+ async getPropsValue(type, { inputEvent, ...defaultValue } = {}) {
1923
+ if (type === "area") {
1924
+ const value = await this.getPropsValue("button");
1925
+ value.className = "action-area";
1926
+ value.text = "";
1927
+ if (value.style) {
1928
+ value.style.backgroundColor = "rgba(255, 255, 255, 0)";
1929
+ }
1930
+ return value;
1931
+ }
1932
+ const [id, defaultPropsValue, data] = await Promise.all([
1933
+ this.createId(type),
1934
+ this.getDefaultPropsValue(type),
1935
+ this.setNewItemId(
1936
+ lodashEs.cloneDeep({
1937
+ type,
1938
+ ...defaultValue
1939
+ })
1940
+ )
1941
+ ]);
1942
+ return {
1943
+ id,
1944
+ ...defaultPropsValue,
1945
+ ...lodashEs.mergeWith({}, lodashEs.cloneDeep(this.state.propsValueMap[type] || {}), data)
1946
+ };
1947
+ }
1948
+ async createId(type) {
1949
+ return `${type}_${utils.guid()}`;
1950
+ }
1951
+ /**
1952
+ * 将组件与组件的子元素配置中的id都设置成一个新的ID
1953
+ * 如果没有相同ID并且force为false则保持不变
1954
+ * @param {Object} config 组件配置
1955
+ * @param {Boolean} force 是否强制设置新的ID
1956
+ */
1957
+ /* eslint no-param-reassign: ["error", { "props": false }] */
1958
+ async setNewItemId(config, force = true) {
1959
+ if (force || editorService.getNodeById(config.id)) {
1960
+ const newId = await this.createId(config.type || "component");
1961
+ this.setRelateId(config.id, newId);
1962
+ config.id = newId;
1963
+ }
1964
+ if (config.items && Array.isArray(config.items)) {
1965
+ for (const item of config.items) {
1966
+ await this.setNewItemId(item);
1967
+ }
1968
+ }
1969
+ return config;
1970
+ }
1971
+ /**
1972
+ * 获取默认属性配置
1973
+ * @param type 组件类型
1974
+ * @returns Object
1975
+ */
1976
+ async getDefaultPropsValue(type) {
1977
+ return ["page", "container"].includes(type) ? {
1978
+ type,
1979
+ layout: "absolute",
1980
+ style: {},
1981
+ name: type,
1982
+ items: []
1983
+ } : {
1984
+ type,
1985
+ style: {},
1986
+ name: type
1987
+ };
1988
+ }
1989
+ resetState() {
1990
+ this.state.propsConfigMap = {};
1991
+ this.state.propsValueMap = {};
1992
+ }
1993
+ /**
1994
+ * 替换关联ID
1995
+ * @param originConfigs 原组件配置
1996
+ * @param targetConfigs 待替换的组件配置
1997
+ */
1998
+ replaceRelateId(originConfigs, targetConfigs) {
1999
+ const relateIdMap = this.getRelateIdMap();
2000
+ if (Object.keys(relateIdMap).length === 0)
2001
+ return;
2002
+ const target = depService.getTarget(dep.DepTargetType.RELATED_COMP_WHEN_COPY, dep.DepTargetType.RELATED_COMP_WHEN_COPY);
2003
+ if (!target)
2004
+ return;
2005
+ originConfigs.forEach((config) => {
2006
+ const newId = relateIdMap[config.id];
2007
+ const targetConfig = targetConfigs.find((targetConfig2) => targetConfig2.id === newId);
2008
+ if (!targetConfig)
2009
+ return;
2010
+ target.deps[config.id]?.keys?.forEach((fullKey) => {
2011
+ const relateOriginId = utils.getValueByKeyPath(fullKey, config);
2012
+ const relateTargetId = relateIdMap[relateOriginId];
2013
+ if (!relateTargetId)
2014
+ return;
2015
+ utils.setValueByKeyPath(fullKey, relateTargetId, targetConfig);
2016
+ });
2017
+ });
2018
+ }
2019
+ /**
2020
+ * 清除setNewItemId前后映射关系
2021
+ */
2022
+ clearRelateId() {
2023
+ this.state.relateIdMap = {};
2024
+ }
2025
+ destroy() {
2026
+ this.resetState();
2027
+ this.removeAllListeners();
2028
+ this.removeAllPlugins();
2029
+ }
2030
+ /**
2031
+ * 获取setNewItemId前后映射关系
2032
+ * @param oldId 原组件ID
2033
+ * @returns 新旧ID映射
2034
+ */
2035
+ getRelateIdMap() {
2036
+ return this.state.relateIdMap;
2037
+ }
2038
+ /**
2039
+ * 记录setNewItemId前后映射关系
2040
+ * @param oldId 原组件ID
2041
+ * @param newId 分配的新ID
2042
+ */
2043
+ setRelateId(oldId, newId) {
2044
+ this.state.relateIdMap[oldId] = newId;
2045
+ }
2046
+ }
2047
+ const propsService = new Props();
2048
+
1858
2049
  class UndoRedo {
1859
2050
  elementList;
1860
2051
  listCursor;
@@ -2109,197 +2300,6 @@
2109
2300
  }
2110
2301
  const storageService = new WebStorage();
2111
2302
 
2112
- class Props extends BaseService {
2113
- state = vue.reactive({
2114
- propsConfigMap: {},
2115
- propsValueMap: {},
2116
- relateIdMap: {}
2117
- });
2118
- constructor() {
2119
- super([
2120
- { name: "setPropsConfig", isAsync: true },
2121
- { name: "getPropsConfig", isAsync: true },
2122
- { name: "setPropsValue", isAsync: true },
2123
- { name: "getPropsValue", isAsync: true },
2124
- { name: "createId", isAsync: false },
2125
- { name: "setNewItemId", isAsync: true },
2126
- { name: "fillConfig", isAsync: true },
2127
- { name: "getDefaultPropsValue", isAsync: true }
2128
- ]);
2129
- }
2130
- setPropsConfigs(configs) {
2131
- Object.keys(configs).forEach((type) => {
2132
- this.setPropsConfig(utils.toLine(type), configs[type]);
2133
- });
2134
- this.emit("props-configs-change");
2135
- }
2136
- async fillConfig(config) {
2137
- return fillConfig(config);
2138
- }
2139
- /**
2140
- * 为指定类型组件设置组件属性表单配置
2141
- * @param type 组件类型
2142
- * @param config 组件属性表单配置
2143
- */
2144
- async setPropsConfig(type, config) {
2145
- this.state.propsConfigMap[type] = await this.fillConfig(Array.isArray(config) ? config : [config]);
2146
- }
2147
- /**
2148
- * 获取指点类型的组件属性表单配置
2149
- * @param type 组件类型
2150
- * @returns 组件属性表单配置
2151
- */
2152
- async getPropsConfig(type) {
2153
- if (type === "area") {
2154
- return await this.getPropsConfig("button");
2155
- }
2156
- return lodashEs.cloneDeep(this.state.propsConfigMap[type] || await this.fillConfig([]));
2157
- }
2158
- setPropsValues(values) {
2159
- Object.keys(values).forEach((type) => {
2160
- this.setPropsValue(utils.toLine(type), values[type]);
2161
- });
2162
- }
2163
- /**
2164
- * 为指点类型组件设置组件初始值
2165
- * @param type 组件类型
2166
- * @param value 组件初始值
2167
- */
2168
- async setPropsValue(type, value) {
2169
- this.state.propsValueMap[type] = value;
2170
- }
2171
- /**
2172
- * 获取指定类型的组件初始值
2173
- * @param type 组件类型
2174
- * @returns 组件初始值
2175
- */
2176
- async getPropsValue(type, { inputEvent, ...defaultValue } = {}) {
2177
- if (type === "area") {
2178
- const value = await this.getPropsValue("button");
2179
- value.className = "action-area";
2180
- value.text = "";
2181
- if (value.style) {
2182
- value.style.backgroundColor = "rgba(255, 255, 255, 0)";
2183
- }
2184
- return value;
2185
- }
2186
- const [id, defaultPropsValue, data] = await Promise.all([
2187
- this.createId(type),
2188
- this.getDefaultPropsValue(type),
2189
- this.setNewItemId(
2190
- lodashEs.cloneDeep({
2191
- type,
2192
- ...defaultValue
2193
- })
2194
- )
2195
- ]);
2196
- return {
2197
- id,
2198
- ...defaultPropsValue,
2199
- ...lodashEs.mergeWith({}, lodashEs.cloneDeep(this.state.propsValueMap[type] || {}), data)
2200
- };
2201
- }
2202
- async createId(type) {
2203
- return `${type}_${utils.guid()}`;
2204
- }
2205
- /**
2206
- * 将组件与组件的子元素配置中的id都设置成一个新的ID
2207
- * 如果没有相同ID并且force为false则保持不变
2208
- * @param {Object} config 组件配置
2209
- * @param {Boolean} force 是否强制设置新的ID
2210
- */
2211
- /* eslint no-param-reassign: ["error", { "props": false }] */
2212
- async setNewItemId(config, force = true) {
2213
- if (force || editorService.getNodeById(config.id)) {
2214
- const newId = await this.createId(config.type || "component");
2215
- this.setRelateId(config.id, newId);
2216
- config.id = newId;
2217
- }
2218
- if (config.items && Array.isArray(config.items)) {
2219
- for (const item of config.items) {
2220
- await this.setNewItemId(item);
2221
- }
2222
- }
2223
- return config;
2224
- }
2225
- /**
2226
- * 获取默认属性配置
2227
- * @param type 组件类型
2228
- * @returns Object
2229
- */
2230
- async getDefaultPropsValue(type) {
2231
- return ["page", "container"].includes(type) ? {
2232
- type,
2233
- layout: "absolute",
2234
- style: {},
2235
- name: type,
2236
- items: []
2237
- } : {
2238
- type,
2239
- style: {},
2240
- name: type
2241
- };
2242
- }
2243
- resetState() {
2244
- this.state.propsConfigMap = {};
2245
- this.state.propsValueMap = {};
2246
- }
2247
- /**
2248
- * 替换关联ID
2249
- * @param originConfigs 原组件配置
2250
- * @param targetConfigs 待替换的组件配置
2251
- */
2252
- replaceRelateId(originConfigs, targetConfigs) {
2253
- const relateIdMap = this.getRelateIdMap();
2254
- if (Object.keys(relateIdMap).length === 0)
2255
- return;
2256
- const target = depService.getTarget(dep.DepTargetType.RELATED_COMP_WHEN_COPY, dep.DepTargetType.RELATED_COMP_WHEN_COPY);
2257
- if (!target)
2258
- return;
2259
- originConfigs.forEach((config) => {
2260
- const newId = relateIdMap[config.id];
2261
- const targetConfig = targetConfigs.find((targetConfig2) => targetConfig2.id === newId);
2262
- if (!targetConfig)
2263
- return;
2264
- target.deps[config.id]?.keys?.forEach((fullKey) => {
2265
- const relateOriginId = utils.getValueByKeyPath(fullKey, config);
2266
- const relateTargetId = relateIdMap[relateOriginId];
2267
- if (!relateTargetId)
2268
- return;
2269
- utils.setValueByKeyPath(fullKey, relateTargetId, targetConfig);
2270
- });
2271
- });
2272
- }
2273
- /**
2274
- * 清除setNewItemId前后映射关系
2275
- */
2276
- clearRelateId() {
2277
- this.state.relateIdMap = {};
2278
- }
2279
- destroy() {
2280
- this.resetState();
2281
- this.removeAllListeners();
2282
- this.removeAllPlugins();
2283
- }
2284
- /**
2285
- * 获取setNewItemId前后映射关系
2286
- * @param oldId 原组件ID
2287
- * @returns 新旧ID映射
2288
- */
2289
- getRelateIdMap() {
2290
- return this.state.relateIdMap;
2291
- }
2292
- /**
2293
- * 记录setNewItemId前后映射关系
2294
- * @param oldId 原组件ID
2295
- * @param newId 分配的新ID
2296
- */
2297
- setRelateId(oldId, newId) {
2298
- this.state.relateIdMap[oldId] = newId;
2299
- }
2300
- }
2301
- const propsService = new Props();
2302
-
2303
2303
  class Editor extends BaseService {
2304
2304
  state = vue.reactive({
2305
2305
  root: null,
@@ -2935,14 +2935,14 @@
2935
2935
  * @param targetId 容器ID
2936
2936
  */
2937
2937
  async moveToContainer(config, targetId) {
2938
- const root = lodashEs.cloneDeep(this.get("root"));
2938
+ const root = this.get("root");
2939
2939
  const { node, parent } = this.getNodeInfo(config.id, false);
2940
2940
  const target = this.getNodeById(targetId, false);
2941
2941
  const stage = this.get("stage");
2942
2942
  if (root && node && parent && stage) {
2943
2943
  const index = getNodeIndex(node.id, parent);
2944
2944
  parent.items?.splice(index, 1);
2945
- await stage.remove({ id: node.id, parentId: parent.id, root });
2945
+ await stage.remove({ id: node.id, parentId: parent.id, root: lodashEs.cloneDeep(root) });
2946
2946
  const layout = await this.getLayout(target);
2947
2947
  const newConfig = lodashEs.mergeWith(lodashEs.cloneDeep(node), config, (objValue, srcValue) => {
2948
2948
  if (Array.isArray(srcValue)) {
@@ -2953,7 +2953,7 @@
2953
2953
  target.items.push(newConfig);
2954
2954
  await stage.select(targetId);
2955
2955
  const targetParent = this.getParentById(target.id);
2956
- await stage.update({ config: lodashEs.cloneDeep(target), parentId: targetParent?.id, root });
2956
+ await stage.update({ config: lodashEs.cloneDeep(target), parentId: targetParent?.id, root: lodashEs.cloneDeep(root) });
2957
2957
  await this.select(newConfig);
2958
2958
  stage.select(newConfig.id);
2959
2959
  this.addModifiedNodeId(target.id);
@@ -2998,6 +2998,7 @@
2998
2998
  this.addModifiedNodeId(config.id);
2999
2999
  this.addModifiedNodeId(parent.id);
3000
3000
  this.pushHistoryState();
3001
+ this.emit("drag-to", { index, targetIndex, config, parent, targetParent });
3001
3002
  }
3002
3003
  /**
3003
3004
  * 撤销当前操作
@@ -5223,14 +5224,17 @@
5223
5224
  const selectNode = async (id) => {
5224
5225
  await services?.editorService.select(id);
5225
5226
  services?.editorService.get("stage")?.select(id);
5227
+ services?.stageOverlayService.get("stage")?.select(id);
5226
5228
  };
5227
5229
  const highlight = lodashEs.throttle((id) => {
5228
5230
  services?.editorService.highlight(id);
5229
5231
  services?.editorService.get("stage")?.highlight(id);
5232
+ services?.stageOverlayService.get("stage")?.highlight(id);
5230
5233
  }, 150);
5231
5234
  const unhightlight = () => {
5232
5235
  services?.editorService.set("highlightNode", null);
5233
5236
  services?.editorService.get("stage")?.clearHighlight();
5237
+ services?.stageOverlayService.get("stage")?.clearHighlight();
5234
5238
  };
5235
5239
  return (_ctx, _cache) => {
5236
5240
  return uiSelectMode.value ? (vue.openBlock(), vue.createElementBlock("div", {
@@ -5370,7 +5374,7 @@
5370
5374
 
5371
5375
  const _sfc_main$z = /* @__PURE__ */ vue.defineComponent({
5372
5376
  ...{
5373
- name: "MEditorLayout"
5377
+ name: "MEditorSplitView"
5374
5378
  },
5375
5379
  __name: "SplitView",
5376
5380
  props: {
@@ -7898,6 +7902,7 @@
7898
7902
  } else {
7899
7903
  await services?.editorService.select(data);
7900
7904
  services?.editorService.get("stage")?.select(data.id);
7905
+ services?.stageOverlayService.get("stage")?.select(data.id);
7901
7906
  }
7902
7907
  };
7903
7908
  const multiSelect = async (data) => {
@@ -7916,6 +7921,7 @@
7916
7921
  }
7917
7922
  await services?.editorService.multiSelect(newNodes);
7918
7923
  services?.editorService.get("stage")?.multiSelect(newNodes);
7924
+ services?.stageOverlayService.get("stage")?.multiSelect(newNodes);
7919
7925
  };
7920
7926
  const throttleTime = 300;
7921
7927
  const highlightHandler = lodashEs.throttle((event, data) => {
@@ -7924,6 +7930,7 @@
7924
7930
  const highlight = (data) => {
7925
7931
  services?.editorService?.highlight(data);
7926
7932
  services?.editorService?.get("stage")?.highlight(data.id);
7933
+ services?.stageOverlayService?.get("stage")?.highlight(data.id);
7927
7934
  };
7928
7935
  const nodeClickHandler = (event, data) => {
7929
7936
  if (!nodeStatusMap?.value)
@@ -8473,8 +8480,8 @@
8473
8480
  globalThis.clearTimeout(timeout);
8474
8481
  timeout = void 0;
8475
8482
  }
8476
- const doc = stage.value?.renderer.contentWindow?.document;
8477
- if (doc && stageOptions) {
8483
+ const doc = stage.value?.renderer.getDocument();
8484
+ if (doc && stageOptions?.containerHighlightClassName) {
8478
8485
  utils.removeClassNameByClassName(doc, stageOptions.containerHighlightClassName);
8479
8486
  }
8480
8487
  clientX = 0;
@@ -9282,7 +9289,9 @@
9282
9289
  disabledDragStart: stageOptions.disabledDragStart,
9283
9290
  renderType: stageOptions.renderType,
9284
9291
  canSelect: (el, event, stop) => {
9285
- const elCanSelect = stageOptions.canSelect(el);
9292
+ if (!stageOptions.canSelect)
9293
+ return true;
9294
+ const elCanSelect = stageOptions.canSelect?.(el);
9286
9295
  if (uiSelectMode.value && elCanSelect && event.type === "mousedown") {
9287
9296
  document.dispatchEvent(new CustomEvent(UI_SELECT_MODE_EVENT_NAME, { detail: el }));
9288
9297
  return stop();
@@ -9577,152 +9586,71 @@
9577
9586
  }
9578
9587
  });
9579
9588
 
9580
- const useStageOverlay = () => {
9581
- const services = vue.inject("services");
9582
- const stageOptions = vue.inject("stageOptions");
9583
- const wrapWidth = vue.ref(0);
9584
- const wrapHeight = vue.ref(0);
9585
- const stageOverlayVisible = vue.ref(false);
9586
- const stageOverlay = vue.ref();
9587
- const stage = vue.computed(() => services?.editorService.get("stage"));
9588
- let subStage = null;
9589
- const div = document.createElement("div");
9590
- let selectEl = null;
9591
- const render = () => {
9592
- if (!selectEl)
9593
- return;
9594
- const content = selectEl.cloneNode(true);
9595
- content.style.position = "static";
9596
- Array.from(div.children).forEach((element) => {
9597
- element.remove();
9598
- });
9599
- div.appendChild(content);
9600
- subStage?.renderer.contentWindow?.magic.onPageElUpdate(div);
9601
- subStage?.select(content);
9602
- };
9603
- const copyDocumentElement = () => {
9604
- const doc = subStage?.renderer.getDocument();
9605
- const documentElement = stage.value?.renderer.getDocument()?.documentElement;
9606
- if (doc && documentElement) {
9607
- doc.replaceChild(documentElement.cloneNode(true), doc.documentElement);
9608
- }
9609
- };
9610
- const updateOverlay = () => {
9611
- if (!selectEl)
9612
- return;
9613
- const { scrollWidth, scrollHeight } = selectEl;
9614
- stageOverlay.value.style.width = `${scrollWidth}px`;
9615
- stageOverlay.value.style.height = `${scrollHeight}px`;
9616
- wrapWidth.value = scrollWidth;
9617
- wrapHeight.value = scrollHeight;
9618
- };
9619
- const updateHandler = () => {
9620
- render();
9621
- updateOverlay();
9622
- };
9623
- const addHandler = () => {
9624
- render();
9625
- updateOverlay();
9626
- };
9627
- const removeHandler = () => {
9628
- render();
9629
- updateOverlay();
9630
- };
9631
- const openOverlay = async (el) => {
9632
- selectEl = el;
9633
- stageOverlayVisible.value = true;
9634
- if (!stageOverlay.value) {
9635
- await vue.nextTick();
9636
- }
9637
- if (!stageOptions) {
9638
- return;
9639
- }
9640
- subStage = useStage({
9641
- ...stageOptions,
9642
- runtimeUrl: "",
9643
- autoScrollIntoView: false,
9644
- render(stage2) {
9645
- copyDocumentElement();
9646
- const rootEl = stage2.renderer.getDocument()?.getElementById("app");
9647
- if (rootEl) {
9648
- rootEl.remove();
9649
- }
9650
- div.style.cssText = `
9651
- width: ${el.scrollWidth}px;
9652
- height: ${el.scrollHeight}px;
9653
- background-color: #fff;
9654
- `;
9655
- render();
9656
- return div;
9657
- }
9658
- });
9659
- subStage.mount(stageOverlay.value);
9660
- const { mask, renderer } = subStage;
9661
- const { contentWindow } = renderer;
9662
- mask.showRule(false);
9663
- updateOverlay();
9664
- contentWindow?.magic.onRuntimeReady({});
9665
- services?.editorService.on("update", updateHandler);
9666
- services?.editorService.on("add", addHandler);
9667
- services?.editorService.on("remove", removeHandler);
9668
- };
9669
- const closeOverlay = () => {
9670
- stageOverlayVisible.value = false;
9671
- subStage?.destroy();
9672
- subStage = null;
9673
- services?.editorService.off("update", updateHandler);
9674
- services?.editorService.off("add", addHandler);
9675
- services?.editorService.off("remove", removeHandler);
9676
- };
9677
- vue.watch(stage, (stage2) => {
9678
- if (stage2) {
9679
- stage2.on("dblclick", async (event) => {
9680
- const el = await stage2.actionManager.getElementFromPoint(event);
9681
- if (el) {
9682
- openOverlay(el);
9683
- }
9684
- });
9685
- } else if (subStage) {
9686
- closeOverlay();
9687
- }
9688
- });
9689
- return {
9690
- wrapWidth,
9691
- wrapHeight,
9692
- stageOverlayVisible,
9693
- stageOverlay,
9694
- closeOverlay
9695
- };
9696
- };
9697
-
9698
9589
  const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
9699
9590
  __name: "StageOverlay",
9700
9591
  setup(__props) {
9701
- const { stageOverlayVisible, stageOverlay, closeOverlay } = useStageOverlay();
9592
+ const services = vue.inject("services");
9593
+ const stageOptions = vue.inject("stageOptions");
9594
+ const stageOverlay = vue.ref();
9595
+ const stageOverlayVisible = vue.computed(() => services?.stageOverlayService.get("stageOverlayVisible"));
9596
+ const wrapWidth = vue.computed(() => services?.stageOverlayService.get("wrapWidth") || 0);
9597
+ const wrapHeight = vue.computed(() => services?.stageOverlayService.get("wrapHeight") || 0);
9598
+ const stage = vue.computed(() => services?.editorService.get("stage"));
9599
+ const style = vue.computed(() => ({
9600
+ width: `${wrapWidth.value}px`,
9601
+ height: `${wrapHeight.value}px`
9602
+ }));
9603
+ vue.watch(stage, (stage2) => {
9604
+ if (stage2) {
9605
+ stage2.on("dblclick", async (event) => {
9606
+ const el = await stage2.actionManager.getElementFromPoint(event);
9607
+ services?.stageOverlayService.openOverlay(el);
9608
+ });
9609
+ } else {
9610
+ services?.stageOverlayService.closeOverlay();
9611
+ }
9612
+ });
9613
+ vue.watch(stageOverlay, (stageOverlay2) => {
9614
+ if (!services)
9615
+ return;
9616
+ const subStage = services.stageOverlayService.createStage(stageOptions);
9617
+ services?.stageOverlayService.set("stage", subStage);
9618
+ if (stageOverlay2 && subStage) {
9619
+ subStage.mount(stageOverlay2);
9620
+ const { mask, renderer } = subStage;
9621
+ const { contentWindow } = renderer;
9622
+ mask.showRule(false);
9623
+ services?.stageOverlayService.updateOverlay();
9624
+ contentWindow?.magic.onRuntimeReady({});
9625
+ }
9626
+ });
9627
+ const closeOverlayHandler = () => {
9628
+ services?.stageOverlayService.closeOverlay();
9629
+ };
9702
9630
  return (_ctx, _cache) => {
9703
- return vue.unref(stageOverlayVisible) ? (vue.openBlock(), vue.createElementBlock("div", {
9631
+ return stageOverlayVisible.value ? (vue.openBlock(), vue.createElementBlock("div", {
9704
9632
  key: 0,
9705
9633
  class: "m-editor-stage-overlay",
9706
- onClick: _cache[1] || (_cache[1] = //@ts-ignore
9707
- (...args) => vue.unref(closeOverlay) && vue.unref(closeOverlay)(...args))
9634
+ onClick: closeOverlayHandler
9708
9635
  }, [
9709
9636
  vue.createVNode(vue.unref(design.TMagicIcon), {
9710
9637
  class: "m-editor-stage-overlay-close",
9711
9638
  size: 20,
9712
- onClick: vue.unref(closeOverlay)
9639
+ onClick: closeOverlayHandler
9713
9640
  }, {
9714
9641
  default: vue.withCtx(() => [
9715
9642
  vue.createVNode(vue.unref(iconsVue.CloseBold))
9716
9643
  ]),
9717
9644
  _: 1
9718
- }, 8, ["onClick"]),
9645
+ }),
9719
9646
  vue.createElementVNode("div", {
9720
9647
  ref_key: "stageOverlay",
9721
9648
  ref: stageOverlay,
9722
9649
  class: "m-editor-stage-overlay-container",
9650
+ style: vue.normalizeStyle(style.value),
9723
9651
  onClick: _cache[0] || (_cache[0] = vue.withModifiers(() => {
9724
9652
  }, ["stop"]))
9725
- }, null, 512)
9653
+ }, null, 4)
9726
9654
  ])) : vue.createCommentVNode("", true);
9727
9655
  };
9728
9656
  }
@@ -9909,7 +9837,8 @@
9909
9837
  __name: "Stage",
9910
9838
  props: {
9911
9839
  stageContentMenu: {},
9912
- customContentMenu: { type: Function }
9840
+ disabledStageOverlay: { type: Boolean, default: false },
9841
+ customContentMenu: {}
9913
9842
  },
9914
9843
  setup(__props) {
9915
9844
  let stage = null;
@@ -10070,7 +9999,7 @@
10070
9999
  onClick: _cache[0] || (_cache[0] = ($event) => stageWrap.value?.container?.focus())
10071
10000
  }, {
10072
10001
  content: vue.withCtx(() => [
10073
- vue.createVNode(_sfc_main$6),
10002
+ !_ctx.disabledStageOverlay ? (vue.openBlock(), vue.createBlock(_sfc_main$6, { key: 0 })) : vue.createCommentVNode("", true),
10074
10003
  (vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
10075
10004
  vue.createVNode(_sfc_main$4, {
10076
10005
  ref_key: "menu",
@@ -10152,7 +10081,8 @@
10152
10081
  __name: "Workspace",
10153
10082
  props: {
10154
10083
  stageContentMenu: {},
10155
- customContentMenu: { type: Function }
10084
+ disabledStageOverlay: { type: Boolean, default: false },
10085
+ customContentMenu: {}
10156
10086
  },
10157
10087
  setup(__props) {
10158
10088
  const services = vue.inject("services");
@@ -10163,9 +10093,10 @@
10163
10093
  vue.renderSlot(_ctx.$slots, "stage", {}, () => [
10164
10094
  page.value ? (vue.openBlock(), vue.createBlock(_sfc_main$3, {
10165
10095
  key: 0,
10096
+ "disabled-stage-overlay": _ctx.disabledStageOverlay,
10166
10097
  "stage-content-menu": _ctx.stageContentMenu,
10167
10098
  "custom-content-menu": _ctx.customContentMenu
10168
- }, null, 8, ["stage-content-menu", "custom-content-menu"])) : vue.createCommentVNode("", true)
10099
+ }, null, 8, ["disabled-stage-overlay", "stage-content-menu", "custom-content-menu"])) : vue.createCommentVNode("", true)
10169
10100
  ]),
10170
10101
  vue.renderSlot(_ctx.$slots, "workspace-content")
10171
10102
  ]);
@@ -10624,7 +10555,170 @@
10624
10555
  }
10625
10556
  const keybindingService = new Keybinding();
10626
10557
 
10558
+ class StageOverlay extends BaseService {
10559
+ state = vue.reactive({
10560
+ wrapDiv: document.createElement("div"),
10561
+ sourceEl: null,
10562
+ contentEl: null,
10563
+ stage: null,
10564
+ stageOptions: null,
10565
+ wrapWidth: 0,
10566
+ wrapHeight: 0,
10567
+ stageOverlayVisible: false
10568
+ });
10569
+ constructor() {
10570
+ super([
10571
+ { name: "openOverlay", isAsync: false },
10572
+ { name: "closeOverlay", isAsync: false },
10573
+ { name: "updateOverlay", isAsync: false },
10574
+ { name: "createStage", isAsync: false }
10575
+ ]);
10576
+ this.get("wrapDiv").classList.add("tmagic-editor-sub-stage-wrap");
10577
+ }
10578
+ get(name) {
10579
+ return this.state[name];
10580
+ }
10581
+ set(name, value) {
10582
+ this.state[name] = value;
10583
+ }
10584
+ openOverlay(el) {
10585
+ const stageOptions = this.get("stageOptions");
10586
+ if (!el || !stageOptions)
10587
+ return;
10588
+ this.set("sourceEl", el);
10589
+ this.createContentEl();
10590
+ this.set("stageOverlayVisible", true);
10591
+ editorService.on("update", this.updateHandler);
10592
+ editorService.on("add", this.addHandler);
10593
+ editorService.on("remove", this.removeHandler);
10594
+ editorService.on("drag-to", this.updateHandler);
10595
+ editorService.on("move-layer", this.updateHandler);
10596
+ }
10597
+ closeOverlay() {
10598
+ this.set("stageOverlayVisible", false);
10599
+ const subStage = this.get("stage");
10600
+ const wrapDiv = this.get("wrapDiv");
10601
+ subStage?.destroy();
10602
+ wrapDiv.remove();
10603
+ this.set("stage", null);
10604
+ this.set("sourceEl", null);
10605
+ this.set("contentEl", null);
10606
+ editorService.off("update", this.updateHandler);
10607
+ editorService.off("add", this.addHandler);
10608
+ editorService.off("remove", this.removeHandler);
10609
+ editorService.off("drag-to", this.updateHandler);
10610
+ editorService.off("move-layer", this.updateHandler);
10611
+ }
10612
+ updateOverlay() {
10613
+ const sourceEl = this.get("sourceEl");
10614
+ if (!sourceEl)
10615
+ return;
10616
+ const { scrollWidth, scrollHeight } = sourceEl;
10617
+ this.set("wrapWidth", scrollWidth);
10618
+ this.set("wrapHeight", scrollHeight);
10619
+ }
10620
+ createStage(stageOptions = {}) {
10621
+ return useStage({
10622
+ ...stageOptions,
10623
+ runtimeUrl: "",
10624
+ autoScrollIntoView: false,
10625
+ render: async (stage) => {
10626
+ this.copyDocumentElement();
10627
+ const rootEls = stage.renderer.getDocument()?.body.children;
10628
+ if (rootEls) {
10629
+ Array.from(rootEls).forEach((element) => {
10630
+ if (["SCRIPT", "STYLE"].includes(element.tagName)) {
10631
+ return;
10632
+ }
10633
+ element.remove();
10634
+ });
10635
+ }
10636
+ const wrapDiv = this.get("wrapDiv");
10637
+ await this.render();
10638
+ return wrapDiv;
10639
+ }
10640
+ });
10641
+ }
10642
+ createContentEl() {
10643
+ const sourceEl = this.get("sourceEl");
10644
+ if (!sourceEl)
10645
+ return;
10646
+ const contentEl = sourceEl.cloneNode(true);
10647
+ this.set("contentEl", contentEl);
10648
+ contentEl.style.position = "static";
10649
+ contentEl.style.overflow = "visible";
10650
+ }
10651
+ copyDocumentElement() {
10652
+ const subStage = this.get("stage");
10653
+ const stage = editorService.get("stage");
10654
+ const doc = subStage?.renderer.getDocument();
10655
+ const documentElement = stage?.renderer.getDocument()?.documentElement;
10656
+ if (doc && documentElement) {
10657
+ doc.replaceChild(documentElement.cloneNode(true), doc.documentElement);
10658
+ }
10659
+ }
10660
+ async render() {
10661
+ this.createContentEl();
10662
+ const contentEl = this.get("contentEl");
10663
+ const sourceEl = this.get("sourceEl");
10664
+ const wrapDiv = this.get("wrapDiv");
10665
+ const subStage = this.get("stage");
10666
+ const stageOptions = this.get("stageOptions");
10667
+ if (!contentEl)
10668
+ return;
10669
+ wrapDiv.style.cssText = `
10670
+ width: ${sourceEl?.scrollWidth}px;
10671
+ height: ${sourceEl?.scrollHeight}px;
10672
+ background-color: #fff;
10673
+ `;
10674
+ Array.from(wrapDiv.children).forEach((element) => {
10675
+ element.remove();
10676
+ });
10677
+ wrapDiv.appendChild(contentEl);
10678
+ setTimeout(() => {
10679
+ subStage?.renderer.contentWindow?.magic.onPageElUpdate(wrapDiv);
10680
+ });
10681
+ if (await stageOptions?.canSelect?.(contentEl)) {
10682
+ subStage?.select(contentEl);
10683
+ }
10684
+ }
10685
+ updateHandler = () => {
10686
+ setTimeout(() => {
10687
+ this.render();
10688
+ this.updateOverlay();
10689
+ this.updateSelectStatus();
10690
+ });
10691
+ };
10692
+ addHandler = () => {
10693
+ this.render();
10694
+ this.updateOverlay();
10695
+ this.updateSelectStatus();
10696
+ };
10697
+ removeHandler = () => {
10698
+ this.render();
10699
+ this.updateOverlay();
10700
+ this.updateSelectStatus();
10701
+ };
10702
+ updateSelectStatus() {
10703
+ const subStage = this.get("stage");
10704
+ const nodes = editorService.get("nodes");
10705
+ if (nodes.length > 1) {
10706
+ subStage?.multiSelect(nodes.map((n) => n.id));
10707
+ } else {
10708
+ subStage?.select(nodes[0].id);
10709
+ }
10710
+ }
10711
+ }
10712
+ const stageOverlayService = new StageOverlay();
10713
+
10627
10714
  const defaultEditorProps = {
10715
+ renderType: StageCore.RenderType.IFRAME,
10716
+ disabledMultiSelect: false,
10717
+ disabledPageFragment: false,
10718
+ disabledStageOverlay: false,
10719
+ containerHighlightClassName: StageCore.CONTAINER_HIGHLIGHT_CLASS_NAME,
10720
+ containerHighlightDuration: 800,
10721
+ containerHighlightType: StageCore.ContainerHighlightType.DEFAULT,
10628
10722
  componentGroupList: () => [],
10629
10723
  datasourceList: () => [],
10630
10724
  menu: () => ({ left: [], right: [] }),
@@ -10637,13 +10731,7 @@
10637
10731
  datasourceConfigs: () => ({}),
10638
10732
  canSelect: (el) => Boolean(el.id),
10639
10733
  isContainer: (el) => el.classList.contains("magic-ui-container"),
10640
- containerHighlightClassName: StageCore.CONTAINER_HIGHLIGHT_CLASS_NAME,
10641
- containerHighlightDuration: 800,
10642
- containerHighlightType: StageCore.ContainerHighlightType.DEFAULT,
10643
- codeOptions: () => ({}),
10644
- renderType: StageCore.RenderType.IFRAME,
10645
- disabledMultiSelect: false,
10646
- disabledPageFragment: false
10734
+ codeOptions: () => ({})
10647
10735
  };
10648
10736
 
10649
10737
  const initServiceState = (props, {
@@ -10990,7 +11078,6 @@
10990
11078
  menu: {},
10991
11079
  layerContentMenu: {},
10992
11080
  stageContentMenu: {},
10993
- render: { type: Function },
10994
11081
  runtimeUrl: {},
10995
11082
  renderType: {},
10996
11083
  autoScrollIntoView: { type: Boolean },
@@ -11002,21 +11089,23 @@
11002
11089
  datasourceEventMethodList: {},
11003
11090
  moveableOptions: { type: Function },
11004
11091
  defaultSelected: {},
11005
- canSelect: { type: Function },
11006
- isContainer: { type: Function },
11007
11092
  containerHighlightClassName: {},
11008
11093
  containerHighlightDuration: {},
11009
11094
  containerHighlightType: {},
11010
11095
  stageRect: {},
11011
11096
  codeOptions: {},
11012
- updateDragEl: { type: Function },
11013
11097
  disabledDragStart: { type: Boolean },
11014
- extendFormState: { type: Function },
11015
11098
  collectorOptions: {},
11016
11099
  guidesOptions: {},
11017
11100
  disabledMultiSelect: { type: Boolean },
11018
11101
  disabledPageFragment: { type: Boolean },
11019
- customContentMenu: { type: Function }
11102
+ disabledStageOverlay: { type: Boolean },
11103
+ render: { type: Function },
11104
+ updateDragEl: { type: Function },
11105
+ canSelect: { type: Function },
11106
+ isContainer: { type: Function },
11107
+ customContentMenu: { type: Function },
11108
+ extendFormState: { type: Function }
11020
11109
  }, defaultEditorProps),
11021
11110
  emits: ["props-panel-mounted", "update:modelValue", "props-form-error", "props-submit-error"],
11022
11111
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -11033,33 +11122,33 @@
11033
11122
  codeBlockService,
11034
11123
  depService,
11035
11124
  dataSourceService,
11036
- keybindingService
11125
+ keybindingService,
11126
+ stageOverlayService
11037
11127
  };
11038
11128
  initServiceEvents(props, emit, services);
11039
11129
  initServiceState(props, services);
11040
11130
  keybindingService.register(keybindingConfig);
11041
11131
  keybindingService.registerEl("global");
11132
+ const stageOptions = {
11133
+ runtimeUrl: props.runtimeUrl,
11134
+ autoScrollIntoView: props.autoScrollIntoView,
11135
+ render: props.render,
11136
+ moveableOptions: props.moveableOptions,
11137
+ canSelect: props.canSelect,
11138
+ updateDragEl: props.updateDragEl,
11139
+ isContainer: props.isContainer,
11140
+ containerHighlightClassName: props.containerHighlightClassName,
11141
+ containerHighlightDuration: props.containerHighlightDuration,
11142
+ containerHighlightType: props.containerHighlightType,
11143
+ disabledDragStart: props.disabledDragStart,
11144
+ renderType: props.renderType,
11145
+ guidesOptions: props.guidesOptions,
11146
+ disabledMultiSelect: props.disabledMultiSelect
11147
+ };
11148
+ stageOverlayService.set("stageOptions", stageOptions);
11042
11149
  vue.provide("services", services);
11043
11150
  vue.provide("codeOptions", props.codeOptions);
11044
- vue.provide(
11045
- "stageOptions",
11046
- vue.reactive({
11047
- runtimeUrl: props.runtimeUrl,
11048
- autoScrollIntoView: props.autoScrollIntoView,
11049
- render: props.render,
11050
- moveableOptions: props.moveableOptions,
11051
- canSelect: props.canSelect,
11052
- updateDragEl: props.updateDragEl,
11053
- isContainer: props.isContainer,
11054
- containerHighlightClassName: props.containerHighlightClassName,
11055
- containerHighlightDuration: props.containerHighlightDuration,
11056
- containerHighlightType: props.containerHighlightType,
11057
- disabledDragStart: props.disabledDragStart,
11058
- renderType: props.renderType,
11059
- guidesOptions: props.guidesOptions,
11060
- disabledMultiSelect: props.disabledMultiSelect
11061
- })
11062
- );
11151
+ vue.provide("stageOptions", stageOptions);
11063
11152
  __expose(services);
11064
11153
  return (_ctx, _cache) => {
11065
11154
  return vue.openBlock(), vue.createBlock(_sfc_main$s, { "disabled-page-fragment": _ctx.disabledPageFragment }, {
@@ -11121,6 +11210,7 @@
11121
11210
  workspace: vue.withCtx(() => [
11122
11211
  vue.renderSlot(_ctx.$slots, "workspace", { editorService: vue.unref(editorService) }, () => [
11123
11212
  vue.createVNode(_sfc_main$1, {
11213
+ "disabled-stage-overlay": _ctx.disabledStageOverlay,
11124
11214
  "stage-content-menu": _ctx.stageContentMenu,
11125
11215
  "custom-content-menu": _ctx.customContentMenu
11126
11216
  }, {
@@ -11131,7 +11221,7 @@
11131
11221
  vue.renderSlot(_ctx.$slots, "workspace-content", { editorService: vue.unref(editorService) })
11132
11222
  ]),
11133
11223
  _: 3
11134
- }, 8, ["stage-content-menu", "custom-content-menu"])
11224
+ }, 8, ["disabled-stage-overlay", "stage-content-menu", "custom-content-menu"])
11135
11225
  ])
11136
11226
  ]),
11137
11227
  "props-panel": vue.withCtx(() => [
@@ -11286,6 +11376,7 @@
11286
11376
  exports.setChildrenLayout = setChildrenLayout;
11287
11377
  exports.setConfig = setConfig;
11288
11378
  exports.setLayout = setLayout;
11379
+ exports.stageOverlayService = stageOverlayService;
11289
11380
  exports.storageService = storageService;
11290
11381
  exports.styleTabConfig = styleTabConfig;
11291
11382
  exports.traverseNode = traverseNode;