@tmagic/editor 1.5.0-beta.1 → 1.5.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/style.css CHANGED
@@ -432,12 +432,13 @@
432
432
  width: 100%;
433
433
  }
434
434
  .m-editor-page-bar-tabs .tmagic-design-button.m-editor-page-bar-switch-type-button {
435
- margin-left: 7px;
435
+ margin-left: 10px;
436
436
  position: relative;
437
437
  top: 1px;
438
438
  border-radius: 3px 3px 0 0;
439
439
  border: 1px solid #d9dbdd;
440
440
  border-bottom: 1px solid transparent;
441
+ padding: 5px 10px;
441
442
  }
442
443
  .m-editor-page-bar-tabs .tmagic-design-button.m-editor-page-bar-switch-type-button.active {
443
444
  background-color: #f3f3f3;
@@ -1012,11 +1012,14 @@ const getMiddleTop = (node, parentNode, stage) => {
1012
1012
  height = 0;
1013
1013
  }
1014
1014
  const { height: parentHeight } = parentNode.style;
1015
- const { scrollTop = 0, wrapperHeight } = stage.mask;
1016
- const wrapperHeightDeal = calcValueByFontsize(stage.renderer.getDocument(), wrapperHeight);
1017
- const scrollTopDeal = calcValueByFontsize(stage.renderer.getDocument(), scrollTop);
1018
- if (isPage(parentNode)) {
1019
- return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
1015
+ let wrapperHeightDeal = parentHeight;
1016
+ if (stage.mask && stage.renderer) {
1017
+ const { scrollTop = 0, wrapperHeight } = stage.mask;
1018
+ wrapperHeightDeal = calcValueByFontsize(stage.renderer.getDocument(), wrapperHeight);
1019
+ const scrollTopDeal = calcValueByFontsize(stage.renderer.getDocument(), scrollTop);
1020
+ if (isPage(parentNode)) {
1021
+ return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
1022
+ }
1020
1023
  }
1021
1024
  return (Math.min(parentHeight, wrapperHeightDeal) - height) / 2;
1022
1025
  };
@@ -1131,7 +1134,7 @@ const fixNodePosition = (config, parent, stage) => {
1131
1134
  return {
1132
1135
  ...config.style || {},
1133
1136
  top: getMiddleTop(config, parent, stage),
1134
- left: fixNodeLeft(config, parent, stage?.renderer.contentWindow?.document)
1137
+ left: fixNodeLeft(config, parent, stage?.renderer?.contentWindow?.document)
1135
1138
  };
1136
1139
  };
1137
1140
  const serializeConfig = (config) => serialize(config, {
@@ -1940,7 +1943,7 @@ class Editor extends BaseService {
1940
1943
  historyService.resetState();
1941
1944
  }
1942
1945
  if (node?.id) {
1943
- this.get("stage")?.renderer.runtime?.getApp?.()?.page?.emit(
1946
+ this.get("stage")?.renderer?.runtime?.getApp?.()?.page?.emit(
1944
1947
  "editor:select",
1945
1948
  {
1946
1949
  node,
@@ -2294,7 +2297,7 @@ class Editor extends BaseService {
2294
2297
  }
2295
2298
  async doPaste(config, position = {}) {
2296
2299
  propsService.clearRelateId();
2297
- const doc = this.get("stage")?.renderer.contentWindow?.document;
2300
+ const doc = this.get("stage")?.renderer?.contentWindow?.document;
2298
2301
  const pasteConfigs = beforePaste(position, cloneDeep(config), doc);
2299
2302
  return pasteConfigs;
2300
2303
  }
@@ -2308,7 +2311,7 @@ class Editor extends BaseService {
2308
2311
  }
2309
2312
  if (!node.style) return config;
2310
2313
  const stage = this.get("stage");
2311
- const doc = stage?.renderer.contentWindow?.document;
2314
+ const doc = stage?.renderer?.contentWindow?.document;
2312
2315
  if (doc) {
2313
2316
  const el = getElById()(doc, node.id);
2314
2317
  const parentEl = layout === Layout.FIXED ? doc.body : el?.offsetParent;
@@ -3881,7 +3884,7 @@ const useStage = (stageOptions) => {
3881
3884
  }
3882
3885
  }
3883
3886
  );
3884
- stage.mask.setGuides([
3887
+ stage.mask?.setGuides([
3885
3888
  getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY)),
3886
3889
  getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY))
3887
3890
  ]);
@@ -3937,6 +3940,9 @@ const useStage = (stageOptions) => {
3937
3940
  globalThis.localStorage.removeItem(storageKey);
3938
3941
  }
3939
3942
  });
3943
+ onBeforeUnmount(() => {
3944
+ stage.destroy();
3945
+ });
3940
3946
  return stage;
3941
3947
  };
3942
3948
 
@@ -4798,7 +4804,7 @@ const _sfc_main$N = /* @__PURE__ */ defineComponent({
4798
4804
  "last-values": _ctx.lastValues,
4799
4805
  "init-values": _ctx.initValues,
4800
4806
  values: _ctx.values,
4801
- prop: `${_ctx.prop}${_ctx.prop ? "." : ""}${_ctx.name}`,
4807
+ prop: _ctx.prop,
4802
4808
  onChange: onChangeHandler
4803
4809
  }, null, 40, ["config", "model", "name", "disabled", "size", "last-values", "init-values", "values", "prop"])),
