@tmagic/editor 1.3.0-alpha.6 → 1.3.0-alpha.8

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 (38) hide show
  1. package/dist/style.css +17 -0
  2. package/dist/tmagic-editor.js +471 -264
  3. package/dist/tmagic-editor.js.map +1 -1
  4. package/dist/tmagic-editor.umd.cjs +474 -265
  5. package/dist/tmagic-editor.umd.cjs.map +1 -1
  6. package/package.json +12 -12
  7. package/src/Editor.vue +3 -0
  8. package/src/components/ContentMenu.vue +15 -8
  9. package/src/components/FunctionEditor.vue +6 -4
  10. package/src/components/SplitView.vue +2 -2
  11. package/src/fields/CodeLink.vue +4 -2
  12. package/src/fields/DataSourceInput.vue +11 -10
  13. package/src/index.ts +4 -2
  14. package/src/initService.ts +2 -0
  15. package/src/layouts/Framework.vue +4 -4
  16. package/src/layouts/PropsPanel.vue +2 -1
  17. package/src/layouts/sidebar/LayerMenu.vue +4 -3
  18. package/src/layouts/sidebar/LayerPanel.vue +55 -32
  19. package/src/layouts/workspace/Stage.vue +13 -3
  20. package/src/layouts/workspace/Workspace.vue +2 -2
  21. package/src/services/codeBlock.ts +3 -2
  22. package/src/services/keybinding.ts +148 -203
  23. package/src/services/storage.ts +3 -2
  24. package/src/theme/data-source-input.scss +18 -0
  25. package/src/theme/stage.scss +4 -0
  26. package/src/theme/theme.scss +1 -0
  27. package/src/type.ts +56 -0
  28. package/src/utils/config.ts +1 -1
  29. package/src/utils/keybinding-config.ts +120 -0
  30. package/src/utils/props.ts +34 -0
  31. package/types/components/ContentMenu.vue.d.ts +2 -0
  32. package/types/index.d.ts +2 -1
  33. package/types/initService.d.ts +1 -1
  34. package/types/layouts/workspace/Workspace.vue.d.ts +1 -1
  35. package/types/services/keybinding.d.ts +13 -5
  36. package/types/type.d.ts +53 -0
  37. package/types/utils/config.d.ts +1 -1
  38. package/types/utils/keybinding-config.d.ts +3 -0
@@ -1,237 +1,182 @@
1
- import KeyController from 'keycon';
1
+ import KeyController, { KeyControllerEvent } from 'keycon';
2
2
 
3
3
  import { isPage } from '@tmagic/utils';
4
4
 
5
+ import { KeyBindingCacheItem, KeyBindingCommand, KeyBindingItem } from '@editor/type';
6
+
5
7
  import BaseService from './BaseService';
6
8
  import editorService from './editor';
7
9
  import uiService from './ui';
8
10
 
9
11
  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
