@tmagic/editor 1.3.0-alpha.5 → 1.3.0-alpha.6
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 +20 -5
- package/dist/tmagic-editor.js +259 -167
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +259 -166
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +10 -10
- package/src/Editor.vue +2 -0
- package/src/{layouts → components}/Resizer.vue +15 -6
- package/src/components/{Layout.vue → SplitView.vue} +1 -1
- package/src/index.ts +2 -1
- package/src/layouts/Framework.vue +3 -3
- package/src/layouts/sidebar/LayerPanel.vue +32 -15
- package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +3 -3
- package/src/layouts/workspace/Workspace.vue +3 -132
- package/src/services/keybinding.ts +240 -0
- package/src/theme/resizer.scss +25 -10
- package/src/type.ts +3 -1
- package/types/index.d.ts +2 -1
- package/types/services/keybinding.d.ts +12 -0
- package/types/type.d.ts +3 -1
- /package/types/{layouts → components}/Resizer.vue.d.ts +0 -0
- /package/types/components/{Layout.vue.d.ts → SplitView.vue.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.3.0-alpha.
|
|
2
|
+
"version": "1.3.0-alpha.6",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@babel/core": "^7.18.0",
|
|
48
48
|
"@element-plus/icons-vue": "^2.0.9",
|
|
49
|
-
"@tmagic/core": "1.3.0-alpha.
|
|
50
|
-
"@tmagic/design": "1.3.0-alpha.
|
|
51
|
-
"@tmagic/form": "1.3.0-alpha.
|
|
52
|
-
"@tmagic/schema": "1.3.0-alpha.
|
|
53
|
-
"@tmagic/stage": "1.3.0-alpha.
|
|
54
|
-
"@tmagic/table": "1.3.0-alpha.
|
|
55
|
-
"@tmagic/utils": "1.3.0-alpha.
|
|
49
|
+
"@tmagic/core": "1.3.0-alpha.6",
|
|
50
|
+
"@tmagic/design": "1.3.0-alpha.6",
|
|
51
|
+
"@tmagic/form": "1.3.0-alpha.6",
|
|
52
|
+
"@tmagic/schema": "1.3.0-alpha.6",
|
|
53
|
+
"@tmagic/stage": "1.3.0-alpha.6",
|
|
54
|
+
"@tmagic/table": "1.3.0-alpha.6",
|
|
55
|
+
"@tmagic/utils": "1.3.0-alpha.6",
|
|
56
56
|
"buffer": "^6.0.3",
|
|
57
57
|
"color": "^3.1.3",
|
|
58
58
|
"events": "^3.3.0",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"vue": "^3.3.4"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@tmagic/design": "1.3.0-alpha.
|
|
68
|
-
"@tmagic/form": "1.3.0-alpha.
|
|
67
|
+
"@tmagic/design": "1.3.0-alpha.6",
|
|
68
|
+
"@tmagic/form": "1.3.0-alpha.6",
|
|
69
69
|
"monaco-editor": "^0.34.0",
|
|
70
70
|
"vue": "^3.3.4"
|
|
71
71
|
},
|
package/src/Editor.vue
CHANGED
|
@@ -96,6 +96,7 @@ import depService from './services/dep';
|
|
|
96
96
|
import editorService from './services/editor';
|
|
97
97
|
import eventsService from './services/events';
|
|
98
98
|
import historyService from './services/history';
|
|
99
|
+
import keybindingService from './services/keybinding';
|
|
99
100
|
import propsService from './services/props';
|
|
100
101
|
import storageService from './services/storage';
|
|
101
102
|
import uiService from './services/ui';
|
|
@@ -130,6 +131,7 @@ export default defineComponent({
|
|
|
130
131
|
codeBlockService,
|
|
131
132
|
depService,
|
|
132
133
|
dataSourceService,
|
|
134
|
+
keybindingService,
|
|
133
135
|
};
|
|
134
136
|
|
|
135
137
|
initServiceEvents(props, emit, services);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<span ref="target" class="m-editor-resizer">
|
|
2
|
+
<span ref="target" class="m-editor-resizer" :class="{ 'm-editor-resizer-draging': isDraging }">
|
|
3
3
|
<slot></slot>
|
|
4
4
|
</span>
|
|
5
5
|
</template>
|
|
@@ -15,6 +15,7 @@ defineOptions({
|
|
|
15
15
|
const emit = defineEmits(['change']);
|
|
16
16
|
|
|
17
17
|
const target = ref<HTMLSpanElement>();
|
|
18
|
+
const isDraging = ref(false);
|
|
18
19
|
|
|
19
20
|
let getso: Gesto;
|
|
20
21
|
|
|
@@ -23,14 +24,22 @@ onMounted(() => {
|
|
|
23
24
|
getso = new Gesto(target.value, {
|
|
24
25
|
container: window,
|
|
25
26
|
pinchOutside: true,
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
})
|
|
28
|
+
.on('drag', (e) => {
|
|
29
|
+
if (!target.value) return;
|
|
30
|
+
|
|
31
|
+
emit('change', e.deltaX);
|
|
32
|
+
})
|
|
33
|
+
.on('dragStart', () => {
|
|
34
|
+
isDraging.value = true;
|
|
35
|
+
})
|
|
36
|
+
.on('dragEnd', () => {
|
|
37
|
+
isDraging.value = false;
|
|
38
|
+
});
|
|
31
39
|
});
|
|
32
40
|
|
|
33
41
|
onUnmounted(() => {
|
|
34
42
|
getso?.unset();
|
|
43
|
+
isDraging.value = false;
|
|
35
44
|
});
|
|
36
45
|
</script>
|
package/src/index.ts
CHANGED
|
@@ -60,7 +60,8 @@ export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
|
60
60
|
export { default as ToolButton } from './components/ToolButton.vue';
|
|
61
61
|
export { default as ContentMenu } from './components/ContentMenu.vue';
|
|
62
62
|
export { default as Icon } from './components/Icon.vue';
|
|
63
|
-
export { default as LayoutContainer } from './components/
|
|
63
|
+
export { default as LayoutContainer } from './components/SplitView.vue';
|
|
64
|
+
export { default as SplitView } from './components/SplitView.vue';
|
|
64
65
|
|
|
65
66
|
const defaultInstallOpt: InstallOptions = {
|
|
66
67
|
// @todo, 自定义图片上传方法等编辑器依赖的外部选项
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<CodeEditor class="m-editor-content" :init-values="root" :options="codeOptions" @save="saveCode"></CodeEditor>
|
|
11
11
|
</slot>
|
|
12
12
|
|
|
13
|
-
<
|
|
13
|
+
<SplitView
|
|
14
14
|
v-else
|
|
15
15
|
class="m-editor-content"
|
|
16
16
|
left-class="m-editor-framework-left"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
<slot name="props-panel"></slot>
|
|
39
39
|
</TMagicScrollbar>
|
|
40
40
|
</template>
|
|
41
|
-
</
|
|
41
|
+
</SplitView>
|
|
42
42
|
|
|
43
43
|
<slot name="content-after"></slot>
|
|
44
44
|
<slot name="footer"></slot>
|
|
@@ -50,7 +50,7 @@ import { computed, inject, ref, watch } from 'vue';
|
|
|
50
50
|
|
|
51
51
|
import { TMagicScrollbar } from '@tmagic/design';
|
|
52
52
|
|
|
53
|
-
import
|
|
53
|
+
import SplitView from '@editor/components/SplitView.vue';
|
|
54
54
|
import type { GetColumnWidth, Services } from '@editor/type';
|
|
55
55
|
|
|
56
56
|
import AddPageBox from './AddPageBox.vue';
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
ref="tree"
|
|
11
11
|
node-key="id"
|
|
12
12
|
empty-text="页面空荡荡的"
|
|
13
|
+
tabindex="-1"
|
|
13
14
|
draggable
|
|
14
15
|
:default-expanded-keys="expandedKeys"
|
|
15
16
|
:default-checked-keys="checkedKeys"
|
|
@@ -75,6 +76,7 @@ defineProps<{
|
|
|
75
76
|
const throttleTime = 150;
|
|
76
77
|
const services = inject<Services>('services');
|
|
77
78
|
const editorService = services?.editorService;
|
|
79
|
+
const keybindingService = services?.keybindingService;
|
|
78
80
|
|
|
79
81
|
const tree = ref<InstanceType<typeof TMagicTree>>();
|
|
80
82
|
const menu = ref<InstanceType<typeof LayerMenu>>();
|
|
@@ -246,27 +248,40 @@ const windowBlurHandler = () => {
|
|
|
246
248
|
isCtrlKeyDown.value = false;
|
|
247
249
|
};
|
|
248
250
|
|
|
251
|
+
const globalKeyupHandler = () => {
|
|
252
|
+
if (document.activeElement !== tree.value?.$el) {
|
|
253
|
+
isCtrlKeyDown.value = false;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
249
257
|
let keycon: KeyController;
|
|
250
258
|
|
|
251
259
|
onMounted(() => {
|
|
252
260
|
editorService?.on('remove', editorServiceRemoveHandler);
|
|
253
261
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
.
|
|
260
|
-
|
|
262
|
+
if (tree.value?.$el) {
|
|
263
|
+
// 如果是在树上按下ctrl,那么在树外松开ctrl时,也要触发松开事件
|
|
264
|
+
keybindingService?.on('keyup', globalKeyupHandler);
|
|
265
|
+
|
|
266
|
+
keycon = new KeyController(tree.value.$el);
|
|
267
|
+
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
|
268
|
+
const ctrl = isMac ? 'meta' : 'ctrl';
|
|
269
|
+
|
|
270
|
+
keycon
|
|
271
|
+
.keydown((e) => {
|
|
272
|
+
if (e.key !== ctrl) {
|
|
273
|
+
isCtrlKeyDown.value = false;
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
.keydown(ctrl, () => {
|
|
277
|
+
isCtrlKeyDown.value = true;
|
|
278
|
+
})
|
|
279
|
+
.keyup(ctrl, () => {
|
|
261
280
|
isCtrlKeyDown.value = false;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
.
|
|
265
|
-
|
|
266
|
-
})
|
|
267
|
-
.keyup(ctrl, () => {
|
|
268
|
-
isCtrlKeyDown.value = false;
|
|
269
|
-
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
tree.value.$el.addEventListener('blur', windowBlurHandler);
|
|
284
|
+
}
|
|
270
285
|
|
|
271
286
|
globalThis.addEventListener('blur', windowBlurHandler);
|
|
272
287
|
});
|
|
@@ -275,7 +290,9 @@ onUnmounted(() => {
|
|
|
275
290
|
keycon.destroy();
|
|
276
291
|
|
|
277
292
|
editorService?.off('remove', editorServiceRemoveHandler);
|
|
293
|
+
keybindingService?.off('keyup', globalKeyupHandler);
|
|
278
294
|
globalThis.removeEventListener('blur', windowBlurHandler);
|
|
295
|
+
tree.value?.$el.removeEventListener('blur', windowBlurHandler);
|
|
279
296
|
});
|
|
280
297
|
|
|
281
298
|
// 鼠标在组件树移动触发高亮
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
:size="size"
|
|
11
11
|
:before-close="handleClose"
|
|
12
12
|
>
|
|
13
|
-
<
|
|
13
|
+
<SplitView v-model:left="left" :min-left="45" class="code-editor-layout">
|
|
14
14
|
<!-- 右侧区域 -->
|
|
15
15
|
<template #center>
|
|
16
16
|
<div v-if="!isEmpty(codeConfig)" class="m-editor-code-block-editor-panel">
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
></FunctionEditor>
|
|
29
29
|
</div>
|
|
30
30
|
</template>
|
|
31
|
-
</
|
|
31
|
+
</SplitView>
|
|
32
32
|
</TMagicDrawer>
|
|
33
33
|
</template>
|
|
34
34
|
|
|
@@ -41,7 +41,7 @@ import { ColumnConfig } from '@tmagic/form';
|
|
|
41
41
|
import { CodeBlockContent } from '@tmagic/schema';
|
|
42
42
|
|
|
43
43
|
import FunctionEditor from '@editor/components/FunctionEditor.vue';
|
|
44
|
-
import
|
|
44
|
+
import SplitView from '@editor/components/SplitView.vue';
|
|
45
45
|
import type { ListState, Services } from '@editor/type';
|
|
46
46
|
import { serializeConfig } from '@editor/utils/editor';
|
|
47
47
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor-workspace" tabindex="-1"
|
|
2
|
+
<div class="m-editor-workspace" tabindex="-1">
|
|
3
3
|
<Breadcrumb></Breadcrumb>
|
|
4
4
|
|
|
5
5
|
<slot name="stage">
|
|
@@ -16,10 +16,7 @@
|
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
18
|
<script lang="ts" setup>
|
|
19
|
-
import { computed, inject
|
|
20
|
-
import KeyController from 'keycon';
|
|
21
|
-
|
|
22
|
-
import { isPage } from '@tmagic/utils';
|
|
19
|
+
import { computed, inject } from 'vue';
|
|
23
20
|
|
|
24
21
|
import type { MenuButton, MenuComponent, Services } from '@editor/type';
|
|
25
22
|
|
|
@@ -36,132 +33,6 @@ defineProps<{
|
|
|
36
33
|
}>();
|
|
37
34
|
|
|
38
35
|
const services = inject<Services>('services');
|
|
39
|
-
const workspace = ref<HTMLDivElement>();
|
|
40
|
-
const nodes = computed(() => services?.editorService.get('nodes'));
|
|
41
|
-
const page = computed(() => services?.editorService.get('page'));
|
|
42
|
-
|
|
43
|
-
const mouseenterHandler = () => {
|
|
44
|
-
workspace.value?.focus();
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const mouseleaveHandler = () => {
|
|
48
|
-
workspace.value?.blur();
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
let keycon: KeyController;
|
|
52
|
-
|
|
53
|
-
onMounted(() => {
|
|
54
|
-
workspace.value?.addEventListener('mouseenter', mouseenterHandler);
|
|
55
|
-
workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
|
|
56
|
-
|
|
57
|
-
keycon = new KeyController(workspace.value);
|
|
58
36
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const ctrl = isMac ? 'meta' : 'ctrl';
|
|
62
|
-
|
|
63
|
-
keycon
|
|
64
|
-
.keyup('delete', (e) => {
|
|
65
|
-
e.inputEvent.preventDefault();
|
|
66
|
-
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
67
|
-
services?.editorService.remove(nodes.value);
|
|
68
|
-
})
|
|
69
|
-
.keyup('backspace', (e) => {
|
|
70
|
-
e.inputEvent.preventDefault();
|
|
71
|
-
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
72
|
-
services?.editorService.remove(nodes.value);
|
|
73
|
-
})
|
|
74
|
-
.keydown([ctrl, 'c'], (e) => {
|
|
75
|
-
e.inputEvent.preventDefault();
|
|
76
|
-
nodes.value && services?.editorService.copy(nodes.value);
|
|
77
|
-
})
|
|
78
|
-
.keydown([ctrl, 'v'], (e) => {
|
|
79
|
-
e.inputEvent.preventDefault();
|
|
80
|
-
nodes.value && services?.editorService.paste({ offsetX: 10, offsetY: 10 });
|
|
81
|
-
})
|
|
82
|
-
.keydown([ctrl, 'x'], (e) => {
|
|
83
|
-
e.inputEvent.preventDefault();
|
|
84
|
-
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
85
|
-
services?.editorService.copy(nodes.value);
|
|
86
|
-
services?.editorService.remove(nodes.value);
|
|
87
|
-
})
|
|
88
|
-
.keydown([ctrl, 'z'], (e) => {
|
|
89
|
-
e.inputEvent.preventDefault();
|
|
90
|
-
services?.editorService.undo();
|
|
91
|
-
})
|
|
92
|
-
.keydown([ctrl, 'shift', 'z'], (e) => {
|
|
93
|
-
e.inputEvent.preventDefault();
|
|
94
|
-
services?.editorService.redo();
|
|
95
|
-
})
|
|
96
|
-
.keydown('up', (e) => {
|
|
97
|
-
e.inputEvent.preventDefault();
|
|
98
|
-
services?.editorService.move(0, -1);
|
|
99
|
-
})
|
|
100
|
-
.keydown('down', (e) => {
|
|
101
|
-
e.inputEvent.preventDefault();
|
|
102
|
-
services?.editorService.move(0, 1);
|
|
103
|
-
})
|
|
104
|
-
.keydown('left', (e) => {
|
|
105
|
-
e.inputEvent.preventDefault();
|
|
106
|
-
services?.editorService.move(-1, 0);
|
|
107
|
-
})
|
|
108
|
-
.keydown('right', (e) => {
|
|
109
|
-
e.inputEvent.preventDefault();
|
|
110
|
-
services?.editorService.move(1, 0);
|
|
111
|
-
})
|
|
112
|
-
.keydown([ctrl, 'up'], (e) => {
|
|
113
|
-
e.inputEvent.preventDefault();
|
|
114
|
-
services?.editorService.move(0, -10);
|
|
115
|
-
})
|
|
116
|
-
.keydown([ctrl, 'down'], (e) => {
|
|
117
|
-
e.inputEvent.preventDefault();
|
|
118
|
-
services?.editorService.move(0, 10);
|
|
119
|
-
})
|
|
120
|
-
.keydown([ctrl, 'left'], (e) => {
|
|
121
|
-
e.inputEvent.preventDefault();
|
|
122
|
-
services?.editorService.move(-10, 0);
|
|
123
|
-
})
|
|
124
|
-
.keydown([ctrl, 'right'], (e) => {
|
|
125
|
-
e.inputEvent.preventDefault();
|
|
126
|
-
services?.editorService.move(10, 0);
|
|
127
|
-
})
|
|
128
|
-
.keydown('tab', (e) => {
|
|
129
|
-
e.inputEvent.preventDefault();
|
|
130
|
-
services?.editorService.selectNextNode();
|
|
131
|
-
})
|
|
132
|
-
.keydown([ctrl, 'tab'], (e) => {
|
|
133
|
-
e.inputEvent.preventDefault();
|
|
134
|
-
services?.editorService.selectNextPage();
|
|
135
|
-
})
|
|
136
|
-
.keydown([ctrl, '='], (e) => {
|
|
137
|
-
e.inputEvent.preventDefault();
|
|
138
|
-
services?.uiService.zoom(0.1);
|
|
139
|
-
})
|
|
140
|
-
.keydown([ctrl, 'numpadplus'], (e) => {
|
|
141
|
-
e.inputEvent.preventDefault();
|
|
142
|
-
services?.uiService.zoom(0.1);
|
|
143
|
-
})
|
|
144
|
-
.keydown([ctrl, '-'], (e) => {
|
|
145
|
-
e.inputEvent.preventDefault();
|
|
146
|
-
services?.uiService.zoom(-0.1);
|
|
147
|
-
})
|
|
148
|
-
.keydown([ctrl, 'numpad-'], (e) => {
|
|
149
|
-
e.inputEvent.preventDefault();
|
|
150
|
-
services?.uiService.zoom(-0.1);
|
|
151
|
-
})
|
|
152
|
-
.keydown([ctrl, '0'], async (e) => {
|
|
153
|
-
e.inputEvent.preventDefault();
|
|
154
|
-
services?.uiService.set('zoom', await services.uiService.calcZoom());
|
|
155
|
-
})
|
|
156
|
-
.keydown([ctrl, '1'], (e) => {
|
|
157
|
-
e.inputEvent.preventDefault();
|
|
158
|
-
services?.uiService.set('zoom', 1);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
onUnmounted(() => {
|
|
163
|
-
workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
|
|
164
|
-
workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
|
|
165
|
-
keycon.destroy();
|
|
166
|
-
});
|
|
37
|
+
const page = computed(() => services?.editorService.get('page'));
|
|
167
38
|
</script>
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import KeyController from 'keycon';
|
|
2
|
+
|
|
3
|
+
import { isPage } from '@tmagic/utils';
|
|
4
|
+
|
|
5
|
+
import BaseService from './BaseService';
|
|
6
|
+
import editorService from './editor';
|
|
7
|
+
import uiService from './ui';
|
|
8
|
+
|
|
9
|
+
class Keybinding extends BaseService {
|
|
10
|
+
private keycon = new KeyController();
|
|
11
|
+
|
|
12
|
+
private ctrlKey = /mac os x/.test(navigator.userAgent.toLowerCase()) ? 'meta' : 'ctrl';
|
|
13
|
+
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
|
|
17
|
+
this.keycon
|
|
18
|
+
.keyup((e) => {
|
|
19
|
+
this.emit('keyup', e.inputEvent);
|
|
20
|
+
})
|
|
21
|
+
.keyup('delete', (e) => {
|
|
22
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
e.inputEvent.preventDefault();
|
|
27
|
+
|
|
28
|
+
this.removeNode();
|
|
29
|
+
})
|
|
30
|
+
.keyup('backspace', (e) => {
|
|
31
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
e.inputEvent.preventDefault();
|
|
36
|
+
|
|
37
|
+
this.removeNode();
|
|
38
|
+
})
|
|
39
|
+
.keydown([this.ctrlKey, 'c'], (e) => {
|
|
40
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
e.inputEvent.preventDefault();
|
|
45
|
+
|
|
46
|
+
const nodes = editorService.get('nodes');
|
|
47
|
+
nodes && editorService.copy(nodes);
|
|
48
|
+
})
|
|
49
|
+
.keydown([this.ctrlKey, 'v'], (e) => {
|
|
50
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
e.inputEvent.preventDefault();
|
|
55
|
+
|
|
56
|
+
const nodes = editorService.get('nodes');
|
|
57
|
+
nodes && editorService.paste({ offsetX: 10, offsetY: 10 });
|
|
58
|
+
})
|
|
59
|
+
.keydown([this.ctrlKey, 'x'], (e) => {
|
|
60
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
e.inputEvent.preventDefault();
|
|
65
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const nodes = editorService.get('nodes');
|
|
70
|
+
|
|
71
|
+
if (!nodes || isPage(nodes[0])) return;
|
|
72
|
+
editorService.copy(nodes);
|
|
73
|
+
editorService.remove(nodes);
|
|
74
|
+
})
|
|
75
|
+
.keydown([this.ctrlKey, 'z'], (e) => {
|
|
76
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
e.inputEvent.preventDefault();
|
|
81
|
+
editorService.undo();
|
|
82
|
+
})
|
|
83
|
+
.keydown([this.ctrlKey, 'shift', 'z'], (e) => {
|
|
84
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
e.inputEvent.preventDefault();
|
|
89
|
+
editorService.redo();
|
|
90
|
+
})
|
|
91
|
+
.keydown('up', (e) => {
|
|
92
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
e.inputEvent.preventDefault();
|
|
97
|
+
editorService.move(0, -1);
|
|
98
|
+
})
|
|
99
|
+
.keydown('down', (e) => {
|
|
100
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
e.inputEvent.preventDefault();
|
|
105
|
+
editorService.move(0, 1);
|
|
106
|
+
})
|
|
107
|
+
.keydown('left', (e) => {
|
|
108
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
e.inputEvent.preventDefault();
|
|
113
|
+
editorService.move(-1, 0);
|
|
114
|
+
})
|
|
115
|
+
.keydown('right', (e) => {
|
|
116
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
e.inputEvent.preventDefault();
|
|
121
|
+
editorService.move(1, 0);
|
|
122
|
+
})
|
|
123
|
+
.keydown([this.ctrlKey, 'up'], (e) => {
|
|
124
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
e.inputEvent.preventDefault();
|
|
129
|
+
editorService.move(0, -10);
|
|
130
|
+
})
|
|
131
|
+
.keydown([this.ctrlKey, 'down'], (e) => {
|
|
132
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
e.inputEvent.preventDefault();
|
|
137
|
+
editorService.move(0, 10);
|
|
138
|
+
})
|
|
139
|
+
.keydown([this.ctrlKey, 'left'], (e) => {
|
|
140
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
e.inputEvent.preventDefault();
|
|
145
|
+
editorService.move(-10, 0);
|
|
146
|
+
})
|
|
147
|
+
.keydown([this.ctrlKey, 'right'], (e) => {
|
|
148
|
+
e.inputEvent.preventDefault();
|
|
149
|
+
editorService.move(10, 0);
|
|
150
|
+
})
|
|
151
|
+
.keydown('tab', (e) => {
|
|
152
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
e.inputEvent.preventDefault();
|
|
157
|
+
editorService.selectNextNode();
|
|
158
|
+
})
|
|
159
|
+
.keydown([this.ctrlKey, 'tab'], (e) => {
|
|
160
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
e.inputEvent.preventDefault();
|
|
165
|
+
editorService.selectNextPage();
|
|
166
|
+
})
|
|
167
|
+
.keydown([this.ctrlKey, '='], (e) => {
|
|
168
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
e.inputEvent.preventDefault();
|
|
173
|
+
uiService.zoom(0.1);
|
|
174
|
+
})
|
|
175
|
+
.keydown([this.ctrlKey, 'numpadplus'], (e) => {
|
|
176
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
e.inputEvent.preventDefault();
|
|
181
|
+
uiService.zoom(0.1);
|
|
182
|
+
})
|
|
183
|
+
.keydown([this.ctrlKey, '-'], (e) => {
|
|
184
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
e.inputEvent.preventDefault();
|
|
189
|
+
uiService.zoom(-0.1);
|
|
190
|
+
})
|
|
191
|
+
.keydown([this.ctrlKey, 'numpad-'], (e) => {
|
|
192
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
e.inputEvent.preventDefault();
|
|
197
|
+
uiService.zoom(-0.1);
|
|
198
|
+
})
|
|
199
|
+
.keydown([this.ctrlKey, '0'], async (e) => {
|
|
200
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
e.inputEvent.preventDefault();
|
|
205
|
+
uiService.set('zoom', await uiService.calcZoom());
|
|
206
|
+
})
|
|
207
|
+
.keydown([this.ctrlKey, '1'], (e) => {
|
|
208
|
+
if (this.isDisabledKeyEvent(e.inputEvent.target)) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
e.inputEvent.preventDefault();
|
|
213
|
+
uiService.set('zoom', 1);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
public destroy() {
|
|
218
|
+
this.keycon.destroy();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private isDisabledKeyEvent(node: EventTarget | null) {
|
|
222
|
+
const el = node as HTMLElement | null;
|
|
223
|
+
|
|
224
|
+
if (!el) return false;
|
|
225
|
+
|
|
226
|
+
// 当前是在输入框中,禁止响应画布快捷键
|
|
227
|
+
return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private removeNode() {
|
|
231
|
+
const nodes = editorService.get('nodes');
|
|
232
|
+
|
|
233
|
+
if (!nodes || isPage(nodes[0])) return;
|
|
234
|
+
editorService.remove(nodes);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export type KeybindingService = Keybinding;
|
|
239
|
+
|
|
240
|
+
export default new Keybinding();
|