@tmagic/editor 1.1.0-beta.8 → 1.1.0-beta.9

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.0-beta.8",
2
+ "version": "1.1.0-beta.9",
3
3
  "name": "@tmagic/editor",
4
4
  "sideEffects": [
5
5
  "dist/*",
@@ -45,11 +45,11 @@
45
45
  "dependencies": {
46
46
  "@babel/core": "^7.18.0",
47
47
  "@element-plus/icons-vue": "^2.0.6",
48
- "@tmagic/core": "1.1.0-beta.8",
49
- "@tmagic/form": "1.1.0-beta.8",
50
- "@tmagic/schema": "1.1.0-beta.8",
51
- "@tmagic/stage": "1.1.0-beta.8",
52
- "@tmagic/utils": "1.1.0-beta.8",
48
+ "@tmagic/core": "1.1.0-beta.9",
49
+ "@tmagic/form": "1.1.0-beta.9",
50
+ "@tmagic/schema": "1.1.0-beta.9",
51
+ "@tmagic/stage": "1.1.0-beta.9",
52
+ "@tmagic/utils": "1.1.0-beta.9",
53
53
  "buffer": "^6.0.3",
54
54
  "color": "^3.1.3",
55
55
  "element-plus": "^2.2.6",
@@ -62,7 +62,7 @@
62
62
  "vue": "^3.2.37"
63
63
  },
64
64
  "peerDependencies": {
65
- "@tmagic/form": "1.1.0-beta.8",
65
+ "@tmagic/form": "1.1.0-beta.9",
66
66
  "element-plus": "^2.2.6",
67
67
  "monaco-editor": "^0.32.1",
68
68
  "vue": "^3.2.37"
package/src/Editor.vue CHANGED
@@ -30,7 +30,7 @@
30
30
 
31
31
  <template #props-panel>
32
32
  <slot name="props-panel">
33
- <props-panel ref="propsPanel" @mounted="(instance) => $emit('props-panel-mounted', instance)">
33
+ <props-panel ref="propsPanel" @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
34
34
  <template #props-panel-header>
35
35
  <slot name="props-panel-header"></slot>
36
36
  </template>
@@ -49,7 +49,7 @@ import { EventOption } from '@tmagic/core';
49
49
  import type { FormConfig } from '@tmagic/form';
50
50
  import type { MApp, MNode } from '@tmagic/schema';
51
51
  import type StageCore from '@tmagic/stage';
52
- import { CONTAINER_HIGHLIGHT_CLASS, MoveableOptions } from '@tmagic/stage';
52
+ import { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
53
53
 
54
54
  import Framework from './layouts/Framework.vue';
55
55
  import NavMenu from './layouts/NavMenu.vue';
@@ -170,6 +170,11 @@ export default defineComponent({
170
170
  default: 800,
171
171
  },
172
172
 
173
+ containerHighlightType: {
174
+ type: String as PropType<ContainerHighlightType>,
175
+ default: ContainerHighlightType.DEFAULT,
176
+ },
177
+
173
178
  stageRect: {
174
179
  type: [String, Object] as PropType<StageRect>,
175
180
  },
@@ -289,6 +294,7 @@ export default defineComponent({
289
294
  isContainer: props.isContainer,
290
295
  containerHighlightClassName: props.containerHighlightClassName,
291
296
  containerHighlightDuration: props.containerHighlightDuration,
297
+ containerHighlightType: props.containerHighlightType,
292
298
  }),
293
299
  );
294
300
 
@@ -81,6 +81,7 @@ watchEffect(() => {
81
81
  isContainer: stageOptions.isContainer,
82
82
  containerHighlightClassName: stageOptions.containerHighlightClassName,
83
83
  containerHighlightDuration: stageOptions.containerHighlightDuration,
84
+ containerHighlightType: stageOptions.containerHighlightType,
84
85
  canSelect: (el, event, stop) => {
85
86
  const elCanSelect = stageOptions.canSelect(el);
86
87
  // 在组件联动过程中不能再往下选择,返回并触发 ui-select
@@ -118,10 +119,13 @@ watchEffect(() => {
118
119
 
119
120
  stage?.on('update', (ev: UpdateEventData) => {
120
121
  if (ev.parentEl) {
121
- services?.editorService.moveToContainer({ id: ev.el.id, style: ev.style }, ev.parentEl.id);
122
+ for (const data of ev.data) {
123
+ services?.editorService.moveToContainer({ id: data.el.id, style: data.style }, ev.parentEl.id);
124
+ }
122
125
  return;
123
126
  }
124
- services?.editorService.update({ id: ev.el.id, style: ev.style });
127
+
128
+ services?.editorService.update(ev.data.map((data) => ({ id: data.el.id, style: data.style })));
125
129
  });
126
130
 
127
131
  stage?.on('sort', (ev: SortEventData) => {
@@ -34,10 +34,10 @@ const menuData = reactive<MenuItem[]>([
34
34
  {
35
35
  type: 'button',
36
36
  text: '水平居中',
37
- display: () => canCenter.value && !props.isMultiSelect,
37
+ display: () => canCenter.value,
38
38
  handler: () => {
39
- if (!node.value) return;
40
- editorService?.alignCenter(node.value);
39
+ if (!nodes.value) return;
40
+ editorService?.alignCenter(nodes.value);
41
41
  },
42
42
  },
43
43
  {
@@ -38,7 +38,7 @@ import {
38
38
  isFixed,
39
39
  setLayout,
40
40
  } from '../utils/editor';
41
- import { beforePaste, beforeRemove, getAddParent } from '../utils/operator';
41
+ import { beforePaste, getAddParent } from '../utils/operator';
42
42
 
43
43
  import BaseService from './BaseService';
44
44
  import propsService from './props';
@@ -64,11 +64,14 @@ class Editor extends BaseService {
64
64
  'select',
65
65
  'doAdd',
66
66
  'add',
67
+ 'doRemove',
67
68
  'remove',
69
+ 'doUpdate',
68
70
  'update',
69
71
  'sort',
70
72
  'copy',
71
73
  'paste',
74
+ 'duAlignCenter',
72
75
  'alignCenter',
73
76
  'moveLayer',
74
77
  'moveToContainer',
@@ -359,55 +362,65 @@ class Editor extends BaseService {
359
362
  return newNodes.length > 1 ? newNodes[0] : newNodes;
360
363
  }
361
364
 
365
+ public async doRemove(node: MNode): Promise<void> {
366
+ const root = this.get<MApp | null>('root');
367
+
368
+ if (!root) throw new Error('没有root');
369
+
370
+ const { parent, node: curNode } = this.getNodeInfo(node.id);
371
+
372
+ if (!parent || !curNode) throw new Error('找不要删除的节点');
373
+
374
+ const index = getNodeIndex(curNode, parent);
375
+
376
+ if (typeof index !== 'number' || index === -1) throw new Error('找不要删除的节点');
377
+
378
+ parent.items?.splice(index, 1);
379
+ const stage = this.get<StageCore | null>('stage');
380
+ stage?.remove({ id: node.id, root: this.get('root') });
381
+
382
+ if (node.type === NodeType.PAGE) {
383
+ this.state.pageLength -= 1;
384
+
385
+ if (root.items[0]) {
386
+ await this.select(root.items[0]);
387
+ stage?.select(root.items[0].id);
388
+ } else {
389
+ this.set('node', null);
390
+ this.set('parent', null);
391
+ this.set('page', null);
392
+ this.set('stage', null);
393
+ this.set('highlightNode', null);
394
+ this.resetModifiedNodeId();
395
+ historyService.reset();
396
+
397
+ return;
398
+ }
399
+ } else {
400
+ await this.select(parent);
401
+ stage?.select(parent.id);
402
+ }
403
+
404
+ this.addModifiedNodeId(parent.id);
405
+ }
406
+
362
407
  /**
363
408
  * 删除组件
364
409
  * @param {Object} node
365
410
  * @return {Object} 删除的组件配置
366
411
  */
367
- public async remove(nodeOrNodeList: MNode | MNode[]): Promise<MNode | MNode[]> {
368
- if (Array.isArray(nodeOrNodeList)) {
369
- // 多选批量删除
370
- const nodes = nodeOrNodeList;
371
- return this.multiRemove(nodes);
372
- }
373
- const node = nodeOrNodeList;
374
- const removeParent = await beforeRemove(node);
375
- // 删除的是页面
376
- if (!removeParent) return node;
377
- // 更新历史记录
378
- this.addModifiedNodeId(removeParent.id);
379
- this.pushHistoryState();
412
+ public async remove(nodeOrNodeList: MNode | MNode[]): Promise<void> {
413
+ const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
380
414
 
381
- this.emit('remove', node);
415
+ await Promise.all(nodes.map((node) => this.doRemove(node)));
382
416
 
383
- return node;
384
- }
385
-
386
- /**
387
- * 批量删除
388
- * @param nodes 批量删除的节点
389
- * @returns 批量删除的节点
390
- */
391
- public async multiRemove(nodes: MNode[]): Promise<MNode[]> {
392
- await Promise.all(
393
- nodes.map(async (removeNode) => {
394
- await beforeRemove(removeNode);
395
- }),
396
- );
397
- const nodeIds = nodes.map((node) => node.id);
398
- this.addModifiedNodeId(nodeIds.join('-'));
417
+ // 更新历史记录
399
418
  this.pushHistoryState();
400
419
 
401
- this.emit('multiRemove', nodes);
402
- return nodes;
420
+ this.emit('remove');
403
421
  }
404
422
 
405
- /**
406
- * 更新节点
407
- * @param config 新的节点配置,配置中需要有id信息
408
- * @returns 更新后的节点配置
409
- */
410
- public async update(config: MNode): Promise<MNode> {
423
+ public async doUpdate(config: MNode) {
411
424
  if (!config?.id) throw new Error('没有配置或者配置缺少id值');
412
425
 
413
426
  const info = this.getNodeInfo(config.id, false);
@@ -460,11 +473,25 @@ class Editor extends BaseService {
460
473
  }
461
474
 
462
475
  this.addModifiedNodeId(newConfig.id);
476
+
477
+ return newConfig;
478
+ }
479
+
480
+ /**
481
+ * 更新节点
482
+ * @param config 新的节点配置,配置中需要有id信息
483
+ * @returns 更新后的节点配置
484
+ */
485
+ public async update(config: MNode | MNode[]): Promise<MNode | MNode[]> {
486
+ const nodes = Array.isArray(config) ? config : [config];
487
+
488
+ const newNodes = await Promise.all(nodes.map((node) => this.doUpdate(node)));
489
+
463
490
  this.pushHistoryState();
464
491
 
465
- this.emit('update', newConfig);
492
+ this.emit('update', newNodes);
466
493
 
467
- return newConfig;
494
+ return newNodes.length > 1 ? newNodes[0] : newNodes;
468
495
  }
469
496
 
470
497
  /**
@@ -518,20 +545,18 @@ class Editor extends BaseService {
518
545
  return this.add(pasteConfigs);
519
546
  }
520
547
 
521
- /**
522
- * 将指点节点设置居中
523
- * @param config 组件节点配置
524
- * @returns 当前组件节点配置
525
- */
526
- public async alignCenter(config: MNode): Promise<MNode | void> {
527
- const parent = this.get<MContainer>('parent');
528
- const node = this.get<MNode>('node');
529
- const layout = await this.getLayout(toRaw(parent), toRaw(node));
548
+ public async doAlignCenter(config: MNode): Promise<MNode> {
549
+ const parent = this.getParentById(config.id);
550
+
551
+ if (!parent) throw new Error('找不到父节点');
552
+
553
+ const node = cloneDeep(toRaw(config));
554
+ const layout = await this.getLayout(parent, node);
530
555
  if (layout === Layout.RELATIVE) {
531
- return;
556
+ return config;
532
557
  }
533
558
 
534
- if (!node.style) return;
559
+ if (!node.style) return config;
535
560
 
536
561
  const stage = this.get<StageCore>('stage');
537
562
  const doc = stage?.renderer.contentWindow?.document;
@@ -546,15 +571,25 @@ class Editor extends BaseService {
546
571
  node.style.left = (parent.style.width - node.style.width) / 2;
547
572
  }
548
573
 
549
- await this.update(node);
550
- this.get<StageCore | null>('stage')?.update({
551
- config: cloneDeep(toRaw(node)),
552
- root: cloneDeep(this.get<MApp>('root')),
553
- });
554
- this.addModifiedNodeId(config.id);
555
- this.pushHistoryState();
574
+ return node;
575
+ }
576
+
577
+ /**
578
+ * 将指点节点设置居中
579
+ * @param config 组件节点配置
580
+ * @returns 当前组件节点配置
581
+ */
582
+ public async alignCenter(config: MNode | MNode[]): Promise<MNode | MNode[]> {
583
+ const nodes = Array.isArray(config) ? config : [config];
584
+ const stage = this.get<StageCore | null>('stage');
585
+
586
+ const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
587
+
588
+ const newNode = await this.update(newNodes);
589
+
590
+ await stage?.multiSelect(newNodes.map((node) => node.id));
556
591
 
557
- return config;
592
+ return newNode;
558
593
  }
559
594
 
560
595
  /**
package/src/type.ts CHANGED
@@ -21,7 +21,7 @@ import type { Component } from 'vue';
21
21
  import type { FormConfig } from '@tmagic/form';
22
22
  import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
23
23
  import type StageCore from '@tmagic/stage';
24
- import type { MoveableOptions } from '@tmagic/stage';
24
+ import type { ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
25
25
 
26
26
  import type { ComponentListService } from './services/componentList';
27
27
  import type { EditorService } from './services/editor';
@@ -53,6 +53,7 @@ export interface StageOptions {
53
53
  autoScrollIntoView: boolean;
54
54
  containerHighlightClassName: string;
55
55
  containerHighlightDuration: number;
56
+ containerHighlightType: ContainerHighlightType;
56
57
  render: () => HTMLDivElement;
57
58
  moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
58
59
  canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
@@ -1,15 +1,14 @@
1
1
  import { toRaw } from 'vue';
2
- import { cloneDeep, isEmpty } from 'lodash-es';
2
+ import { isEmpty } from 'lodash-es';
3
3
 
4
- import { Id, MApp, MContainer, MNode, NodeType } from '@tmagic/schema';
4
+ import { Id, MApp, MContainer, MNode } from '@tmagic/schema';
5
5
  import StageCore from '@tmagic/stage';
6
6
  import { isPage } from '@tmagic/utils';
7
7
 
8
8
  import editorService from '../services/editor';
9
- import historyService from '../services/history';
10
9
  import propsService from '../services/props';
11
10
  import { AddMNode, PastePosition } from '../type';
12
- import { generatePageNameByApp, getInitPositionStyle, getNodeIndex } from '../utils/editor';
11
+ import { generatePageNameByApp, getInitPositionStyle } from '../utils/editor';
13
12
 
14
13
  /**
15
14
  * 粘贴前置操作:返回分配了新id以及校准了坐标的配置
@@ -87,59 +86,6 @@ export const getPositionInContainer = (position: PastePosition = {}, id: Id) =>
87
86
  };
88
87
  };
89
88
 
90
- /**
91
- * 删除前置操作:实现了在编辑器中删除元素节点,并返回父级元素信息以供stage更新
92
- * @param node 待删除的节点
93
- * @returns 父级元素,root根元素
94
- */
95
- export const beforeRemove = async (node: MNode): Promise<MContainer | void> => {
96
- if (!node?.id) return;
97
-
98
- const stage = editorService.get<StageCore | null>('stage');
99
- const root = editorService.get<MApp | null>('root');
100
-
101
- if (!root) throw new Error('没有root');
102
-
103
- const { parent, node: curNode } = editorService.getNodeInfo(node.id, false);
104
-
105
- if (!parent || !curNode) throw new Error('找不要删除的节点');
106
-
107
- const index = getNodeIndex(curNode, parent);
108
-
109
- if (typeof index !== 'number' || index === -1) throw new Error('找不要删除的节点');
110
- // 从配置中删除元素
111
- parent.items?.splice(index, 1);
112
-
113
- // 通知stage更新
114
- stage?.remove({ id: node.id, root: cloneDeep(root) });
115
-
116
- if (node.type === NodeType.PAGE) {
117
- editorService.state.pageLength -= 1;
118
-
119
- if (root.items[0]) {
120
- await editorService.select(root.items[0]);
121
- stage?.select(root.items[0].id);
122
- } else {
123
- editorService.set('node', null);
124
- editorService.set('nodes', []);
125
- editorService.set('parent', null);
126
- editorService.set('page', null);
127
- editorService.set('stage', null);
128
- editorService.set('highlightNode', null);
129
- editorService.resetModifiedNodeId();
130
- historyService.reset();
131
-
132
- editorService.emit('remove', node);
133
-
134
- return;
135
- }
136
- } else {
137
- await editorService.select(parent);
138
- stage?.select(parent.id);
139
- }
140
- return parent;
141
- };
142
-
143
89
  export const getAddParent = (addNode: AddMNode | MNode[]) => {
144
90
  const curNode = editorService.get<MContainer>('node');
145
91
 
@@ -2,7 +2,7 @@ import { PropType } from 'vue';
2
2
  import type { FormConfig } from '@tmagic/form';
3
3
  import type { MApp, MNode } from '@tmagic/schema';
4
4
  import type StageCore from '@tmagic/stage';
5
- import { MoveableOptions } from '@tmagic/stage';
5
+ import { ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
6
6
  import type { ComponentGroup, MenuBarData, MenuItem, Services, SideBarData, StageRect } from './type';
7
7
  declare const _default: import("vue").DefineComponent<{
8
8
  /** 页面初始值 */
@@ -83,6 +83,10 @@ declare const _default: import("vue").DefineComponent<{
83
83
  type: NumberConstructor;
84
84
  default: number;
85
85
  };
86
+ containerHighlightType: {
87
+ type: PropType<ContainerHighlightType>;
88
+ default: ContainerHighlightType;
89
+ };
86
90
  stageRect: {
87
91
  type: PropType<StageRect>;
88
92
  };
@@ -172,6 +176,10 @@ declare const _default: import("vue").DefineComponent<{
172
176
  type: NumberConstructor;
173
177
  default: number;
174
178
  };
179
+ containerHighlightType: {
180
+ type: PropType<ContainerHighlightType>;
181
+ default: ContainerHighlightType;
182
+ };
175
183
  stageRect: {
176
184
  type: PropType<StageRect>;
177
185
  };
@@ -200,5 +208,6 @@ declare const _default: import("vue").DefineComponent<{
200
208
  isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
201
209
  containerHighlightClassName: string;
202
210
  containerHighlightDuration: number;
211
+ containerHighlightType: ContainerHighlightType;
203
212
  }>;
204
213
  export default _default;
@@ -73,24 +73,20 @@ declare class Editor extends BaseService {
73
73
  * @returns 添加后的节点
74
74
  */
75
75
  add(addNode: AddMNode | MNode[], parent?: MContainer | null): Promise<MNode | MNode[]>;
76
+ doRemove(node: MNode): Promise<void>;
76
77
  /**
77
78
  * 删除组件
78
79
  * @param {Object} node
79
80
  * @return {Object} 删除的组件配置
80
81
  */
81
- remove(nodeOrNodeList: MNode | MNode[]): Promise<MNode | MNode[]>;
82
- /**
83
- * 批量删除
84
- * @param nodes 批量删除的节点
85
- * @returns 批量删除的节点
86
- */
87
- multiRemove(nodes: MNode[]): Promise<MNode[]>;
82
+ remove(nodeOrNodeList: MNode | MNode[]): Promise<void>;
83
+ doUpdate(config: MNode): Promise<MNode>;
88
84
  /**
89
85
  * 更新节点
90
86
  * @param config 新的节点配置,配置中需要有id信息
91
87
  * @returns 更新后的节点配置
92
88
  */
93
- update(config: MNode): Promise<MNode>;
89
+ update(config: MNode | MNode[]): Promise<MNode | MNode[]>;
94
90
  /**
95
91
  * 将id为id1的组件移动到id为id2的组件位置上,例如:[1,2,3,4] -> sort(1,3) -> [2,1,3,4]
96
92
  * @param id1 组件ID
@@ -110,12 +106,13 @@ declare class Editor extends BaseService {
110
106
  * @returns 添加后的组件节点配置
111
107
  */
112
108
  paste(position?: PastePosition): Promise<MNode | MNode[] | void>;
109
+ doAlignCenter(config: MNode): Promise<MNode>;
113
110
  /**
114
111
  * 将指点节点设置居中
115
112
  * @param config 组件节点配置
116
113
  * @returns 当前组件节点配置
117
114
  */
118
- alignCenter(config: MNode): Promise<MNode | void>;
115
+ alignCenter(config: MNode | MNode[]): Promise<MNode | MNode[]>;
119
116
  /**
120
117
  * 移动当前选中节点位置
121
118
  * @param offset 偏移量
package/types/type.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { Component } from 'vue';
2
2
  import type { FormConfig } from '@tmagic/form';
3
3
  import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
4
4
  import type StageCore from '@tmagic/stage';
5
- import type { MoveableOptions } from '@tmagic/stage';
5
+ import type { ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
6
6
  import type { ComponentListService } from './services/componentList';
7
7
  import type { EditorService } from './services/editor';
8
8
  import type { EventsService } from './services/events';
@@ -29,6 +29,7 @@ export interface StageOptions {
29
29
  autoScrollIntoView: boolean;
30
30
  containerHighlightClassName: string;
31
31
  containerHighlightDuration: number;
32
+ containerHighlightType: ContainerHighlightType;
32
33
  render: () => HTMLDivElement;
33
34
  moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
34
35
  canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
@@ -17,11 +17,5 @@ export declare const getPositionInContainer: (position: PastePosition | undefine
17
17
  left: number;
18
18
  top: number;
19
19
  };
20
- /**
21
- * 删除前置操作:实现了在编辑器中删除元素节点,并返回父级元素信息以供stage更新
22
- * @param node 待删除的节点
23
- * @returns 父级元素,root根元素
24
- */
25
- export declare const beforeRemove: (node: MNode) => Promise<MContainer | void>;
26
20
  export declare const getAddParent: (addNode: AddMNode | MNode[]) => MContainer | undefined;
27
21
  export declare const getDefaultConfig: (addNode: AddMNode, parentNode: MContainer) => Promise<any>;