- }
12
+ public ctrlKey = /mac os x/.test(navigator.userAgent.toLowerCase()) ? 'meta' : 'ctrl';
13
+
14
+ private controllers = new Map<string, KeyController>();
15
+
16
+ private bindingList: KeyBindingCacheItem[] = [];
17
+
18
+ private commands: Record<KeyBindingCommand | string, (e: KeyboardEvent) => void | Promise<void>> = {
19
+ [KeyBindingCommand.DELETE_NODE]: () => {
20
+ const nodes = editorService.get('nodes');
21
+
22
+ if (!nodes || isPage(nodes[0])) return;
23
+ editorService.remove(nodes);
24
+ },
25
+ [KeyBindingCommand.COPY_NODE]: () => {
26
+ const nodes = editorService.get('nodes');
27
+ nodes && editorService.copy(nodes);
28
+ },
29
+ [KeyBindingCommand.CUT_NODE]: () => {
30
+ const nodes = editorService.get('nodes');
31
+
32
+ if (!nodes || isPage(nodes[0])) return;
33
+ editorService.copy(nodes);
34
+ editorService.remove(nodes);
35
+ },
36
+ [KeyBindingCommand.PASTE_NODE]: () => {
37
+ const nodes = editorService.get('nodes');
38
+ nodes && editorService.paste({ offsetX: 10, offsetY: 10 });
39
+ },
40
+ [KeyBindingCommand.UNDO]: () => {
41
+ editorService.undo();
42
+ },
43
+ [KeyBindingCommand.REDO]: () => {
44
+ editorService.redo();
45
+ },
46
+ [KeyBindingCommand.ZOOM_IN]: () => {
47
+ uiService.zoom(0.1);
48
+ },
49
+ [KeyBindingCommand.ZOOM_OUT]: () => {
50
+ uiService.zoom(-0.1);
51
+ },
52
+ [KeyBindingCommand.ZOOM_RESET]: () => {
53
+ uiService.set('zoom', 1);
54
+ },
55
+ [KeyBindingCommand.ZOOM_FIT]: async () => {
56
+ uiService.set('zoom', await uiService.calcZoom());
57
+ },
58
+ [KeyBindingCommand.MOVE_UP_1]: () => {
59
+ editorService.move(0, -1);
60
+ },
61
+ [KeyBindingCommand.MOVE_DOWN_1]: () => {
62
+ editorService.move(0, 1);
63
+ },
64
+ [KeyBindingCommand.MOVE_LEFT_1]: () => {
65
+ editorService.move(-1, 0);
66
+ },
67
+ [KeyBindingCommand.MOVE_RIGHT_1]: () => {
68
+ editorService.move(1, 0);
69
+ },
70
+ [KeyBindingCommand.MOVE_UP_10]: () => {
71
+ editorService.move(0, -10);
72
+ },
73
+ [KeyBindingCommand.MOVE_DOWN_10]: () => {
74
+ editorService.move(0, 10);
75
+ },
76
+ [KeyBindingCommand.MOVE_LEFT_10]: () => {
77
+ editorService.move(-10, 0);
78
+ },
79
+ [KeyBindingCommand.MOVE_RIGHT_10]: () => {
80
+ editorService.move(10, 0);
81
+ },
82
+ [KeyBindingCommand.SWITCH_NODE]: () => {
83
+ editorService.selectNextNode();
84
+ },
85
+ };
86
+
87
+ public registeCommand(command: string, handler: (e: KeyboardEvent) => void | Promise<void>) {
88
+ this.commands[command] = handler;
89
+ }
79
90
 
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
- }
91
+ public unregisteCommand(command: string) {
92
+ delete this.commands[command];
93
+ }
87
94
 
88
- e.inputEvent.preventDefault();
89
- editorService.redo();
90
- })
91
- .keydown('up', (e) => {
92
- if (this.isDisabledKeyEvent(e.inputEvent.target)) {
93
- return;
94
- }
95
+ public registeEl(name: string, el?: HTMLElement) {
96
+ if (name !== 'global' && !el) {
97
+ throw new Error('只有name为global可以不传el');
98
+ }
95
99
 
96
- e.inputEvent.preventDefault();
97
- editorService.move(0, -1);
98
- })
99
- .keydown('down', (e) => {
100
- if (this.isDisabledKeyEvent(e.inputEvent.target)) {
101
- return;
102
- }
100
+ const keycon = new KeyController(el);
101
+ this.controllers.set(name, keycon);
102
+ this.bind(name);
103
+ }
103
104
 
104
- e.inputEvent.preventDefault();
105
- editorService.move(0, 1);
106
- })
107
- .keydown('left', (e) => {
108
- if (this.isDisabledKeyEvent(e.inputEvent.target)) {
109
- return;
110
- }
105
+ public unregisteEl(name: string) {
106
+ this.controllers.get(name)?.destroy();
107
+ this.controllers.delete(name);
108
+ this.bindingList.forEach((item) => {
109
+ item.binded = false;
110
+ });
111
+ }
111
112
 
112
- e.inputEvent.preventDefault();
113
- editorService.move(-1, 0);
114
- })
115
- .keydown('right', (e) => {
116
- if (this.isDisabledKeyEvent(e.inputEvent.target)) {
117
- return;
118
- }
113
+ public registe(maps: KeyBindingItem[]) {
114
+ for (const keybindingItem of maps) {
115
+ const { command, keybinding, when } = keybindingItem;
119
116
 
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
- }
117
+ for (const [type = '', eventType = 'keydown'] of when) {
118
+ const cacheItem: KeyBindingCacheItem = { type, command, keybinding, eventType, binded: false };
127
119
 
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
- }
120
+ this.bindingList.push(cacheItem);
121
+ }
122
+ }
135
123
 
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
- }
124
+ this.bind();
125
+ }
143
126
 
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
- }
127
+ public reset() {
128
+ this.controllers.forEach((keycon) => {
129
+ keycon.destroy();
130
+ });
131
+ this.controllers.clear();
132
+ this.bindingList = [];
133
+ }
155
134
 
