@tmagic/editor 1.1.0-beta.10 → 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.
Files changed (50) hide show
  1. package/dist/style.css +46 -0
  2. package/dist/tmagic-editor.mjs +862 -740
  3. package/dist/tmagic-editor.mjs.map +1 -1
  4. package/dist/tmagic-editor.umd.js +864 -739
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/package.json +10 -10
  7. package/src/Editor.vue +4 -3
  8. package/src/components/ContentMenu.vue +4 -4
  9. package/src/components/Icon.vue +6 -20
  10. package/src/components/ScrollBar.vue +147 -0
  11. package/src/components/ScrollViewer.vue +89 -44
  12. package/src/components/ToolButton.vue +40 -138
  13. package/src/fields/UISelect.vue +2 -2
  14. package/src/index.ts +2 -0
  15. package/src/layouts/NavMenu.vue +156 -23
  16. package/src/layouts/sidebar/LayerMenu.vue +3 -3
  17. package/src/layouts/sidebar/LayerPanel.vue +39 -8
  18. package/src/layouts/workspace/PageBar.vue +1 -1
  19. package/src/layouts/workspace/Stage.vue +8 -90
  20. package/src/layouts/workspace/ViewerMenu.vue +3 -3
  21. package/src/layouts/workspace/Workspace.vue +133 -138
  22. package/src/services/editor.ts +17 -6
  23. package/src/services/props.ts +26 -53
  24. package/src/services/ui.ts +16 -20
  25. package/src/theme/nav-menu.scss +6 -0
  26. package/src/type.ts +26 -10
  27. package/src/utils/index.ts +1 -0
  28. package/src/utils/operator.ts +1 -1
  29. package/src/utils/props.ts +0 -3
  30. package/src/utils/scroll-viewer.ts +90 -158
  31. package/src/utils/stage.ts +91 -0
  32. package/types/Editor.vue.d.ts +7 -7
  33. package/types/components/ContentMenu.vue.d.ts +8 -8
  34. package/types/components/Icon.vue.d.ts +62 -12
  35. package/types/components/ScrollBar.vue.d.ts +83 -0
  36. package/types/components/ScrollViewer.vue.d.ts +131 -19
  37. package/types/components/ToolButton.vue.d.ts +56 -59
  38. package/types/index.d.ts +2 -0
  39. package/types/layouts/NavMenu.vue.d.ts +92 -23
  40. package/types/layouts/sidebar/LayerMenu.vue.d.ts +7 -7
  41. package/types/layouts/sidebar/LayerPanel.vue.d.ts +17 -15
  42. package/types/layouts/workspace/Workspace.vue.d.ts +54 -4
  43. package/types/services/editor.d.ts +1 -0
  44. package/types/services/props.d.ts +40 -9
  45. package/types/services/ui.d.ts +1 -1
  46. package/types/type.d.ts +23 -10
  47. package/types/utils/index.d.ts +1 -0
  48. package/types/utils/props.d.ts +0 -1
  49. package/types/utils/scroll-viewer.d.ts +16 -18
  50. package/types/utils/stage.d.ts +3 -0
@@ -1,18 +1,20 @@
1
1
  <template>
2
2
  <div class="m-editor-workspace" tabindex="1" ref="workspace">
3
- <magic-stage :key="page?.id"></magic-stage>
3
+ <slot name="stage">
4
+ <MagicStage :key="page?.id"></MagicStage>
5
+ </slot>
4
6
 
5
7
  <slot name="workspace-content"></slot>
6
8
 
7
- <page-bar>
9
+ <PageBar>
8
10
  <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
9
11
  <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
10
- </page-bar>
12
+ </PageBar>
11
13
  </div>
12
14
  </template>
13
15
 
14
- <script lang="ts">
15
- import { computed, defineComponent, inject, onMounted, onUnmounted, ref } from 'vue';
16
+ <script lang="ts" setup>
17
+ import { computed, inject, onMounted, onUnmounted, ref } from 'vue';
16
18
  import KeyController from 'keycon';
