@tmagic/editor 1.0.0-beta.13 → 1.0.0-beta.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.
Files changed (91) hide show
  1. package/coverage/clover.xml +646 -550
  2. package/coverage/coverage-final.json +19 -18
  3. package/coverage/lcov-report/index.html +55 -55
  4. package/coverage/lcov-report/src/Editor.vue.html +1 -1
  5. package/coverage/lcov-report/{layouts/sidebar/LayerMenu.vue.html → src/components/ContentMenu.vue.html} +137 -95
  6. package/coverage/lcov-report/src/components/Icon.vue.html +5 -5
  7. package/coverage/lcov-report/src/components/ScrollViewer.vue.html +1 -1
  8. package/coverage/lcov-report/src/components/ToolButton.vue.html +180 -63
  9. package/coverage/lcov-report/src/components/index.html +34 -19
  10. package/coverage/lcov-report/src/index.html +1 -1
  11. package/coverage/lcov-report/src/layouts/AddPageBox.vue.html +1 -1
  12. package/coverage/lcov-report/src/layouts/Framework.vue.html +13 -13
  13. package/coverage/lcov-report/src/layouts/NavMenu.vue.html +1 -1
  14. package/coverage/lcov-report/src/layouts/PropsPanel.vue.html +1 -1
  15. package/coverage/lcov-report/src/layouts/Resizer.vue.html +1 -1
  16. package/coverage/lcov-report/src/layouts/index.html +15 -15
  17. package/coverage/lcov-report/src/layouts/sidebar/ComponentListPanel.vue.html +78 -12
  18. package/coverage/lcov-report/src/layouts/sidebar/LayerMenu.vue.html +149 -92
  19. package/coverage/lcov-report/src/layouts/sidebar/LayerPanel.vue.html +43 -121
  20. package/coverage/lcov-report/src/layouts/sidebar/Sidebar.vue.html +1 -1
  21. package/coverage/lcov-report/src/layouts/sidebar/index.html +40 -40
  22. package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +99 -12
  23. package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +86 -95
  24. package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +208 -97
  25. package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +3 -3
  26. package/coverage/lcov-report/src/layouts/workspace/index.html +35 -35
  27. package/coverage/lcov-report/src/services/BaseService.ts.html +11 -11
  28. package/coverage/lcov-report/src/services/componentList.ts.html +1 -1
  29. package/coverage/lcov-report/src/services/editor.ts.html +102 -9
  30. package/coverage/lcov-report/src/services/events.ts.html +1 -1
  31. package/coverage/lcov-report/src/services/history.ts.html +29 -8
  32. package/coverage/lcov-report/src/services/index.html +25 -25
  33. package/coverage/lcov-report/src/services/props.ts.html +4 -7
  34. package/coverage/lcov-report/src/services/ui.ts.html +1 -1
  35. package/coverage/lcov-report/src/type.ts.html +8 -14
  36. package/coverage/lcov-report/src/utils/compose.ts.html +4 -4
  37. package/coverage/lcov-report/src/utils/config.ts.html +1 -1
  38. package/coverage/lcov-report/src/utils/editor.ts.html +2 -2
  39. package/coverage/lcov-report/src/utils/index.html +1 -1
  40. package/coverage/lcov-report/src/utils/index.ts.html +1 -1
  41. package/coverage/lcov-report/src/utils/logger.ts.html +1 -1
  42. package/coverage/lcov-report/src/utils/props.ts.html +59 -2
  43. package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +1 -1
  44. package/coverage/lcov-report/src/utils/undo-redo.ts.html +1 -1
  45. package/coverage/lcov.info +1623 -1354
  46. package/dist/style.css +39 -18
  47. package/dist/tmagic-editor.es.js +598 -412
  48. package/dist/tmagic-editor.es.js.map +1 -1
  49. package/dist/tmagic-editor.umd.js +595 -408
  50. package/dist/tmagic-editor.umd.js.map +1 -1
  51. package/dist/types/src/Editor.vue.d.ts +1 -1
  52. package/dist/types/src/components/ToolButton.vue.d.ts +12 -1
  53. package/dist/types/src/index.d.ts +1 -0
  54. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -0
  55. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +2 -0
  56. package/dist/types/src/services/history.d.ts +1 -0
  57. package/dist/types/src/services/props.d.ts +2 -2
  58. package/dist/types/src/type.d.ts +6 -8
  59. package/dist/types/src/utils/polyfills.d.ts +0 -0
  60. package/package.json +8 -7
  61. package/src/components/ContentMenu.vue +107 -0
  62. package/src/components/ToolButton.vue +66 -27
  63. package/src/index.ts +2 -0
  64. package/src/layouts/Framework.vue +6 -6
  65. package/src/layouts/sidebar/ComponentListPanel.vue +23 -1
  66. package/src/layouts/sidebar/LayerMenu.vue +91 -72
  67. package/src/layouts/sidebar/LayerPanel.vue +23 -49
  68. package/src/layouts/workspace/PageBar.vue +35 -6
  69. package/src/layouts/workspace/Stage.vue +41 -44
  70. package/src/layouts/workspace/ViewerMenu.vue +104 -67
  71. package/src/layouts/workspace/Workspace.vue +2 -2
  72. package/src/services/editor.ts +32 -1
  73. package/src/services/history.ts +7 -0
  74. package/src/services/props.ts +2 -3
  75. package/src/theme/common/var.scss +1 -0
  76. package/src/theme/component-list-panel.scss +2 -0
  77. package/src/theme/content-menu.scss +33 -26
  78. package/src/theme/layer-panel.scss +1 -1
  79. package/src/theme/page-bar.scss +22 -1
  80. package/src/type.ts +6 -8
  81. package/src/utils/editor.ts +1 -1
  82. package/src/utils/polyfills.ts +22 -0
  83. package/src/utils/props.ts +19 -0
  84. package/coverage/lcov-report/Icon.vue.html +0 -172
  85. package/coverage/lcov-report/ToolButton.vue.html +0 -655
  86. package/coverage/lcov-report/layouts/sidebar/index.html +0 -116
  87. package/coverage/lcov-report/utils/index.html +0 -116
  88. package/coverage/lcov-report/utils/undo-redo.ts.html +0 -313
  89. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -980
  90. package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -188
  91. package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
