@tmagic/editor 1.3.12 → 1.3.14

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.12",
2
+ "version": "1.3.14",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -42,14 +42,14 @@
42
42
  "dependencies": {
43
43
  "@babel/core": "^7.18.0",
44
44
  "@element-plus/icons-vue": "^2.3.1",
45
- "@tmagic/core": "1.3.12",
46
- "@tmagic/dep": "1.3.12",
47
- "@tmagic/design": "1.3.12",
48
- "@tmagic/form": "1.3.12",
49
- "@tmagic/schema": "1.3.12",
50
- "@tmagic/stage": "1.3.12",
51
- "@tmagic/table": "1.3.12",
52
- "@tmagic/utils": "1.3.12",
45
+ "@tmagic/core": "1.3.14",
46
+ "@tmagic/dep": "1.3.14",
47
+ "@tmagic/design": "1.3.14",
48
+ "@tmagic/form": "1.3.14",
49
+ "@tmagic/schema": "1.3.14",
50
+ "@tmagic/stage": "1.3.14",
51
+ "@tmagic/table": "1.3.14",
52
+ "@tmagic/utils": "1.3.14",
53
53
  "buffer": "^6.0.3",
54
54
  "color": "^3.1.3",
55
55
  "emmet-monaco-es": "^5.3.0",
@@ -63,8 +63,8 @@
63
63
  "vue": "^3.3.8"
64
64
  },
65
65
  "peerDependencies": {
66
- "@tmagic/design": "1.3.12",
67
- "@tmagic/form": "1.3.12",
66
+ "@tmagic/design": "1.3.14",
67
+ "@tmagic/form": "1.3.14",
68
68
  "monaco-editor": "^0.41.0",
69
69
  "vue": "^3.3.8"
70
70
  },
@@ -39,7 +39,12 @@
39
39
  </template>
40
40
  </TMagicDropdown>
41
41
 
42
- <component v-else-if="data.type === 'component'" v-bind="data.props || {}" :is="data.component"></component>
42
+ <component
43
+ v-else-if="data.type === 'component'"
44
+ v-bind="data.props || {}"
45
+ v-on="(data as MenuComponent).listeners || {}"
46
+ :is="data.component"
47
+ ></component>
43
48
  </div>
44
49
  </template>
45
50
 
@@ -12,7 +12,8 @@ import { isEmpty } from 'lodash-es';
12
12
 
13
13
  import { TMagicCard } from '@tmagic/design';
14
14
  import type { FieldProps } from '@tmagic/form';
15
- import { HookType } from '@tmagic/schema';
15
+ import { FormState } from '@tmagic/form';
16
+ import { HookCodeType, HookType } from '@tmagic/schema';
16
17
 
17
18
  import type { Services } from '@editor/type';
18
19
 
@@ -38,13 +39,40 @@ const codeConfig = computed(() => ({
38
39
  name: 'hookData',
39
40
  enableToggleMode: false,
40
41
  expandAll: true,
41
- titleKey: 'codeId',
42
+ title: (mForm: FormState, { model, index }: any) => {
43
+ if (model.codeType === HookCodeType.DATA_SOURCE_METHOD) {
44
+ if (Array.isArray(model.codeId)) {
45
+ const ds = services?.dataSourceService.getDataSourceById(model.codeId[0]);
46
+ return `${ds?.title} / ${model.codeId[1]}`;
47
+ }
48
+
49
+ return Array.isArray(model.codeId) ? model.codeId.join('/') : index;
50
+ }
51
+ return model.codeId || index;
52
+ },
42
53
  items: [
43
54
  {
44
- type: 'code-select-col',
45
- name: 'codeId',
46
- labelWidth: 0,
47
- disabled: () => !services?.codeBlockService.getEditStatus(),
55
+ type: 'row',
56
+ items: [
57
+ {
58
+ type: 'select',
59
+ name: 'codeType',
60
+ span: 8,
61
+ options: [
62
+ { value: HookCodeType.CODE, text: '代码块' },
63
+ { value: HookCodeType.DATA_SOURCE_METHOD, text: '数据源方法' },
64
+ ],
65
+ defaultValue: 'code',
66
+ },
67
+ {
68
+ type: (mForm: FormState, { model }: any) =>
69
+ model.codeType === HookCodeType.DATA_SOURCE_METHOD ? 'data-source-method-select' : 'code-select-col',
70
+ name: 'codeId',
71
+ span: 16,
72
+ labelWidth: 0,
73
+ disabled: () => !services?.codeBlockService.getEditStatus(),
74
+ },
75
+ ],
48
76
  },
49
77
  ],
50
78
  }));