4804
4810
  _ctx.config.fieldConfig ? (openBlock(), createBlock(unref(TMagicTooltip), {
@@ -7385,8 +7391,9 @@ const _sfc_main$v = /* @__PURE__ */ defineComponent({
7385
7391
  createVNode(unref(TMagicPopover), {
7386
7392
  "popper-class": "page-bar-popover",
7387
7393
  placement: "top",
7394
+ trigger: "hover",
7388
7395
  width: 160,
7389
- trigger: "hover"
7396
+ "destroy-on-close": true
7390
7397
  }, {
7391
7398
  reference: withCtx(() => [
7392
7399
  createVNode(unref(TMagicIcon), { class: "m-editor-page-list-menu-icon" }, {
@@ -7583,8 +7590,9 @@ const _sfc_main$t = /* @__PURE__ */ defineComponent({
7583
7590
  createVNode(unref(TMagicPopover), {
7584
7591
  "popper-class": "page-bar-popover",
7585
7592
  placement: "top",
7593
+ trigger: "hover",
7586
7594
  width: 160,
7587
- trigger: "hover"
7595
+ "destroy-on-close": true
7588
7596
  }, {
7589
7597
  reference: withCtx(() => [
7590
7598
  createVNode(unref(TMagicIcon), { class: "m-editor-page-bar-menu-icon" }, {
@@ -8897,7 +8905,8 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
8897
8905
  key: 0,
8898
8906
  placement: "right",
8899
8907
  trigger: "hover",
8900
- "popper-class": "data-source-list-panel-add-menu"
8908
+ "popper-class": "data-source-list-panel-add-menu",
8909
+ "destroy-on-close": true
8901
8910
  }, {
8902
8911
  reference: withCtx(() => [
8903
8912
  createVNode(unref(TMagicButton), {
@@ -9181,8 +9190,8 @@ const usePasteMenu = (menu) => ({
9181
9190
  const stage = services?.editorService?.get("stage");
9182
9191
  const rect = menu.value.$el.getBoundingClientRect();
9183
9192
  const parentRect = stage?.container?.getBoundingClientRect();
9184
- const initialLeft = calcValueByFontsize(stage?.renderer.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) / services.uiService.get("zoom");
9185
- const initialTop = calcValueByFontsize(stage?.renderer.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) / services.uiService.get("zoom");
9193
+ const initialLeft = calcValueByFontsize(stage?.renderer?.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) / services.uiService.get("zoom");
9194
+ const initialTop = calcValueByFontsize(stage?.renderer?.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) / services.uiService.get("zoom");
9186
9195
  services?.editorService?.paste({ left: initialLeft, top: initialTop });
9187
9196
  } else {
9188
9197
  services?.editorService?.paste();
@@ -9965,7 +9974,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
9965
9974
  globalThis.clearTimeout(timeout);
9966
9975
  timeout = void 0;
9967
9976
  }
9968
- const doc = stage.value?.renderer.getDocument();
9977
+ const doc = stage.value?.renderer?.getDocument();
9969
9978
  if (doc && stageOptions?.containerHighlightClassName) {
9970
9979
  removeClassNameByClassName(doc, stageOptions.containerHighlightClassName);
9971
9980
  }
@@ -10591,7 +10600,7 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
10591
10600
  if (!stage2) return;
10592
10601
  nextTick(() => unWatch());
10593
10602
  stage2.on("select", (el, event) => {
10594
- const els = stage2.renderer.getElementsFromPoint(event) || [];
10603
+ const els = stage2.renderer?.getElementsFromPoint(event) || [];
10595
10604
  const ids = els.map((el2) => getIdFromEl()(el2)).filter((id) => Boolean(id));
10596
10605
  buttonVisible.value = ids.length > 3;
10597
10606
  filterTextChangeHandler(ids);
@@ -10690,7 +10699,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
10690
10699
  watch(stage, (stage2) => {
10691
10700
  if (stage2) {
10692
10701
  stage2.on("dblclick", async (event) => {
10693
- const el = await stage2.actionManager.getElementFromPoint(event);
10702
+ const el = await stage2.actionManager?.getElementFromPoint(event) || null;
10694
10703
  services?.stageOverlayService.openOverlay(el);
10695
10704
  });
10696
10705
  } else {
@@ -10705,7 +10714,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
10705
10714
  subStage.mount(stageOverlay2);
10706
10715
  const { mask, renderer } = subStage;
10707
10716
  const { contentWindow } = renderer;
10708
- mask.showRule(false);
10717
+ mask?.showRule(false);
10709
10718
  services?.stageOverlayService.updateOverlay();
10710
10719
  contentWindow?.magic.onRuntimeReady({});
10711
10720
  }
@@ -11018,7 +11027,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
11018
11027
  const config = parseDSL(`(${data})`);
11019
11028
  if (!config || config.dragType !== DragType.COMPONENT_LIST) return;
11020
11029
  e.preventDefault();
11021
- const doc = stage?.renderer.contentWindow?.document;
11030
+ const doc = stage?.renderer?.contentWindow?.document;
11022
11031
  const parentEl = doc?.querySelector(`.${stageOptions?.containerHighlightClassName}`);
11023
11032
  let parent = page.value;
11024
11033
  const parentId = getIdFromEl()(parentEl);
@@ -11961,6 +11970,10 @@ class StageOverlay extends BaseService {
11961
11970
  const subStage = this.get("stage");
11962
11971
  const wrapDiv = this.get("wrapDiv");
11963
11972
  subStage?.destroy();
11973
+ for (let i = 0, l = wrapDiv.children.length; i < l; i++) {
11974
+ const child = wrapDiv.children[i];
11975
+ child.remove();
11976
+ }
11964
11977
  wrapDiv.remove();
11965
11978
  this.set("stage", null);
11966
11979
  this.set("sourceEl", null);
@@ -11986,7 +11999,7 @@ class StageOverlay extends BaseService {
11986
11999
  autoScrollIntoView: false,
11987
12000
  render: async (stage) => {
11988
12001
  this.copyDocumentElement();
11989
- const rootEls = stage.renderer.getDocument()?.body.children;
12002
+ const rootEls = stage.renderer?.getDocument()?.body.children;
11990
12003
  if (rootEls) {
11991
12004
  Array.from(rootEls).forEach((element) => {
11992
12005
  if (["SCRIPT", "STYLE"].includes(element.tagName)) {
@@ -12015,8 +12028,8 @@ class StageOverlay extends BaseService {
12015
12028
  copyDocumentElement() {
12016
12029
  const subStage = this.get("stage");
12017
12030
  const stage = editorService.get("stage");
12018
- const doc = subStage?.renderer.getDocument();
12019
- const documentElement = stage?.renderer.getDocument()?.documentElement;
12031
+ const doc = subStage?.renderer?.getDocument();
12032
+ const documentElement = stage?.renderer?.getDocument()?.documentElement;
12020
12033
  if (doc && documentElement) {
12021
12034
  doc.replaceChild(documentElement.cloneNode(true), doc.documentElement);
12022
12035
  }
@@ -12034,12 +12047,13 @@ class StageOverlay extends BaseService {
12034
12047
  height: ${sourceEl?.scrollHeight}px;
12035
12048
  background-color: #fff;
12036
12049
  `;
12037
- Array.from(wrapDiv.children).forEach((element) => {
12038
- element.remove();
12039
- });
12050
+ for (let i = 0, l = wrapDiv.children.length; i < l; i++) {
12051
+ const child = wrapDiv.children[i];
12052
+ child.remove();
12053
+ }
12040
12054
  wrapDiv.appendChild(contentEl);
12041
12055
  setTimeout(() => {
12042
- subStage?.renderer.contentWindow?.magic.onPageElUpdate(wrapDiv);
12056
+ subStage?.renderer?.contentWindow?.magic.onPageElUpdate(wrapDiv);
12043
12057
  });
12044
12058
  if (await stageOptions?.canSelect?.(contentEl)) {
12045
12059
  const id = getIdFromEl()(contentEl);
@@ -12279,7 +12293,7 @@ const initServiceEvents = (props, emit, { editorService, codeBlockService, dataS
12279
12293
  };
12280
12294
  const getApp = () => {
12281
12295
  const stage = editorService.get("stage");
12282
- return stage?.renderer.runtime?.getApp?.();
12296
+ return stage?.renderer?.runtime?.getApp?.();
12283
12297
  };
12284
12298
  const updateDataSourceSchema = () => {
12285
12299
  const root = editorService.get("root");
@@ -1016,11 +1016,14 @@
1016
1016
  height = 0;
1017
1017
  }
1018
1018
  const { height: parentHeight } = parentNode.style;
1019
- const { scrollTop = 0, wrapperHeight } = stage.mask;
1020
- const wrapperHeightDeal = utils.calcValueByFontsize(stage.renderer.getDocument(), wrapperHeight);
1021
- const scrollTopDeal = utils.calcValueByFontsize(stage.renderer.getDocument(), scrollTop);
1022
- if (utils.isPage(parentNode)) {
1023
- return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
1019
+ let wrapperHeightDeal = parentHeight;
1020
+ if (stage.mask && stage.renderer) {
1021
+ const { scrollTop = 0, wrapperHeight } = stage.mask;
1022
+ wrapperHeightDeal = utils.calcValueByFontsize(stage.renderer.getDocument(), wrapperHeight);
1023
+ const scrollTopDeal = utils.calcValueByFontsize(stage.renderer.getDocument(), scrollTop);
1024
+ if (utils.isPage(parentNode)) {
1025
+ return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
1026
+ }
1024
1027
  }
1025
1028
  return (Math.min(parentHeight, wrapperHeightDeal) - height) / 2;
1026
1029
  };
@@ -1135,7 +1138,7 @@
1135
1138
  return {
1136
1139
  ...config.style || {},
1137
1140
  top: getMiddleTop(config, parent, stage),
1138
- left: fixNodeLeft(config, parent, stage?.renderer.contentWindow?.document)
1141
+ left: fixNodeLeft(config, parent, stage?.renderer?.contentWindow?.document)
1139
1142
  };
1140
1143
  };
1141
1144
  const serializeConfig = (config) => serialize(config, {
@@ -1944,7 +1947,7 @@
1944
1947
  historyService.resetState();
1945
1948
  }
1946
1949
  if (node?.id) {
1947
- this.get("stage")?.renderer.runtime?.getApp?.()?.page?.emit(
1950
+ this.get("stage")?.renderer?.runtime?.getApp?.()?.page?.emit(
1948
1951
  "editor:select",
1949
1952
  {
1950
1953
  node,
@@ -2298,7 +2301,7 @@
2298
2301
  }
2299
2302
  async doPaste(config, position = {}) {
2300
2303
  propsService.clearRelateId();
2301
- const doc = this.get("stage")?.renderer.contentWindow?.document;
2304
+ const doc = this.get("stage")?.renderer?.contentWindow?.document;
2302
2305
  const pasteConfigs = beforePaste(position, lodashEs.cloneDeep(config), doc);
2303
2306
  return pasteConfigs;
2304
2307
  }
@@ -2312,7 +2315,7 @@
2312
2315
  }
2313
2316
  if (!node.style) return config;
2314
2317
  const stage = this.get("stage");
2315
- const doc = stage?.renderer.contentWindow?.document;
2318
+ const doc = stage?.renderer?.contentWindow?.document;
2316
2319
  if (doc) {
2317
2320
  const el = utils.getElById()(doc, node.id);
2318
2321
  const parentEl = layout === Layout.FIXED ? doc.body : el?.offsetParent;
@@ -3885,7 +3888,7 @@
3885
3888
  }
3886
3889
  }
3887
3890
  );
3888
- stage.mask.setGuides([
3891
+ stage.mask?.setGuides([
3889
3892
  getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY)),
3890
3893
  getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY))
3891
3894
  ]);
@@ -3941,6 +3944,9 @@
3941
3944
  globalThis.localStorage.removeItem(storageKey);
3942
3945
  }
3943
3946
  });
3947
+ vue.onBeforeUnmount(() => {
3948
+ stage.destroy();
3949
+ });
3944
3950
  return stage;
3945
3951
  };
3946
3952
 
@@ -4802,7 +4808,7 @@
4802
4808
  "last-values": _ctx.lastValues,
4803
4809
  "init-values": _ctx.initValues,
4804
4810
  values: _ctx.values,
4805
- prop: `${_ctx.prop}${_ctx.prop ? "." : ""}${_ctx.name}`,
4811
+ prop: _ctx.prop,
4806
4812
  onChange: onChangeHandler
4807
4813
  }, null, 40, ["config", "model", "name", "disabled", "size", "last-values", "init-values", "values", "prop"])),
4808
4814
  _ctx.config.fieldConfig ? (vue.openBlock(), vue.createBlock(vue.unref(design.TMagicTooltip), {
@@ -7389,8 +7395,9 @@
7389
7395
  vue.createVNode(vue.unref(design.TMagicPopover), {
7390
7396
  "popper-class": "page-bar-popover",
7391
7397
  placement: "top",
7398
+ trigger: "hover",
7392
7399
  width: 160,
7393
- trigger: "hover"
7400
+ "destroy-on-close": true
7394
7401
  }, {
7395
7402
  reference: vue.withCtx(() => [
7396
7403
  vue.createVNode(vue.unref(design.TMagicIcon), { class: "m-editor-page-list-menu-icon" }, {
@@ -7587,8 +7594,9 @@
7587
7594
  vue.createVNode(vue.unref(design.TMagicPopover), {
7588
7595
  "popper-class": "page-bar-popover",
7589
7596
  placement: "top",
7597
+ trigger: "hover",
7590
7598
  width: 160,
7591
- trigger: "hover"
7599
+ "destroy-on-close": true
7592
7600
  }, {
7593
7601
  reference: vue.withCtx(() => [
7594
7602
  vue.createVNode(vue.unref(design.TMagicIcon), { class: "m-editor-page-bar-menu-icon" }, {
@@ -8901,7 +8909,8 @@
8901
8909
  key: 0,
8902
8910
  placement: "right",
8903
8911
  trigger: "hover",
8904
- "popper-class": "data-source-list-panel-add-menu"
8912
+ "popper-class": "data-source-list-panel-add-menu",
8913
+ "destroy-on-close": true
8905
8914
  }, {
8906
8915
  reference: vue.withCtx(() => [
8907
8916
  vue.createVNode(vue.unref(design.TMagicButton), {
@@ -9185,8 +9194,8 @@
9185
9194
  const stage = services?.editorService?.get("stage");
9186
9195
  const rect = menu.value.$el.getBoundingClientRect();
9187
9196
  const parentRect = stage?.container?.getBoundingClientRect();
9188
- const initialLeft = utils.calcValueByFontsize(stage?.renderer.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) / services.uiService.get("zoom");
9189
- const initialTop = utils.calcValueByFontsize(stage?.renderer.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) / services.uiService.get("zoom");
9197
+ const initialLeft = utils.calcValueByFontsize(stage?.renderer?.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) / services.uiService.get("zoom");
9198
+ const initialTop = utils.calcValueByFontsize(stage?.renderer?.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) / services.uiService.get("zoom");
9190
9199
  services?.editorService?.paste({ left: initialLeft, top: initialTop });
9191
9200
  } else {
9192
9201
  services?.editorService?.paste();
@@ -9969,7 +9978,7 @@
9969
9978
  globalThis.clearTimeout(timeout);
9970
9979
  timeout = void 0;
9971
9980
  }
9972
- const doc = stage.value?.renderer.getDocument();
9981
+ const doc = stage.value?.renderer?.getDocument();
9973
9982
  if (doc && stageOptions?.containerHighlightClassName) {
9974
9983
  utils.removeClassNameByClassName(doc, stageOptions.containerHighlightClassName);
9975
9984
  }
@@ -10595,7 +10604,7 @@
10595
10604
  if (!stage2) return;
10596
10605
  vue.nextTick(() => unWatch());
10597
10606
  stage2.on("select", (el, event) => {
10598
- const els = stage2.renderer.getElementsFromPoint(event) || [];
10607
+ const els = stage2.renderer?.getElementsFromPoint(event) || [];
10599
10608
  const ids = els.map((el2) => utils.getIdFromEl()(el2)).filter((id) => Boolean(id));
10600
10609
  buttonVisible.value = ids.length > 3;
10601
10610
  filterTextChangeHandler(ids);
@@ -10694,7 +10703,7 @@
10694
10703
  vue.watch(stage, (stage2) => {
10695
10704
  if (stage2) {
10696
10705
  stage2.on("dblclick", async (event) => {
10697
- const el = await stage2.actionManager.getElementFromPoint(event);
10706
+ const el = await stage2.actionManager?.getElementFromPoint(event) || null;
10698
10707
  services?.stageOverlayService.openOverlay(el);
10699
10708
  });
10700
10709
  } else {
@@ -10709,7 +10718,7 @@
10709
10718
  subStage.mount(stageOverlay2);
10710
10719
  const { mask, renderer } = subStage;
10711
10720
  const { contentWindow } = renderer;
10712
- mask.showRule(false);
10721
+ mask?.showRule(false);
10713
10722
  services?.stageOverlayService.updateOverlay();
10714
10723
  contentWindow?.magic.onRuntimeReady({});
10715
10724
  }
@@ -11022,7 +11031,7 @@
11022
11031
  const config = parseDSL(`(${data})`);
11023
11032
  if (!config || config.dragType !== DragType.COMPONENT_LIST) return;
11024
11033
  e.preventDefault();
11025
- const doc = stage?.renderer.contentWindow?.document;
11034
+ const doc = stage?.renderer?.contentWindow?.document;
11026
11035
  const parentEl = doc?.querySelector(`.${stageOptions?.containerHighlightClassName}`);
11027
11036
  let parent = page.value;
11028
11037
  const parentId = utils.getIdFromEl()(parentEl);
@@ -11965,6 +11974,10 @@
11965
11974
  const subStage = this.get("stage");
11966
11975
  const wrapDiv = this.get("wrapDiv");
11967
11976
  subStage?.destroy();
11977
+ for (let i = 0, l = wrapDiv.children.length; i < l; i++) {
11978
+ const child = wrapDiv.children[i];
11979
+ child.remove();
11980
+ }
11968
11981
  wrapDiv.remove();
11969
11982
  this.set("stage", null);
11970
11983
  this.set("sourceEl", null);
@@ -11990,7 +12003,7 @@
11990
12003
  autoScrollIntoView: false,
11991
12004
  render: async (stage) => {
11992
12005
  this.copyDocumentElement();
11993
- const rootEls = stage.renderer.getDocument()?.body.children;
12006
+ const rootEls = stage.renderer?.getDocument()?.body.children;
11994
12007
  if (rootEls) {
11995
12008
  Array.from(rootEls).forEach((element) => {
11996
12009
  if (["SCRIPT", "STYLE"].includes(element.tagName)) {
@@ -12019,8 +12032,8 @@
12019
12032
  copyDocumentElement() {
12020
12033
  const subStage = this.get("stage");
12021
12034
  const stage = editorService.get("stage");
12022
- const doc = subStage?.renderer.getDocument();
12023
- const documentElement = stage?.renderer.getDocument()?.documentElement;
12035
+ const doc = subStage?.renderer?.getDocument();
12036
+ const documentElement = stage?.renderer?.getDocument()?.documentElement;
12024
12037
  if (doc && documentElement) {
12025
12038
  doc.replaceChild(documentElement.cloneNode(true), doc.documentElement);
12026
12039
  }
@@ -12038,12 +12051,13 @@
12038
12051
  height: ${sourceEl?.scrollHeight}px;
12039
12052
  background-color: #fff;
12040
12053
  `;
12041
- Array.from(wrapDiv.children).forEach((element) => {
12042
- element.remove();
12043
- });
12054
+ for (let i = 0, l = wrapDiv.children.length; i < l; i++) {
12055
+ const child = wrapDiv.children[i];
12056
+ child.remove();
12057
+ }
12044
12058
  wrapDiv.appendChild(contentEl);
12045
12059
  setTimeout(() => {
12046
- subStage?.renderer.contentWindow?.magic.onPageElUpdate(wrapDiv);
12060
+ subStage?.renderer?.contentWindow?.magic.onPageElUpdate(wrapDiv);
12047
12061
  });
12048
12062
  if (await stageOptions?.canSelect?.(contentEl)) {
12049
12063
  const id = utils.getIdFromEl()(contentEl);
@@ -12283,7 +12297,7 @@
12283
12297
  };
12284
12298
  const getApp = () => {
12285
12299
  const stage = editorService.get("stage");
12286
- return stage?.renderer.runtime?.getApp?.();
12300
+ return stage?.renderer?.runtime?.getApp?.();
12287
12301
  };
12288
12302
  const updateDataSourceSchema = () => {
12289
12303
  const root = editorService.get("root");
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.5.0-beta.1",
2
+ "version": "1.5.0-beta.3",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -55,8 +55,8 @@
55
55
  "moveable": "^0.53.0",
56
56
  "serialize-javascript": "^6.0.0",
57
57
  "sortablejs": "^1.15.2",
58
- "@tmagic/table": "1.5.0-beta.1",
59
- "@tmagic/dep": "1.5.0-beta.1"
58
+ "@tmagic/dep": "1.5.0-beta.3",
59
+ "@tmagic/table": "1.5.0-beta.3"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/events": "^3.0.0",
@@ -77,12 +77,12 @@
77
77
  "monaco-editor": "^0.48.0",
78
78
  "typescript": "*",
79
79
  "vue": "^3.4.35",
80
- "@tmagic/core": "1.5.0-beta.1",
81
- "@tmagic/design": "1.5.0-beta.1",
82
- "@tmagic/form": "1.5.0-beta.1",
83
- "@tmagic/schema": "1.5.0-beta.1",
84
- "@tmagic/stage": "1.5.0-beta.1",
85
- "@tmagic/utils": "1.5.0-beta.1"
80
+ "@tmagic/form": "1.5.0-beta.3",
81
+ "@tmagic/schema": "1.5.0-beta.3",
82
+ "@tmagic/core": "1.5.0-beta.3",
83
+ "@tmagic/design": "1.5.0-beta.3",
84
+ "@tmagic/stage": "1.5.0-beta.3",
85
+ "@tmagic/utils": "1.5.0-beta.3"
86
86
  },
87
87
  "peerDependenciesMeta": {
88
88
  "typescript": {
package/src/Editor.vue CHANGED
@@ -141,7 +141,15 @@ import uiService from './services/ui';
141
141
  import keybindingConfig from './utils/keybinding-config';
142
142
  import { defaultEditorProps, EditorProps } from './editorProps';
143
143
  import { initServiceEvents, initServiceState } from './initService';
144
- import type { EventBus, FrameworkSlots, PropsPanelSlots, Services, SidebarSlots, WorkspaceSlots } from './type';
144
+ import type {
145
+ EventBus,
146
+ FrameworkSlots,
147
+ PropsPanelSlots,
148
+ Services,
149
+ SidebarSlots,
150
+ StageOptions,
151
+ WorkspaceSlots,
152
+ } from './type';
145
153
 
146
154
  defineSlots<
147
155
  FrameworkSlots &
@@ -186,7 +194,7 @@ initServiceState(props, services);
186
194
  keybindingService.register(keybindingConfig);
187
195
  keybindingService.registerEl('global');
188
196
 
189
- const stageOptions = {
197
+ const stageOptions: StageOptions = {
190
198
  runtimeUrl: props.runtimeUrl,
191
199
  autoScrollIntoView: props.autoScrollIntoView,
192
200
  render: props.render,
@@ -82,7 +82,7 @@ export interface EditorProps {
82
82
  /** 禁用属性配置面板右下角显示源码的按钮 */
83
83
  disabledShowSrc?: boolean;
84
84
  /** 中间工作区域中画布渲染的内容 */
85
- render?: (stage: StageCore) => HTMLDivElement | Promise<HTMLDivElement>;
85
+ render?: (stage: StageCore) => HTMLDivElement | void | Promise<HTMLDivElement | void>;
86
86
  /** 选中时会在画布上复制出一个大小相同的dom,实际拖拽的是这个dom,此方法用于干预这个dom的生成方式 */
87
87
  updateDragEl?: UpdateDragEl;
88
88
  /** 用于设置画布上的dom是否可以被选中 */
@@ -22,7 +22,7 @@
22
22
  :last-values="lastValues"
23
23
  :init-values="initValues"
24
24
  :values="values"
25
- :prop="`${prop}${prop ? '.' : ''}${name}`"
25
+ :prop="prop"
26
26
  @change="onChangeHandler"
27
27
  ></component>
28
28
 
@@ -1,4 +1,4 @@
1
- import { computed, watch } from 'vue';
1
+ import { computed, onBeforeUnmount, watch } from 'vue';
2
2
 
3
3
  import type { MNode } from '@tmagic/schema';
4
4
  import StageCore, { GuidesType, RemoveEventData, SortEventData, UpdateEventData } from '@tmagic/stage';
@@ -62,7 +62,7 @@ export const useStage = (stageOptions: StageOptions) => {
62
62
  },
63
63
  );
64
64
 
65
- stage.mask.setGuides([
65
+ stage.mask?.setGuides([
66
66
  getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY)),
67
67
  getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY)),
68
68
  ]);
@@ -131,5 +131,9 @@ export const useStage = (stageOptions: StageOptions) => {
131
131
  }
132
132
  });
133
133
 
134
+ onBeforeUnmount(() => {
135
+ stage.destroy();
136
+ });
137
+
134
138
  return stage;
135
139
  };
@@ -242,7 +242,7 @@ export const initServiceEvents = (
242
242
 
243
243
  const getApp = () => {
244
244
  const stage = editorService.get('stage');
245
- return stage?.renderer.runtime?.getApp?.();
245
+ return stage?.renderer?.runtime?.getApp?.();
246
246
  };
247
247
 
248
248
  const updateDataSourceSchema = () => {
@@ -24,7 +24,13 @@
24
24
  </slot>
25
25
  </div>
26
26
 
27
- <TMagicPopover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
27
+ <TMagicPopover
28
+ popper-class="page-bar-popover"
29
+ placement="top"
30
+ trigger="hover"
31
+ :width="160"
32
+ :destroy-on-close="true"
33
+ >
28
34
  <div>
29
35
  <slot name="page-bar-popover" :page="item">
30
36
  <ToolButton
@@ -4,7 +4,13 @@
4
4
  id="m-editor-page-bar-list-icon"
5
5
  class="m-editor-page-bar-item m-editor-page-bar-item-icon"
6
6
  >
7
- <TMagicPopover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
7
+ <TMagicPopover
8
+ popper-class="page-bar-popover"
9
+ placement="top"
10
+ trigger="hover"
11
+ :width="160"
12
+ :destroy-on-close="true"
13
+ >
8
14
  <div>
9
15
  <slot name="page-list-popover" :list="list">
10
16
  <ToolButton
@@ -111,7 +111,7 @@ const dragendHandler = () => {
111
111
  globalThis.clearTimeout(timeout);
112
112
  timeout = undefined;
113
113
  }
114
- const doc = stage.value?.renderer.getDocument();
114
+ const doc = stage.value?.renderer?.getDocument();
115
115
  if (doc && stageOptions?.containerHighlightClassName) {
116
116
  removeClassNameByClassName(doc, stageOptions.containerHighlightClassName);
117
117
  }
@@ -2,7 +2,13 @@
2
2
  <TMagicScrollbar class="data-source-list-panel m-editor-layer-panel">
3
3
  <div class="search-wrapper">
4
4
  <SearchInput @search="filterTextChangeHandler"></SearchInput>
5
- <TMagicPopover v-if="editable" placement="right" trigger="hover" popper-class="data-source-list-panel-add-menu">
5
+ <TMagicPopover
6
+ v-if="editable"
7
+ placement="right"
8
+ trigger="hover"
9
+ popper-class="data-source-list-panel-add-menu"
10
+ :destroy-on-close="true"
11
+ >
6
12
  <template #reference>
7
13
  <TMagicButton type="primary" size="small">新增</TMagicButton>
8
14
  </template>
@@ -61,7 +61,7 @@ const unWatch = watch(
61
61
  nextTick(() => unWatch());
62
62
 
63
63
  stage.on('select', (el: HTMLElement, event: MouseEvent) => {
64
- const els = stage.renderer.getElementsFromPoint(event) || [];
64
+ const els = stage.renderer?.getElementsFromPoint(event) || [];
65
65
  const ids = els.map((el) => getIdFromEl()(el)).filter((id) => Boolean(id)) as string[];
66
66
 
67
67
  buttonVisible.value = ids.length > 3;
@@ -196,7 +196,7 @@ const dropHandler = async (e: DragEvent) => {
196
196
 
197
197
  e.preventDefault();
198
198
 
199
- const doc = stage?.renderer.contentWindow?.document;
199
+ const doc = stage?.renderer?.contentWindow?.document;
200
200
  const parentEl: HTMLElement | null | undefined = doc?.querySelector(`.${stageOptions?.containerHighlightClassName}`);
201
201
 
202
202
  let parent: MContainer | undefined | null = page.value;
@@ -209,7 +209,7 @@ const dropHandler = async (e: DragEvent) => {
209
209
  const layout = await services?.editorService.getLayout(parent);
210
210
 
211
211
  const containerRect = stageContainer.value.getBoundingClientRect();
212
- const { scrollTop, scrollLeft } = stage.mask;
212
+ const { scrollTop, scrollLeft } = stage.mask!;
213
213
  const { style = {} } = config.data;
214
214
 
215
215
  let top = 0;
@@ -34,7 +34,7 @@ const style = computed(() => ({
34
34
  watch(stage, (stage) => {
35
35
  if (stage) {
36
36
  stage.on('dblclick', async (event: MouseEvent) => {
37
- const el = await stage.actionManager.getElementFromPoint(event);
37
+ const el = (await stage.actionManager?.getElementFromPoint(event)) || null;
38
38
  services?.stageOverlayService.openOverlay(el);
39
39
  });
40
40
  } else {
@@ -53,8 +53,8 @@ watch(stageOverlay, (stageOverlay) => {
53
53
 
54
54
  const { mask, renderer } = subStage;
55
55
 
56
- const { contentWindow } = renderer;
57
- mask.showRule(false);
56
+ const { contentWindow } = renderer!;
57
+ mask?.showRule(false);
58
58
 
59
59
  services?.stageOverlayService.updateOverlay();
60
60
 
@@ -267,7 +267,7 @@ class Editor extends BaseService {
267
267
 
268
268
  if (node?.id) {
269
269
  this.get('stage')
270
- ?.renderer.runtime?.getApp?.()
270
+ ?.renderer?.runtime?.getApp?.()
271
271
  ?.page?.emit(
272
272
  'editor:select',
273
273
  {
@@ -737,7 +737,7 @@ class Editor extends BaseService {
737
737
 
738
738
  public async doPaste(config: MNode[], position: PastePosition = {}): Promise<MNode[]> {
739
739
  propsService.clearRelateId();
740
- const doc = this.get('stage')?.renderer.contentWindow?.document;
740
+ const doc = this.get('stage')?.renderer?.contentWindow?.document;
741
741
  const pasteConfigs = beforePaste(position, cloneDeep(config), doc);
742
742
  return pasteConfigs;
743
743
  }
@@ -756,7 +756,7 @@ class Editor extends BaseService {
756
756
  if (!node.style) return config;
757
757
 
758
758
  const stage = this.get('stage');
759
- const doc = stage?.renderer.contentWindow?.document;
759
+ const doc = stage?.renderer?.contentWindow?.document;
760
760
 
761
761
  if (doc) {
762
762
  const el = getElById()(doc, node.id);
@@ -64,6 +64,12 @@ class StageOverlay extends BaseService {
64
64
  const subStage = this.get('stage');
65
65
  const wrapDiv = this.get('wrapDiv');
66
66
  subStage?.destroy();
67
+
68
+ for (let i = 0, l = wrapDiv.children.length; i < l; i++) {
69
+ const child = wrapDiv.children[i];
70
+ child.remove();
71
+ }
72
+
67
73
  wrapDiv.remove();
68
74
 
69
75
  this.set('stage', null);
@@ -97,7 +103,7 @@ class StageOverlay extends BaseService {
97
103
  render: async (stage: StageCore) => {
98
104
  this.copyDocumentElement();
99
105
 
100
- const rootEls = stage.renderer.getDocument()?.body.children;
106
+ const rootEls = stage.renderer?.getDocument()?.body.children;
101
107
  if (rootEls) {
102
108
  Array.from(rootEls).forEach((element) => {
103
109
  if (['SCRIPT', 'STYLE'].includes(element.tagName)) {
@@ -135,8 +141,8 @@ class StageOverlay extends BaseService {
135
141
  const subStage = this.get('stage');
136
142
  const stage = editorService.get('stage');
137
143
 
138
- const doc = subStage?.renderer.getDocument();
139
- const documentElement = stage?.renderer.getDocument()?.documentElement;
144
+ const doc = subStage?.renderer?.getDocument();
145
+ const documentElement = stage?.renderer?.getDocument()?.documentElement;
140
146
 
141
147
  if (doc && documentElement) {
142
148
  doc.replaceChild(documentElement.cloneNode(true), doc.documentElement);
@@ -160,13 +166,15 @@ class StageOverlay extends BaseService {
160
166
  background-color: #fff;
161
167
  `;
162
168
 
163
- Array.from(wrapDiv.children).forEach((element) => {
164
- element.remove();
165
- });
169
+ for (let i = 0, l = wrapDiv.children.length; i < l; i++) {
170
+ const child = wrapDiv.children[i];
171
+ child.remove();
172
+ }
173
+
166
174
  wrapDiv.appendChild(contentEl);
167
175
 
168
176
  setTimeout(() => {
169
- subStage?.renderer.contentWindow?.magic.onPageElUpdate(wrapDiv);
177
+ subStage?.renderer?.contentWindow?.magic.onPageElUpdate(wrapDiv);
170
178
  });
171
179
 
172
180
  if (await stageOptions?.canSelect?.(contentEl)) {
@@ -5,12 +5,13 @@
5
5
  width: 100%;
6
6
 
7
7
  .tmagic-design-button.m-editor-page-bar-switch-type-button {
8
- margin-left: 7px;
8
+ margin-left: 10px;
9
9
  position: relative;
10
10
  top: 1px;
11
11
  border-radius: 3px 3px 0 0;
12
12
  border: 1px solid $--border-color;
13
13
  border-bottom: 1px solid transparent;
14
+ padding: 5px 10px;
14
15
 
15
16
  &.active {
16
17
  background-color: #f3f3f3;
package/src/type.ts CHANGED
@@ -145,7 +145,7 @@ export interface StageOptions {
145
145
  containerHighlightDuration?: number;
146
146
  containerHighlightType?: ContainerHighlightType;
147
147
  disabledDragStart?: boolean;
148
- render?: (stage: StageCore) => HTMLDivElement | Promise<HTMLDivElement>;
148
+ render?: (stage: StageCore) => HTMLDivElement | void | Promise<HTMLDivElement | void>;
149
149
  moveableOptions?: MoveableOptions | ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions);
150
150
  canSelect?: (el: HTMLElement) => boolean | Promise<boolean>;
151
151
  isContainer?: (el: HTMLElement) => boolean | Promise<boolean>;
@@ -47,10 +47,10 @@ export const usePasteMenu = (menu?: Ref<InstanceType<typeof ContentMenu> | undef
47
47
  const rect = menu.value.$el.getBoundingClientRect();
48
48
  const parentRect = stage?.container?.getBoundingClientRect();
49
49
  const initialLeft =
50
- calcValueByFontsize(stage?.renderer.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) /
50
+ calcValueByFontsize(stage?.renderer?.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) /
51
51
  services.uiService.get('zoom');
52
52
  const initialTop =
53
- calcValueByFontsize(stage?.renderer.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) /
53
+ calcValueByFontsize(stage?.renderer?.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) /
54
54
  services.uiService.get('zoom');
55
55
  services?.editorService?.paste({ left: initialLeft, top: initialTop });
56
56
  } else {
@@ -109,12 +109,16 @@ const getMiddleTop = (node: MNode, parentNode: MNode, stage: StageCore | null) =
109
109
  }
110
110
 
111
111
  const { height: parentHeight } = parentNode.style;
112
- // wrapperHeight 是未 calcValue的高度, 所以要将其calcValueByFontsize一下, 否则在pad or pc端计算的结果有误
113
- const { scrollTop = 0, wrapperHeight } = stage.mask;
114
- const wrapperHeightDeal = calcValueByFontsize(stage.renderer.getDocument()!, wrapperHeight);
115
- const scrollTopDeal = calcValueByFontsize(stage.renderer.getDocument()!, scrollTop);
116
- if (isPage(parentNode)) {
117
- return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
112
+
113
+ let wrapperHeightDeal = parentHeight;
114
+ if (stage.mask && stage.renderer) {
115
+ // wrapperHeight 是未 calcValue的高度, 所以要将其calcValueByFontsize一下, 否则在pad or pc端计算的结果有误
116
+ const { scrollTop = 0, wrapperHeight } = stage.mask;
117
+ wrapperHeightDeal = calcValueByFontsize(stage.renderer.getDocument()!, wrapperHeight);
118
+ const scrollTopDeal = calcValueByFontsize(stage.renderer.getDocument()!, scrollTop);
119
+ if (isPage(parentNode)) {
120
+ return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
121
+ }
118
122
  }
119
123
 
120
124
  // 如果容器的元素高度大于当前视口高度的2倍, 添加的元素居中位置也会看不见, 所以要取最小值计算
@@ -263,7 +267,7 @@ export const fixNodePosition = (config: MNode, parent: MContainer, stage: StageC
263
267
  return {
264
268
  ...(config.style || {}),
265
269
  top: getMiddleTop(config, parent, stage),
266
- left: fixNodeLeft(config, parent, stage?.renderer.contentWindow?.document),
270
+ left: fixNodeLeft(config, parent, stage?.renderer?.contentWindow?.document),
267
271
  };
268
272
  };
269
273
 
package/types/index.d.ts CHANGED
@@ -916,7 +916,7 @@ interface StageOptions {
916
916
  containerHighlightDuration?: number;
917
917
  containerHighlightType?: ContainerHighlightType;
918
918
  disabledDragStart?: boolean;
919
- render?: (stage: StageCore__default) => HTMLDivElement | Promise<HTMLDivElement>;
919
+ render?: (stage: StageCore__default) => HTMLDivElement | void | Promise<HTMLDivElement | void>;
920
920
  moveableOptions?: MoveableOptions | ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions);
921
921
  canSelect?: (el: HTMLElement) => boolean | Promise<boolean>;
922
922
  isContainer?: (el: HTMLElement) => boolean | Promise<boolean>;
@@ -2694,7 +2694,7 @@ interface EditorProps {
2694
2694
  /** 禁用属性配置面板右下角显示源码的按钮 */
2695
2695
  disabledShowSrc?: boolean;
2696
2696
  /** 中间工作区域中画布渲染的内容 */
2697
- render?: (stage: StageCore__default) => HTMLDivElement | Promise<HTMLDivElement>;
2697
+ render?: (stage: StageCore__default) => HTMLDivElement | void | Promise<HTMLDivElement | void>;
2698
2698
  /** 选中时会在画布上复制出一个大小相同的dom,实际拖拽的是这个dom,此方法用于干预这个dom的生成方式 */
2699
2699
  updateDragEl?: UpdateDragEl;
2700
2700
  /** 用于设置画布上的dom是否可以被选中 */