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

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 (88) hide show
  1. package/README.md +1 -0
  2. package/coverage/clover.xml +1444 -0
  3. package/coverage/coverage-final.json +34 -0
  4. package/coverage/lcov-report/Icon.vue.html +172 -0
  5. package/coverage/lcov-report/ToolButton.vue.html +655 -0
  6. package/coverage/lcov-report/base.css +224 -0
  7. package/coverage/lcov-report/block-navigation.js +87 -0
  8. package/coverage/lcov-report/favicon.png +0 -0
  9. package/coverage/lcov-report/index.html +206 -0
  10. package/coverage/lcov-report/layouts/sidebar/LayerMenu.vue.html +364 -0
  11. package/coverage/lcov-report/layouts/sidebar/index.html +116 -0
  12. package/coverage/lcov-report/prettify.css +1 -0
  13. package/coverage/lcov-report/prettify.js +2 -0
  14. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  15. package/coverage/lcov-report/sorter.js +196 -0
  16. package/coverage/lcov-report/src/Editor.vue.html +787 -0
  17. package/coverage/lcov-report/src/components/Icon.vue.html +172 -0
  18. package/coverage/lcov-report/src/components/ScrollViewer.vue.html +283 -0
  19. package/coverage/lcov-report/src/components/ToolButton.vue.html +655 -0
  20. package/coverage/lcov-report/src/components/index.html +146 -0
  21. package/coverage/lcov-report/src/index.html +131 -0
  22. package/coverage/lcov-report/src/layouts/AddPageBox.vue.html +214 -0
  23. package/coverage/lcov-report/src/layouts/Framework.vue.html +304 -0
  24. package/coverage/lcov-report/src/layouts/NavMenu.vue.html +208 -0
  25. package/coverage/lcov-report/src/layouts/PropsPanel.vue.html +316 -0
  26. package/coverage/lcov-report/src/layouts/Resizer.vue.html +268 -0
  27. package/coverage/lcov-report/src/layouts/index.html +176 -0
  28. package/coverage/lcov-report/src/layouts/sidebar/ComponentListPanel.vue.html +292 -0
  29. package/coverage/lcov-report/src/layouts/sidebar/LayerMenu.vue.html +364 -0
  30. package/coverage/lcov-report/src/layouts/sidebar/LayerPanel.vue.html +853 -0
  31. package/coverage/lcov-report/src/layouts/sidebar/Sidebar.vue.html +343 -0
  32. package/coverage/lcov-report/src/layouts/sidebar/index.html +161 -0
  33. package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +631 -0
  34. package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +766 -0
  35. package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +421 -0
  36. package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +586 -0
  37. package/coverage/lcov-report/src/layouts/workspace/index.html +161 -0
  38. package/coverage/lcov-report/src/services/BaseService.ts.html +643 -0
  39. package/coverage/lcov-report/src/services/componentList.ts.html +229 -0
  40. package/coverage/lcov-report/src/services/editor.ts.html +1984 -0
  41. package/coverage/lcov-report/src/services/events.ts.html +331 -0
  42. package/coverage/lcov-report/src/services/history.ts.html +457 -0
  43. package/coverage/lcov-report/src/services/index.html +206 -0
  44. package/coverage/lcov-report/src/services/props.ts.html +418 -0
  45. package/coverage/lcov-report/src/services/ui.ts.html +514 -0
  46. package/coverage/lcov-report/src/type.ts.html +850 -0
  47. package/coverage/lcov-report/src/utils/compose.ts.html +184 -0
  48. package/coverage/lcov-report/src/utils/config.ts.html +172 -0
  49. package/coverage/lcov-report/src/utils/editor.ts.html +838 -0
  50. package/coverage/lcov-report/src/utils/index.html +221 -0
  51. package/coverage/lcov-report/src/utils/index.ts.html +151 -0
  52. package/coverage/lcov-report/src/utils/logger.ts.html +226 -0
  53. package/coverage/lcov-report/src/utils/props.ts.html +739 -0
  54. package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +733 -0
  55. package/coverage/lcov-report/src/utils/undo-redo.ts.html +313 -0
  56. package/coverage/lcov-report/utils/index.html +116 -0
  57. package/coverage/lcov-report/utils/undo-redo.ts.html +313 -0
  58. package/coverage/lcov.info +3407 -0
  59. package/dist/style.css +3 -2
  60. package/dist/tmagic-editor.es.js +388 -196
  61. package/dist/tmagic-editor.es.js.map +1 -1
  62. package/dist/tmagic-editor.umd.js +393 -202
  63. package/dist/tmagic-editor.umd.js.map +1 -1
  64. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -1
  65. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +1 -1
  66. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +2 -1
  67. package/dist/types/src/services/editor.d.ts +5 -2
  68. package/dist/types/src/services/props.d.ts +1 -1
  69. package/dist/types/src/services/ui.d.ts +1 -0
  70. package/dist/types/src/type.d.ts +3 -1
  71. package/dist/types/src/utils/editor.d.ts +4 -3
  72. package/package.json +28 -9
  73. package/src/components/ScrollViewer.vue +1 -1
  74. package/src/components/ToolButton.vue +3 -3
  75. package/src/layouts/PropsPanel.vue +1 -1
  76. package/src/layouts/sidebar/ComponentListPanel.vue +2 -2
  77. package/src/layouts/sidebar/LayerMenu.vue +1 -0
  78. package/src/layouts/workspace/Workspace.vue +106 -3
  79. package/src/services/BaseService.ts +1 -1
  80. package/src/services/editor.ts +79 -13
  81. package/src/services/props.ts +2 -1
  82. package/src/services/ui.ts +5 -0
  83. package/src/theme/layer-panel.scss +1 -0
  84. package/src/type.ts +3 -1
  85. package/src/utils/editor.ts +31 -6
  86. package/src/utils/props.ts +1 -1
  87. package/tsconfig.json +0 -9
  88. package/vite.config.ts +0 -30
