@tmagic/editor 1.0.4 → 1.1.0-beta.1

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.
@@ -3,7 +3,7 @@ import { PropType } from 'vue';
3
3
  import type { FormConfig } from '@tmagic/form';
4
4
  import type { MApp, MNode } from '@tmagic/schema';
5
5
  import type StageCore from '@tmagic/stage';
6
- import type { MoveableOptions } from '@tmagic/stage';
6
+ import { MoveableOptions } from '@tmagic/stage';
7
7
  import type { ComponentGroup, MenuBarData, MenuItem, Services, SideBarData, StageRect } from './type';
8
8
  declare const _default: DefineComponent<{
9
9
  /** 页面初始值 */
@@ -72,6 +72,18 @@ declare const _default: DefineComponent<{
72
72
  type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
73
73
  default: (el: HTMLElement) => boolean;
74
74
  };
75
+ isContainer: {
76
+ type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
77
+ default: (el: HTMLElement) => boolean;
78
+ };
79
+ containerHighlightClassName: {
80
+ type: StringConstructor;
81
+ default: string;
82
+ };
83
+ containerHighlightDuration: {
84
+ type: NumberConstructor;
85
+ default: number;
86
+ };
75
87
  stageRect: {
76
88
  type: PropType<StageRect>;
77
89
  };
@@ -149,6 +161,18 @@ declare const _default: DefineComponent<{
149
161
  type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
150
162
  default: (el: HTMLElement) => boolean;
151
163
  };
164
+ isContainer: {
165
+ type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
166
+ default: (el: HTMLElement) => boolean;
167
+ };
168
+ containerHighlightClassName: {
169
+ type: StringConstructor;
170
+ default: string;
171
+ };
172
+ containerHighlightDuration: {
173
+ type: NumberConstructor;
174
+ default: number;
175
+ };
152
176
  stageRect: {
153
177
  type: PropType<StageRect>;
154
178
  };
@@ -174,5 +198,8 @@ declare const _default: DefineComponent<{
174
198
  propsValues: Record<string, MNode>;
175
199
  eventMethodList: Record<string, any>;
176
200
  canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
201
+ isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
202
+ containerHighlightClassName: string;
203
+ containerHighlightDuration: number;
177
204
  }>;
178
205
  export default _default;
@@ -10,5 +10,7 @@ declare const _default: DefineComponent<{}, {
10
10
  }[] | undefined>;
11
11
  appendComponent({ text, type, data }: ComponentItem): void;
12
12
  dragstartHandler({ text, type, data }: ComponentItem, e: DragEvent): void;
13
+ dragendHandler(): void;
14
+ dragHandler(e: DragEvent): void;
13
15
  }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly<ExtractPropTypes<{}>>, {}>;
14
16
  export default _default;
