@tmagic/editor 1.0.0-rc.1 → 1.0.0-rc.12

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 (96) hide show
  1. package/dist/style.css +7 -3
  2. package/dist/tmagic-editor.es.js +304 -1405
  3. package/dist/tmagic-editor.es.js.map +1 -1
  4. package/dist/tmagic-editor.umd.js +304 -1407
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/dist/types/src/Editor.vue.d.ts +42 -1
  7. package/dist/types/src/fields/Code.vue.d.ts +4 -4
  8. package/dist/types/src/fields/CodeLink.vue.d.ts +1 -3
  9. package/dist/types/src/layouts/Framework.vue.d.ts +15 -3
  10. package/dist/types/src/layouts/PropsPanel.vue.d.ts +2 -4
  11. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +3 -27
  12. package/dist/types/src/services/BaseService.d.ts +1 -1
  13. package/dist/types/src/services/editor.d.ts +6 -3
  14. package/dist/types/src/services/history.d.ts +1 -18
  15. package/dist/types/src/services/props.d.ts +8 -2
  16. package/dist/types/src/type.d.ts +9 -0
  17. package/dist/types/src/utils/editor.d.ts +0 -6
  18. package/dist/types/src/utils/props.d.ts +10 -1
  19. package/package.json +17 -18
  20. package/src/Editor.vue +41 -9
  21. package/src/components/ContentMenu.vue +59 -26
  22. package/src/layouts/CodeEditor.vue +1 -4
  23. package/src/layouts/Framework.vue +14 -1
  24. package/src/layouts/PropsPanel.vue +1 -1
  25. package/src/layouts/sidebar/LayerMenu.vue +3 -0
  26. package/src/layouts/sidebar/TabPane.vue +1 -1
  27. package/src/layouts/workspace/Stage.vue +14 -31
  28. package/src/layouts/workspace/ViewerMenu.vue +17 -2
  29. package/src/layouts/workspace/Workspace.vue +21 -26
  30. package/src/services/BaseService.ts +1 -1
  31. package/src/services/editor.ts +49 -14
  32. package/src/services/props.ts +64 -9
  33. package/src/theme/page-bar.scss +1 -0
  34. package/src/theme/props-panel.scss +6 -4
  35. package/src/theme/workspace.scss +4 -0
  36. package/src/type.ts +10 -0
  37. package/src/utils/editor.ts +7 -52
  38. package/src/utils/polyfills.ts +5 -19
  39. package/src/utils/props.ts +31 -7
  40. package/LICENSE +0 -5432
  41. package/coverage/clover.xml +0 -1560
  42. package/coverage/coverage-final.json +0 -36
  43. package/coverage/lcov-report/base.css +0 -224
  44. package/coverage/lcov-report/block-navigation.js +0 -87
  45. package/coverage/lcov-report/favicon.png +0 -0
  46. package/coverage/lcov-report/index.html +0 -206
  47. package/coverage/lcov-report/prettify.css +0 -1
  48. package/coverage/lcov-report/prettify.js +0 -2
  49. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  50. package/coverage/lcov-report/sorter.js +0 -196
  51. package/coverage/lcov-report/src/Editor.vue.html +0 -787
  52. package/coverage/lcov-report/src/components/ContentMenu.vue.html +0 -406
  53. package/coverage/lcov-report/src/components/Icon.vue.html +0 -172
  54. package/coverage/lcov-report/src/components/ScrollViewer.vue.html +0 -283
  55. package/coverage/lcov-report/src/components/ToolButton.vue.html +0 -772
  56. package/coverage/lcov-report/src/components/index.html +0 -161
  57. package/coverage/lcov-report/src/index.html +0 -131
  58. package/coverage/lcov-report/src/layouts/AddPageBox.vue.html +0 -214
  59. package/coverage/lcov-report/src/layouts/Framework.vue.html +0 -304
  60. package/coverage/lcov-report/src/layouts/NavMenu.vue.html +0 -208
  61. package/coverage/lcov-report/src/layouts/PropsPanel.vue.html +0 -319
  62. package/coverage/lcov-report/src/layouts/Resizer.vue.html +0 -268
  63. package/coverage/lcov-report/src/layouts/index.html +0 -176
  64. package/coverage/lcov-report/src/layouts/sidebar/ComponentListPanel.vue.html +0 -358
  65. package/coverage/lcov-report/src/layouts/sidebar/LayerMenu.vue.html +0 -421
  66. package/coverage/lcov-report/src/layouts/sidebar/LayerPanel.vue.html +0 -775
  67. package/coverage/lcov-report/src/layouts/sidebar/Sidebar.vue.html +0 -226
  68. package/coverage/lcov-report/src/layouts/sidebar/TabPane.vue.html +0 -289
  69. package/coverage/lcov-report/src/layouts/sidebar/index.html +0 -176
  70. package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +0 -718
  71. package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +0 -757
  72. package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +0 -532
  73. package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +0 -586
  74. package/coverage/lcov-report/src/layouts/workspace/index.html +0 -161
  75. package/coverage/lcov-report/src/services/BaseService.ts.html +0 -643
  76. package/coverage/lcov-report/src/services/componentList.ts.html +0 -229
  77. package/coverage/lcov-report/src/services/editor.ts.html +0 -2077
  78. package/coverage/lcov-report/src/services/events.ts.html +0 -331
  79. package/coverage/lcov-report/src/services/history.ts.html +0 -478
  80. package/coverage/lcov-report/src/services/index.html +0 -206
  81. package/coverage/lcov-report/src/services/props.ts.html +0 -415
  82. package/coverage/lcov-report/src/services/ui.ts.html +0 -580
  83. package/coverage/lcov-report/src/type.ts.html +0 -850
  84. package/coverage/lcov-report/src/utils/compose.ts.html +0 -184
  85. package/coverage/lcov-report/src/utils/config.ts.html +0 -172
  86. package/coverage/lcov-report/src/utils/editor.ts.html +0 -838
  87. package/coverage/lcov-report/src/utils/index.html +0 -221
  88. package/coverage/lcov-report/src/utils/index.ts.html +0 -151
  89. package/coverage/lcov-report/src/utils/logger.ts.html +0 -226
  90. package/coverage/lcov-report/src/utils/props.ts.html +0 -796
  91. package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +0 -733
  92. package/coverage/lcov-report/src/utils/undo-redo.ts.html +0 -313
  93. package/coverage/lcov.info +0 -3708
  94. package/dist/types/src/components/ToolButton.vue.d.ts +0 -46
  95. package/dist/types/src/fields/UISelect.vue.d.ts +0 -35
  96. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +0 -18
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div v-if="menuData.length" v-show="visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
2
+ <div v-if="menuData.length && visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
3
3
  <div>