156
- e.inputEvent.preventDefault();
157
- editorService.selectNextNode();
158
- })
159
- .keydown([this.ctrlKey, 'tab'], (e) => {
160
- if (this.isDisabledKeyEvent(e.inputEvent.target)) {
161
- return;
162
- }
135
+ public destroy() {
136
+ this.reset();
137
+ }
163
138
 
164
- e.inputEvent.preventDefault();
165
- editorService.selectNextPage();
166
- })
167
- .keydown([this.ctrlKey, '='], (e) => {
168
- if (this.isDisabledKeyEvent(e.inputEvent.target)) {
169
- return;
170
- }
139
+ private bind(name?: string) {
140
+ for (const item of this.bindingList) {
141
+ const { type, eventType, command, keybinding, binded } = item;
171
142
 
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
- }
143
+ if (name && name !== type) {
144
+ continue;
145
+ }
179
146
 
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
- }
147
+ if (binded) {
148
+ continue;
149
+ }
187
150
 
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
- }
151
+ const keycon = this.controllers.get(type);
152
+ if (!keycon) {
153
+ continue;
154
+ }
195
155
 
156
+ const handler = (e: KeyControllerEvent) => {
196
157
  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
158
 
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;
159
+ this.commands[command]?.(e.inputEvent);
160
+ };
161
+ this.getKeyconKeys(keybinding).forEach((keys) => {
162
+ if (keys[0]) {
163
+ keycon[eventType](keys, handler);
164
+ } else {
165
+ keycon[eventType](handler);
210
166
  }
211
-
212
- e.inputEvent.preventDefault();
213
- uiService.set('zoom', 1);
214
167
  });
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
168
 
226
- // 当前是在输入框中,禁止响应画布快捷键
227
- return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable;
169
+ item.binded = true;
170
+ }
228
171
  }
229
172
 
230
- private removeNode() {
231
- const nodes = editorService.get('nodes');
173
+ private getKeyconKeys(keybinding: string | string[] = '') {
174
+ const splitKey = (key: string) => key.split('+').map((k) => (k === 'ctrl' ? this.ctrlKey : k));
232
175
 
233
- if (!nodes || isPage(nodes[0])) return;
234
- editorService.remove(nodes);
176
+ if (Array.isArray(keybinding)) {
177
+ return keybinding.map((key) => splitKey(key));
178
+ }
179
+ return [splitKey(keybinding)];
235
180
  }
236
181
  }
237
182
 
@@ -1,5 +1,7 @@
1
1
  import serialize from 'serialize-javascript';
2
2
 
3
+ import { getConfig } from '@editor/utils/config';
4
+
3
5
  import BaseService from './BaseService';
4
6
 
