@tmagic/editor 1.0.0-beta.13 → 1.0.0-beta.16

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 (101) hide show
  1. package/coverage/clover.xml +703 -601
  2. package/coverage/coverage-final.json +35 -33
  3. package/coverage/lcov-report/index.html +56 -56
  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 +23 -140
  21. package/coverage/lcov-report/{utils/undo-redo.ts.html → src/layouts/sidebar/TabPane.vue.html} +94 -118
  22. package/coverage/lcov-report/src/layouts/sidebar/index.html +64 -49
  23. package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +99 -12
  24. package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +86 -95
  25. package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +208 -97
  26. package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +3 -3
  27. package/coverage/lcov-report/src/layouts/workspace/index.html +35 -35
  28. package/coverage/lcov-report/src/services/BaseService.ts.html +11 -11
  29. package/coverage/lcov-report/src/services/componentList.ts.html +1 -1
  30. package/coverage/lcov-report/src/services/editor.ts.html +103 -10
  31. package/coverage/lcov-report/src/services/events.ts.html +1 -1
  32. package/coverage/lcov-report/src/services/history.ts.html +29 -8
  33. package/coverage/lcov-report/src/services/index.html +25 -25
  34. package/coverage/lcov-report/src/services/props.ts.html +4 -7
  35. package/coverage/lcov-report/src/services/ui.ts.html +1 -1
  36. package/coverage/lcov-report/src/type.ts.html +8 -14
  37. package/coverage/lcov-report/src/utils/compose.ts.html +4 -4
  38. package/coverage/lcov-report/src/utils/config.ts.html +1 -1
  39. package/coverage/lcov-report/src/utils/editor.ts.html +2 -2
  40. package/coverage/lcov-report/src/utils/index.html +1 -1
  41. package/coverage/lcov-report/src/utils/index.ts.html +1 -1
  42. package/coverage/lcov-report/src/utils/logger.ts.html +1 -1
  43. package/coverage/lcov-report/src/utils/props.ts.html +59 -2
  44. package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +1 -1
  45. package/coverage/lcov-report/src/utils/undo-redo.ts.html +1 -1
  46. package/coverage/lcov.info +1679 -1402
  47. package/dist/style.css +47 -20
  48. package/dist/tmagic-editor.es.js +732 -485
  49. package/dist/tmagic-editor.es.js.map +1 -1
  50. package/dist/tmagic-editor.umd.js +733 -485
  51. package/dist/tmagic-editor.umd.js.map +1 -1
  52. package/dist/types/src/Editor.vue.d.ts +1 -1
  53. package/dist/types/src/components/ToolButton.vue.d.ts +12 -1
  54. package/dist/types/src/fields/UISelect.vue.d.ts +4 -1
  55. package/dist/types/src/index.d.ts +1 -0
  56. package/dist/types/src/layouts/CodeEditor.vue.d.ts +13 -4
  57. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -0
  58. package/dist/types/src/layouts/sidebar/Sidebar.vue.d.ts +2 -3
  59. package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +14 -0
  60. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +2 -0
  61. package/dist/types/src/services/history.d.ts +1 -0
  62. package/dist/types/src/services/props.d.ts +2 -2
  63. package/dist/types/src/type.d.ts +6 -8
  64. package/dist/types/src/utils/polyfills.d.ts +0 -0
  65. package/package.json +15 -10
  66. package/src/components/ContentMenu.vue +107 -0
  67. package/src/components/ToolButton.vue +66 -27
  68. package/src/fields/UISelect.vue +14 -6
  69. package/src/index.ts +2 -0
  70. package/src/layouts/CodeEditor.vue +20 -10
  71. package/src/layouts/Framework.vue +6 -6
  72. package/src/layouts/sidebar/ComponentListPanel.vue +23 -1
  73. package/src/layouts/sidebar/LayerMenu.vue +91 -72
  74. package/src/layouts/sidebar/LayerPanel.vue +23 -49
  75. package/src/layouts/sidebar/Sidebar.vue +13 -52
  76. package/src/layouts/sidebar/TabPane.vue +68 -0
  77. package/src/layouts/workspace/PageBar.vue +35 -6
  78. package/src/layouts/workspace/Stage.vue +41 -44
  79. package/src/layouts/workspace/ViewerMenu.vue +104 -67
  80. package/src/layouts/workspace/Workspace.vue +2 -2
  81. package/src/services/editor.ts +33 -2
  82. package/src/services/history.ts +7 -0
  83. package/src/services/props.ts +2 -3
  84. package/src/theme/common/var.scss +1 -0
  85. package/src/theme/component-list-panel.scss +2 -0
  86. package/src/theme/content-menu.scss +33 -26
  87. package/src/theme/layer-panel.scss +1 -1
  88. package/src/theme/nav-menu.scss +6 -2
  89. package/src/theme/page-bar.scss +22 -1
  90. package/src/theme/props-panel.scss +4 -0
  91. package/src/type.ts +6 -8
  92. package/src/utils/editor.ts +1 -1
  93. package/src/utils/polyfills.ts +22 -0
  94. package/src/utils/props.ts +19 -0
  95. package/coverage/lcov-report/Icon.vue.html +0 -172
  96. package/coverage/lcov-report/ToolButton.vue.html +0 -655
  97. package/coverage/lcov-report/layouts/sidebar/index.html +0 -116
  98. package/coverage/lcov-report/utils/index.html +0 -116
  99. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -980
  100. package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -188
  101. package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