4
4
  <tool-button
5
5
  v-for="(item, index) in menuData"
@@ -11,13 +11,19 @@
11
11
  ></tool-button>
12
12
  </div>
13
13
  <teleport to="body">
14
- <content-menu class="sub-menu" ref="subMenu" :menu-data="subMenuData"></content-menu>
14
+ <content-menu
15
+ class="sub-menu"
16
+ ref="subMenu"
17
+ :menu-data="subMenuData"
18
+ :is-sub-menu="true"
19
+ @hide="hide"
20
+ ></content-menu>
15
21
  </teleport>
16
22
  </div>
17
23
  </template>
18
24
 
19
25
  <script lang="ts">
20
- import { defineComponent, nextTick, onMounted, PropType, ref } from 'vue';
26
+ import { defineComponent, nextTick, onMounted, onUnmounted, PropType, ref } from 'vue';
21
27
 
22
28
  import { MenuButton, MenuItem } from '@editor/type';
23
29
 
@@ -31,9 +37,16 @@ export default defineComponent({
31
37
  type: Array as PropType<MenuItem[]>,
32
38
  default: () => [],
33
39
  },
40
+
41
+ isSubMenu: {
42
+ type: Boolean,
43
+ default: false,
44
+ },
34
45
  },
35
46
 
36
- setup() {
47
+ emits: ['hide', 'show'],
48
+
49
+ setup(props, { emit }) {
37
50
  const menu = ref<HTMLDivElement>();
38
51
  const subMenu = ref<any>();
39
52
  const visible = ref(false);
@@ -44,20 +57,35 @@ export default defineComponent({
44
57
  });
45
58
 
46
59
  const hide = () => {
60
+ if (!visible.value) return;
61
+
47
62
  visible.value = false;
63
+ subMenu.value?.hide();
64
+
65
+ emit('hide');
66
+ };
67
+
68
+ const hideHandler = (e: MouseEvent) => {
69
+ const target = e.target as HTMLElement | undefined;
70
+ if (!visible.value || !target) {
71
+ return;
72
+ }
73
+ if (menu.value?.contains(target) || subMenu.value?.$el?.contains(target)) {
74
+ return;
75
+ }
76
+ hide();
48
77
  };
49
78
 
50
79
  onMounted(() => {
51
- globalThis.addEventListener(
52
- 'mousedown',
53
- (e: MouseEvent) => {
54
- if (!visible.value || (e.target && menu.value?.contains(e.target as HTMLElement))) {
55
- return;
56
- }
57
- hide();
58
- },
59
- true,
60
- );
80
+ if (props.isSubMenu) return;
81
+
82
+ globalThis.addEventListener('mousedown', hideHandler, true);
83
+ });
84
+
85
+ onUnmounted(() => {
86
+ if (props.isSubMenu) return;
87
+
88
+ globalThis.removeEventListener('mousedown', hideHandler, true);
61
89
  });
62
90
 
63
91
  return {
@@ -70,21 +98,26 @@ export default defineComponent({
70
98
  hide,
71
99
 
72
100
  show(e: MouseEvent) {
73
- visible.value = true;
101
+ // 加settimeout是以为,如果菜单中的按钮监听的是mouseup,那么菜单显示出来时鼠标如果正好在菜单上就会马上触发按钮的mouseup
102
+ setTimeout(() => {
103
+ visible.value = true;
104
+
105
+ nextTick(() => {
106
+ const menuHeight = menu.value?.clientHeight || 0;
74
107
 
75
- nextTick(() => {
76
- const menuHeight = menu.value?.clientHeight || 0;
108
+ let top = e.clientY;
109
+ if (menuHeight + e.clientY > document.body.clientHeight) {
110
+ top = document.body.clientHeight - menuHeight;
111
+ }
77
112
 
78
- let top = e.clientY;
79
- if (menuHeight + e.clientY > document.body.clientHeight) {
80
- top = document.body.clientHeight - menuHeight;
81
- }
113
+ menuStyle.value = {
114
+ top: `${top}px`,
115
+ left: `${e.clientX}px`,
116
+ };
82
117
 
83
- menuStyle.value = {
84
- top: `${top}px`,
85
- left: `${e.clientX}px`,
86
- };
87
- });
118
+ emit('show');
119
+ });
120
+ }, 300);
88
121
  },
89
122
 
90
123
  showSubMenu(item: MenuItem) {
@@ -94,11 +94,7 @@ export default defineComponent({
94
94
  const options = {
95
95
  value: values.value,
96
96
  language: props.language,
97
- tabSize: 2,
98
97
  theme: 'vs-dark',
99
- fontFamily: 'dm, Menlo, Monaco, "Courier New", monospace',
100
- fontSize: 14,
101
- formatOnPaste: true,
102
98
  ...props.options,
103
99
  };
104
100
 
@@ -117,6 +113,7 @@ export default defineComponent({
117
113
  codeEditor.value.addEventListener('keydown', (e) => {
118
114
  if (e.keyCode === 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
119
115
  e.preventDefault();
116
+ e.stopPropagation();
120
117
  emit('save', getEditorValue());
121
118
  }
122
119
  });
@@ -2,7 +2,13 @@
2
2
  <div class="m-editor">
3
3
  <slot name="nav" class="m-editor-nav-menu"></slot>
4
4
 
5
- <magic-code-editor v-if="showSrc" class="m-editor-content" :init-values="root" @save="saveCode"></magic-code-editor>
5
+ <magic-code-editor
6
+ v-if="showSrc"
7
+ class="m-editor-content"
8
+ :init-values="root"
9
+ :options="codeOptions"
10
+ @save="saveCode"
11
+ ></magic-code-editor>
6
12
 
7
13
  <div class="m-editor-content" v-else>
8
14
  <div class="m-editor-framework-left" :style="`width: ${columnWidth?.left}px`">
@@ -48,6 +54,13 @@ export default defineComponent({
48
54
  Resizer,
49
55
  },
50
56
 
57
+ props: {
58
+ codeOptions: {
59
+ type: Object,
60
+ default: () => ({}),
61
+ },
62
+ },
63
+
51
64
  setup() {
52
65
  const { editorService, uiService } = inject<Services>('services') || {};
53
66
 
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <m-form
3
3
  :class="`m-editor-props-panel ${propsPanelSize}`"
4
- popper-class="m-editor-props-panel-popper"
4
+ :popper-class="`m-editor-props-panel-popper ${propsPanelSize}`"
5
5
  ref="configForm"
6
6
  :size="propsPanelSize"
7
7
  :init-values="values"
@@ -22,6 +22,8 @@ export default defineComponent({
22
22
  const isPage = computed(() => node.value?.type === NodeType.PAGE);
23
23
  const componentList = computed(() => services?.componentListService.getList() || []);
24
24
 
25
+ const layerContentMenu = inject<MenuItem[]>('layerContentMenu', []);
26
+
25
27
  const createMenuItems = (group: ComponentGroup): MenuButton[] =>
26
28
  group.items.map((component) => ({
27
29
  text: component.text,
@@ -101,6 +103,7 @@ export default defineComponent({
101
103
  node.value && services?.editorService.remove(node.value);
102
104
  },
103
105
  },
106
+ ...layerContentMenu,
104
107
  ]),
105
108
 
106
109
  show(e: MouseEvent) {
@@ -30,7 +30,7 @@ export default defineComponent({
30
30
 
31
31
  props: {
32
32
  data: {
33
- type: Object as PropType<SideItem>,
33
+ type: [Object, String] as PropType<SideItem>,
34
34
  },
35
35
  },
36
36
 
@@ -28,7 +28,6 @@ import {
28
28
  markRaw,
29
29
  onMounted,
30
30
  onUnmounted,
31
- PropType,
32
31
  ref,
33
32
  toRaw,
34
33
  watch,
@@ -37,11 +36,11 @@ import {
37
36
  import { cloneDeep } from 'lodash-es';
38
37
 
39
38
  import type { MApp, MNode, MPage } from '@tmagic/schema';
40
- import type { MoveableOptions, Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
39
+ import type { Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
41
40
  import StageCore from '@tmagic/stage';
42
41
 
43
42
  import ScrollViewer from '@editor/components/ScrollViewer.vue';
44
- import { Layout, Services, StageRect } from '@editor/type';
43
+ import { Layout, Services, StageOptions, StageRect } from '@editor/type';
45
44
 
46
45
  import ViewerMenu from './ViewerMenu.vue';
47
46
 
@@ -53,28 +52,9 @@ export default defineComponent({
53
52
  ScrollViewer,
54
53
  },
55
54
 
56
- props: {
57
- render: {
58
- type: Function as PropType<() => HTMLDivElement>,
59
- },
60
-
61
- runtimeUrl: String,
62
-
63
- canSelect: {
64
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
65
- default: (el: HTMLElement) => Boolean(el.id),
66
- },
67
-
68
- moveableOptions: {
69
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
70
- default: () => (core?: StageCore) => ({
71
- container: core?.renderer?.contentWindow?.document.getElementById('app'),
72
- }),
73
- },
74
- },
75
-
76
- setup(props) {
55
+ setup() {
77
56
  const services = inject<Services>('services');
57
+ const stageOptions = inject<StageOptions>('stageOptions');
78
58
 
79
59
  const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
80
60
  const stageContainer = ref<HTMLDivElement>();
@@ -94,14 +74,15 @@ export default defineComponent({
94
74
  if (stage) return;
95
75
 
96
76
  if (!stageContainer.value) return;
97
- if (!(props.runtimeUrl || props.render) || !root.value) return;
77
+ if (!(stageOptions?.runtimeUrl || stageOptions?.render) || !root.value) return;
98
78
 
99
79
  stage = new StageCore({
100
- render: props.render,
101
- runtimeUrl: props.runtimeUrl,
80
+ render: stageOptions.render,
81
+ runtimeUrl: stageOptions.runtimeUrl,
102
82
  zoom: zoom.value,
83
+ autoScrollIntoView: stageOptions.autoScrollIntoView,
103
84
  canSelect: (el, event, stop) => {
104
- const elCanSelect = props.canSelect(el);
85
+ const elCanSelect = stageOptions.canSelect(el);
105
86
  // 在组件联动过程中不能再往下选择,返回并触发 ui-select
106
87
  if (uiSelectMode.value && elCanSelect && event.type === 'mousedown') {
107
88
  document.dispatchEvent(new CustomEvent('ui-select', { detail: el }));
@@ -110,7 +91,8 @@ export default defineComponent({
110
91
 
111
92
  return elCanSelect;
112
93
  },
113
- moveableOptions: props.moveableOptions,
94
+ moveableOptions: stageOptions.moveableOptions,
95
+ updateDragEl: stageOptions.updateDragEl,
114
96
  });
115
97
 
116
98
  services?.editorService.set('stage', markRaw(stage));
@@ -141,7 +123,7 @@ export default defineComponent({
141
123
  stage?.on('runtime-ready', (rt) => {
142
124
  runtime = rt;
143
125
  // toRaw返回的值是一个引用而非快照,需要cloneDeep
144
- root.value && runtime?.updateRootConfig(cloneDeep(toRaw(root.value)));
126
+ root.value && runtime?.updateRootConfig?.(cloneDeep(toRaw(root.value)));
145
127
  page.value?.id && runtime?.updatePageId?.(page.value.id);
146
128
  setTimeout(() => {
147
129
  node.value && stage?.select(toRaw(node.value.id));
@@ -156,7 +138,7 @@ export default defineComponent({
156
138
 
157
139
  watch(root, (root) => {
158
140
  if (runtime && root) {
159
- runtime.updateRootConfig(cloneDeep(toRaw(root)));
141
+ runtime.updateRootConfig?.(cloneDeep(toRaw(root)));
160
142
  }
161
143
  });
162
144
 
@@ -209,6 +191,7 @@ export default defineComponent({
209
191
  const { scrollTop, scrollLeft } = stage.mask;
210
192
  if (layout === Layout.ABSOLUTE) {
211
193
  config.style = {
194
+ ...(config.style || {}),
212
195
  position: 'absolute',
213
196
  top: e.clientY - containerRect.top + scrollTop,
214
197
  left: e.clientX - containerRect.left + scrollLeft,
@@ -27,6 +27,8 @@ export default defineComponent({
27
27
  const parent = computed(() => editorService?.get('parent'));
28
28
  const isPage = computed(() => node.value?.type === NodeType.PAGE);
29
29
 
30
+ const stageContentMenu = inject<MenuItem[]>('stageContentMenu', []);
31
+
30
32
  onMounted(() => {
31
33
  const data = globalThis.localStorage.getItem(COPY_STORAGE_KEY);
32
34
  canPaste.value = data !== 'undefined' && !!data;
@@ -69,8 +71,20 @@ export default defineComponent({
69
71
  text: '粘贴',
70
72
  display: () => canPaste.value,
71
73
  handler: () => {
72
- const top = menu.value?.$el.offsetTop || 0;
73
- const left = menu.value?.$el.offsetLeft || 0;
74
+ const stage = editorService?.get<StageCore>('stage');
75
+
76
+ const rect = menu.value?.$el.getBoundingClientRect();
77
+ const parentRect = stage?.container?.getBoundingClientRect();
78
+ let left = (rect?.left || 0) - (parentRect?.left || 0);
79
+ let top = (rect?.top || 0) - (parentRect?.top || 0);
80
+
81
+ if (node.value?.items && stage) {
82
+ const parentEl = stage.renderer.contentWindow?.document.getElementById(`${node.value.id}`);
83
+ const parentElRect = parentEl?.getBoundingClientRect();
84
+ left = left - (parentElRect?.left || 0);
85
+ top = top - (parentElRect?.top || 0);
86
+ }
87
+
74
88
  editorService?.paste({ left, top });
75
89
  },
76
90
  },
@@ -138,6 +152,7 @@ export default defineComponent({
138
152
  editorService?.get<StageCore>('stage').clearGuides();
139
153
  },
140
154
  },
155
+ ...stageContentMenu,
141
156
  ]),
142
157
 
143
158
  show(e: MouseEvent) {
@@ -1,12 +1,6 @@
1
1
  <template>
2
2
  <div class="m-editor-workspace" tabindex="1" ref="workspace">
3
- <magic-stage
4
- :key="page?.id"
5
- :runtime-url="runtimeUrl"
6
- :render="render"
7
- :moveable-options="moveableOptions"
8
- :can-select="canSelect"
9
- ></magic-stage>
3
+ <magic-stage :key="page?.id"></magic-stage>
10
4
 
11
5
  <slot name="workspace-content"></slot>
12
6
 
@@ -18,12 +12,10 @@
18
12
  </template>
19
13
 
20
14
  <script lang="ts">
21
- import { computed, defineComponent, inject, onMounted, onUnmounted, PropType, ref } from 'vue';
15
+ import { computed, defineComponent, inject, onMounted, onUnmounted, ref } from 'vue';
22
16
  import KeyController from 'keycon';
23
17
 
24
18
  import type { MNode, MPage } from '@tmagic/schema';
25
- import type { MoveableOptions } from '@tmagic/stage';
26
- import StageCore from '@tmagic/stage';
27
19
  import { isPage } from '@tmagic/utils';
28
20
 
29
21
  import type { Services } from '@editor/type';
@@ -39,22 +31,6 @@ export default defineComponent({
39
31
  MagicStage,
40
32
  },
41
33
 
42
- props: {
43
- runtimeUrl: String,
44
-
45
- render: {
46
- type: Function as PropType<() => HTMLDivElement>,
47
- },
48
-
49
- moveableOptions: {
50
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
51
- },
52
-
53
- canSelect: {
54
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
55
- },
56
- },
57
-
58
34
  setup() {
59
35
  const services = inject<Services>('services');
60
36
  const workspace = ref<HTMLDivElement>();
@@ -65,8 +41,13 @@ export default defineComponent({
65
41
  workspace.value?.focus();
66
42
  };
67
43
 
44
+ const mouseleaveHandler = () => {
45
+ workspace.value?.blur();
46
+ };
47
+
68
48
  onMounted(() => {
69
49
  workspace.value?.addEventListener('mouseenter', mouseenterHandler);
50
+ workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
70
51
 
71
52
  keycon = new KeyController(workspace.value);
72
53
 
@@ -80,6 +61,11 @@ export default defineComponent({
80
61
  if (!node.value || isPage(node.value)) return;
81
62
  services?.editorService.remove(node.value);
82
63
  })
64
+ .keyup('backspace', (e) => {
65
+ e.inputEvent.preventDefault();
66
+ if (!node.value || isPage(node.value)) return;
67
+ services?.editorService.remove(node.value);
68
+ })
83
69
  .keydown([ctrl, 'c'], (e) => {
84
70
  e.inputEvent.preventDefault();
85
71
  node.value && services?.editorService.copy(node.value);
@@ -146,14 +132,23 @@ export default defineComponent({
146
132
  e.inputEvent.preventDefault();
147
133
  services?.uiService.zoom(0.1);
148
134
  })
135
+ .keydown([ctrl, 'numpadplus'], (e) => {
136
+ e.inputEvent.preventDefault();
137
+ services?.uiService.zoom(0.1);
138
+ })
149
139
  .keydown([ctrl, '-'], (e) => {
150
140
  e.inputEvent.preventDefault();
151
141
  services?.uiService.zoom(-0.1);
142
+ })
143
+ .keydown([ctrl, 'numpad-'], (e) => {
144
+ e.inputEvent.preventDefault();
145
+ services?.uiService.zoom(-0.1);
152
146
  });
153
147
  });
154
148
 
155
149
  onUnmounted(() => {
156
150
  workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
151
+ workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
157
152
  keycon.destroy();
158
153
  });
159
154
 
@@ -91,7 +91,7 @@ const doAction = async (
91
91
  * editorService.afterAdd();
92
92
  * }
93
93
  *
94
- * 调用时的参数会透传到before方法的参数中, 然后before的return 会作为原方法的参数和after的参数,after最后一个参数则是原方法的return值;
94
+ * 调用时的参数会透传到before方法的参数中, 然后before的return 会作为原方法的参数和after的参数,after第一个参数则是原方法的return值;
95
95
  * 如需终止后续方法调用可以return new Error();
96
96
  *
97
97
  * 方法2:
@@ -33,11 +33,11 @@ import {
33
33
  change2Fixed,
34
34
  COPY_STORAGE_KEY,
35
35
  Fixed2Other,
36
+ generatePageNameByApp,
36
37
  getNodeIndex,
37
38
  initPosition,
38
39
  isFixed,
39
40
  setLayout,
40
- setNewItemId,
41
41
  } from '@editor/utils/editor';
42
42
  import { log } from '@editor/utils/logger';
43
43
 
@@ -108,10 +108,14 @@ class Editor extends BaseService {
108
108
  /**
109
109
  * 根据id获取组件、组件的父组件以及组件所属的页面节点
110
110
  * @param {number | string} id 组件id
111
+ * @param {boolean} raw 是否使用toRaw
111
112
  * @returns {EditorNodeInfo}
112
113
  */
113
- public getNodeInfo(id: Id): EditorNodeInfo {
114
- const root = toRaw(this.get<MApp | null>('root'));
114
+ public getNodeInfo(id: Id, raw = true): EditorNodeInfo {
115
+ let root = this.get<MApp | null>('root');
116
+ if (raw) {
117
+ root = toRaw(root);
118
+ }
115
119
  if (!root) return {};
116
120
 
117
121
  if (id === root.id) {
@@ -141,21 +145,23 @@ class Editor extends BaseService {
141
145
  /**
142
146
  * 根据ID获取指点节点配置
143
147
  * @param id 组件ID
148
+ * @param {boolean} raw 是否使用toRaw
144
149
  * @returns 组件节点配置
145
150
  */
146
- public getNodeById(id: Id): MNode | undefined {
147
- const { node } = this.getNodeInfo(id);
151
+ public getNodeById(id: Id, raw = true): MNode | undefined {
152
+ const { node } = this.getNodeInfo(id, raw);
148
153
  return node;
149
154
  }
150
155
 
151
156
  /**
152
157
  * 根据ID获取指点节点的父节点配置
153
158
  * @param id 组件ID
159
+ * @param {boolean} raw 是否使用toRaw
154
160
  * @returns 指点组件的父节点配置
155
161
  */
156
- public getParentById(id: Id): MContainer | undefined {
162
+ public getParentById(id: Id, raw = true): MContainer | undefined {
157
163
  if (!this.get<MApp | null>('root')) return;
158
- const { parent } = this.getNodeInfo(id);
164
+ const { parent } = this.getNodeInfo(id, raw);
159
165
  return parent;
160
166
  }
161
167
 
@@ -194,6 +200,20 @@ class Editor extends BaseService {
194
200
  historyService.empty();
195
201
  }
196
202
 
203
+ if (node?.id) {
204
+ this.get<StageCore>('stage')
205
+ ?.renderer.runtime?.getApp?.()
206
+ ?.emit(
207
+ 'editor:select',
208
+ {
209
+ node,
210
+ page,
211
+ parent,
212
+ },
213
+ getNodePath(node.id, this.get<MApp>('root').items),
214
+ );
215
+ }
216
+
197
217
  this.emit('select', node);
198
218
 
199
219
  return node!;
@@ -265,7 +285,7 @@ class Editor extends BaseService {
265
285
  } else if (curNode.items) {
266
286
  parentNode = curNode;
267
287
  } else {
268
- parentNode = this.getParentById(curNode.id);
288
+ parentNode = this.getParentById(curNode.id, false);
269
289
  }
270
290
 
271
291
  if (!parentNode) throw new Error('未找到父元素');
@@ -318,7 +338,7 @@ class Editor extends BaseService {
318
338
 
319
339
  if (!root) throw new Error('没有root');
320
340
 
321
- const { parent, node: curNode } = this.getNodeInfo(node.id);
341
+ const { parent, node: curNode } = this.getNodeInfo(node.id, false);
322
342
 
323
343
  if (!parent || !curNode) throw new Error('找不要删除的节点');
324
344
 
@@ -370,7 +390,7 @@ class Editor extends BaseService {
370
390
  public async update(config: MNode): Promise<MNode> {
371
391
  if (!config?.id) throw new Error('没有配置或者配置缺少id值');
372
392
 
373
- const info = this.getNodeInfo(config.id);
393
+ const info = this.getNodeInfo(config.id, false);
374
394
 
375
395
  if (!info.node) throw new Error(`获取不到id为${config.id}的节点`);
376
396
 
@@ -480,7 +500,7 @@ class Editor extends BaseService {
480
500
  return;
481
501
  }
482
502
 
483
- setNewItemId(config, this.get('root'));
503
+ await propsService.setNewItemId(config, this.get('root'));
484
504
  if (config.style) {
485
505
  config.style = {
486
506
  ...config.style,
@@ -488,6 +508,10 @@ class Editor extends BaseService {
488
508
  };
489
509
  }
490
510
 
511
+ if (isPage(config)) {
512
+ config.name = generatePageNameByApp(this.get('root'));
513
+ }
514
+
491
515
  return await this.add(config);
492
516
  }
493
517
 
@@ -504,7 +528,18 @@ class Editor extends BaseService {
504
528
  return;
505
529
  }
506
530
 
507
- if (parent.style?.width && node.style?.width) {
531
+ if (!node.style) return;
532
+
533
+ const stage = this.get<StageCore>('stage');
534
+ const doc = stage?.renderer.contentWindow?.document;
535
+
536
+ if (doc) {
537
+ const parentEl = doc.getElementById(`${parent.id}`);
538
+ const el = doc.getElementById(`${node.id}`);
539
+ if (parentEl && el) {
540
+ node.style.left = (parentEl.clientWidth - el.clientWidth) / 2;
541
+ }
542
+ } else if (parent.style && isNumber(parent.style?.width) && isNumber(node.style?.width)) {
508
543
  node.style.left = (parent.style.width - node.style.width) / 2;
509
544
  }
510
545
 
@@ -526,9 +561,9 @@ class Editor extends BaseService {
526
561
  const brothers: MNode[] = parent?.items || [];
527
562
  const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
528
563
 
529
- if (offset === LayerOffset.BOTTOM) {
564
+ if (offset === LayerOffset.TOP) {
530
565
  brothers.splice(brothers.length - 1, 0, brothers.splice(index, 1)[0]);
531
- } else if (offset === LayerOffset.TOP) {
566
+ } else if (offset === LayerOffset.BOTTOM) {
532
567
  brothers.splice(0, 0, brothers.splice(index, 1)[0]);
533
568
  } else {
534
569
  brothers.splice(index + parseInt(`${offset}`, 10), 0, brothers.splice(index, 1)[0]);