@@ -17,6 +17,7 @@
17
17
  <CodeParams
18
18
  v-if="paramsConfig.length"
19
19
  name="params"
20
+ :key="model[name]"
20
21
  :model="model"
21
22
  :size="size"
22
23
  :params-config="paramsConfig"
@@ -33,7 +34,7 @@
33
34
  </div>
34
35
  </template>
35
36
 
36
- <script lang="ts" setup name="">
37
+ <script lang="ts" setup>
37
38
  import { computed, inject, ref, watch } from 'vue';
38
39
  import { Edit, View } from '@element-plus/icons-vue';
39
40
  import { isEmpty, map } from 'lodash-es';
@@ -106,16 +106,19 @@ const deleteHandler = () => {
106
106
  const selectNode = async (id: Id) => {
107
107
  await services?.editorService.select(id);
108
108
  services?.editorService.get('stage')?.select(id);
109
+ services?.stageOverlayService.get('stage')?.select(id);
109
110
  };
110
111
 
111
112
  const highlight = throttle((id: Id) => {
112
113
  services?.editorService.highlight(id);
113
114
  services?.editorService.get('stage')?.highlight(id);
115
+ services?.stageOverlayService.get('stage')?.highlight(id);
114
116
  }, 150);
115
117
 
116
118
  const unhightlight = () => {
117
119
  services?.editorService.set('highlightNode', null);
118
120
  services?.editorService.get('stage')?.clearHighlight();
121
+ services?.stageOverlayService.get('stage')?.clearHighlight();
119
122
  };
120
123
  </script>
121
124
 
@@ -1,124 +1,40 @@
1
- import { computed, ComputedRef, inject, nextTick, ref, watch } from 'vue';
2
- import Moveable from 'moveable';
1
+ import { computed, ComputedRef, ref, watch } from 'vue';
3
2
 
4
- import { type Services } from '@editor/type';
3
+ interface State {
4
+ status: boolean;
5
+ top: number;
6
+ left: number;
7
+ }
5
8
 
6
9
  export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
7
- const services = inject<Services>('services');
8
- const moveable = ref<Moveable>();
9
- const floatBox = ref<HTMLElement[]>();
10
-
11
- const floatBoxStates = computed(() => services?.uiService.get('floatBox'));
12
-
13
- const curKey = ref('');
14
- const target = computed(() =>
15
- floatBox.value
16
- ? floatBox.value.find((item) => item.classList.contains(`m-editor-float-box-${curKey.value}`))
17
- : undefined,
10
+ const floatBoxStates = ref<{
11
+ [key in (typeof slideKeys.value)[number]]: State;
12
+ }>(
13
+ slideKeys.value.reduce(
14
+ (total, cur) => ({
15
+ ...total,
16
+ [cur]: {
17
+ status: false,
18
+ top: 0,
19
+ left: 0,
20
+ },
21
+ }),
22
+ {},
23
+ ),
18
24
  );
19
25
 
20
26
  const showingBoxKeys = computed(() =>
21
- [...(floatBoxStates.value?.keys() ?? [])].filter((key) => floatBoxStates.value?.get(key)?.status),
27
+ Object.keys(floatBoxStates.value).filter((key) => floatBoxStates.value[key].status),
22
28
  );
23
-
24
29
  const isDraging = ref(false);
25
30
 
26
- const showFloatBox = async (key: string) => {
27
- const curBoxStatus = floatBoxStates.value?.get(curKey.value)?.status;
28
- if (curKey.value === key && curBoxStatus) return;
29
- curKey.value = key;
30
- setSlideState(key, {
31
- zIndex: getMaxZIndex() + 1,
32
- status: true,
33
- });
34
-
35
- await nextTick();
36
- if (moveable.value) {
37
- moveable.value.target = target.value;
38
- moveable.value.dragTarget = getDragTarget();
39
- moveable.value.updateRect();
40
- } else {
41
- initFloatBoxMoveable();
42
- }
43
- };
44
-
45
- const setSlideState = (key: string, data: Record<string, string | number | boolean>) => {
46
- const slideState = floatBoxStates.value?.get(key);
47
- if (!slideState) return;
48
- floatBoxStates.value?.set(key, {
49
- ...slideState,
50
- ...data,
51
- });
52
- };
53
-
54
- const getDragTarget = (key?: string) => `.m-editor-float-box-header-${key ?? curKey.value}`;
55
-
56
- const closeFloatBox = (key: string) => {
57
- setSlideState(key, {
58
- status: false,
59
- });
60
-
61
- // 如果只有一个,关掉后需要销毁moveable实例
62
- if (!floatBoxStates.value?.values) return;
63
- const keys = [...floatBoxStates.value?.keys()];
64
- const values = [...floatBoxStates.value?.values()];
65
- const lastFloatBoxLen = values.filter((state) => state.status).length;
66
- if (lastFloatBoxLen === 0) {
67
- moveable.value?.destroy();
68
- moveable.value = undefined;
69
- return;
70
- }
71
-
72
- // 如果关掉的 box 是最大的,需要选中下面的一层
73
- if (key === curKey.value) {
74
- // 查找显示的最大 zIndex 对应的 index
75
- const zIndexList = values.filter((item) => item.status).map((item) => item.zIndex);
76
- const maxZIndex = Math.max(...zIndexList);
77
- const key = keys.find((key) => floatBoxStates.value?.get(key)?.zIndex === maxZIndex);
78
- if (!key) return;
79
- showFloatBox(key);
80
- }
81
- };
82
-
83
- const getMaxZIndex = () => {
84
- if (!floatBoxStates.value?.values()) return 0;
85
- const list = [...floatBoxStates.value?.values()].map((state) => state.zIndex);
86
- return Math.max(...list) ?? 0;
87
- };
88
-
89
- const initFloatBoxMoveable = () => {
90
- const dragTarget = getDragTarget();
91
- moveable.value = new Moveable(document.body, {
92
- target: target.value,
93
- draggable: true,
94
- resizable: true,
95
- edge: true,
96
- keepRatio: false,
97
- origin: false,
98
- snappable: true,
99
- dragTarget,
100
- dragTargetSelf: false,
101
- linePadding: 10,
102
- controlPadding: 10,
103
- elementGuidelines: [...(floatBoxStates.value?.keys() ?? [])].map((key) => getDragTarget(key)),
104
- bounds: { left: 0, top: 0, right: 0, bottom: 0, position: 'css' },
105
- });
106
- moveable.value.on('drag', (e) => {
107
- e.target.style.transform = e.transform;
108
- });
109
- moveable.value.on('resize', (e) => {
110
- e.target.style.width = `${e.width}px`;
111
- e.target.style.height = `${e.height}px`;
112
- e.target.style.transform = e.drag.transform;
113
- });
114
- };
115
-
31
+ const dragstartHandler = () => (isDraging.value = true);
116
32
  const dragendHandler = (key: string, e: DragEvent) => {
117
- setSlideState(key, {
33
+ floatBoxStates.value[key] = {
118
34
  left: e.clientX,
119
35
  top: e.clientY,
120
- });
121
- showFloatBox(key);
36
+ status: true,
37
+ };
122
38
  isDraging.value = false;
123
39
  };
124
40
 
@@ -127,13 +43,17 @@ export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
127
43
  e.preventDefault();
128
44
  });