@@ -111,6 +111,12 @@ declare class Editor extends BaseService {
111
111
  * @param offset 偏移量
112
112
  */
113
113
  moveLayer(offset: number | LayerOffset): Promise<void>;
114
+ /**
115
+ * 移动到指定容器中
116
+ * @param config 需要移动的节点
117
+ * @param targetId 容器ID
118
+ */
119
+ moveToContainer(config: MNode, targetId: Id): Promise<MNode | undefined>;
114
120
  /**
115
121
  * 撤销当前操作
116
122
  * @returns 上一次数据
@@ -25,9 +25,12 @@ export interface Services {
25
25
  export interface StageOptions {
26
26
  runtimeUrl: string;
27
27
  autoScrollIntoView: boolean;
28
+ containerHighlightClassName: string;
29
+ containerHighlightDuration: number;
28
30
  render: () => HTMLDivElement;
29
31
  moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
30
32
  canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
33
+ isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
31
34
  updateDragEl: (el: HTMLDivElement) => void;
32
35
  }
33
36
  export interface StoreState {
@@ -32,9 +32,13 @@ export declare const generatePageNameByApp: (app: MApp) => string;
32
32
  */
33
33
  export declare const isFixed: (node: MNode) => boolean;
34
34
  export declare const getNodeIndex: (node: MNode, parent: MContainer | MApp) => number;
35
- export declare const toRelative: (node: MNode) => MNode;
36
- export declare const initPosition: (node: MNode, layout: Layout, parentNode: MNode, stage: StageCore) => MNode;
35
+ export declare const getRelativeStyle: (style?: Record<string, any>) => Record<string, any>;
36
+ export declare const getInitPositionStyle: (style: Record<string, any> | undefined, layout: Layout, parentNode: MNode, stage: StageCore) => Record<string, any>;
37
37
  export declare const setLayout: (node: MNode, layout: Layout) => MNode;
38
- export declare const change2Fixed: (node: MNode, root: MApp) => MNode;
39
- export declare const Fixed2Other: (node: MNode, root: MApp, getLayout: (parent: MNode, node?: MNode | undefined) => Promise<Layout>) => Promise<MNode>;
38
+ export declare const change2Fixed: (node: MNode, root: MApp) => {
39
+ left: number;
40
+ top: number;
41
+ };
42
+ export declare const Fixed2Other: (node: MNode, root: MApp, getLayout: (parent: MNode, node?: MNode | undefined) => Promise<Layout>) => Promise<Record<string, any>>;
40
43
  export declare const getGuideLineFromCache: (key: string) => number[];
44
+ export declare const fixNodeLeft: (config: MNode, parent: MContainer, doc?: Document | undefined) => any;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.4",
2
+ "version": "1.1.0-beta.1",
3
3
  "name": "@tmagic/editor",
4
4
  "sideEffects": [
5
5
  "dist/*",
@@ -42,12 +42,12 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "@babel/core": "^7.18.0",
45
- "@element-plus/icons": "0.0.11",
46
- "@tmagic/core": "1.0.4",
47
- "@tmagic/form": "1.0.4",
48
- "@tmagic/schema": "1.0.4",
49
- "@tmagic/stage": "1.0.4",
50
- "@tmagic/utils": "1.0.4",
45
+ "@element-plus/icons-vue": "^2.0.6",
46
+ "@tmagic/core": "1.1.0-beta.1",
47
+ "@tmagic/form": "1.1.0-beta.1",
48
+ "@tmagic/schema": "1.1.0-beta.1",
49
+ "@tmagic/stage": "1.1.0-beta.1",
50
+ "@tmagic/utils": "1.1.0-beta.1",
51
51
  "buffer": "^6.0.3",
52
52
  "color": "^3.1.3",
53
53
  "element-plus": "^2.2.6",
@@ -60,7 +60,7 @@
60
60
  "vue": "^3.2.0"
61
61
  },
62
62
  "peerDependencies": {
63
- "@tmagic/form": "1.0.4",
63
+ "@tmagic/form": "1.1.0-beta.1",
64
64
  "element-plus": "^2.2.6",
65
65
  "monaco-editor": "^0.32.1",
66
66
  "vue": "^3.2.0"
package/src/Editor.vue CHANGED
@@ -7,12 +7,12 @@
7
7
  <template #sidebar>
8
8
  <slot name="sidebar" :editorService="editorService">
9
9
  <sidebar :data="sidebar">
10
- <template #layer-panel>
11
- <slot name="layer-panel"></slot>
10
+ <template #layer-panel-header>
11
+ <slot name="layer-panel-header"></slot>
12
12
  </template>
13
13
 
14
- <template #component-list-panel>
15
- <slot name="component-list-panel"></slot>
14
+ <template #component-list-panel-header>
15
+ <slot name="component-list-panel-header"></slot>
16
16
  </template>
17
17
  </sidebar>
18
18
  </slot>
@@ -30,7 +30,11 @@
30
30
 
31
31
  <template #props-panel>
32
32
  <slot name="props-panel">
33
- <props-panel ref="propsPanel" @mounted="(instance) => $emit('props-panel-mounted', instance)"></props-panel>
33
+ <props-panel ref="propsPanel" @mounted="(instance) => $emit('props-panel-mounted', instance)">
34
+ <template #props-panel-header>
35
+ <slot name="props-panel-header"></slot>
36
+ </template>
37
+ </props-panel>
34
38
  </slot>
35
39
  </template>
36
40
 
@@ -45,7 +49,7 @@ import { EventOption } from '@tmagic/core';
45
49
  import type { FormConfig } from '@tmagic/form';
46
50
  import type { MApp, MNode } from '@tmagic/schema';
47
51
  import type StageCore from '@tmagic/stage';
48
- import type { MoveableOptions } from '@tmagic/stage';
52
+ import { CONTAINER_HIGHLIGHT_CLASS, MoveableOptions } from '@tmagic/stage';
49
53
 
50
54
  import Framework from '@editor/layouts/Framework.vue';
51
55
  import NavMenu from '@editor/layouts/NavMenu.vue';
@@ -150,6 +154,21 @@ export default defineComponent({
150
154
  default: (el: HTMLElement) => Boolean(el.id),
151
155
  },
152
156
 
157
+ isContainer: {
158
+ type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
159
+ default: (el: HTMLElement) => el.classList.contains('magic-ui-container'),
160
+ },
161
+
162
+ containerHighlightClassName: {
163
+ type: String,
164
+ default: CONTAINER_HIGHLIGHT_CLASS,
165
+ },
166
+
167
+ containerHighlightDuration: {
168
+ type: Number,
169
+ default: 800,
170
+ },
171
+
153
172
  stageRect: {
154
173
  type: [String, Object] as PropType<StageRect>,
155
174
  },
@@ -265,6 +284,9 @@ export default defineComponent({
265
284
  moveableOptions: props.moveableOptions,
266
285
  canSelect: props.canSelect,
267
286
  updateDragEl: props.updateDragEl,
287
+ isContainer: props.isContainer,
288
+ containerHighlightClassName: props.containerHighlightClassName,
289
+ containerHighlightDuration: props.containerHighlightDuration,
268
290
  }),
269
291
  );
270
292
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  <script lang="ts">
9
9
  import { Component, defineComponent, PropType, toRaw } from 'vue';
10
- import { Edit } from '@element-plus/icons';
10
+ import { Edit } from '@element-plus/icons-vue';
11
11
 
12
12
  export default defineComponent({
13
13
  name: 'm-icon',
@@ -52,7 +52,7 @@
52
52
 
53
53
  <script lang="ts">
54
54
  import { computed, defineComponent, inject, markRaw, PropType } from 'vue';
55
- import { ArrowDown, Back, Delete, Grid, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons';
55
+ import { ArrowDown, Back, Delete, Grid, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
56
56
 
57
57
  import { NodeType } from '@tmagic/schema';
58
58
 
@@ -14,7 +14,7 @@
14
14
 
15
15
  <script lang="ts">
16
16
  import { computed, defineComponent, inject, markRaw, ref } from 'vue';
17
- import { Close, Delete, Pointer } from '@element-plus/icons';
17
+ import { Close, Delete, Pointer } from '@element-plus/icons-vue';
18
18
 
19
19
  import { FormState } from '@tmagic/form';
20
20
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  <script lang="ts">
15
15
  import { defineComponent, inject, toRaw } from 'vue';
16
- import { Plus } from '@element-plus/icons';
16
+ import { Plus } from '@element-plus/icons-vue';
17
17
 
18
18
  import { NodeType } from '@tmagic/schema';
19
19
 
@@ -1,13 +1,16 @@
1
1
  <template>
2
- <m-form
3
- :class="`m-editor-props-panel ${propsPanelSize}`"
4
- :popper-class="`m-editor-props-panel-popper ${propsPanelSize}`"
5
- ref="configForm"
6
- :size="propsPanelSize"
7
- :init-values="values"
8
- :config="curFormConfig"
9
- @change="submit"
10
- ></m-form>
2
+ <div class="`m-editor-props-panel">
3
+ <slot name="props-panel-header"></slot>
4
+ <m-form
5
+ :class="`m-editor-props-panel ${propsPanelSize}`"
6
+ :popper-class="`m-editor-props-panel-popper ${propsPanelSize}`"
7
+ ref="configForm"
8
+ :size="propsPanelSize"
9
+ :init-values="values"
10
+ :config="curFormConfig"
11
+ @change="submit"
12
+ ></m-form>
13
+ </div>
11
14
  </template>
12
15
 
13
16
  <script lang="ts">
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <el-scrollbar>
3
- <slot name="component-list-panel"></slot>
3
+ <slot name="component-list-panel-header"></slot>
4
+
4
5
  <el-collapse class="ui-component-panel" :model-value="collapseValue">
5
6
  <el-input
6
7
  prefix-icon="el-icon-search"
@@ -20,6 +21,8 @@
20
21
  :key="item.type"
21
22
  @click="appendComponent(item)"
22
23
  @dragstart="dragstartHandler(item, $event)"
24
+ @dragend="dragendHandler"
25
+ @drag="dragHandler"
23
26
  >
24
27
  <m-icon :icon="item.icon"></m-icon>
25
28
 
@@ -37,8 +40,12 @@
37
40
  import { computed, defineComponent, inject, ref } from 'vue';
38
41
  import serialize from 'serialize-javascript';
39
42
 
43
+ import type StageCore from '@tmagic/stage';
44
+ import { GHOST_EL_ID_PREFIX } from '@tmagic/stage';
45
+ import { addClassName, removeClassNameByClassName } from '@tmagic/utils';
46
+
40
47
  import MIcon from '@editor/components/Icon.vue';
41
- import type { ComponentGroup, ComponentItem, Services } from '@editor/type';
48
+ import type { ComponentGroup, ComponentItem, Services, StageOptions } from '@editor/type';
42
49
 
43
50
  export default defineComponent({
44
51
  name: 'ui-component-panel',
@@ -48,6 +55,9 @@ export default defineComponent({
48
55
  setup() {
49
56
  const searchText = ref('');
50
57
  const services = inject<Services>('services');
58
+ const stageOptions = inject<StageOptions>('stageOptions');
59
+
60
+ const stage = computed(() => services?.editorService.get<StageCore>('stage'));
51
61
  const list = computed(() =>
52
62
  services?.componentListService.getList().map((group: ComponentGroup) => ({
53
63
  ...group,
@@ -60,6 +70,10 @@ export default defineComponent({
60
70
  .map((x, i) => i),
61
71
  );
62
72
 
73
+ let timeout: NodeJS.Timeout | undefined;
74
+ let clientX: number;
75
+ let clientY: number;
76
+
63
77
  return {
64
78
  searchText,
65
79
  collapseValue,
@@ -86,6 +100,45 @@ export default defineComponent({
86
100
  );
87
101
  }
88
102
  },
103
+
104
+ dragendHandler() {
105
+ if (timeout) {
106
+ globalThis.clearTimeout(timeout);
107
+ timeout = undefined;
108
+ }
109
+ const doc = stage.value?.renderer.contentWindow?.document;
110
+ if (doc && stageOptions) {
111
+ removeClassNameByClassName(doc, stageOptions.containerHighlightClassName);
112
+ }
113
+ clientX = 0;
114
+ clientY = 0;
115
+ },
116
+
117
+ dragHandler(e: DragEvent) {
118
+ if (e.clientX !== clientX || e.clientY !== clientY) {
119
+ clientX = e.clientX;
120
+ clientY = e.clientY;
121
+ if (timeout) {
122
+ globalThis.clearTimeout(timeout);
123
+ timeout = undefined;
124
+ }
125
+ return;
126
+ }
127
+
128
+ if (timeout) return;
129
+
130
+ timeout = globalThis.setTimeout(async () => {
131
+ if (!stageOptions || !stage.value) return;
132
+ const doc = stage.value.renderer.contentWindow?.document;
133
+ const els = stage.value.getElementsFromPoint(e);
134
+ for (const el of els) {
135
+ if (doc && !el.id.startsWith(GHOST_EL_ID_PREFIX) && (await stageOptions.isContainer(el))) {
136
+ addClassName(el, doc, stageOptions?.containerHighlightClassName);
137
+ break;
138
+ }
139
+ }
140
+ }, stageOptions?.containerHighlightDuration);
141
+ },
89
142
  };
90
143
  },
91
144
  });
@@ -4,7 +4,7 @@
4
4
 
5
5
  <script lang="ts">
6
6
  import { computed, defineComponent, inject, markRaw, ref } from 'vue';
7
- import { Delete, DocumentCopy, Files, Plus } from '@element-plus/icons';
7
+ import { Delete, DocumentCopy, Files, Plus } from '@element-plus/icons-vue';
8
8
 
9
9
  import { NodeType } from '@tmagic/schema';
10
10
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <el-scrollbar class="magic-editor-layer-panel">
3
- <slot name="layer-panel"></slot>
3
+ <slot name="layer-panel-header"></slot>
4
4
 
5
5
  <el-input
6
6
  class="filterInput"
@@ -7,12 +7,12 @@
7
7
  tab-position="left"
8
8
  >
9
9
  <tab-pane v-for="(item, index) in data.items" :key="index" :data="item">
10
- <template #layer-panel v-if="item === 'layer'">
11
- <slot name="layer-panel"></slot>
10
+ <template #layer-panel-header v-if="item === 'layer'">
11
+ <slot name="layer-panel-header"></slot>
12
12
  </template>
13
13
 
14
- <template #component-list-panel v-if="item === 'component-list'">
15
- <slot name="component-list-panel"></slot>
14
+ <template #component-list-panel-header v-if="item === 'component-list'">
15
+ <slot name="component-list-panel-header"></slot>
16
16
  </template>
17
17
  </tab-pane>
18
18
  </el-tabs>
@@ -8,12 +8,14 @@
8
8
  </template>
9
9
 
10
10
  <component :is="config.component" v-bind="config.props || {}" v-on="config?.listeners || {}">
11
- <template #layer-panel v-if="data === 'layer'">
12
- <slot name="layer-panel"></slot>
11
+ <template #component-list-panel-header v-if="data === 'component-list' || config.slots?.componentListPanelHeader">
12
+ <slot v-if="data === 'component-list'" name="component-list-panel-header"></slot>
13
+ <component v-else-if="config.slots?.componentListPanelHeader" :is="config.slots.componentListPanelHeader" />
13
14
  </template>
14
15
 
15
- <template #component-list-panel v-if="data === 'component-list'">
16
- <slot name="component-list-panel"></slot>
16
+ <template #layer-panel-header v-if="data === 'layer' || config.slots?.layerPanelHeader">
17
+ <slot v-if="data === 'layer'" name="layer-panel-header"></slot>
18
+ <component v-else-if="config.slots?.layerPanelHeader" :is="config.slots.layerPanelHeader" />
17
19
  </template>
18
20
 
19
21
  <template #layer-node-content="{ data, node }" v-if="config.slots?.layerNodeContent">
@@ -25,7 +27,7 @@
25
27
 
26
28
  <script lang="ts">
27
29
  import { computed, defineComponent, PropType } from 'vue';
28
- import { Coin, Files } from '@element-plus/icons';
30
+ import { Coin, Files } from '@element-plus/icons-vue';
29
31
 
30
32
  import MIcon from '@editor/components/Icon.vue';
31
33
  import { SideComponent, SideItem } from '@editor/type';
@@ -70,7 +70,7 @@ import {
70
70
  toRaw,
71
71
  watch,
72
72
  } from 'vue';
73
- import { ArrowLeftBold, ArrowRightBold, CaretBottom, Delete, DocumentCopy, Plus } from '@element-plus/icons';
73
+ import { ArrowLeftBold, ArrowRightBold, CaretBottom, Delete, DocumentCopy, Plus } from '@element-plus/icons-vue';
74
74
 
75
75
  import type { MApp, MPage } from '@tmagic/schema';
76
76
  import { NodeType } from '@tmagic/schema';
@@ -35,8 +35,15 @@ import {
35
35
  } from 'vue';
36
36
  import { cloneDeep } from 'lodash-es';
37
37
 
38
- import type { MApp, MNode, MPage } from '@tmagic/schema';
39
- import StageCore, { GuidesType, Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
38
+ import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
39
+ import StageCore, {
40
+ calcValueByFontsize,
41
+ getOffset,
42
+ GuidesType,
43
+ Runtime,
44
+ SortEventData,
45
+ UpdateEventData,
46
+ } from '@tmagic/stage';
40
47
 
41
48
  import ScrollViewer from '@editor/components/ScrollViewer.vue';
42
49
  import {
@@ -90,6 +97,9 @@ export default defineComponent({
90
97
  runtimeUrl: stageOptions.runtimeUrl,
91
98
  zoom: zoom.value,
92
99
  autoScrollIntoView: stageOptions.autoScrollIntoView,
100
+ isContainer: stageOptions.isContainer,
101
+ containerHighlightClassName: stageOptions.containerHighlightClassName,
102
+ containerHighlightDuration: stageOptions.containerHighlightDuration,
93
103
  canSelect: (el, event, stop) => {
94
104
  const elCanSelect = stageOptions.canSelect(el);
95
105
  // 在组件联动过程中不能再往下选择,返回并触发 ui-select
@@ -122,6 +132,10 @@ export default defineComponent({
122
132
  });
123
133
 
124
134
  stage?.on('update', (ev: UpdateEventData) => {
135
+ if (ev.parentEl) {
136
+ services?.editorService.moveToContainer({ id: ev.el.id, style: ev.style }, ev.parentEl.id);
137
+ return;
138
+ }
125
139
  services?.editorService.update({ id: ev.el.id, style: ev.style });
126
140
  });
127
141
 
@@ -207,23 +221,50 @@ export default defineComponent({
207
221
 
208
222
  async dropHandler(e: DragEvent) {
209
223
  e.preventDefault();
210
- if (e.dataTransfer && page.value && stageContainer.value && stage) {
224
+
225
+ const doc = stage?.renderer.contentWindow?.document;
226
+ const parentEl: HTMLElement | null | undefined = doc?.querySelector(
227
+ `.${stageOptions?.containerHighlightClassName}`,
228
+ );
229
+
230
+ let parent: MContainer | undefined = page.value;
231
+ if (parentEl) {
232
+ parent = services?.editorService.getNodeById(parentEl.id, false) as MContainer;
233
+ }
234
+
235
+ if (e.dataTransfer && parent && stageContainer.value && stage) {
211
236
  // eslint-disable-next-line no-eval
212
237
  const config = eval(`(${e.dataTransfer.getData('data')})`);
213
- const layout = await services?.editorService.getLayout(page.value);
238
+ const layout = await services?.editorService.getLayout(parent);
214
239
 
215
240
  const containerRect = stageContainer.value.getBoundingClientRect();
216
241
  const { scrollTop, scrollLeft } = stage.mask;
242
+ const { style = {} } = config;
243
+
244
+ let top = 0;
245
+ let left = 0;
246
+ let position = 'relative';
247
+
217
248
  if (layout === Layout.ABSOLUTE) {
218
- config.style = {
219
- ...(config.style || {}),
220
- position: 'absolute',
221
- top: e.clientY - containerRect.top + scrollTop,
222
- left: e.clientX - containerRect.left + scrollLeft,
223
- };
249
+ position = 'absolute';
250
+ top = e.clientY - containerRect.top + scrollTop;
251
+ left = e.clientX - containerRect.left + scrollLeft;
252
+
253
+ if (parentEl && doc) {
254
+ const { left: parentLeft, top: parentTop } = getOffset(parentEl);
255
+ left = left - calcValueByFontsize(doc, parentLeft);
256
+ top = top - calcValueByFontsize(doc, parentTop);
257
+ }
224
258
  }
225
259
 
226
- services?.editorService.add(config, page.value);
260
+ config.style = {
261
+ ...style,
262
+ position,
263
+ top,
264
+ left,
265
+ };
266
+
267
+ services?.editorService.add(config, parent);
227
268
  }
228
269
  },
229
270
  };
@@ -4,7 +4,7 @@
4
4
 
5
5
  <script lang="ts">
6
6
  import { computed, defineComponent, inject, markRaw, onMounted, reactive, ref, watch } from 'vue';
7
- import { Bottom, Delete, DocumentCopy, Top } from '@element-plus/icons';
7
+ import { Bottom, Delete, DocumentCopy, Top } from '@element-plus/icons-vue';
8
8
 
9
9
  import { NodeType } from '@tmagic/schema';
10
10
  import type StageCore from '@tmagic/stage';