5
7
  interface Options {
@@ -64,8 +66,7 @@ export class WebStorage extends BaseService {
64
66
 
65
67
  switch (protocol) {
66
68
  case Protocol.OBJECT:
67
- // eslint-disable-next-line no-eval
68
- return eval(`(${item})`);
69
+ return getConfig('parseDSL')(`(${item})`);
69
70
  case Protocol.JSON:
70
71
  return JSON.parse(item);
71
72
  case Protocol.NUMBER:
@@ -0,0 +1,18 @@
1
+ .tmagic-data-source-input-text {
2
+ .el-input__wrapper.tmagic-data-source-input-text-wrapper {
3
+ overflow: hidden;
4
+ padding-right: 30px;
5
+ }
6
+
7
+ .el-input__inner {
8
+ display: flex;
9
+ align-items: center;
10
+ overflow: hidden;
11
+ white-space: nowrap;
12
+ }
13
+
14
+ .tmagic-data-source-input-icon {
15
+ position: absolute;
16
+ right: 7px;
17
+ }
18
+ }
@@ -6,6 +6,10 @@
6
6
  display: flex;
7
7
  justify-content: center;
8
8
  align-items: center;
9
+
10
+ &:focus-visible {
11
+ outline: none;
12
+ }
9
13
  }
10
14
 
11
15
  .m-editor-stage-container {
@@ -19,4 +19,5 @@
19
19
  @import "./dep-list.scss";
20
20
  @import "./data-source.scss";
21
21
  @import "./data-source-fields.scss";
22
+ @import "./data-source-input.scss";
22
23
  @import "./key-value.scss";
package/src/type.ts CHANGED
@@ -45,6 +45,7 @@ export type BeforeAdd = (config: MNode, parent: MContainer) => Promise<MNode> |
45
45
  export type GetConfig = (config: FormConfig) => Promise<FormConfig> | FormConfig;
46
46
 
47
47
  export interface InstallOptions {
48
+ parseDSL: (dsl: string) => MApp;
48
49
  [key: string]: any;
49
50
  }
50
51
 
@@ -429,3 +430,58 @@ export interface EventSelectConfig {
429
430
  /** 联动代码配置 */
430
431
  codeActionConfig?: FormItem;
431
432
  }
433
+
434
+ export enum KeyBindingCommand {
435
+ /** 复制 */
436
+ COPY_NODE = 'tmagic-system-copy-node',
437
+ /** 粘贴 */
438
+ PASTE_NODE = 'tmagic-system-paste-node',
439
+ /** 删除 */
440
+ DELETE_NODE = 'tmagic-system-delete-node',
441
+ /** 剪切 */
442
+ CUT_NODE = 'tmagic-system-cut-node',
443
+ /** 撤销 */
444
+ UNDO = 'tmagic-system-undo',
445
+ /** 重做 */
446
+ REDO = 'tmagic-system-redo',
447
+ /** 放大 */
448
+ ZOOM_IN = 'tmagic-system-zoom-in',
449
+ /** 缩小 */
450
+ ZOOM_OUT = 'tmagic-system-zoom-out',
451
+ /** 缩放到实际大小 */
452
+ ZOOM_RESET = 'tmagic-system-zoom-reset',
453
+ /** 缩放以适应 */
454
+ ZOOM_FIT = 'tmagic-system-zoom-fit',
455
+ /** 向上移动1px */
456
+ MOVE_UP_1 = 'tmagic-system-move-up-1',
457
+ /** 向下移动1px */
458
+ MOVE_DOWN_1 = 'tmagic-system-move-down-1',
459
+ /** 向左移动1px */
460
+ MOVE_LEFT_1 = 'tmagic-system-move-left-1',
461
+ /** 向右移动1px */
462
+ MOVE_RIGHT_1 = 'tmagic-system-move-right-1',
463
+ /** 向上移动10px */
464
+ MOVE_UP_10 = 'tmagic-system-move-up-10',
465
+ /** 向下移动10px */
466
+ MOVE_DOWN_10 = 'tmagic-system-move-down-10',
467
+ /** 向左移动10px */
468
+ MOVE_LEFT_10 = 'tmagic-system-move-left-10',
469
+ /** 向右移动10px */
470
+ MOVE_RIGHT_10 = 'tmagic-system-move-right-10',
471
+ /** 切换组件 */
472
+ SWITCH_NODE = 'tmagic-system-switch-node',
473
+ }
474
+
475
+ export interface KeyBindingItem {
476
+ command: KeyBindingCommand | string;
477
+ keybinding?: string | string[];
478
+ when: [string, 'keyup' | 'keydown'][];
479
+ }
480
+
481
+ export interface KeyBindingCacheItem {
482
+ type: string;
483
+ command: KeyBindingCommand | string;
484
+ keybinding?: string | string[];
485
+ eventType: 'keyup' | 'keydown';
486
+ binded: boolean;
487
+ }
@@ -24,6 +24,6 @@ const setConfig = (option: InstallOptions): void => {
24
24
  $TMAGIC_EDITOR = option;
25
25
  };
26
26
 
27
- const getConfig = (key: keyof InstallOptions): unknown => $TMAGIC_EDITOR[key];
27
+ const getConfig = <K extends keyof InstallOptions>(key: K): InstallOptions[K] => $TMAGIC_EDITOR[key];
28
28
 
29
29
  export { getConfig, setConfig };
@@ -0,0 +1,120 @@
1
+ import { KeyBindingCommand, KeyBindingItem } from '@editor/type';
2
+
3
+ export default [
4
+ {
5
+ command: KeyBindingCommand.DELETE_NODE,
6
+ keybinding: ['delete', 'backspace'],
7
+ when: [
8
+ ['stage', 'keyup'],
9
+ ['layer-panel', 'keydown'],
10
+ ],
11
+ },
12
+ {
13
+ command: KeyBindingCommand.COPY_NODE,
14
+ keybinding: 'ctrl+c',
15
+ when: [
16
+ ['stage', 'keydown'],
17
+ ['layer-panel', 'keydown'],
18
+ ],
19
+ },
20
+ {
21
+ command: KeyBindingCommand.PASTE_NODE,
22
+ keybinding: 'ctrl+v',
23
+ when: [
24
+ ['stage', 'keydown'],
25
+ ['layer-panel', 'keydown'],
26
+ ],
27
+ },
28
+ {
29
+ command: KeyBindingCommand.CUT_NODE,
30
+ keybinding: 'ctrl+x',
31
+ when: [
32
+ ['stage', 'keydown'],
33
+ ['layer-panel', 'keydown'],
34
+ ],
35
+ },
36
+ {
37
+ command: KeyBindingCommand.UNDO,
38
+ keybinding: 'ctrl+z',
39
+ when: [
40
+ ['stage', 'keydown'],
41
+ ['layer-panel', 'keydown'],
42
+ ],
43
+ },
44
+ {
45
+ command: KeyBindingCommand.REDO,
46
+ keybinding: 'ctrl+shift+z',
47
+ when: [
48
+ ['stage', 'keydown'],
49
+ ['layer-panel', 'keydown'],
50
+ ],
51
+ },
52
+ {
53
+ command: KeyBindingCommand.MOVE_UP_1,
54
+ keybinding: 'up',
55
+ when: [['stage', 'keydown']],
56
+ },
57
+ {
58
+ command: KeyBindingCommand.MOVE_DOWN_1,
59
+ keybinding: 'down',
60
+ when: [['stage', 'keydown']],
61
+ },
62
+ {
63
+ command: KeyBindingCommand.MOVE_LEFT_1,
64
+ keybinding: 'left',
65
+ when: [['stage', 'keydown']],
66
+ },
67
+ {
68
+ command: KeyBindingCommand.MOVE_RIGHT_1,
69
+ keybinding: 'right',
70
+ when: [['stage', 'keydown']],
71
+ },
72
+ {
73
+ command: KeyBindingCommand.MOVE_UP_10,
74
+ keybinding: 'ctrl+up',
75
+ when: [['stage', 'keydown']],
76
+ },
77
+ {
78
+ command: KeyBindingCommand.MOVE_DOWN_10,
79
+ keybinding: 'ctrl+down',
80
+ when: [['stage', 'keydown']],
81
+ },
82
+ {
83
+ command: KeyBindingCommand.MOVE_LEFT_10,
84
+ keybinding: 'ctrl+left',
85
+ when: [['stage', 'keydown']],
86
+ },
87
+ {
88
+ command: KeyBindingCommand.MOVE_RIGHT_10,
89
+ keybinding: 'ctrl+right',
90
+ when: [['stage', 'keydown']],
91
+ },
92
+ {
93
+ command: KeyBindingCommand.SWITCH_NODE,
94
+ keybinding: 'tab',
95
+ when: [
96
+ ['stage', 'keydown'],
97
+ ['layer-panel', 'keydown'],
98
+ ],
99
+ },
100
+ {
101
+ command: KeyBindingCommand.ZOOM_IN,
102
+ keybinding: ['ctrl+=', 'ctrl+numpadplus'],
103
+ when: [['stage', 'keydown']],
104
+ },
105
+ {
106
+ command: KeyBindingCommand.ZOOM_OUT,
107
+ keybinding: ['ctrl+-', 'ctrl+numpad-'],
108
+ when: [['stage', 'keydown']],
109
+ },
110
+ {
111
+ command: KeyBindingCommand.ZOOM_FIT,
112
+ keybinding: 'ctrl+0',
113
+ when: [['stage', 'keydown']],
114
+ },
115
+ {
116
+ command: KeyBindingCommand.ZOOM_RESET,
117
+ keybinding: 'ctrl+1',
118
+ when: [['stage', 'keydown']],
119
+ },
120
+ ] as KeyBindingItem[];
@@ -105,6 +105,40 @@ export const fillConfig = (config: FormConfig = []) => [
105
105
  },
106
106
  ],
107
107
  },
108
+ {
109
+ type: 'fieldset',
110
+ legend: '边框',
111
+ items: [
112
+ {
113
+ name: 'borderWidth',
114
+ text: '宽度',
115
+ defaultValue: '0',
116
+ },
117
+ {
118
+ name: 'borderColor',
119
+ text: '颜色',
120
+ type: 'colorPicker',
121
+ },
122
+ {
123
+ name: 'borderStyle',
124
+ text: '样式',
125
+ type: 'select',
126
+ defaultValue: 'none',
127
+ options: [
128
+ { text: 'none', value: 'none' },
129
+ { text: 'hidden', value: 'hidden' },
130
+ { text: 'dotted', value: 'dotted' },
131
+ { text: 'dashed', value: 'dashed' },
132
+ { text: 'solid', value: 'solid' },
133
+ { text: 'double', value: 'double' },
134
+ { text: 'groove', value: 'groove' },
135
+ { text: 'ridge', value: 'ridge' },
136
+ { text: 'inset', value: 'inset' },
137
+ { text: 'outset', value: 'outset' },
138
+ ],
139
+ },
140
+ ],
141
+ },
108
142
  {
109
143
  type: 'fieldset',
110
144
  legend: '背景',