@tmagic/editor 1.1.0-beta.12 → 1.1.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.
- package/dist/style.css +46 -0
- package/dist/tmagic-editor.mjs +781 -688
- package/dist/tmagic-editor.mjs.map +1 -1
- package/dist/tmagic-editor.umd.js +783 -686
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/package.json +8 -8
- package/src/Editor.vue +3 -3
- package/src/components/ContentMenu.vue +4 -4
- package/src/components/Icon.vue +6 -20
- package/src/components/ScrollBar.vue +147 -0
- package/src/components/ScrollViewer.vue +89 -44
- package/src/components/ToolButton.vue +40 -138
- package/src/index.ts +2 -0
- package/src/layouts/NavMenu.vue +156 -23
- package/src/layouts/sidebar/LayerMenu.vue +3 -3
- package/src/layouts/workspace/Stage.vue +8 -90
- package/src/layouts/workspace/ViewerMenu.vue +3 -3
- package/src/layouts/workspace/Workspace.vue +131 -138
- package/src/services/ui.ts +16 -20
- package/src/theme/nav-menu.scss +6 -0
- package/src/type.ts +26 -10
- package/src/utils/index.ts +1 -0
- package/src/utils/scroll-viewer.ts +90 -158
- package/src/utils/stage.ts +91 -0
- package/types/Editor.vue.d.ts +7 -7
- package/types/components/ContentMenu.vue.d.ts +8 -8
- package/types/components/Icon.vue.d.ts +62 -12
- package/types/components/ScrollBar.vue.d.ts +83 -0
- package/types/components/ScrollViewer.vue.d.ts +131 -19
- package/types/components/ToolButton.vue.d.ts +56 -59
- package/types/index.d.ts +2 -0
- package/types/layouts/NavMenu.vue.d.ts +92 -23
- package/types/layouts/sidebar/LayerMenu.vue.d.ts +7 -7
- package/types/layouts/sidebar/LayerPanel.vue.d.ts +12 -12
- package/types/layouts/workspace/Workspace.vue.d.ts +54 -4
- package/types/services/ui.d.ts +1 -1
- package/types/type.d.ts +23 -10
- package/types/utils/index.d.ts +1 -0
- package/types/utils/scroll-viewer.d.ts +16 -18
- package/types/utils/stage.d.ts +3 -0
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-editor-workspace" tabindex="1" ref="workspace">
|
|
3
3
|
<slot name="stage">
|
|
4
|
-
<
|
|
4
|
+
<MagicStage :key="page?.id"></MagicStage>
|
|
5
5
|
</slot>
|
|
6
6
|
|
|
7
7
|
<slot name="workspace-content"></slot>
|
|
8
8
|
|
|
9
|
-
<
|
|
9
|
+
<PageBar>
|
|
10
10
|
<template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
|
|
11
11
|
<template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
|
|
12
|
-
</
|
|
12
|
+
</PageBar>
|
|
13
13
|
</div>
|
|
14
14
|
</template>
|
|
15
15
|
|
|
16
|
-
<script lang="ts">
|
|
17
|
-
import { computed,
|
|
16
|
+
<script lang="ts" setup>
|
|
17
|
+
import { computed, inject, onMounted, onUnmounted, ref } from 'vue';
|
|
18
18
|
import KeyController from 'keycon';
|
|
19
19
|
|
|
20
20
|
import type { MNode, MPage } from '@tmagic/schema';
|
|
@@ -25,140 +25,133 @@ import type { Services } from '../../type';
|
|
|
25
25
|
import PageBar from './PageBar.vue';
|
|
26
26
|
import MagicStage from './Stage.vue';
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
28
|
+
const services = inject<Services>('services');
|
|
29
|
+
const workspace = ref<HTMLDivElement>();
|
|
30
|
+
const nodes = computed(() => services?.editorService.get<MNode[]>('nodes'));
|
|
31
|
+
const page = computed(() => services?.editorService.get<MPage>('page'));
|
|
32
|
+
|
|
33
|
+
const mouseenterHandler = () => {
|
|
34
|
+
workspace.value?.focus();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const mouseleaveHandler = () => {
|
|
38
|
+
workspace.value?.blur();
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
let keycon: KeyController;
|
|
42
|
+
|
|
43
|
+
onMounted(() => {
|
|
44
|
+
workspace.value?.addEventListener('mouseenter', mouseenterHandler);
|
|
45
|
+
workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
|
|
46
|
+
|
|
47
|
+
keycon = new KeyController(workspace.value);
|
|
48
|
+
|
|
49
|
+
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
|
50
|
+
|
|
51
|
+
const ctrl = isMac ? 'meta' : 'ctrl';
|
|
52
|
+
|
|
53
|
+
keycon
|
|
54
|
+
.keyup('delete', (e) => {
|
|
55
|
+
e.inputEvent.preventDefault();
|
|
56
|
+
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
57
|
+
services?.editorService.remove(nodes.value);
|
|
58
|
+
})
|
|
59
|
+
.keyup('backspace', (e) => {
|
|
60
|
+
e.inputEvent.preventDefault();
|
|
61
|
+
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
62
|
+
services?.editorService.remove(nodes.value);
|
|
63
|
+
})
|
|
64
|
+
.keydown([ctrl, 'c'], (e) => {
|
|
65
|
+
e.inputEvent.preventDefault();
|
|
66
|
+
nodes.value && services?.editorService.copy(nodes.value);
|
|
67
|
+
})
|
|
68
|
+
.keydown([ctrl, 'v'], (e) => {
|
|
69
|
+
e.inputEvent.preventDefault();
|
|
70
|
+
nodes.value && services?.editorService.paste({ offsetX: 10, offsetY: 10 });
|
|
71
|
+
})
|
|
72
|
+
.keydown([ctrl, 'x'], (e) => {
|
|
73
|
+
e.inputEvent.preventDefault();
|
|
74
|
+
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
75
|
+
services?.editorService.copy(nodes.value);
|
|
76
|
+
services?.editorService.remove(nodes.value);
|
|
77
|
+
})
|
|
78
|
+
.keydown([ctrl, 'z'], (e) => {
|
|
79
|
+
e.inputEvent.preventDefault();
|
|
80
|
+
services?.editorService.undo();
|
|
81
|
+
})
|
|
82
|
+
.keydown([ctrl, 'shift', 'z'], (e) => {
|
|
83
|
+
e.inputEvent.preventDefault();
|
|
84
|
+
services?.editorService.redo();
|
|
85
|
+
})
|
|
86
|
+
.keydown('up', (e) => {
|
|
87
|
+
e.inputEvent.preventDefault();
|
|
88
|
+
services?.editorService.move(0, -1);
|
|
89
|
+
})
|
|
90
|
+
.keydown('down', (e) => {
|
|
91
|
+
e.inputEvent.preventDefault();
|
|
92
|
+
services?.editorService.move(0, 1);
|
|
93
|
+
})
|
|
94
|
+
.keydown('left', (e) => {
|
|
95
|
+
e.inputEvent.preventDefault();
|
|
96
|
+
services?.editorService.move(-1, 0);
|
|
97
|
+
})
|
|
98
|
+
.keydown('right', (e) => {
|
|
99
|
+
e.inputEvent.preventDefault();
|
|
100
|
+
services?.editorService.move(1, 0);
|
|
101
|
+
})
|
|
102
|
+
.keydown([ctrl, 'up'], (e) => {
|
|
103
|
+
e.inputEvent.preventDefault();
|
|
104
|
+
services?.editorService.move(0, -10);
|
|
105
|
+
})
|
|
106
|
+
.keydown([ctrl, 'down'], (e) => {
|
|
107
|
+
e.inputEvent.preventDefault();
|
|
108
|
+
services?.editorService.move(0, 10);
|
|
109
|
+
})
|
|
110
|
+
.keydown([ctrl, 'left'], (e) => {
|
|
111
|
+
e.inputEvent.preventDefault();
|
|
112
|
+
services?.editorService.move(-10, 0);
|
|
113
|
+
})
|
|
114
|
+
.keydown([ctrl, 'right'], (e) => {
|
|
115
|
+
e.inputEvent.preventDefault();
|
|
116
|
+
services?.editorService.move(10, 0);
|
|
117
|
+
})
|
|
118
|
+
.keydown('tab', (e) => {
|
|
119
|
+
e.inputEvent.preventDefault();
|
|
120
|
+
services?.editorService.selectNextNode();
|
|
121
|
+
})
|
|
122
|
+
.keydown([ctrl, 'tab'], (e) => {
|
|
123
|
+
e.inputEvent.preventDefault();
|
|
124
|
+
services?.editorService.selectNextPage();
|
|
125
|
+
})
|
|
126
|
+
.keydown([ctrl, '='], (e) => {
|
|
127
|
+
e.inputEvent.preventDefault();
|
|
128
|
+
services?.uiService.zoom(0.1);
|
|
129
|
+
})
|
|
130
|
+
.keydown([ctrl, 'numpadplus'], (e) => {
|
|
131
|
+
e.inputEvent.preventDefault();
|
|
132
|
+
services?.uiService.zoom(0.1);
|
|
133
|
+
})
|
|
134
|
+
.keydown([ctrl, '-'], (e) => {
|
|
135
|
+
e.inputEvent.preventDefault();
|
|
136
|
+
services?.uiService.zoom(-0.1);
|
|
137
|
+
})
|
|
138
|
+
.keydown([ctrl, 'numpad-'], (e) => {
|
|
139
|
+
e.inputEvent.preventDefault();
|
|
140
|
+
services?.uiService.zoom(-0.1);
|
|
141
|
+
})
|
|
142
|
+
.keydown([ctrl, '0'], (e) => {
|
|
143
|
+
e.inputEvent.preventDefault();
|
|
144
|
+
services?.uiService.set('zoom', services.uiService.calcZoom());
|
|
145
|
+
})
|
|
146
|
+
.keydown([ctrl, '1'], (e) => {
|
|
147
|
+
e.inputEvent.preventDefault();
|
|
148
|
+
services?.uiService.set('zoom', 1);
|
|
149
149
|
});
|
|
150
|
+
});
|
|
150
151
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
return {
|
|
158
|
-
workspace,
|
|
159
|
-
|
|
160
|
-
page: computed(() => services?.editorService.get<MPage>('page')),
|
|
161
|
-
};
|
|
162
|
-
},
|
|
152
|
+
onUnmounted(() => {
|
|
153
|
+
workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
|
|
154
|
+
workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
|
|
155
|
+
keycon.destroy();
|
|
163
156
|
});
|
|
164
157
|
</script>
|
package/src/services/ui.ts
CHANGED
|
@@ -98,10 +98,6 @@ class Ui extends BaseService {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
(state as any)[name] = value;
|
|
101
|
-
|
|
102
|
-
if (name === 'stageContainerRect') {
|
|
103
|
-
state.zoom = this.calcZoom();
|
|
104
|
-
}
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
public get<T>(name: keyof typeof state): T {
|
|
@@ -113,6 +109,22 @@ class Ui extends BaseService {
|
|
|
113
109
|
if (this.get<number>('zoom') < 0.1) this.set('zoom', 0.1);
|
|
114
110
|
}
|
|
115
111
|
|
|
112
|
+
public calcZoom() {
|
|
113
|
+
const { stageRect, stageContainerRect } = state;
|
|
114
|
+
const { height, width } = stageContainerRect;
|
|
115
|
+
if (!width || !height) return 1;
|
|
116
|
+
|
|
117
|
+
// 30为标尺的大小
|
|
118
|
+
const stageWidth = stageRect.width + 30;
|
|
119
|
+
const stageHeight = stageRect.height + 30;
|
|
120
|
+
|
|
121
|
+
if (width > stageWidth && height > stageHeight) {
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
// 60/80是为了不要让画布太过去贴住四周(这样好看些)
|
|
125
|
+
return Math.min((width - 60) / stageWidth || 1, (height - 80) / stageHeight || 1);
|
|
126
|
+
}
|
|
127
|
+
|
|
116
128
|
private setColumnWidth({ left, center, right }: SetColumnWidth) {
|
|
117
129
|
const columnWidth = {
|
|
118
130
|
...toRaw(this.get<GetColumnWidth>('columnWidth')),
|
|
@@ -150,22 +162,6 @@ class Ui extends BaseService {
|
|
|
150
162
|
};
|
|
151
163
|
state.zoom = this.calcZoom();
|
|
152
164
|
}
|
|
153
|
-
|
|
154
|
-
private calcZoom() {
|
|
155
|
-
const { stageRect, stageContainerRect } = state;
|
|
156
|
-
const { height, width } = stageContainerRect;
|
|
157
|
-
if (!width || !height) return 1;
|
|
158
|
-
|
|
159
|
-
// 30为标尺的大小
|
|
160
|
-
const stageWidth = stageRect.width + 30;
|
|
161
|
-
const stageHeight = stageRect.height + 30;
|
|
162
|
-
|
|
163
|
-
if (width > stageWidth && height > stageHeight) {
|
|
164
|
-
return 1;
|
|
165
|
-
}
|
|
166
|
-
// 60/80是为了不要让画布太过去贴住四周(这样好看些)
|
|
167
|
-
return Math.min((width - 60) / stageWidth || 1, (height - 80) / stageHeight || 1);
|
|
168
|
-
}
|
|
169
165
|
}
|
|
170
166
|
|
|
171
167
|
export type UiService = Ui;
|
package/src/theme/nav-menu.scss
CHANGED
package/src/type.ts
CHANGED
|
@@ -82,16 +82,22 @@ export interface ComponentGroupState {
|
|
|
82
82
|
list: ComponentGroup[];
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
export enum ColumnLayout {
|
|
86
|
+
LEFT = 'left',
|
|
87
|
+
CENTER = 'center',
|
|
88
|
+
RIGHT = 'right',
|
|
89
|
+
}
|
|
90
|
+
|
|
85
91
|
export interface SetColumnWidth {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
[ColumnLayout.LEFT]?: number;
|
|
93
|
+
[ColumnLayout.CENTER]?: number | 'auto';
|
|
94
|
+
[ColumnLayout.RIGHT]?: number;
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
export interface GetColumnWidth {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
[ColumnLayout.LEFT]: number;
|
|
99
|
+
[ColumnLayout.CENTER]: number;
|
|
100
|
+
[ColumnLayout.RIGHT]: number;
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
export interface StageRect {
|
|
@@ -174,6 +180,7 @@ export interface MenuButton {
|
|
|
174
180
|
/** type为button/dropdown时点击运行的方法 */
|
|
175
181
|
handler?: (data: Services, event: MouseEvent) => Promise<any> | any;
|
|
176
182
|
/** type为dropdown时,下拉的菜单列表, 或者有子菜单时 */
|
|
183
|
+
className?: string;
|
|
177
184
|
items?: MenuButton[];
|
|
178
185
|
}
|
|
179
186
|
|
|
@@ -187,6 +194,7 @@ export interface MenuComponent {
|
|
|
187
194
|
listeners?: Record<string, Function>;
|
|
188
195
|
slots?: Record<string, any>;
|
|
189
196
|
/** 是否显示,默认为true */
|
|
197
|
+
className?: string;
|
|
190
198
|
display?: boolean | ((data?: Services) => Promise<boolean> | boolean);
|
|
191
199
|
}
|
|
192
200
|
|
|
@@ -209,16 +217,17 @@ export type MenuItem =
|
|
|
209
217
|
| 'guides'
|
|
210
218
|
| 'rule'
|
|
211
219
|
| MenuButton
|
|
212
|
-
| MenuComponent
|
|
220
|
+
| MenuComponent
|
|
221
|
+
| string;
|
|
213
222
|
|
|
214
223
|
/** 工具栏 */
|
|
215
224
|
export interface MenuBarData {
|
|
216
225
|
/** 顶部工具栏左边项 */
|
|
217
|
-
|
|
226
|
+
[ColumnLayout.LEFT]?: MenuItem[];
|
|
218
227
|
/** 顶部工具栏中间项 */
|
|
219
|
-
|
|
228
|
+
[ColumnLayout.CENTER]?: MenuItem[];
|
|
220
229
|
/** 顶部工具栏右边项 */
|
|
221
|
-
|
|
230
|
+
[ColumnLayout.RIGHT]?: MenuItem[];
|
|
222
231
|
}
|
|
223
232
|
|
|
224
233
|
export interface SideComponent extends MenuComponent {
|
|
@@ -287,3 +296,10 @@ export enum Keys {
|
|
|
287
296
|
|
|
288
297
|
export const H_GUIDE_LINE_STORAGE_KEY = '$MagicStageHorizontalGuidelinesData';
|
|
289
298
|
export const V_GUIDE_LINE_STORAGE_KEY = '$MagicStageVerticalGuidelinesData';
|
|
299
|
+
|
|
300
|
+
export interface ScrollViewerEvent {
|
|
301
|
+
scrollLeft: number;
|
|
302
|
+
scrollTop: number;
|
|
303
|
+
scrollHeight: number;
|
|
304
|
+
scrollWidth: number;
|
|
305
|
+
}
|
package/src/utils/index.ts
CHANGED