@@ -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
  });
@@ -1,47 +1,31 @@
1
1
  <template>
2
- <div class="magic-editor-content-menu" ref="menu">
3
- <div>
4
- <div class="magic-editor-content-menu-item" @click="() => center()" v-if="canCenter">水平居中</div>
5
- <div class="magic-editor-content-menu-item" @click="() => copy()">复制</div>
6
- <div class="magic-editor-content-menu-item" @click="paste" v-if="canPaste">粘贴</div>
7
- <template v-if="canMoveZPos">
8
- <div class="separation"></div>
9
- <div class="magic-editor-content-menu-item" @click="topItem">上移一层</div>
10
- <div class="magic-editor-content-menu-item" @click="bottomItem">下移一层</div>
11
- <div class="magic-editor-content-menu-item" @click="top">置顶</div>
12
- <div class="magic-editor-content-menu-item" @click="bottom">置底</div>
13
- </template>
14
- <template v-if="canDelete">
15
- <div class="separation"></div>
16
- <div class="magic-editor-content-menu-item" @click="() => remove()">删除</div>
17
- </template>
18
- <div class="separation"></div>
19
- <div class="magic-editor-content-menu-item" @click="clearGuides">清空参考线</div>
20
- </div>
21
- </div>
2
+ <content-menu :menu-data="menuData" ref="menu"></content-menu>
22
3
  </template>
23
4
 
24
5
  <script lang="ts">
25
- import { computed, defineComponent, inject, onMounted, ref, watch } from 'vue';
6
+ import { computed, defineComponent, inject, markRaw, onMounted, reactive, ref, watch } from 'vue';
7
+ import { Bottom, Delete, DocumentCopy, Top } from '@element-plus/icons';
26
8
 
27
9
  import { NodeType } from '@tmagic/schema';
28
10
  import type StageCore from '@tmagic/stage';
29
11
 
30
- import { LayerOffset, Layout, Services } from '@editor/type';
12
+ import ContentMenu from '@editor/components/ContentMenu.vue';
13
+ import { LayerOffset, Layout, MenuItem, Services } from '@editor/type';
31
14
  import { COPY_STORAGE_KEY } from '@editor/utils/editor';
32
15
 