@@ -1,91 +1,110 @@
1
1
  <template>
2
- <div v-if="node" class="magic-editor-content-menu">
3
- <div
4
- v-if="node.items"
5
- class="magic-editor-content-menu-item"
6
- @mouseenter="setSubVisitable(true)"
7
- @mouseleave="setSubVisitable(false)"
8
- >
9
- 新增
10
- </div>
11
- <div v-if="node.type !== 'app'" class="magic-editor-content-menu-item" @click="() => copy(node)">复制</div>
12
- <div
13
- v-if="node.type !== 'app' && node.type !== 'page'"
14
- class="magic-editor-content-menu-item"
15
- @click="() => remove()"
16
- >
17
- 删除
18
- </div>
19
- <div class="subMenu" v-show="subVisible" @mouseenter="setSubVisitable(true)" @mouseleave="setSubVisitable(false)">
20
- <el-scrollbar>
21
- <template v-if="node.type === 'tabs'">
22
- <div
23
- class="magic-editor-content-menu-item"
24
- @click="
25
- () =>
26
- append({
27
- type: 'tab-pane',
28
- })
29
- "
30
- >
31
- 标签
32
- </div>
33
- </template>
34
- <template v-else-if="node.items">
35
- <div v-for="list in componentGroupList" :key="list.title">
36
- <template v-for="item in list.items">
37
- <div class="magic-editor-content-menu-item" v-if="item" :key="item.type" @click="() => append(item)">
38
- {{ item.text }}
39
- </div>
40
- </template>
41
- <div class="separation"></div>
42
- </div>
43
- </template>
44
- </el-scrollbar>
45
- </div>
46
- </div>
2
+ <content-menu :menu-data="menuData" ref="menu" style="overflow: initial"></content-menu>
47
3
  </template>
48
4
 
49
5
  <script lang="ts">
50
- import { computed, defineComponent, inject, ref } from 'vue';
6
+ import { computed, defineComponent, inject, markRaw, ref } from 'vue';
7
+ import { Delete, DocumentCopy, Files, Plus } from '@element-plus/icons';
51
8
 