129
45
 
130
- const dragstartHandler = () => (isDraging.value = true);
131
-
132
- // 监听 slide 长度变化,更新 ui serice map
133
46
  watch(
134
47
  () => slideKeys.value,
135
48
  () => {
136
- services?.uiService.setFloatBox(slideKeys.value);
49
+ for (const key in slideKeys.value) {
50
+ if (floatBoxStates.value[key]) continue;
51
+ floatBoxStates.value[key] = {
52
+ status: false,
53
+ top: 0,
54
+ left: 0,
55
+ };
56
+ }
137
57
  },
138
58
  {
139
59
  deep: true,
@@ -142,12 +62,9 @@ export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
142
62
  );
143
63
 
144
64
  return {
145
- showFloatBox,
146
- closeFloatBox,
147
65
  dragstartHandler,
148
66
  dragendHandler,
149
67
  floatBoxStates,
150
- floatBox,
151
68
  showingBoxKeys,
152
69
  };
153
70
  };
@@ -123,7 +123,7 @@ watch(
123
123
 
124
124
  watch(active, (active) => {
125
125
  if (active === NodeType.PAGE) {
126
- if (!activePage.value) {
126
+ if (!activePage.value && !pageList.value.length) {
127
127
  editorService?.selectRoot();
128
128
  return;
129
129
  }
@@ -132,11 +132,12 @@ watch(active, (active) => {
132
132
  }
133
133
 
134
134
  if (active === NodeType.PAGE_FRAGMENT) {
135
- if (!activePageFragment.value) {
135
+ // 之前没有选中过页面片并且当前没有页面片
136
+ if (!activePageFragment.value && !pageFragmentList.value.length) {
136
137
  editorService?.selectRoot();
137
138
  return;
138
139
  }
139
- switchPage(activePageFragment.value);
140
+ switchPage(activePageFragment.value || pageFragmentList.value[0].id);
140
141
  }
141
142
  });
142
143
 
@@ -4,7 +4,7 @@
4
4
  <div
5
5
  class="m-editor-sidebar-header-item"
6
6
  v-for="(config, index) in sideBarItems"
7
- v-show="!floatBoxStates?.get(config.$key)?.status"
7
+ v-show="!floatBoxStates[config.$key]?.status"
8
8
  draggable="true"
9
9
  :key="config.$key ?? index"
10
10
  :class="{ 'is-active': activeTabName === config.text }"
@@ -23,7 +23,7 @@
23
23
  v-show="activeTabName === config.text"
24
24
  >
25
25
  <component
26
- v-if="config && !floatBoxStates?.get(config.$key)?.status"
26
+ v-if="config && !floatBoxStates[config.$key]?.status"
27
27
  :is="config.component"
28
28
  v-bind="config.props || {}"
29
29
  v-on="config?.listeners || {}"
@@ -96,43 +96,37 @@
96
96
  </div>
97
97
 
98
98
  <Teleport to="body">
99
- <div class="m-editor-float-box-list">
100
- <div
101
- v-for="(config, index) in sideBarItems"
99
+ <template v-for="(config, index) in sideBarItems">
100
+ <FloatingBox
102
101
  :key="config.$key ?? index"
103
- ref="floatBox"
104
- :class="['m-editor-float-box', `m-editor-float-box-${config.$key}`]"
105
- :style="{
106
- left: `${floatBoxStates?.get(config.$key)?.left}px`,
107
- top: `${floatBoxStates?.get(config.$key)?.top}px`,
108
- zIndex: floatBoxStates?.get(config.$key)?.zIndex,
102
+ v-if="floatBoxStates[config.$key]?.status"
103
+ v-model:visible="floatBoxStates[config.$key].status"
104
+ :title="config.text"
105
+ :position="{
106
+ left: floatBoxStates[config.$key].left,
107
+ top: floatBoxStates[config.$key].top,
109
108
  }"
110
- v-show="floatBoxStates?.get(config.$key)?.status"
111
109
  >
112
- <div
113
- :class="['m-editor-float-box-header', `m-editor-float-box-header-${config.$key}`]"
114
- @click="showFloatBox(config.$key)"
115
- >
116
- <div>{{ config.text }}</div>
117
- <MIcon class="m-editor-float-box-close" :icon="Close" @click.stop="closeFloatBox(config.$key)"></MIcon>
118
- </div>
119
- <div class="m-editor-float-box-body">
120
- <component
121
- v-if="config && floatBoxStates?.get(config.$key)?.status"
122
- :is="config.boxComponentConfig?.component || config.component"
123
- v-bind="config.boxComponentConfig?.props || config.props || {}"
124
- v-on="config?.listeners || {}"
125
- />
126
- </div>
127
- </div>
128
- </div>
110
+ <template #body>
111
+ <div class="m-editor-slide-list-box">
112
+ <component
113
+ v-if="config && floatBoxStates[config.$key].status"
114
+ :is="config.boxComponentConfig?.component || config.component"
115
+ v-bind="config.boxComponentConfig?.props || config.props || {}"
116
+ v-on="config?.listeners || {}"
117
+ />
118
+ </div>
119
+ </template>
120
+ </FloatingBox>
121
+ </template>
129
122
  </Teleport>
130
123
  </template>
131
124
 
132
125
  <script setup lang="ts">
133
126
  import { computed, inject, ref, watch } from 'vue';
134
- import { Close, Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
127
+ import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
135
128
 
129
+ import FloatingBox from '@editor/components/FloatingBox.vue';
136
130
  import MIcon from '@editor/components/Icon.vue';
137
131
  import { useFloatBox } from '@editor/hooks/use-float-box';
138
132
  import type {
@@ -200,11 +194,6 @@ const getItemConfig = (data: SideItem): SideComponent => {
200
194
  text: '代码编辑',
201
195
  component: CodeBlockListPanel,
202
196
  slots: {},
203
- boxComponentConfig: {
204
- props: {
205
- slideType: 'box',
206
- },
207
- },
208
197
  },
209
198
  'data-source': {
210
199
  $key: 'data-source',
@@ -213,11 +202,6 @@ const getItemConfig = (data: SideItem): SideComponent => {
213
202
  text: '数据源',
214
203
  component: DataSourceListPanel,
215
204
  slots: {},
216
- boxComponentConfig: {
217
- props: {
218
- slideType: 'box',
219
- },
220
- },
221
205
  },
222
206
  };
223
207
 
@@ -235,8 +219,7 @@ watch(
235
219
 
236
220
  const slideKeys = computed(() => sideBarItems.value.map((sideBarItem) => sideBarItem.$key));
237
221
 
238
- const { showFloatBox, closeFloatBox, dragstartHandler, dragendHandler, floatBoxStates, floatBox, showingBoxKeys } =
239
- useFloatBox(slideKeys);
222
+ const { dragstartHandler, dragendHandler, floatBoxStates, showingBoxKeys } = useFloatBox(slideKeys);
240
223
 
241
224
  watch(
242
225
  () => showingBoxKeys.value.length,
@@ -14,7 +14,7 @@
14
14
  @node-dragstart="handleDragStart"
15
15
  @node-dragleave="handleDragLeave"
16
16
  @node-dragend="handleDragEnd"
17
- @node-contextmenu="nodeContentmenuHandler"
17
+ @node-contextmenu="nodeContentMenuHandler"
18
18
  @node-mouseenter="mouseenterHandler"
19
19
  @node-click="nodeClickHandler"
20
20
  >
@@ -113,7 +113,7 @@ const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useD
113
113
  const {
114
114
  menu,
115
115
  nodeClickHandler,
116
- nodeContentmenuHandler,
116
+ nodeContentMenuHandler,
117
117
  highlightHandler: mouseenterHandler,
118
118
  } = useClick(services, isCtrlKeyDown, nodeStatusMap);
119
119
  </script>
@@ -26,6 +26,7 @@ export const useClick = (
26
26
  } else {
27
27
  await services?.editorService.select(data);
28
28
  services?.editorService.get('stage')?.select(data.id);
29
+ services?.stageOverlayService.get('stage')?.select(data.id);
29
30
  }
30
31
  };
31
32
 
@@ -50,6 +51,7 @@ export const useClick = (
50
51
 
51
52
  await services?.editorService.multiSelect(newNodes);
52
53
  services?.editorService.get('stage')?.multiSelect(newNodes);
54
+ services?.stageOverlayService.get('stage')?.multiSelect(newNodes);
53
55
  };
54
56
 
55
57
  const throttleTime = 300;
@@ -62,6 +64,7 @@ export const useClick = (
62
64
  const highlight = (data: TreeNodeData) => {
63
65
  services?.editorService?.highlight(data);
64
66
  services?.editorService?.get('stage')?.highlight(data.id);
67
+ services?.stageOverlayService?.get('stage')?.highlight(data.id);
65
68
  };
66
69
 
67
70
  const nodeClickHandler = (event: MouseEvent, data: TreeNodeData) => {
@@ -91,7 +94,7 @@ export const useClick = (
91
94
 
92
95
  nodeClickHandler,
93
96
 
94
- nodeContentmenuHandler(event: MouseEvent, data: TreeNodeData) {
97
+ nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData) {
95
98
  event.preventDefault();
96
99
 
97
100
  const nodes = services?.editorService.get('nodes') || [];
@@ -1,7 +1,7 @@
1
1
  import { computed, ref, watch } from 'vue';
2
2
 
3
3
  import type { Id, MNode, MPage, MPageFragment } from '@tmagic/schema';
4
- import { getNodePath } from '@tmagic/utils';
4
+ import { getNodePath, isPage, isPageFragment } from '@tmagic/utils';
5
5
 
6
6
  import { LayerNodeStatus, Services } from '@editor/type';
7
7
  import { traverseNode } from '@editor/utils';
@@ -48,13 +48,14 @@ export const useNodeStatus = (services: Services | undefined) => {
48
48
 
49
49
  // 切换页面或者新增页面,重新生成节点状态
50
50
  watch(
51
- page,
52
- (page) => {
53
- if (!page) {
51
+ () => page.value?.id,
52
+ (pageId) => {
53
+ if (!pageId) {
54
54
  return;
55
55
  }
56
+
56
57
  // 生成节点状态
57
- nodeStatusMaps.value.set(page.id, createPageNodeStatus(page, nodeStatusMaps.value.get(page.id)));
58
+ nodeStatusMaps.value.set(pageId, createPageNodeStatus(page.value!, nodeStatusMaps.value.get(pageId)));
58
59
  },
59
60
  {
60
61
  immediate: true,
@@ -85,6 +86,8 @@ export const useNodeStatus = (services: Services | undefined) => {
85
86
 
86
87
  services?.editorService.on('add', (newNodes: MNode[]) => {
87
88
  newNodes.forEach((node) => {
89
+ if (isPage(node) || isPageFragment(node)) return;
90
+
88
91
  traverseNode(node, (node: MNode) => {
89
92
  nodeStatusMap.value?.set(node.id, {
90
93
  visible: true,
@@ -892,6 +892,8 @@ class Editor extends BaseService {
892
892
  this.addModifiedNodeId(parent.id);
893
893
 
894
894
  this.pushHistoryState();
895
+
896
+ this.emit('drag-to', { index, targetIndex, config, parent, targetParent });
895
897
  }
896
898
 
897
899
  /**
@@ -51,6 +51,8 @@ class StageOverlay extends BaseService {
51
51
  editorService.on('update', this.updateHandler);
52
52
  editorService.on('add', this.addHandler);
53
53
  editorService.on('remove', this.removeHandler);
54
+ editorService.on('drag-to', this.updateHandler);
55
+ editorService.on('move-layer', this.updateHandler);
54
56
  }
55
57
 
56
58
  public closeOverlay() {
@@ -67,6 +69,8 @@ class StageOverlay extends BaseService {
67
69
  editorService.off('update', this.updateHandler);
68
70
  editorService.off('add', this.addHandler);
69
71
  editorService.off('remove', this.removeHandler);
72
+ editorService.off('drag-to', this.updateHandler);
73
+ editorService.off('move-layer', this.updateHandler);
70
74
  }
71
75
 
72
76
  public updateOverlay() {
@@ -99,13 +103,6 @@ class StageOverlay extends BaseService {
99
103
  }
100
104
 
101
105
  const wrapDiv = this.get('wrapDiv');
102
- const sourceEl = this.get('sourceEl');
103
-
104
- wrapDiv.style.cssText = `
105
- width: ${sourceEl?.scrollWidth}px;
106
- height: ${sourceEl?.scrollHeight}px;
107
- background-color: #fff;
108
- `;
109
106
 
110
107
  await this.render();
111
108
 
@@ -141,12 +138,19 @@ class StageOverlay extends BaseService {
141
138
  this.createContentEl();
142
139
 
143
140
  const contentEl = this.get('contentEl');
141
+ const sourceEl = this.get('sourceEl');
144
142
  const wrapDiv = this.get('wrapDiv');
145
143
  const subStage = this.get('stage');
146
144
  const stageOptions = this.get('stageOptions');
147
145
 
148
146
  if (!contentEl) return;
149
147
 
148
+ wrapDiv.style.cssText = `
149
+ width: ${sourceEl?.scrollWidth}px;
150
+ height: ${sourceEl?.scrollHeight}px;
151
+ background-color: #fff;
152
+ `;
153
+
150
154
  Array.from(wrapDiv.children).forEach((element) => {
151
155
  element.remove();
152
156
  });
@@ -162,19 +166,37 @@ class StageOverlay extends BaseService {
162
166
  }
163
167
 
164
168
  private updateHandler = () => {
165
- this.render();
166
- this.updateOverlay();
169
+ setTimeout(() => {
170
+ this.render();
171
+ this.updateOverlay();
172
+
173
+ this.updateSelectStatus();
174
+ });
167
175
  };
168
176
 
169
177
  private addHandler = () => {
170
178
  this.render();
171
179
  this.updateOverlay();
180
+
181
+ this.updateSelectStatus();
172
182
  };
173
183
 
174
184
  private removeHandler = () => {
175
185
  this.render();
176
186
  this.updateOverlay();
187
+
188
+ this.updateSelectStatus();
177
189
  };
190
+
191
+ private updateSelectStatus() {
192
+ const subStage = this.get('stage');
193
+ const nodes = editorService.get('nodes');
194
+ if (nodes.length > 1) {
195
+ subStage?.multiSelect(nodes.map((n) => n.id));
196
+ } else {
197
+ subStage?.select(nodes[0].id);
198
+ }
199
+ }
178
200
  }
179
201
 
180
202
  export type StageOverlayService = StageOverlay;
@@ -70,3 +70,14 @@
70
70
  }
71
71
  }
72
72
  }
73
+
74
+ .m-editor-slide-list-box {
75
+ min-width: 270px;
76
+ min-height: 500px;
77
+ max-height: 1024px;
78
+ > div {
79
+ &:first-child {
80
+ width: 100%;
81
+ }
82
+ }
83
+ }