33
16
  export default defineComponent({
34
- name: 'magic-editor-ui-viewer-menu',
17
+ components: { ContentMenu },
35
18
 
36
19
  setup() {
37
20
  const services = inject<Services>('services');
38
21
  const editorService = services?.editorService;
39
- const menu = ref<HTMLDivElement>();
22
+ const menu = ref<InstanceType<typeof ContentMenu>>();
40
23
  const canPaste = ref(false);
41
24
  const canCenter = ref(false);
42
25
 
43
26
  const node = computed(() => editorService?.get('node'));
44
27
  const parent = computed(() => editorService?.get('parent'));
28
+ const isPage = computed(() => node.value?.type === NodeType.PAGE);
45
29
 
46
30
  onMounted(() => {
47
31
  const data = globalThis.localStorage.getItem(COPY_STORAGE_KEY);
@@ -62,49 +46,102 @@ export default defineComponent({
62
46
 
63
47
  return {
64
48
  menu,
65
- canPaste,
66
-
67
- canDelete: computed(() => node.value?.type !== NodeType.PAGE),
68
- canMoveZPos: computed(() => node.value?.type !== NodeType.PAGE),
69
- canCenter,
70
-
71
- center() {
72
- node.value && editorService?.alignCenter(node.value);
73
- },
74
-
75
- copy() {
76
- node.value && editorService?.copy(node.value);
77
- canPaste.value = true;
78
- },
79
-
80
- paste() {
81
- const top = menu.value?.offsetTop || 0;
82
- const left = menu.value?.offsetLeft || 0;
83
- editorService?.paste({ left, top });
84
- },
85
-
86
- remove() {
87
- node.value && editorService?.remove(node.value);
88
- },
89
-
90
- top() {
91
- editorService?.moveLayer(LayerOffset.TOP);
92
- },
93
-
94
- bottom() {
95
- editorService?.moveLayer(LayerOffset.BOTTOM);
96
- },
97
-
98
- topItem() {
99
- editorService?.moveLayer(1);
100
- },
101
-
102
- bottomItem() {
103
- editorService?.moveLayer(-1);
104
- },
105
-
106
- clearGuides() {
107
- editorService?.get<StageCore>('stage').clearGuides();
49
+ menuData: reactive<MenuItem[]>([
50
+ {
51
+ type: 'button',
52
+ text: '水平居中',
53
+ display: () => canCenter.value,
54
+ handler: () => {
55
+ node.value && editorService?.alignCenter(node.value);
56
+ },
57
+ },
58
+ {
59
+ type: 'button',
60
+ text: '复制',
61
+ icon: markRaw(DocumentCopy),
62
+ handler: () => {
63
+ node.value && editorService?.copy(node.value);
64
+ canPaste.value = true;
65
+ },
66
+ },
67
+ {
68
+ type: 'button',
69
+ text: '粘贴',
70
+ display: () => canPaste.value,
71
+ handler: () => {
72
+ const top = menu.value?.$el.offsetTop || 0;
73
+ const left = menu.value?.$el.offsetLeft || 0;
74
+ editorService?.paste({ left, top });
75
+ },
76
+ },
77
+ {
78
+ type: 'divider',
79
+ direction: 'horizontal',
80
+ display: () => !isPage.value,
81
+ },
82
+ {
83
+ type: 'button',
84
+ text: '上移一层',
85
+ icon: markRaw(Top),
86
+ display: () => !isPage.value,
87
+ handler: () => {
88
+ editorService?.moveLayer(1);
89
+ },
90
+ },
91
+ {
92
+ type: 'button',
93
+ text: '下移一层',
94
+ icon: markRaw(Bottom),
95
+ display: () => !isPage.value,
96
+ handler: () => {
97
+ editorService?.moveLayer(-1);
98
+ },
99
+ },
100
+ {
101
+ type: 'button',
102
+ text: '置顶',
103
+ display: () => !isPage.value,
104
+ handler: () => {
105
+ editorService?.moveLayer(LayerOffset.TOP);
106
+ },
107
+ },
108
+ {
109
+ type: 'button',
110
+ text: '置底',
111
+ display: () => !isPage.value,
112
+ handler: () => {
113
+ editorService?.moveLayer(LayerOffset.BOTTOM);
114
+ },
115
+ },
116
+ {
117
+ type: 'divider',
118
+ direction: 'horizontal',
119
+ display: () => !isPage.value,
120
+ },
121
+ {
122
+ type: 'button',
123
+ text: '删除',
124
+ icon: Delete,
125
+ display: () => !isPage.value,
126
+ handler: () => {
127
+ node.value && editorService?.remove(node.value);
128
+ },
129
+ },
130
+ {
131
+ type: 'divider',
132
+ direction: 'horizontal',
133
+ },
134
+ {
135
+ type: 'button',
136
+ text: '清空参考线',
137
+ handler: () => {
138
+ editorService?.get<StageCore>('stage').clearGuides();
139
+ },
140
+ },
141
+ ]),
142
+
143
+ show(e: MouseEvent) {
144
+ menu.value?.show(e);
108
145
  },
109
146
  };
110
147
  },
@@ -84,11 +84,11 @@ export default defineComponent({
84
84
  e.inputEvent.preventDefault();
85
85
  node.value && services?.editorService.copy(node.value);
86
86
  })
87
- .keyup([ctrl, 'v'], (e) => {
87
+ .keydown([ctrl, 'v'], (e) => {
88
88
  e.inputEvent.preventDefault();
89
89
  node.value && services?.editorService.paste();
90
90
  })
91
- .keyup([ctrl, 'x'], (e) => {
91
+ .keydown([ctrl, 'x'], (e) => {
92
92
  e.inputEvent.preventDefault();
93
93
  if (!node.value || isPage(node.value)) return;
94
94
  services?.editorService.copy(node.value);
@@ -54,6 +54,7 @@ class Editor extends BaseService {
54
54
  stage: null,
55
55
  highlightNode: null,
56
56
  modifiedNodeIds: new Map(),
57
+ pageLength: 0,
57
58
  });
58
59
 
59
60
  constructor() {
@@ -69,6 +70,7 @@ class Editor extends BaseService {
69
70
  'paste',
70
71
  'alignCenter',
71
72
  'moveLayer',
73
+ 'move',
72
74
  'undo',
73
75
  'redo',
74
76
  'highlight',
@@ -89,6 +91,7 @@ class Editor extends BaseService {
89
91
  log('store set ', name, ' ', value);
90
92
 
91
93
  if (name === 'root') {
94
+ this.state.pageLength = (value as unknown as MApp)?.items?.length || 0;
92
95
  this.emit('root-change', value);
93
96
  }
94
97
  }
@@ -190,6 +193,9 @@ class Editor extends BaseService {
190
193
  } else {
191
194
  historyService.empty();
192
195
  }
196
+
197
+ this.emit('select', node);
198
+
193
199
  return node!;
194
200
  }
195
201
 
@@ -249,8 +255,9 @@ class Editor extends BaseService {
249
255
  const curNode = this.get<MContainer>('node');
250
256
 
251
257
  let parentNode: MNode | undefined;
258
+ const isPage = type === NodeType.PAGE;
252
259
 
253
- if (type === NodeType.PAGE) {
260
+ if (isPage) {
254
261
  parentNode = this.get<MApp>('root');
255
262
  // 由于支持中间件扩展,在parent参数为undefined时,parent会变成next函数
256
263
  } else if (parent && typeof parent !== 'function') {
@@ -284,12 +291,18 @@ class Editor extends BaseService {
284
291
  await this.select(newNode);
285
292
 
286
293
  this.addModifiedNodeId(newNode.id);
287
- if (type !== NodeType.PAGE) {
294
+ if (!isPage) {
288
295
  this.pushHistoryState();
289
296
  }
290
297
 
291
298
  stage?.select(newNode.id);
292
299
 
300
+ if (isPage) {
301
+ this.state.pageLength += 1;
302
+ }
303
+
304
+ this.emit('add', newNode);
305
+
293
306
  return newNode;
294
307
  }
295
308
 
@@ -318,9 +331,23 @@ class Editor extends BaseService {
318
331
  stage?.remove({ id: node.id, root: this.get('root') });
319
332
 
320
333
  if (node.type === NodeType.PAGE) {
334
+ this.state.pageLength -= 1;
335
+
321
336
  if (root.items[0]) {
322
337
  await this.select(root.items[0]);
323
338
  stage?.select(root.items[0].id);
339
+ } else {
340
+ this.set('node', null);
341
+ this.set('parent', null);
342
+ this.set('page', null);
343
+ this.set('stage', null);
344
+ this.set('highlightNode', null);
345
+ this.resetModifiedNodeId();
346
+ historyService.reset();
347
+
348
+ this.emit('remove', node);
349
+
350
+ return node;
324
351
  }
325
352
  } else {
326
353
  await this.select(parent);
@@ -330,6 +357,8 @@ class Editor extends BaseService {
330
357
  this.addModifiedNodeId(parent.id);
331
358
  this.pushHistoryState();
332
359
 
360
+ this.emit('remove', node);
361
+
333
362
  return node;
334
363
  }
335
364
 
@@ -391,6 +420,8 @@ class Editor extends BaseService {
391
420
  this.addModifiedNodeId(newConfig.id);
392
421
  this.pushHistoryState();
393
422
 
423
+ this.emit('update', newConfig);
424
+
394
425
  return newConfig;
395
426
  }
396
427
 
@@ -51,6 +51,13 @@ class History extends BaseService {
51
51
  this.on('change', this.setCanUndoRedo);
52
52
  }
53
53
 
54
+ public reset() {
55
+ this.state.pageSteps = {};
56
+ this.state.pageId = undefined;
57
+ this.state.canRedo = false;
58
+ this.state.canUndo = false;
59
+ }
60
+
54
61
  public changePage(page: MPage): void {
55
62
  if (!page) return;
56
63
 
@@ -17,7 +17,7 @@
17
17
  */
18
18
 
19
19
  import { reactive } from 'vue';
20
- import { cloneDeep } from 'lodash-es';
20
+ import { cloneDeep, mergeWith } from 'lodash-es';
21
21
 
22
22
  import type { FormConfig } from '@tmagic/form';
23
23
  import type { MComponent, MNode } from '@tmagic/schema';
@@ -100,8 +100,7 @@ class Props extends BaseService {
100
100
 
101
101
  return cloneDeep({
102
102
  ...getDefaultPropsValue(type),
103
- ...defaultValue,
104
- ...(this.state.propsValueMap[type] || {}),
103
+ ...mergeWith(this.state.propsValueMap[type] || {}, defaultValue),
105
104
  });
106
105
  }
107
106
  }
@@ -2,6 +2,7 @@ $--theme-color: #2882e0;
2
2
 
3
3
  $--font-color: #070303;
4
4
  $--border-color: #d9dbdd;
5
+ $--hover-color: #f3f5f9;
5
6
 
6
7
  $--nav-height: 35px;
7
8
  $--nav-color: #070303;
@@ -12,6 +12,7 @@
12
12
  top: 0;
13
13
  left: 0;
14
14
  box-sizing: border-box;
15
+ z-index: 1;
15
16
 
16
17
  .el-input__prefix {
17
18
  padding: 10px;
@@ -62,6 +63,7 @@
62
63
  color: $--font-color;
63
64
  flex-direction: column;
64
65
  width: 42px;
66
+ cursor: pointer;
65
67
 
66
68
  i {
67
69
  font-size: 20px;
@@ -2,38 +2,45 @@
2
2
  position: fixed;
3
3
  font-size: 12px;
4
4
  background: #fff;
5
- color: #333;
6
5
  box-shadow: 0 2px 8px 2px rgba(68, 73, 77, 0.16);
7
6
  z-index: 9999;
8
7
  transform-origin: 0% 0%;
9
8
  font-weight: 600;
10
9
  padding: 4px 0px;
10
+ overflow: auto;
11
+ max-height: 100%;
11
12
 
12
- .separation {
13
- width: 100%;
14
- height: 0;
15
- border-color: rgba(155, 155, 155, 0.1);
16
- }
17
-
18
- .subMenu {
19
- position: absolute;
20
- right: 0;
21
- transform: translate(100%, 0);
22
- background-color: #fff;
13
+ .menu-item {
23
14
  color: #333;
24
- box-shadow: 0 2px 8px 2px rgba(68, 73, 77, 0.16);
25
- top: 0;
26
- height: 223px;
27
- }
28
- }
15
+ display: flex;
16
+ -webkit-box-align: center;
17
+ align-items: center;
18
+ cursor: pointer;
19
+ min-width: 140px;
20
+ transition: all 0.2s ease 0s;
21
+ padding: 5px 14px;
22
+ border-left: 2px solid transparent;
23
+
24
+ .el-button {
25
+ width: 100%;
26
+ justify-content: flex-start;
27
+ }
29
28
 
30
- .magic-editor-content-menu-item {
31
- display: flex;
32
- -webkit-box-align: center;
33
- align-items: center;
34
- cursor: pointer;
35
- min-width: 140px;
36
- transition: all 0.2s ease 0s;
37
- padding: 10px 14px;
38
- border-left: 2px solid transparent;
29
+ .el-button--text,
30
+ i {
31
+ color: $--font-color;
32
+ }
33
+
34
+ &.divider {
35
+ padding: 0 14px;
36
+
37
+ .el-divider {
38
+ margin: 0;
39
+ }
40
+ }
41
+
42
+ &:hover {
43
+ background-color: $--hover-color;
44
+ }
45
+ }
39
46
  }
@@ -56,7 +56,7 @@
56
56
  }
57
57
 
58
58
  .magic-editor-layer-panel .cus-tree-node-hover {
59
- background-color: #f3f5f9;
59
+ background-color: $--hover-color;
60
60
  width: 100%;
61
61
  }
62
62
 
@@ -43,13 +43,17 @@
43
43
  display: flex !important;
44
44
  transition: all 0.3s ease 0s;
45
45
  border-bottom: 2px solid transparent;
46
- margin: 0 5px;
46
+ margin: 0;
47
47
 
48
48
  .is-disabled {
49
49
  opacity: 0.5;
50
50
  }
51
51
 
52
- .el-button--text,
52
+ .is-text {
53
+ padding: 5px;
54
+ }
55
+
56
+ .is-text,
53
57
  i {
54
58
  color: $--font-color;
55
59
  }