52
- import type { MNode } from '@tmagic/schema';
9
+ import { NodeType } from '@tmagic/schema';
53
10
 
54
- import type { AddMNode, Services } from '@editor/type';
11
+ import ContentMenu from '@editor/components/ContentMenu.vue';
12
+ import type { ComponentGroup, MenuButton, MenuItem, Services } from '@editor/type';
55
13
 
56
14
  export default defineComponent({
57
- name: 'magic-editor-content-menu',
15
+ components: { ContentMenu },
58
16
 
59
17
  setup() {
60
18
  const services = inject<Services>('services');
61
- const subVisible = ref(false);
19
+ const menu = ref<InstanceType<typeof ContentMenu>>();
62
20
  const node = computed(() => services?.editorService.get('node'));
21
+ const isRoot = computed(() => node.value?.type === NodeType.ROOT);
22
+ const isPage = computed(() => node.value?.type === NodeType.PAGE);
23
+ const componentList = computed(() => services?.componentListService.getList() || []);
63
24
 
64
- return {
65
- subVisible,
66
-
67
- node,
68
-
69
- componentGroupList: computed(() => services?.componentListService.getList()),
70
-
71
- append(config: AddMNode) {
72
- services?.editorService.add({
73
- name: config.text,
74
- type: config.type,
75
- ...(config.data || {}),
76
- });
77
- },
25
+ const createMenuItems = (group: ComponentGroup): MenuButton[] =>
26
+ group.items.map((component) => ({
27
+ text: component.text,
28
+ type: 'button',
29
+ icon: component.icon,
30
+ handler: () => {
31
+ services?.editorService.add({
32
+ name: component.text,
33
+ type: component.type,
34
+ ...(component.data || {}),
35
+ });
36
+ },
37
+ }));
78
38
 
79
- remove() {
80
- node.value && services?.editorService.remove(node.value);
81
- },
39
+ const getSubMenuData = computed<MenuButton[]>(() => {
40
+ if (node.value?.type === 'tabs') {
41
+ return [
42
+ {
43
+ text: '标签页',
44
+ type: 'button',
45
+ icon: Files,
46
+ handler: () => {
47
+ services?.editorService.add({
48
+ type: 'tab-pane',
49
+ });
50
+ },
51
+ },
52
+ ];
53
+ }
54
+ if (node.value?.items) {
55
+ return (
56
+ componentList.value.reduce(
57
+ (subMenuData: MenuButton[], group: ComponentGroup, index) =>
58
+ subMenuData.concat(
59
+ createMenuItems(group),
60
+ index < componentList.value.length - 1
61
+ ? [
62
+ {
63
+ type: 'divider',
64
+ direction: 'horizontal',
65
+ },
66
+ ]
67
+ : [],
68
+ ),
69
+ [],
70
+ ) || []
71
+ );
72
+ }
73
+ return [];
74
+ });
82
75
 
83
- copy(node?: MNode) {
84
- node && services?.editorService.copy(node);
85
- },
76
+ return {
77
+ menu,
78
+ menuData: computed<MenuItem[]>(() => [
79
+ {
80
+ type: 'button',
81
+ text: '新增',
82
+ icon: markRaw(Plus),
83
+ display: () => node.value?.items,
84
+ items: getSubMenuData.value,
85
+ },
86
+ {
87
+ type: 'button',
88
+ text: '复制',
89
+ icon: markRaw(DocumentCopy),
90
+ display: () => !isRoot.value,
91
+ handler: () => {
92
+ node.value && services?.editorService.copy(node.value);
93
+ },
94
+ },
95
+ {
96
+ type: 'button',
97
+ text: '删除',
98
+ icon: markRaw(Delete),
99
+ display: () => !isRoot.value && !isPage.value,
100
+ handler: () => {
101
+ node.value && services?.editorService.remove(node.value);
102
+ },
103
+ },
104
+ ]),
86
105
 
87
- setSubVisitable(v: boolean) {
88
- subVisible.value = v;
106
+ show(e: MouseEvent) {
107
+ menu.value?.show(e);
89
108
  },
90
109
  };
91
110
  },
@@ -33,8 +33,8 @@
33
33
  <div
34
34
  :id="data.id"
35
35
  class="cus-tree-node"
36
- @mousedown="toogleClickFlag"
37
- @mouseup="toogleClickFlag"
36
+ @mousedown="toggleClickFlag"
37
+ @mouseup="toggleClickFlag"
38
38
  @mouseenter="highlightHandler(data)"
39
39
  :class="{ 'cus-tree-node-hover': canHighlight && data.id === highlightNode?.id }"
40
40
  >
@@ -48,13 +48,13 @@
48
48
  </el-tree>
49
49
 
50
50
  <teleport to="body">
51
- <layer-menu :style="menuStyle"></layer-menu>
51
+ <layer-menu ref="menu"></layer-menu>
52
52
  </teleport>
53
53
  </el-scrollbar>
54
54
  </template>
55
55
 
56
56
  <script lang="ts">
57
- import { computed, defineComponent, inject, onMounted, Ref, ref, watchEffect } from 'vue';
57
+ import { computed, defineComponent, inject, Ref, ref, watchEffect } from 'vue';
58
58
  import type { ElTree } from 'element-plus';
59
59
  import { throttle } from 'lodash-es';
60
60
 
@@ -169,46 +169,6 @@ const useFilter = (tree: Ref<InstanceType<typeof ElTree> | undefined>) => ({
169
169
  },
170
170
  });
171
171
 
172
- const useContentMenu = (editorService?: EditorService) => {
173
- const menuStyle = ref({
174
- position: 'absolute',
175
- left: '0',
176
- top: '0',
177
- display: 'none',
178
- });
179
-
180
- onMounted(() => {
181
- document.addEventListener(
182
- 'click',
183
- () => {
184
- menuStyle.value.display = 'none';
185
- },
186
- true,
187
- );
188
- });
189
-
190
- return {
191
- menuStyle,
192
-
193
- contextmenu(event: MouseEvent, data: MNode) {
194
- const bodyHeight = globalThis.document.body.clientHeight;
195
-
196
- const left = `${event.clientX + 20}px`;
197
- let top = `${event.clientY - 10}px`;
198
-
199
- if (event.clientY + 300 > bodyHeight) {
200
- top = `${bodyHeight - 300}px`;
201
- }
202
-
203
- menuStyle.value.left = left;
204
- menuStyle.value.top = top;
205
- menuStyle.value.display = '';
206
-
207
- select(data, editorService);
208
- },
209
- };
210
- };
211
-
212
172
  export default defineComponent({
213
173
  name: 'magic-editor-layer-panel',
214
174
 
@@ -217,13 +177,14 @@ export default defineComponent({
217
177
  setup() {
218
178
  const services = inject<Services>('services');
219
179
  const tree = ref<InstanceType<typeof ElTree>>();
180
+ const menu = ref<InstanceType<typeof LayerMenu>>();
220
181
  const clicked = ref(false);
221
182
  const editorService = services?.editorService;
222
183
  const highlightHandler = throttle((data: MNode) => {
223
184
  highlight(data, editorService);
224
185
  }, throttleTime);
225
186
 
226
- const toogleClickFlag = () => {
187
+ const toggleClickFlag = () => {
227
188
  clicked.value = !clicked.value;
228
189
  };
229
190
 
@@ -232,12 +193,22 @@ export default defineComponent({
232
193
  () => statusData.highlightNode.value?.id !== statusData.clickNode.value?.id && !clicked.value,
233
194
  );
234
195
 
196
+ editorService?.on('remove', () => {
197
+ setTimeout(() => {
198
+ tree.value?.getNode(editorService.get('node').id)?.updateChildren();
199
+ }, 0);
200
+ });
201
+
235
202
  return {
236
203
  tree,
204
+ menu,
237
205
  ...statusData,
238
206
  ...useDrop(tree, editorService),
239
207
  ...useFilter(tree),
240
- ...useContentMenu(editorService),
208
+
209
+ highlightHandler,
210
+ toggleClickFlag,
211
+ canHighlight,
241
212
 
242
213
  clickHandler(data: MNode): void {
243
214
  if (services?.uiService.get<boolean>('uiSelectMode')) {
@@ -247,9 +218,12 @@ export default defineComponent({
247
218
  tree.value?.setCurrentKey(data.id);
248
219
  select(data, editorService);
249
220
  },
250
- highlightHandler,
251
- toogleClickFlag,
252
- canHighlight,
221
+
222
+ async contextmenu(event: MouseEvent, data: MNode) {
223
+ event.preventDefault();
224
+ await select(data, editorService);
225
+ menu.value?.show(event);
226
+ },
253
227
  };
254
228
  },
255
229
  });
@@ -22,11 +22,25 @@
22
22
  </slot>
23
23
  </div>
24
24
 
25
- <el-popover placement="top" :width="160" trigger="hover">
25
+ <el-popover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
26
26
  <div>
27
27
  <slot name="page-bar-popover" :page="item">
28
- <div class="magic-editor-content-menu-item" @click="() => copy(item)">复制</div>
29
- <div class="magic-editor-content-menu-item" @click="() => remove(item)">删除</div>
28
+ <tool-button
29
+ :data="{
30
+ type: 'button',
31
+ text: '复制',
32
+ icon: DocumentCopy,
33
+ handler: () => copy(item),
34
+ }"
35
+ ></tool-button>
36
+ <tool-button
37
+ :data="{
38
+ type: 'button',
39
+ text: '删除',
40
+ icon: Delete,
41
+ handler: () => remove(item),
42
+ }"
43
+ ></tool-button>
30
44
  </slot>
31
45
  </div>
32
46
  <template #reference>
@@ -44,12 +58,24 @@
44
58
  </template>
45
59
 
46
60
  <script lang="ts">
47
- import { computed, ComputedRef, defineComponent, inject, onMounted, onUnmounted, ref, toRaw, watch } from 'vue';
48
- import { ArrowLeftBold, ArrowRightBold, CaretBottom, Plus } from '@element-plus/icons';
61
+ import {
62
+ computed,
63
+ ComputedRef,
64
+ defineComponent,
65
+ inject,
66
+ markRaw,
67
+ onMounted,
68
+ onUnmounted,
69
+ ref,
70
+ toRaw,
71
+ watch,
72
+ } from 'vue';
73
+ import { ArrowLeftBold, ArrowRightBold, CaretBottom, Delete, DocumentCopy, Plus } from '@element-plus/icons';
49
74
 
50
75
  import type { MApp, MPage } from '@tmagic/schema';
51
76
  import { NodeType } from '@tmagic/schema';
52
77
 
78
+ import ToolButton from '@editor/components/ToolButton.vue';
53
79
  import type { Services } from '@editor/type';
54
80
  import { generatePageNameByApp } from '@editor/utils/editor';
55
81
 
@@ -138,7 +164,7 @@ const useScroll = (root: ComputedRef<MApp | undefined>) => {
138
164
  };
139
165
 
140
166
  export default defineComponent({
141
- components: { ArrowLeftBold, ArrowRightBold, CaretBottom, Plus },
167
+ components: { ArrowLeftBold, ArrowRightBold, CaretBottom, Plus, ToolButton },
142
168
 
143
169
  setup() {
144
170
  const services = inject<Services>('services');
@@ -147,6 +173,9 @@ export default defineComponent({
147
173
  const root = computed(() => editorService?.get<MApp>('root'));
148
174
 
149
175
  return {
176
+ Delete: markRaw(Delete),
177
+ DocumentCopy: markRaw(DocumentCopy),
178
+
150
179
  ...useScroll(root),
151
180
 
152
181
  root,
@@ -9,11 +9,13 @@
9
9
  <div
10
10
  class="m-editor-stage-container"
11
11
  ref="stageContainer"
12
- @contextmenu="contextmenuHandler"
13
12
  :style="`transform: scale(${zoom})`"
13
+ @contextmenu="contextmenuHandler"
14
+ @drop="dropHandler"
15
+ @dragover="dragoverHandler"
14
16
  ></div>
15
17
  <teleport to="body">
16
- <viewer-menu ref="menu" :style="menuStyle"></viewer-menu>
18
+ <viewer-menu ref="menu"></viewer-menu>
17
19
  </teleport>
18
20
  </scroll-viewer>
19
21
  </template>
@@ -39,49 +41,10 @@ import type { MoveableOptions, Runtime, SortEventData, UpdateEventData } from '@
39
41
  import StageCore from '@tmagic/stage';
40
42
 
41
43
  import ScrollViewer from '@editor/components/ScrollViewer.vue';
42
- import type { Services, StageRect } from '@editor/type';
44
+ import { Layout, Services, StageRect } from '@editor/type';
43
45
 
44
46
  import ViewerMenu from './ViewerMenu.vue';
45
47
 
46
- const useMenu = () => {
47
- const menu = ref<InstanceType<typeof ViewerMenu>>();
48
- const menuStyle = ref({
49
- display: 'none',
50
- left: '0',
51
- top: '0',
52
- });
53
-
54
- onMounted(() => {
55
- document.addEventListener(
56
- 'click',
57
- () => {
58
- menuStyle.value.display = 'none';
59
- },
60
- true,
61
- );
62
- });
63
-
64
- return {
65
- menu,
66
- menuStyle,
67
-
68
- contextmenuHandler(e: MouseEvent) {
69
- e.preventDefault();
70
-
71
- const menuHeight = menu.value?.$el.clientHeight;
72
- let top = e.clientY;
73
- if (menuHeight + e.clientY > document.body.clientHeight) {
74
- top = document.body.clientHeight - menuHeight;
75
- }
76
- menuStyle.value = {
77
- display: 'block',
78
- top: `${top}px`,
79
- left: `${e.clientX}px`,
80
- };
81
- },
82
- };
83
- };
84
-
85
48
  export default defineComponent({
86
49
  name: 'magic-stage',
87
50
 
@@ -115,12 +78,13 @@ export default defineComponent({
115
78
 
116
79
  const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
117
80
  const stageContainer = ref<HTMLDivElement>();
81
+ const menu = ref<InstanceType<typeof ViewerMenu>>();
118
82
 
119
83
  const stageRect = computed(() => services?.uiService.get<StageRect>('stageRect'));
120
84
  const uiSelectMode = computed(() => services?.uiService.get<boolean>('uiSelectMode'));
121
85
  const root = computed(() => services?.editorService.get<MApp>('root'));
122
86
  const page = computed(() => services?.editorService.get<MPage>('page'));
123
- const zoom = computed(() => services?.uiService.get<number>('zoom'));
87
+ const zoom = computed(() => services?.uiService.get<number>('zoom') || 1);
124
88
  const node = computed(() => services?.editorService.get<MNode>('node'));
125
89
 
126
90
  let stage: StageCore | null = null;
@@ -218,9 +182,42 @@ export default defineComponent({
218
182
  return {
219
183
  stageWrap,
220
184
  stageContainer,
185
+ menu,
221
186
  stageRect,
222
187
  zoom,
223
- ...useMenu(),
188
+
189
+ contextmenuHandler(e: MouseEvent) {
190
+ e.preventDefault();
191
+ menu.value?.show(e);
192
+ },
193
+
194
+ dragoverHandler(e: DragEvent) {
195
+ e.preventDefault();
196
+ if (e.dataTransfer) {
197
+ e.dataTransfer.dropEffect = 'move';
198
+ }
199
+ },
200
+
201
+ async dropHandler(e: DragEvent) {
202
+ e.preventDefault();
203
+ if (e.dataTransfer && page.value && stageContainer.value && stage) {
204
+ // eslint-disable-next-line no-eval
205
+ const config = eval(`(${e.dataTransfer.getData('data')})`);
206
+ const layout = await services?.editorService.getLayout(page.value);
207
+
208
+ const containerRect = stageContainer.value.getBoundingClientRect();
209
+ const { scrollTop, scrollLeft } = stage.mask;
210
+ if (layout === Layout.ABSOLUTE) {
211
+ config.style = {
212
+ position: 'absolute',
213
+ top: e.clientY - containerRect.top + scrollTop,
214
+ left: e.clientX - containerRect.left + scrollLeft,
215
+ };
216
+ }
217
+
218
+ services?.editorService.add(config, page.value);
219
+ }
220
+ },
224
221
  };
225
222
  },
226
223
  });