@@ -7,6 +7,6 @@ declare const _default: DefineComponent<{}, {
7
7
  items: ComponentItem[];
8
8
  title: string;
9
9
  }[] | undefined>;
10
- appendComponent({ text, type, ...config }: ComponentItem): void;
10
+ appendComponent({ text, type, data }: ComponentItem): void;
11
11
  }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly<ExtractPropTypes<{}>>, {}>;
12
12
  export default _default;
@@ -2,7 +2,7 @@ import type { Translator } from 'element-plus';
2
2
  import type { Nullable } from 'element-plus/es/utils';
3
3
  import type { default } from 'element-plus/es/components/tree/src/model/node';
4
4
  import type { TreeOptionProps, TreeKey, LoadFunction, FilterNodeMethodFunction, TreeNodeData, FakeNode, TreeNodeLoadedDefaultProps, TreeData } from 'element-plus/es/components/tree/src/tree.type';
5
- import type { DebouncedFunc } from 'lodash';
5
+ import type { DebouncedFunc } from 'lodash-es';
6
6
  import type { DefineComponent, ComputedRef, ComponentInternalInstance, ExtractPropTypes, PropType, Component, ComputedOptions, MethodOptions, VNodeProps, AllowedComponentProps, ComponentCustomProps, Slot, ComponentPublicInstance, ComponentOptionsBase, ComponentOptionsMixin, DebuggerEvent, nextTick, WatchOptions, WatchStopHandle, ShallowUnwrapRef, ComponentCustomProperties, EmitsOptions, Ref } from 'vue';
7
7
  import type { Id, MNode } from '@tmagic/schema';