17
19
 
18
20
  import type { MNode, MPage } from '@tmagic/schema';
@@ -23,140 +25,133 @@ import type { Services } from '../../type';
23
25
  import PageBar from './PageBar.vue';
24
26
  import MagicStage from './Stage.vue';
25
27
 
26
- export default defineComponent({
27
- name: 'm-editor-workspace',
28
-
29
- components: {
30
- PageBar,
31
- MagicStage,
32
- },
33
-
34
- setup() {
35
- const services = inject<Services>('services');
36
- const workspace = ref<HTMLDivElement>();
37
- const nodes = computed(() => services?.editorService.get<MNode[]>('nodes'));
38
- let keycon: KeyController;
39
-
40
- const mouseenterHandler = () => {
41
- workspace.value?.focus();
42
- };
43
-
44
- const mouseleaveHandler = () => {
45
- workspace.value?.blur();
46
- };
47
-
48
- onMounted(() => {
49
- workspace.value?.addEventListener('mouseenter', mouseenterHandler);
50
- workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
51
-
52
- keycon = new KeyController(workspace.value);
53
-
54
- const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
55
-
56
- const ctrl = isMac ? 'meta' : 'ctrl';
57
-
58
- keycon
59
- .keyup('delete', (e) => {
60
- e.inputEvent.preventDefault();
61
- if (!nodes.value || isPage(nodes.value[0])) return;
62
- services?.editorService.remove(nodes.value);
63
- })
64
- .keyup('backspace', (e) => {
65
- e.inputEvent.preventDefault();
66
- if (!nodes.value || isPage(nodes.value[0])) return;
67
- services?.editorService.remove(nodes.value);
68
- })
69
- .keydown([ctrl, 'c'], (e) => {
70
- e.inputEvent.preventDefault();
71
- nodes.value && services?.editorService.copy(nodes.value);
72
- })
73
- .keydown([ctrl, 'v'], (e) => {
74
- e.inputEvent.preventDefault();
75
- nodes.value && services?.editorService.paste({ offsetX: 10, offsetY: 10 });
76
- })
77
- .keydown([ctrl, 'x'], (e) => {
78
- e.inputEvent.preventDefault();
79
- if (!nodes.value || isPage(nodes.value[0])) return;
80
- services?.editorService.copy(nodes.value);
81
- services?.editorService.remove(nodes.value);
82
- })
83
- .keydown([ctrl, 'z'], (e) => {
84
- e.inputEvent.preventDefault();
85
- services?.editorService.undo();
86
- })
87
- .keydown([ctrl, 'shift', 'z'], (e) => {
88
- e.inputEvent.preventDefault();
89
- services?.editorService.redo();
90
- })
91
- .keydown('up', (e) => {
92
- e.inputEvent.preventDefault();
93
- services?.editorService.move(0, -1);
94
- })
95
- .keydown('down', (e) => {
96
- e.inputEvent.preventDefault();
97
- services?.editorService.move(0, 1);
98
- })
99
- .keydown('left', (e) => {
100
- e.inputEvent.preventDefault();
101
- services?.editorService.move(-1, 0);
102
- })
103
- .keydown('right', (e) => {
104
- e.inputEvent.preventDefault();
105
- services?.editorService.move(1, 0);
106
- })
107
- .keydown([ctrl, 'up'], (e) => {
108
- e.inputEvent.preventDefault();
109
- services?.editorService.move(0, -10);
110
- })
111
- .keydown([ctrl, 'down'], (e) => {
112
- e.inputEvent.preventDefault();
113
- services?.editorService.move(0, 10);
114
- })
115
- .keydown([ctrl, 'left'], (e) => {
116
- e.inputEvent.preventDefault();
117
- services?.editorService.move(-10, 0);
118
- })
119
- .keydown([ctrl, 'right'], (e) => {
120
- e.inputEvent.preventDefault();
121
- services?.editorService.move(10, 0);
122
- })
123
- .keydown('tab', (e) => {
124
- e.inputEvent.preventDefault();
125
- services?.editorService.selectNextNode();
126
- })
127
- .keydown([ctrl, 'tab'], (e) => {
128
- e.inputEvent.preventDefault();
129
- services?.editorService.selectNextPage();
130
- })
131
- .keydown([ctrl, '='], (e) => {
132
- e.inputEvent.preventDefault();
133
- services?.uiService.zoom(0.1);
134
- })
135
- .keydown([ctrl, 'numpadplus'], (e) => {
136
- e.inputEvent.preventDefault();
137
- services?.uiService.zoom(0.1);
138
- })
139
- .keydown([ctrl, '-'], (e) => {
140
- e.inputEvent.preventDefault();
141
- services?.uiService.zoom(-0.1);
142
- })
143
- .keydown([ctrl, 'numpad-'], (e) => {
144
- e.inputEvent.preventDefault();
145
- services?.uiService.zoom(-0.1);
146
- });
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);
147
149
  });
150
+ });
148
151
 
149
- onUnmounted(() => {
150
- workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
151
- workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
152
- keycon.destroy();
153
- });
154
-
155
- return {
156
- workspace,
157
-
158
- page: computed(() => services?.editorService.get<MPage>('page')),
159
- };
160
- },
152
+ onUnmounted(() => {
153
+ workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
154
+ workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
155
+ keycon.destroy();
161
156
  });
162
157
  </script>
@@ -71,6 +71,7 @@ class Editor extends BaseService {
71
71
  'sort',
72
72
  'copy',
73
73
  'paste',
74
+ 'doPaste',
74
75
  'duAlignCenter',
75
76
  'alignCenter',
76
77
  'moveLayer',
@@ -367,7 +368,7 @@ class Editor extends BaseService {
367
368
 
368
369
  this.emit('add', newNodes);
369
370
 
370
- return newNodes.length > 1 ? newNodes[0] : newNodes;
371
+ return Array.isArray(addNode) ? newNodes : newNodes[0];
371
372
  }
372
373
 
373
374
  public async doRemove(node: MNode): Promise<void> {
@@ -503,7 +504,7 @@ class Editor extends BaseService {
503
504
 
504
505
  this.emit('update', newNodes);
505
506
 
506
- return newNodes.length > 1 ? newNodes[0] : newNodes;
507
+ return Array.isArray(config) ? newNodes : newNodes[0];
507
508
  }
508
509
 
509
510
  /**
@@ -556,11 +557,16 @@ class Editor extends BaseService {
556
557
 
557
558
  if (!Array.isArray(config)) return;
558
559
 
559
- const pasteConfigs = await beforePaste(position, config);
560
+ const pasteConfigs = await this.doPaste(config, position);
560
561
 
561
562
  return this.add(pasteConfigs);
562
563
  }
563
564
 
565
+ public async doPaste(config: MNode[], position: PastePosition = {}): Promise<MNode[]> {
566
+ const pasteConfigs = await beforePaste(position, cloneDeep(config));
567
+ return pasteConfigs;
568
+ }
569
+
564
570
  public async doAlignCenter(config: MNode): Promise<MNode> {
565
571
  const parent = this.getParentById(config.id);
566
572
 
@@ -614,7 +620,7 @@ class Editor extends BaseService {
614
620
  */
615
621
  public async moveLayer(offset: number | LayerOffset): Promise<void> {
616
622
  const parent = this.get<MContainer>('parent');
617
- const node = this.get('node');
623
+ const node = this.get<MNode>('node');
618
624
  const brothers: MNode[] = parent?.items || [];
619
625
  const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
620
626
 
@@ -626,11 +632,15 @@ class Editor extends BaseService {
626
632
  brothers.splice(index + parseInt(`${offset}`, 10), 0, brothers.splice(index, 1)[0]);
627
633
  }
628
634
 
635
+ const grandparent = this.getParentById(parent.id);
629
636
  this.get<StageCore | null>('stage')?.update({
630
637
  config: cloneDeep(toRaw(parent)),
631
- parentId: parent.id,
638
+ parentId: grandparent?.id,
632
639
  root: cloneDeep(this.get<MApp>('root')),
633
640
  });
641
+
642
+ this.addModifiedNodeId(parent.id);
643
+ this.pushHistoryState();
634
644
  }
635
645
 
636
646
  /**
@@ -664,7 +674,8 @@ class Editor extends BaseService {
664
674
 
665
675
  await stage.select(targetId);
666
676
 
667
- await stage.update({ config: cloneDeep(target), parentId: parent.id, root });
677
+ const targetParent = this.getParentById(target.id);
678
+ await stage.update({ config: cloneDeep(target), parentId: targetParent?.id, root });
668
679
 
669
680
  await this.select(newConfig);
670
681
  stage.select(newConfig.id);
@@ -20,12 +20,11 @@ import { reactive } from 'vue';
20
20
  import { cloneDeep, mergeWith } from 'lodash-es';
21
21
 
22
22
  import type { FormConfig } from '@tmagic/form';
23
- import type { Id, MComponent, MNode, MPage } from '@tmagic/schema';
24
- import { NodeType } from '@tmagic/schema';
25
- import { isPop, toLine } from '@tmagic/utils';
23
+ import type { MComponent, MNode } from '@tmagic/schema';
24
+ import { toLine } from '@tmagic/utils';
26
25
 
27
26
  import type { PropsState } from '../type';
28
- import { DEFAULT_CONFIG, fillConfig } from '../utils/props';
27
+ import { fillConfig } from '../utils/props';
29
28
 
30
29
  import BaseService from './BaseService';
31
30
 
@@ -43,6 +42,7 @@ class Props extends BaseService {
43
42
  'getPropsValue',
44
43
  'createId',
45
44
  'setNewItemId',
45
+ 'fillConfig',
46
46
  'getDefaultPropsValue',
47
47
  ]);
48
48
  }
@@ -54,13 +54,17 @@ class Props extends BaseService {
54
54
  this.emit('props-configs-change');
55
55
  }
56
56
 
57
+ public async fillConfig(config: FormConfig) {
58
+ return fillConfig(config);
59
+ }
60
+
57
61
  /**
58
62
  * 为指定类型组件设置组件属性表单配置
59
63
  * @param type 组件类型
60
64
  * @param config 组件属性表单配置
61
65
  */
62
- public setPropsConfig(type: string, config: FormConfig) {
63
- this.state.propsConfigMap[type] = fillConfig(Array.isArray(config) ? config : [config]);
66
+ public async setPropsConfig(type: string, config: FormConfig) {
67
+ this.state.propsConfigMap[type] = await this.fillConfig(Array.isArray(config) ? config : [config]);
64
68
  }
65
69
 
66
70
  /**
@@ -73,7 +77,7 @@ class Props extends BaseService {
73
77
  return await this.getPropsConfig('button');
74
78
  }
75
79
 
76
- return cloneDeep(this.state.propsConfigMap[type] || DEFAULT_CONFIG);
80
+ return cloneDeep(this.state.propsConfigMap[type] || (await this.fillConfig([])));
77
81
  }
78
82
 
79
83
  public setPropsValues(values: Record<string, MNode>) {
@@ -125,19 +129,6 @@ class Props extends BaseService {
125
129
  };
126
130
  }
127
131
 
128
- /**
129
- * 生成指定位数的GUID,无【-】格式
130
- * @param digit 位数,默认值8
131
- * @returns
132
- */
133
- guid(digit = 8): string {
134
- return 'x'.repeat(digit).replace(/[xy]/g, (c) => {
135
- const r = (Math.random() * 16) | 0;
136
- const v = c == 'x' ? r : (r & 0x3) | 0x8;
137
- return v.toString(16);
138
- });
139
- }
140
-
141
132
  public async createId(type: string | number): Promise<string> {
142
133
  return `${type}_${this.guid()}`;
143
134
  }
@@ -147,19 +138,12 @@ class Props extends BaseService {
147
138
  * @param {Object} config 组件配置
148
139
  */
149
140
  /* eslint no-param-reassign: ["error", { "props": false }] */
150
- public async setNewItemId(config: MNode, parent?: MPage) {
151
- const oldId = config.id;
152
-
141
+ public async setNewItemId(config: MNode) {
153
142
  config.id = await this.createId(config.type || 'component');
154
143
 
155
- // 只有弹窗在页面下的一级子元素才有效
156
- if (isPop(config) && parent?.type === NodeType.PAGE) {
157
- updatePopId(oldId, config.id, parent);
158
- }
159
-
160
144
  if (config.items && Array.isArray(config.items)) {
161
145
  for (const item of config.items) {
162
- await this.setNewItemId(item, config as MPage);
146
+ await this.setNewItemId(item);
163
147
  }
164
148
  }
165
149
 
@@ -186,31 +170,20 @@ class Props extends BaseService {
186
170
  name: type,
187
171
  };
188
172
  }
189
- }
190
173
 
191
- /**
192
- * 复制页面时,需要把组件下关联的弹窗id换测复制出来的弹窗的id
193
- * @param {number} oldId 复制的源弹窗id
194
- * @param {number} popId 新的弹窗id
195
- * @param {Object} pageConfig 页面配置
196
- */
197
- const updatePopId = (oldId: Id, popId: Id, pageConfig: MPage) => {
198
- pageConfig.items?.forEach((config) => {
199
- if (config.pop === oldId) {
200
- config.pop = popId;
201
- return;
202
- }
203
-
204
- if (config.popId === oldId) {
205
- config.popId = popId;
206
- return;
207
- }
208
-
209
- if (Array.isArray(config.items)) {
210
- updatePopId(oldId, popId, config as MPage);
211
- }
212
- });
213
- };
174
+ /**
175
+ * 生成指定位数的GUID,无【-】格式
176
+ * @param digit 位数,默认值8
177
+ * @returns
178
+ */
179
+ private guid(digit = 8): string {
180
+ return 'x'.repeat(digit).replace(/[xy]/g, (c) => {
181
+ const r = (Math.random() * 16) | 0;
182
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
183
+ return v.toString(16);
184
+ });
185
+ }
186
+ }
214
187
 
215
188
  export type PropsService = Props;
216
189
 
@@ -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;
@@ -69,5 +69,11 @@
69
69
  .menu-item-text {
70
70
  color: $--nav-color;
71
71
  }
72
+
73
+ &.rule {
74
+ .el-icon {
75
+ transform: rotate(-90deg);
76
+ }
77
+ }
72
78
  }
73
79
  }
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
- left?: number;
87
- center?: number | 'auto';
88
- right?: number;
92
+ [ColumnLayout.LEFT]?: number;
93
+ [ColumnLayout.CENTER]?: number | 'auto';
94
+ [ColumnLayout.RIGHT]?: number;
89
95
  }
90
96
 
91
97
  export interface GetColumnWidth {
92
- left: number;
93
- center: number;
94
- right: number;
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
- left?: MenuItem[];
226
+ [ColumnLayout.LEFT]?: MenuItem[];
218
227
  /** 顶部工具栏中间项 */
219
- center?: MenuItem[];
228
+ [ColumnLayout.CENTER]?: MenuItem[];
220
229
  /** 顶部工具栏右边项 */
221
- right?: MenuItem[];
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
+ }
@@ -20,3 +20,4 @@ export * from './config';
20
20
  export * from './props';
21
21
  export * from './logger';
22
22
  export * from './editor';
23
+ export * from './stage';