8
8
  declare const _default: DefineComponent<{}, {
@@ -1,4 +1,4 @@
1
- import type { DefineComponent, ComputedRef, ComponentOptionsMixin, VNodeProps, AllowedComponentProps, ComponentCustomProps, ExtractPropTypes, PropType } from 'vue';
1
+ import type { DefineComponent, Ref, ComputedRef, ComponentOptionsMixin, VNodeProps, AllowedComponentProps, ComponentCustomProps, ExtractPropTypes, PropType } from 'vue';
2
2
  import type { MPage } from '@tmagic/schema';
3
3
  import type { MoveableOptions } from '@tmagic/stage';
4
4
  import StageCore from '@tmagic/stage';
@@ -14,6 +14,7 @@ declare const _default: DefineComponent<{
14
14
  type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
15
15
  };
16
16
  }, {
17
+ workspace: Ref<HTMLDivElement | undefined>;
17
18
  page: ComputedRef<MPage | undefined>;
18
19
  }, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, Record<string, any>, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly<ExtractPropTypes<{
19
20
  runtimeUrl: StringConstructor;
@@ -41,13 +41,15 @@ declare class Editor extends BaseService {
41
41
  /**
42
42
  * 只有容器拥有布局
43
43
  */
44
- getLayout(node: MNode): Promise<Layout>;
44
+ getLayout(parent: MNode, node?: MNode): Promise<Layout>;
45
45
  /**
46
46
  * 选中指定节点(将指定节点设置成当前选中状态)
47
47
  * @param config 指定节点配置或者ID
48
48
  * @returns 当前选中的节点配置
49
49
  */
50
50
  select(config: MNode | Id): Promise<MNode> | never;
51
+ selectNextNode(): Promise<MNode> | never;
52
+ selectNextPage(): Promise<MNode> | never;
51
53
  /**
52
54
  * 高亮指定节点
53
55
  * @param config 指定节点配置或者ID
@@ -60,7 +62,7 @@ declare class Editor extends BaseService {
60
62
  * @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
61
63
  * @returns 添加后的节点
62
64
  */
63
- add({ type, ...config }: AddMNode, parent?: MContainer | null): Promise<MNode>;
65
+ add(addNode: AddMNode, parent?: MContainer | null): Promise<MNode>;
64
66
  /**
65
67
  * 删除组件
66
68
  * @param {Object} node
@@ -116,6 +118,7 @@ declare class Editor extends BaseService {
116
118
  * @returns 下一步数据
117
119
  */
118
120
  redo(): Promise<StepValue | null>;
121
+ move(left: number, top: number): Promise<void>;
119
122
  destroy(): void;
120
123
  resetModifiedNodeId(): void;
121
124
  private addModifiedNodeId;
@@ -29,7 +29,7 @@ declare class Props extends BaseService {
29
29
  * @param type 组件类型
30
30
  * @returns 组件初始值
31
31
  */
32
- getPropsValue(type: string): Promise<MComponent>;
32
+ getPropsValue(type: string, defaultValue?: {}): Promise<MComponent>;
33
33
  }
34
34
  export declare type PropsService = Props;
35
35
  declare const _default: Props;
@@ -24,6 +24,7 @@ declare class Ui extends BaseService {
24
24
  constructor();
25
25
  set<T = any>(name: keyof UiState, value: T): void;
26
26
  get<T>(name: keyof typeof state): T;
27
+ zoom(zoom: number): void;
27
28
  private setColumnWidth;
28
29
  private setStageRect;
29
30
  private calcZoom;
@@ -169,7 +169,9 @@ export interface ComponentItem {
169
169
  type: string;
170
170
  /** element-plus icon class */
171
171
  icon?: string | Component;
172
- [key: string]: any;
172
+ data?: {
173
+ [key: string]: any;
174
+ };
173
175
  }
174
176
  export interface ComponentGroup {
175
177
  /** 显示文案 */
@@ -1,4 +1,5 @@
1
1
  import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
2
+ import type StageCore from '@tmagic/stage';
2
3
  import { Layout } from '../type';
3
4
  export declare const COPY_STORAGE_KEY = "$MagicEditorCopyData";
4
5
  export declare const generateId: (type: string | number) => string;
@@ -36,9 +37,9 @@ export declare const setNewItemId: (config: MNode, parent?: MPage | undefined) =
36
37
  * @returns {boolean}
37
38
  */
38
39
  export declare const isFixed: (node: MNode) => boolean;
39
- export declare const getNodeIndex: (node: MNode, parent: MContainer) => number;
40
+ export declare const getNodeIndex: (node: MNode, parent: MContainer | MApp) => number;
40
41
  export declare const toRelative: (node: MNode) => MNode;
41
- export declare const initPosition: (node: MNode, layout: Layout) => MNode;
42
+ export declare const initPosition: (node: MNode, layout: Layout, parentNode: MNode, stage: StageCore) => MNode;
42
43
  export declare const setLayout: (node: MNode, layout: Layout) => MNode;
43
44
  export declare const change2Fixed: (node: MNode, root: MApp) => MNode;
44
- export declare const Fixed2Other: (node: MNode, root: MApp, getLayout: (node: MNode) => Promise<Layout>) => Promise<MNode>;
45
+ export declare const Fixed2Other: (node: MNode, root: MApp, getLayout: (parent: MNode, node?: MNode | undefined) => Promise<Layout>) => Promise<MNode>;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.0-beta.10",
2
+ "version": "1.0.0-beta.13",
3
3
  "name": "@tmagic/editor",
4
4
  "sideEffects": false,
5
5
  "main": "dist/tmagic-editor.umd.js",
@@ -16,8 +16,11 @@
16
16
  "require": "./dist/style.css"
17
17
  }
18
18
  },
19
+ "license": "Apache-2.0",
19
20
  "scripts": {
20
- "build": "vite build"
21
+ "build": "vite build",
22
+ "test": "jest --maxWorkers=8",
23
+ "test:coverage": "jest --maxWorkers=16 --coverage"
21
24
  },
22
25
  "engines": {
23
26
  "node": ">=14"
@@ -26,16 +29,26 @@
26
29
  "type": "git",
27
30
  "url": "https://github.com/Tencent/tmagic-editor.git"
28
31
  },
32
+ "homepage": "https://tencent.github.io/tmagic-editor/docs/",
33
+ "keywords": [
34
+ "editor",
35
+ "drag",
36
+ "resize",
37
+ "vue",
38
+ "vue3",
39
+ "typescript"
40
+ ],
29
41
  "dependencies": {
30
42
  "@element-plus/icons": "0.0.11",
31
- "@tmagic/core": "^1.0.0-beta.10",
32
- "@tmagic/form": "^1.0.0-beta.10",
33
- "@tmagic/schema": "^1.0.0-beta.10",
34
- "@tmagic/stage": "^1.0.0-beta.10",
35
- "@tmagic/utils": "^1.0.0-beta.10",
43
+ "@tmagic/core": "^1.0.0-beta.13",
44
+ "@tmagic/form": "^1.0.0-beta.13",
45
+ "@tmagic/schema": "^1.0.0-beta.13",
46
+ "@tmagic/stage": "^1.0.0-beta.13",
47
+ "@tmagic/utils": "^1.0.0-beta.13",
36
48
  "color": "^3.1.3",
37
49
  "element-plus": "^2.1.7",
38
50
  "events": "^3.3.0",
51
+ "keycon": "^1.1.2",
39
52
  "lodash-es": "^4.17.21",
40
53
  "monaco-editor": "^0.32.1",
41
54
  "serialize-javascript": "^6.0.0",
@@ -43,18 +56,24 @@
43
56
  },
44
57
  "devDependencies": {
45
58
  "@types/events": "^3.0.0",
59
+ "@types/jest": "^26.0.23",
46
60
  "@types/lodash-es": "^4.17.4",
47
61
  "@types/node": "^15.12.4",
48
62
  "@types/serialize-javascript": "^5.0.1",
49
63
  "@vitejs/plugin-vue": "^1.2.3",
50
64
  "@vitejs/plugin-vue-jsx": "^1.1.6",
51
65
  "@vue/compiler-sfc": "^3.2.0",
52
- "@vue/test-utils": "^2.0.0-rc.12",
66
+ "@vue/test-utils": "^2.0.0-rc.20",
67
+ "@vue/vue3-jest": "^27.0.0-alpha.4",
68
+ "jest": "^27.5.1",
69
+ "jest-serializer-vue": "^2.0.2",
70
+ "jest-transform-stub": "^2.0.0",
53
71
  "sass": "^1.35.1",
72
+ "ts-jest": "^27.1.4",
54
73
  "typescript": "^4.3.4",
55
74
  "vite": "^2.3.7",
56
75
  "vite-plugin-dts": "^0.9.6",
57
76
  "vue-tsc": "^0.0.24"
58
77
  },
59
- "gitHead": "fc39ecb4f5b117a4ebbfd115382887983cb8f9de"
78
+ "gitHead": "ca2b203614cbdaff580e5cb6f35630f50b827451"
60
79
  }
@@ -55,7 +55,7 @@ export default defineComponent({
55
55
  style: computed(
56
56
  () => `
57
57
  width: ${props.width}px;
58
- height: ${props.height}px;
58
+ height: ${(props.height || 0) - 40}px;
59
59
  position: absolute;
60
60
  margin-top: 30px;
61
61
  `,
@@ -64,13 +64,13 @@ export default defineComponent({
64
64
  const services = inject<Services>('services');
65
65
  const uiService = services?.uiService;
66
66
 
67
- const zoomInHandler = () => uiService?.set('zoom', zoom.value + 0.1);
68
- const zoomOutHandler = () => uiService?.set('zoom', zoom.value - 0.1);
69
-
70
67
  const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1);
71
68
  const showGuides = computed((): boolean => uiService?.get<boolean>('showGuides') ?? true);
72
69
  const showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
73
70
 
71
+ const zoomInHandler = () => uiService?.zoom(0.1);
72
+ const zoomOutHandler = () => uiService?.zoom(-0.1);
73
+
74
74
  const item = computed((): MenuButton | MenuComponent => {
75
75
  if (typeof props.data !== 'string') {
76
76
  return props.data;
@@ -39,9 +39,9 @@ export default defineComponent({
39
39
  return;
40
40
  }
41
41
 
42
- values.value = node.value;
43
42
  const type = node.value.type || (node.value.items ? 'container' : 'text');
44
43
  curFormConfig.value = (await services?.propsService.getPropsConfig(type)) || [];
44
+ values.value = node.value;
45
45
  };
46
46
 
47
47
  watchEffect(init);
@@ -56,11 +56,11 @@ export default defineComponent({
56
56
  collapseValue,
57
57
  list,
58
58
 
59
- appendComponent({ text, type, ...config }: ComponentItem): void {
59
+ appendComponent({ text, type, data = {} }: ComponentItem): void {
60
60
  services?.editorService.add({
61
61
  name: text,
62
62
  type,
63
- ...config,
63
+ ...data,
64
64
  });
65
65
  },
66
66
  };
@@ -72,6 +72,7 @@ export default defineComponent({
72
72
  services?.editorService.add({
73
73
  name: config.text,
74
74
  type: config.type,
75
+ ...(config.data || {}),
75
76
  });
76
77
  },
77
78
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="m-editor-workspace">
2
+ <div class="m-editor-workspace" tabindex="1" ref="workspace">
3
3
  <magic-stage
4
4
  :key="page?.id"
5
5
  :runtime-url="runtimeUrl"
@@ -18,11 +18,13 @@
18
18
  </template>
19
19
 
20
20
  <script lang="ts">
21
- import { computed, defineComponent, inject, PropType } from 'vue';
21
+ import { computed, defineComponent, inject, onMounted, onUnmounted, PropType, ref } from 'vue';
22
+ import KeyController from 'keycon';
22
23
 
23
- import type { MPage } from '@tmagic/schema';
24
+ import type { MNode, MPage } from '@tmagic/schema';
24
25
  import type { MoveableOptions } from '@tmagic/stage';
25
26
  import StageCore from '@tmagic/stage';
27
+ import { isPage } from '@tmagic/utils';
26
28
 
27
29
  import type { Services } from '@editor/type';
28
30
 
@@ -55,8 +57,109 @@ export default defineComponent({
55
57
 
56
58
  setup() {
57
59
  const services = inject<Services>('services');
60
+ const workspace = ref<HTMLDivElement>();
61
+ const node = computed(() => services?.editorService.get<MNode>('node'));
62
+ let keycon: KeyController;
63
+
64
+ const mouseenterHandler = () => {
65
+ workspace.value?.focus();
66
+ };
67
+
68
+ onMounted(() => {
69
+ workspace.value?.addEventListener('mouseenter', mouseenterHandler);
70
+
71
+ keycon = new KeyController(workspace.value);
72
+
73
+ const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
74
+
75
+ const ctrl = isMac ? 'meta' : 'ctrl';
76
+
77
+ keycon
78
+ .keyup('delete', (e) => {
79
+ e.inputEvent.preventDefault();
80
+ if (!node.value || isPage(node.value)) return;
81
+ services?.editorService.remove(node.value);
82
+ })
83
+ .keydown([ctrl, 'c'], (e) => {
84
+ e.inputEvent.preventDefault();
85
+ node.value && services?.editorService.copy(node.value);
86
+ })
87
+ .keyup([ctrl, 'v'], (e) => {
88
+ e.inputEvent.preventDefault();
89
+ node.value && services?.editorService.paste();
90
+ })
91
+ .keyup([ctrl, 'x'], (e) => {
92
+ e.inputEvent.preventDefault();
93
+ if (!node.value || isPage(node.value)) return;
94
+ services?.editorService.copy(node.value);
95
+ services?.editorService.remove(node.value);
96
+ })
97
+ .keydown([ctrl, 'z'], (e) => {
98
+ e.inputEvent.preventDefault();
99
+ services?.editorService.undo();
100
+ })
101
+ .keydown([ctrl, 'shift', 'z'], (e) => {
102
+ e.inputEvent.preventDefault();
103
+ services?.editorService.redo();
104
+ })
105
+ .keydown('up', (e) => {
106
+ e.inputEvent.preventDefault();
107
+ services?.editorService.move(0, -1);
108
+ })
109
+ .keydown('down', (e) => {
110
+ e.inputEvent.preventDefault();
111
+ services?.editorService.move(0, 1);
112
+ })
113
+ .keydown('left', (e) => {
114
+ e.inputEvent.preventDefault();
115
+ services?.editorService.move(-1, 0);
116
+ })
117
+ .keydown('right', (e) => {
118
+ e.inputEvent.preventDefault();
119
+ services?.editorService.move(1, 0);
120
+ })
121
+ .keydown([ctrl, 'up'], (e) => {
122
+ e.inputEvent.preventDefault();
123
+ services?.editorService.move(0, -10);
124
+ })
125
+ .keydown([ctrl, 'down'], (e) => {
126
+ e.inputEvent.preventDefault();
127
+ services?.editorService.move(0, 10);
128
+ })
129
+ .keydown([ctrl, 'left'], (e) => {
130
+ e.inputEvent.preventDefault();
131
+ services?.editorService.move(-10, 0);
132
+ })
133
+ .keydown([ctrl, 'right'], (e) => {
134
+ e.inputEvent.preventDefault();
135
+ services?.editorService.move(10, 0);
136
+ })
137
+ .keydown('tab', (e) => {
138
+ e.inputEvent.preventDefault();
139
+ services?.editorService.selectNextNode();
140
+ })
141
+ .keydown([ctrl, 'tab'], (e) => {
142
+ e.inputEvent.preventDefault();
143
+ services?.editorService.selectNextPage();
144
+ })
145
+ .keydown([ctrl, '='], (e) => {
146
+ e.inputEvent.preventDefault();
147
+ services?.uiService.zoom(0.1);
148
+ })
149
+ .keydown([ctrl, '-'], (e) => {
150
+ e.inputEvent.preventDefault();
151
+ services?.uiService.zoom(-0.1);
152
+ });
153
+ });
154
+
155
+ onUnmounted(() => {
156
+ workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
157
+ keycon.destroy();
158
+ });
58
159
 
59
160
  return {
161
+ workspace,
162
+
60
163
  page: computed(() => services?.editorService.get<MPage>('page')),
61
164
  };
62
165
  },
@@ -53,7 +53,7 @@ const doAction = async (
53
53
  let returnValue: any = await fn(beforeArgs, sourceMethod.bind(scope));
54
54
 
55
55
  for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
56
- returnValue = await afterMethod(...beforeArgs, returnValue);
56
+ returnValue = await afterMethod(returnValue, ...beforeArgs);
57
57
 
58
58
  if (isError(returnValue)) throw returnValue;
59
59
  }
@@ -22,8 +22,8 @@ import serialize from 'serialize-javascript';
22
22
 
23
23
  import type { Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
24
24
  import { NodeType } from '@tmagic/schema';
25
- import type StageCore from '@tmagic/stage';
26
- import { getNodePath, isPop } from '@tmagic/utils';
25
+ import StageCore from '@tmagic/stage';
26
+ import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
27
27
 
28
28
  import historyService, { StepValue } from '@editor/services/history';
29
29
  import propsService from '@editor/services/props';
@@ -108,7 +108,7 @@ class Editor extends BaseService {
108
108
  * @returns {EditorNodeInfo}
109
109
  */
110
110
  public getNodeInfo(id: Id): EditorNodeInfo {
111
- const root = this.get<MApp | null>('root');
111
+ const root = toRaw(this.get<MApp | null>('root'));
112
112
  if (!root) return {};
113
113
 
114
114
  if (id === root.id) {
@@ -159,13 +159,15 @@ class Editor extends BaseService {
159
159
  /**
160
160
  * 只有容器拥有布局
161
161
  */
162
- public async getLayout(node: MNode): Promise<Layout> {
163
- if (node.layout) {
164
- return node.layout;
162
+ public async getLayout(parent: MNode, node?: MNode): Promise<Layout> {
163
+ if (node && typeof node !== 'function' && isFixed(node)) return Layout.FIXED;
164
+
165
+ if (parent.layout) {
166
+ return parent.layout;
165
167
  }
166
168
 
167
169
  // 如果该节点没有设置position,则认为是流式布局,例如获取root的布局时
168
- if (!node.style?.position) {
170
+ if (!parent.style?.position) {
169
171
  return Layout.RELATIVE;
170
172
  }
171
173
 
@@ -191,6 +193,39 @@ class Editor extends BaseService {
191
193
  return node!;
192
194
  }
193
195
 
196
+ public async selectNextNode(): Promise<MNode> | never {
197
+ const node = toRaw(this.get('node'));
198
+
199
+ if (!node || isPage(node) || node.type === NodeType.ROOT) return node;
200
+
201
+ const parent = toRaw(this.getParentById(node.id));
202
+
203
+ if (!parent) return node;
204
+
205
+ const index = getNodeIndex(node, parent);
206
+
207
+ const nextNode = parent.items[index + 1] || parent.items[0];
208
+
209
+ await this.select(nextNode);
210
+ this.get<StageCore>('stage')?.select(nextNode.id);
211
+
212
+ return nextNode;
213
+ }
214
+
215
+ public async selectNextPage(): Promise<MNode> | never {
216
+ const root = toRaw(this.get<MApp>('root'));
217
+ const page = toRaw(this.get('page'));
218
+
219
+ const index = getNodeIndex(page, root);
220
+
221
+ const nextPage = root.items[index + 1] || root.items[0];
222
+
223
+ await this.select(nextPage);
224
+ this.get<StageCore>('stage')?.select(nextPage.id);
225
+
226
+ return nextPage;
227
+ }
228
+
194
229
  /**
195
230
  * 高亮指定节点
196
231
  * @param config 指定节点配置或者ID
@@ -209,7 +244,8 @@ class Editor extends BaseService {
209
244
  * @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
210
245
  * @returns 添加后的节点
211
246
  */
212
- public async add({ type, ...config }: AddMNode, parent?: MContainer | null): Promise<MNode> {
247
+ public async add(addNode: AddMNode, parent?: MContainer | null): Promise<MNode> {
248
+ const { type, ...config } = addNode;
213
249
  const curNode = this.get<MContainer>('node');
214
250
 
215
251
  let parentNode: MNode | undefined;
@@ -227,8 +263,13 @@ class Editor extends BaseService {
227
263
 
228
264
  if (!parentNode) throw new Error('未找到父元素');
229
265
 
230
- const layout = await this.getLayout(parentNode);
231
- const newNode = initPosition({ ...toRaw(await propsService.getPropsValue(type)), ...config }, layout);
266
+ const layout = await this.getLayout(toRaw(parentNode), addNode as MNode);
267
+ const newNode = initPosition(
268
+ { ...toRaw(await propsService.getPropsValue(type, config)) },
269
+ layout,
270
+ parentNode,
271
+ this.get<StageCore>('stage'),
272
+ );
232
273
 
233
274
  if ((parentNode?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && newNode.type !== NodeType.PAGE) {
234
275
  throw new Error('app下不能添加组件');
@@ -339,9 +380,10 @@ class Editor extends BaseService {
339
380
 
340
381
  if (`${newConfig.id}` === `${this.get('node').id}`) {
341
382
  this.set('node', newConfig);
342
- this.get<StageCore | null>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
343
383
  }
344
384
 
385
+ this.get<StageCore | null>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
386
+
345
387
  if (newConfig.type === NodeType.PAGE) {
346
388
  this.set('page', newConfig);
347
389
  }
@@ -426,7 +468,7 @@ class Editor extends BaseService {
426
468
  public async alignCenter(config: MNode): Promise<MNode | void> {
427
469
  const parent = this.get<MContainer>('parent');
428
470
  const node = this.get<MNode>('node');
429
- const layout = await this.getLayout(parent);
471
+ const layout = await this.getLayout(toRaw(parent), toRaw(node));
430
472
  if (layout === Layout.RELATIVE) {
431
473
  return;
432
474
  }
@@ -484,6 +526,26 @@ class Editor extends BaseService {
484
526
  return value;
485
527
  }
486
528
 
529
+ public async move(left: number, top: number) {
530
+ const node = toRaw(this.get('node'));
531
+ if (!node || isPage(node)) return;
532
+
533
+ const { style, id } = node;
534
+ if (!style || style.position !== 'absolute') return;
535
+
536
+ if (top && !isNumber(style.top)) return;
537
+ if (left && !isNumber(style.left)) return;
538
+
539
+ this.update({
540
+ id,
541
+ style: {
542
+ ...style,
543
+ left: Number(style.left) + left,
544
+ top: Number(style.top) + top,
545
+ },
546
+ });
547
+ }
548
+
487
549
  public destroy() {
488
550
  this.removeAllListeners();
489
551
  this.set('root', null);
@@ -520,7 +582,11 @@ class Editor extends BaseService {
520
582
  this.isHistoryStateChange = true;
521
583
  await this.update(value.data);
522
584
  this.set('modifiedNodeIds', value.modifiedNodeIds);
523
- setTimeout(() => value.nodeId && this.select(value.nodeId), 0);
585
+ setTimeout(async () => {
586
+ if (!value.nodeId) return;
587
+ await this.select(value.nodeId);
588
+ this.get<StageCore | null>('stage')?.select(value.nodeId);
589
+ }, 0);
524
590
  }
525
591
 
526
592
  private async toggleFixedPosition(dist: MNode, src: MNode, root: MApp) {
@@ -87,7 +87,7 @@ class Props extends BaseService {
87
87
  * @param type 组件类型
88
88
  * @returns 组件初始值
89
89
  */
90
- public async getPropsValue(type: string) {
90
+ public async getPropsValue(type: string, defaultValue = {}) {
91
91
  if (type === 'area') {
92
92
  const value = (await this.getPropsValue('button')) as MComponent;
93
93
  value.className = 'action-area';
@@ -100,6 +100,7 @@ class Props extends BaseService {
100
100
 
101
101
  return cloneDeep({
102
102
  ...getDefaultPropsValue(type),
103
+ ...defaultValue,
103
104
  ...(this.state.propsValueMap[type] || {}),
104
105
  });
105
106
  }
@@ -91,6 +91,11 @@ class Ui extends BaseService {
91
91
  return (state as any)[name];
92
92
  }
93
93
 
94
+ public zoom(zoom: number) {
95
+ this.set('zoom', (this.get<number>('zoom') * 100 + zoom * 100) / 100);
96
+ if (this.get<number>('zoom') < 0.1) this.set('zoom', 0.1);
97
+ }
98
+
94
99
  private setColumnWidth({ left, center, right }: SetColumnWidth) {
95
100
  const columnWidth = {
96
101
  ...toRaw(this.get<GetColumnWidth>('columnWidth')),
@@ -52,6 +52,7 @@
52
52
 
53
53
  .magic-editor-layer-panel .cus-tree-node {
54
54
  width: 100%;
55
+ overflow: hidden;
55
56
  }
56
57
 
57
58
  .magic-editor-layer-panel .cus-tree-node-hover {
package/src/type.ts CHANGED
@@ -220,7 +220,9 @@ export interface ComponentItem {
220
220
  type: string;
221
221
  /** element-plus icon class */
222
222
  icon?: string | Component;
223
- [key: string]: any;
223
+ data?: {
224
+ [key: string]: any;
225
+ };
224
226
  }
225
227
 
226
228
  export interface ComponentGroup {