@tmagic/editor 1.2.0-beta.2 → 1.2.0-beta.21

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 (101) hide show
  1. package/dist/style.css +41 -28
  2. package/dist/{tmagic-editor.mjs → tmagic-editor.js} +1693 -1272
  3. package/dist/tmagic-editor.js.map +1 -0
  4. package/dist/{tmagic-editor.umd.js → tmagic-editor.umd.cjs} +1700 -1274
  5. package/dist/tmagic-editor.umd.cjs.map +1 -0
  6. package/package.json +16 -14
  7. package/src/Editor.vue +54 -37
  8. package/src/components/CodeDraftEditor.vue +145 -0
  9. package/src/components/ContentMenu.vue +4 -4
  10. package/src/components/FunctionEditor.vue +145 -0
  11. package/src/components/Icon.vue +7 -5
  12. package/src/components/Layout.vue +149 -0
  13. package/src/components/ScrollBar.vue +1 -1
  14. package/src/components/ScrollViewer.vue +10 -1
  15. package/src/components/ToolButton.vue +30 -15
  16. package/src/fields/Code.vue +1 -1
  17. package/src/fields/CodeLink.vue +1 -1
  18. package/src/fields/CodeSelect.vue +89 -110
  19. package/src/fields/UISelect.vue +9 -8
  20. package/src/index.ts +1 -0
  21. package/src/layouts/AddPageBox.vue +3 -2
  22. package/src/layouts/CodeEditor.vue +2 -3
  23. package/src/layouts/Framework.vue +62 -40
  24. package/src/layouts/NavMenu.vue +1 -1
  25. package/src/layouts/PropsPanel.vue +11 -13
  26. package/src/layouts/Resizer.vue +1 -1
  27. package/src/layouts/sidebar/ComponentListPanel.vue +15 -13
  28. package/src/layouts/sidebar/LayerMenu.vue +9 -7
  29. package/src/layouts/sidebar/LayerPanel.vue +277 -177
  30. package/src/layouts/sidebar/Sidebar.vue +113 -27
  31. package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +34 -85
  32. package/src/layouts/sidebar/code-block/CodeBlockList.vue +55 -89
  33. package/src/layouts/workspace/Breadcrumb.vue +32 -0
  34. package/src/layouts/workspace/PageBar.vue +12 -11
  35. package/src/layouts/workspace/PageBarScrollContainer.vue +1 -1
  36. package/src/layouts/workspace/Stage.vue +26 -9
  37. package/src/layouts/workspace/ViewerMenu.vue +11 -9
  38. package/src/layouts/workspace/Workspace.vue +10 -3
  39. package/src/services/BaseService.ts +6 -1
  40. package/src/services/codeBlock.ts +124 -125
  41. package/src/services/componentList.ts +6 -1
  42. package/src/services/editor.ts +43 -19
  43. package/src/services/events.ts +6 -1
  44. package/src/services/history.ts +7 -16
  45. package/src/services/props.ts +7 -2
  46. package/src/services/storage.ts +1 -0
  47. package/src/services/ui.ts +12 -0
  48. package/src/theme/breadcrumb.scss +6 -0
  49. package/src/theme/code-block.scss +30 -21
  50. package/src/theme/component-list-panel.scss +3 -7
  51. package/src/theme/layer-panel.scss +7 -2
  52. package/src/theme/theme.scss +1 -0
  53. package/src/type.ts +76 -50
  54. package/src/utils/editor.ts +9 -1
  55. package/src/utils/index.ts +1 -0
  56. package/src/utils/props.ts +2 -2
  57. package/src/utils/scroll-viewer.ts +18 -2
  58. package/src/utils/stage.ts +9 -2
  59. package/types/Editor.vue.d.ts +42 -29
  60. package/types/components/CodeDraftEditor.vue.d.ts +148 -0
  61. package/types/components/ContentMenu.vue.d.ts +1 -3
  62. package/types/components/FunctionEditor.vue.d.ts +120 -0
  63. package/types/components/Icon.vue.d.ts +1 -3
  64. package/types/{layouts → components}/Layout.vue.d.ts +12 -1
  65. package/types/components/ScrollBar.vue.d.ts +1 -3
  66. package/types/components/ScrollViewer.vue.d.ts +45 -1
  67. package/types/components/ToolButton.vue.d.ts +1 -3
  68. package/types/fields/Code.vue.d.ts +1 -3
  69. package/types/fields/CodeLink.vue.d.ts +1 -3
  70. package/types/fields/CodeSelect.vue.d.ts +10 -12
  71. package/types/fields/UISelect.vue.d.ts +1 -3
  72. package/types/index.d.ts +1 -0
  73. package/types/layouts/AddPageBox.vue.d.ts +1 -3
  74. package/types/layouts/CodeEditor.vue.d.ts +6 -15
  75. package/types/layouts/NavMenu.vue.d.ts +1 -3
  76. package/types/layouts/sidebar/LayerMenu.vue.d.ts +25 -9
  77. package/types/layouts/sidebar/LayerPanel.vue.d.ts +38 -886
  78. package/types/layouts/sidebar/Sidebar.vue.d.ts +10 -5
  79. package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +1 -1
  80. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +6 -5
  81. package/types/layouts/{sidebar/TabPane.vue.d.ts → workspace/Breadcrumb.vue.d.ts} +5 -43
  82. package/types/layouts/workspace/Stage.vue.d.ts +25 -8
  83. package/types/layouts/workspace/ViewerMenu.vue.d.ts +6 -3
  84. package/types/layouts/workspace/Workspace.vue.d.ts +23 -5
  85. package/types/services/BaseService.d.ts +2 -1
  86. package/types/services/codeBlock.d.ts +57 -36
  87. package/types/services/componentList.d.ts +1 -0
  88. package/types/services/editor.d.ts +5 -6
  89. package/types/services/events.d.ts +1 -0
  90. package/types/services/history.d.ts +5 -15
  91. package/types/services/props.d.ts +3 -2
  92. package/types/services/ui.d.ts +2 -1
  93. package/types/type.d.ts +64 -48
  94. package/types/utils/editor.d.ts +1 -0
  95. package/types/utils/index.d.ts +1 -0
  96. package/types/utils/props.d.ts +1 -1
  97. package/types/utils/scroll-viewer.d.ts +5 -0
  98. package/dist/tmagic-editor.mjs.map +0 -1
  99. package/dist/tmagic-editor.umd.js.map +0 -1
  100. package/src/layouts/Layout.vue +0 -100
  101. package/src/layouts/sidebar/TabPane.vue +0 -116
@@ -91,7 +91,7 @@ class Props extends BaseService {
91
91
  * @param type 组件类型
92
92
  * @param value 组件初始值
93
93
  */
94
- public setPropsValue(type: string, value: MNode) {
94
+ public async setPropsValue(type: string, value: MNode) {
95
95
  this.state.propsValueMap[type] = value;
96
96
  }
97
97
 
@@ -171,10 +171,15 @@ class Props extends BaseService {
171
171
  };
172
172
  }
173
173
 
174
- public destroy() {
174
+ public resetState() {
175
175
  this.state.propsConfigMap = {};
176
176
  this.state.propsValueMap = {};
177
+ }
178
+
179
+ public destroy() {
180
+ this.resetState();
177
181
  this.removeAllListeners();
182
+ this.removeAllPlugins();
178
183
  }
179
184
 
180
185
  /**
@@ -109,6 +109,7 @@ export class WebStorage extends BaseService {
109
109
 
110
110
  public destroy() {
111
111
  this.removeAllListeners();
112
+ this.removeAllPlugins();
112
113
  }
113
114
 
114
115
  private getValueAndProtocol(value: string | null) {
@@ -97,8 +97,20 @@ class Ui extends BaseService {
97
97
  return Math.min((width - 60) / stageWidth || 1, (height - 80) / stageHeight || 1);
98
98
  }
99
99
 
100
+ public resetState() {
101
+ this.set('showSrc', false);
102
+ this.set('uiSelectMode', false);
103
+ this.set('zoom', 1);
104
+ this.set('stageContainerRect', {
105
+ width: 0,
106
+ height: 0,
107
+ });
108
+ }
109
+
100
110
  public destroy() {
111
+ this.resetState();
101
112
  this.removeAllListeners();
113
+ this.removeAllPlugins();
102
114
  }
103
115
 
104
116
  private async setStageRect(value: StageRect) {
@@ -0,0 +1,6 @@
1
+ .m-editor-breadcrumb {
2
+ position: absolute;
3
+ left: 5px;
4
+ top: 5px;
5
+ z-index: 10;
6
+ }
@@ -3,6 +3,9 @@
3
3
  .el-tree-node__content {
4
4
  height: auto;
5
5
  }
6
+ .el-tree-node__label {
7
+ width: 100%;
8
+ }
6
9
  .code-header-wrapper {
7
10
  display: flex;
8
11
  align-items: center;
@@ -32,9 +35,7 @@
32
35
  display: flex;
33
36
  align-items: center;
34
37
  .right-tool {
35
- position: absolute;
36
- right: 15px;
37
- padding-left: 5px;
38
+ width: fit-content !important;
38
39
  display: flex;
39
40
  align-items: center;
40
41
  .edit-icon {
@@ -47,7 +48,8 @@
47
48
  white-space: nowrap;
48
49
  text-overflow: ellipsis;
49
50
  padding: 10px 15px;
50
- margin-right: 60px;
51
+ width: 0 !important;
52
+ flex: 1;
51
53
  }
52
54
  }
53
55
  .code-comp-map-wrapper {
@@ -74,20 +76,12 @@
74
76
 
75
77
  .m-fields-code-select {
76
78
  width: 100%;
77
- .el-card__body {
78
- padding: 5px;
79
- }
80
- .tool-bar {
81
- display: flex;
82
- align-items: center;
83
- justify-content: end;
84
- height: 20px;
85
- .tool-item {
86
- display: flex;
87
- align-items: center;
88
- }
89
- }
90
79
  }
80
+
81
+ .el-dialog.is-fullscreen.code-editor-dialog {
82
+ overflow: hidden;
83
+ }
84
+
91
85
  .code-editor-dialog {
92
86
  .el-dialog__body {
93
87
  height: 90%;
@@ -97,7 +91,7 @@
97
91
  height: 100%;
98
92
  background: #fff;
99
93
  .el-card__body {
100
- height: calc(100% - 80px);
94
+ height: 100%;
101
95
  background: #fff;
102
96
  }
103
97
  }
@@ -109,6 +103,9 @@
109
103
  .side-tree {
110
104
  height: 100%;
111
105
  overflow: auto;
106
+ .el-tree-node__label {
107
+ width: 100%;
108
+ }
112
109
 
113
110
  .list-container {
114
111
  width: 100%;
@@ -134,6 +131,7 @@
134
131
  display: flex;
135
132
  align-items: center;
136
133
  font-size: 16px;
134
+ margin-bottom: 10px;
137
135
  .code-name-label {
138
136
  margin-right: 10px;
139
137
  }
@@ -166,18 +164,29 @@
166
164
 
167
165
  .m-editor-wrapper {
168
166
  height: 100%;
167
+ &.fullScreen {
168
+ height: 100%;
169
+ width: 100%;
170
+ position: fixed;
171
+ top: 0;
172
+ left: 0;
173
+ z-index: 100;
174
+ }
169
175
  .m-editor-container {
170
- height: calc(100% - 70px);
176
+ height: calc(100% - 45px);
171
177
  }
172
178
  .m-editor-content-bottom {
173
- height: 40px;
179
+ height: 45px;
174
180
  width: 100%;
175
181
  display: flex;
176
182
  justify-content: end;
177
183
  background: #fff;
184
+ position: absolute;
185
+ right: 20px;
186
+ bottom: 0;
178
187
  > button {
179
188
  height: 30px;
180
- margin-top: 15px;
189
+ margin-top: 5px;
181
190
  }
182
191
  }
183
192
  }
@@ -1,11 +1,11 @@
1
1
  .ui-component-panel {
2
2
  height: 100%;
3
3
  border-top: 0 !important;
4
- margin-top: 50px;
4
+ margin-top: 48px;
5
5
  background-color: $--sidebar-content-background-color;
6
6
 
7
7
  .search-input {
8
- background: #f8fbff;
8
+ background: #fff;
9
9
  color: #bbbbbb;
10
10
  padding: 10px;
11
11
  position: absolute;
@@ -15,11 +15,7 @@
15
15
  z-index: 1;
16
16
 
17
17
  .el-input__prefix {
18
- padding: 10px;
19
- }
20
-
21
- .el-input__suffix {
22
- padding: 10px 5px;
18
+ padding: 7px;
23
19
  }
24
20
  }
25
21
 
@@ -10,10 +10,15 @@
10
10
  left: 0;
11
11
  z-index: 1;
12
12
 
13
- .el-input__suffix {
14
- padding: 10px 5px;
13
+ .el-input__prefix {
14
+ padding: 7px;
15
15
  }
16
16
  }
17
+
18
+ .magic-editor-layer-tree {
19
+ padding-top: 48px;
20
+ }
21
+
17
22
  .node-content {
18
23
  flex: 1;
19
24
  display: flex;
@@ -13,3 +13,4 @@
13
13
  @import "./icon.scss";
14
14
  @import "./code-block.scss";
15
15
  @import "./layout.scss";
16
+ @import "./breadcrumb.scss";
package/src/type.ts CHANGED
@@ -19,9 +19,14 @@
19
19
  import type { Component } from 'vue';
20
20
 
21
21
  import type { FormConfig } from '@tmagic/form';
22
- import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
22
+ import type { CodeBlockContent, CodeBlockDSL, Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
23
23
  import type StageCore from '@tmagic/stage';
24
- import type { ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
24
+ import type {
25
+ ContainerHighlightType,
26
+ CustomizeMoveableOptionsCallbackConfig,
27
+ MoveableOptions,
28
+ UpdateDragEl,
29
+ } from '@tmagic/stage';
25
30
 
26
31
  import type { CodeBlockService } from './services/codeBlock';
27
32
  import type { ComponentListService } from './services/componentList';
@@ -31,6 +36,7 @@ import type { HistoryService } from './services/history';
31
36
  import type { PropsService } from './services/props';
32
37
  import type { StorageService } from './services/storage';
33
38
  import type { UiService } from './services/ui';
39
+ import type { UndoRedo } from './utils/undo-redo';
34
40
 
35
41
  export type BeforeAdd = (config: MNode, parent: MContainer) => Promise<MNode> | MNode;
36
42
  export type GetConfig = (config: FormConfig) => Promise<FormConfig> | FormConfig;
@@ -56,11 +62,11 @@ export interface StageOptions {
56
62
  containerHighlightClassName: string;
57
63
  containerHighlightDuration: number;
58
64
  containerHighlightType: ContainerHighlightType;
59
- render: () => HTMLDivElement;
60
- moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
65
+ render: (stage: StageCore) => HTMLDivElement | Promise<HTMLDivElement>;
66
+ moveableOptions: MoveableOptions | ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions);
61
67
  canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
62
68
  isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
63
- updateDragEl: (el: HTMLDivElement) => void;
69
+ updateDragEl: UpdateDragEl;
64
70
  }
65
71
 
66
72
  export interface StoreState {
@@ -164,18 +170,17 @@ export interface MenuButton {
164
170
  * 按钮类型
165
171
  * button: 只有文字不带边框的按钮
166
172
  * text: 纯文本
173
+ * divider: 分割线
167
174
  * dropdown: 下拉菜单
168
- * divider: 分隔线
169
- * zoom: 放大缩小
170
175
  */
171
- type: 'button' | 'dropdown' | 'text' | 'divider' | 'zoom';
176
+ type: 'button' | 'text' | 'divider' | 'dropdown';
172
177
  /** 当type为divider时有效,分割线方向, 默认vertical */
173
178
  direction?: 'horizontal' | 'vertical';
174
179
  /** 展示的文案 */
175
180
  text?: string;
176
181
  /** 鼠标悬浮是显示的气泡中的文案 */
177
182
  tooltip?: string;
178
- /** element-plus icon class */
183
+ /** Vue组件或url */
179
184
  icon?: string | Component<{}, {}, any>;
180
185
  /** 是否置灰,默认为false */
181
186
  disabled?: boolean | ((data?: Services) => boolean);
@@ -183,8 +188,8 @@ export interface MenuButton {
183
188
  display?: boolean | ((data?: Services) => boolean);
184
189
  /** type为button/dropdown时点击运行的方法 */
185
190
  handler?: (data: Services, event: MouseEvent) => Promise<any> | any;
186
- /** type为dropdown时,下拉的菜单列表, 或者有子菜单时 */
187
191
  className?: string;
192
+ /** type为dropdown时,下拉的菜单列表, 或者有子菜单时 */
188
193
  items?: MenuButton[];
189
194
  }
190
195
 
@@ -200,6 +205,7 @@ export interface MenuComponent {
200
205
  /** 是否显示,默认为true */
201
206
  className?: string;
202
207
  display?: boolean | ((data?: Services) => Promise<boolean> | boolean);
208
+ [key: string]: any;
203
209
  }
204
210
 
205
211
  /**
@@ -207,8 +213,13 @@ export interface MenuComponent {
207
213
  * 'delete': 删除按钮
208
214
  * 'undo': 撤销按钮
209
215
  * 'redo': 恢复按钮
216
+ * 'zoom': 'zoom-in', 'zoom-out', 'scale-to-original', 'scale-to-fit' 的集合
210
217
  * 'zoom-in': 放大按钮
211
218
  * 'zoom-out': 缩小按钮
219
+ * 'guides': 显示隐藏参考线
220
+ * 'rule': 显示隐藏标尺
221
+ * 'scale-to-original': 缩放到实际大小
222
+ * 'scale-to-fit': 缩放以适应
212
223
  */
213
224
  export type MenuItem =
214
225
  | '/'
@@ -220,6 +231,8 @@ export type MenuItem =
220
231
  | 'zoom-out'
221
232
  | 'guides'
222
233
  | 'rule'
234
+ | 'scale-to-original'
235
+ | 'scale-to-fit'
223
236
  | MenuButton
224
237
  | MenuComponent
225
238
  | string;
@@ -237,13 +250,14 @@ export interface MenuBarData {
237
250
  export interface SideComponent extends MenuComponent {
238
251
  /** 显示文案 */
239
252
  text: string;
240
- /** element-plus icon class */
253
+ /** vue组件或url */
241
254
  icon: Component<{}, {}, any>;
242
255
  }
243
256
 
244
257
  /**
245
258
  * component-list: 组件列表
246
259
  * layer: 已选组件树
260
+ * code-block: 代码块
247
261
  */
248
262
  export type SideItem = 'component-list' | 'layer' | 'code-block' | SideComponent;
249
263
 
@@ -262,8 +276,9 @@ export interface ComponentItem {
262
276
  text: string;
263
277
  /** 组件类型 */
264
278
  type: string;
265
- /** element-plus icon class */
266
- icon?: string | Component;
279
+ /** Vue组件或url */
280
+ icon?: string | Component<{}, {}, any>;
281
+ /** 新增组件时需要透传到组价节点上的数据 */
267
282
  data?: {
268
283
  [key: string]: any;
269
284
  };
@@ -308,28 +323,13 @@ export interface ScrollViewerEvent {
308
323
  scrollWidth: number;
309
324
  }
310
325
 
311
- export interface CodeBlockDSL {
312
- [id: string]: CodeBlockContent;
313
- }
314
-
315
- export interface CodeBlockContent {
316
- /** 代码块名称 */
317
- name: string;
318
- /** 代码块内容 */
319
- content: string;
320
- /** 代码块与组件的绑定关系 */
321
- comps?: CodeRelation;
322
- /** 扩展字段 */
323
- [propName: string]: any;
324
- }
325
-
326
326
  export type CodeState = {
327
327
  /** 是否展示代码块编辑区 */
328
328
  isShowCodeEditor: boolean;
329
329
  /** 代码块DSL数据源 */
330
330
  codeDsl: CodeBlockDSL | null;
331
331
  /** 当前选中的代码块id */
332
- id: string;
332
+ id: Id;
333
333
  /** 代码块是否可编辑 */
334
334
  editable: boolean;
335
335
  /** 代码编辑面板的展示模式 */
@@ -337,12 +337,23 @@ export type CodeState = {
337
337
  /** list模式下左侧展示的代码列表 */
338
338
  combineIds: string[];
339
339
  /** 为业务逻辑预留的不可删除的代码块列表,由业务逻辑维护(如代码块上线后不可删除) */
340
- undeletableList: string[];
340
+ undeletableList: Id[];
341
+ /** 代码块和组件的绑定关系 */
342
+ relations: CodeRelation;
343
+ };
344
+
345
+ export type HookData = {
346
+ /** 代码块id */
347
+ codeId: Id;
348
+ /** 参数 */
349
+ params?: object;
341
350
  };
342
351
 
343
352
  export type CodeRelation = {
344
- /** 组件id:['created'] */
345
- [compId: string | number]: string[];
353
+ [codeId: Id]: {
354
+ /** 组件id:['created'] */
355
+ [compId: Id]: string[];
356
+ };
346
357
  };
347
358
 
348
359
  export enum CodeEditorMode {
@@ -352,28 +363,29 @@ export enum CodeEditorMode {
352
363
  EDITOR = 'editor',
353
364
  }
354
365
 
355
- export interface CodeDslList {
366
+ export interface CodeDslItem {
356
367
  /** 代码块id */
357
- id: string;
368
+ id: Id;
358
369
  /** 代码块名称 */
359
370
  name: string;
360
371
  /** 代码块函数内容 */
361
372
  codeBlockContent?: CodeBlockContent;
362
373
  /** 是否展示代码绑定关系 */
363
374
  showRelation?: boolean;
375
+ /** 代码块对应绑定的组件信息 */
376
+ combineInfo?: CombineInfo[];
364
377
  }
365
378
 
366
- export interface ListState {
367
- /** 代码块列表 */
368
- codeList: CodeDslList[];
379
+ export interface CombineInfo {
380
+ /** 组件id */
381
+ compId: Id;
382
+ /** 组件名称 */
383
+ compName: string;
369
384
  }
370
385
 
371
- export interface ListRelationState extends ListState {
372
- /** 与代码块绑定的组件id信息 */
373
- bindComps: {
374
- /** 代码块id : 组件信息 */
375
- [id: string]: MNode[];
376
- };
386
+ export interface ListState {
387
+ /** 代码块列表 */
388
+ codeList: CodeDslItem[];
377
389
  }
378
390
 
379
391
  export enum CodeDeleteErrorType {
@@ -383,11 +395,25 @@ export enum CodeDeleteErrorType {
383
395
  BIND = 'bind',
384
396
  }
385
397
 
386
- export enum CodeSelectOp {
387
- /** 增加 */
388
- ADD = 'add',
389
- /** 删除 */
390
- DELETE = 'delete',
391
- /** 单选修改 */
392
- CHANGE = 'change',
398
+ // 代码块草稿localStorage key
399
+ export const CODE_DRAFT_STORAGE_KEY = 'magicCodeDraft';
400
+
401
+ export interface CodeParamStatement {
402
+ /** 参数名称 */
403
+ name: string;
404
+ /** 参数类型 */
405
+ type?: string;
406
+ }
407
+
408
+ export interface StepValue {
409
+ data: MPage;
410
+ modifiedNodeIds: Map<Id, Id>;
411
+ nodeId: Id;
412
+ }
413
+
414
+ export interface HistoryState {
415
+ pageId?: Id;
416
+ pageSteps: Record<Id, UndoRedo<StepValue>>;
417
+ canRedo: boolean;
418
+ canUndo: boolean;
393
419
  }
@@ -16,13 +16,14 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
+ import serialize from 'serialize-javascript';
20
+
19
21
  import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
20
22
  import { NodeType } from '@tmagic/schema';
21
23
  import type StageCore from '@tmagic/stage';
22
24
  import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
23
25
 
24
26
  import { Layout } from '../type';
25
-
26
27
  export const COPY_STORAGE_KEY = '$MagicEditorCopyData';
27
28
 
28
29
  /**
@@ -237,3 +238,10 @@ export const fixNodePosition = (config: MNode, parent: MContainer, stage: StageC
237
238
  left: fixNodeLeft(config, parent, stage?.renderer.contentWindow?.document),
238
239
  };
239
240
  };
241
+
242
+ // 序列化配置
243
+ export const serializeConfig = (config: any) =>
244
+ serialize(config, {
245
+ space: 2,
246
+ unsafe: true,
247
+ }).replace(/"(\w+)":\s/g, '$1: ');
@@ -21,3 +21,4 @@ export * from './props';
21
21
  export * from './logger';
22
22
  export * from './editor';
23
23
  export * from './stage';
24
+ export * from './operator';
@@ -226,14 +226,14 @@ export const fillConfig = (config: FormConfig = []) => [
226
226
  {
227
227
  name: 'created',
228
228
  text: 'created',
229
- type: 'code-select',
230
229
  labelWidth: '100px',
230
+ type: 'code-select',
231
231
  },
232
232
  {
233
233
  name: 'mounted',
234
234
  text: 'mounted',
235
- type: 'code-select',
236
235
  labelWidth: '100px',
236
+ type: 'code-select',
237
237
  },
238
238
  ],
239
239
  },
@@ -4,6 +4,10 @@ interface ScrollViewerOptions {
4
4
  container: HTMLDivElement;
5
5
  target: HTMLDivElement;
6
6
  zoom: number;
7
+ correctionScrollSize?: {
8
+ width: number;
9
+ height: number;
10
+ };
7
11
  }
8
12
 
9
13
  export class ScrollViewer extends EventEmitter {
@@ -23,6 +27,11 @@ export class ScrollViewer extends EventEmitter {
23
27
  private translateXCorrectionValue = 0;
24
28
  private translateYCorrectionValue = 0;
25
29
 
30
+ private correctionScrollSize = {
31
+ width: 0,
32
+ height: 0,
33
+ };
34
+
26
35
  private resizeObserver = new ResizeObserver(() => {
27
36
  this.setSize();
28
37
  this.setScrollSize();
@@ -35,6 +44,13 @@ export class ScrollViewer extends EventEmitter {
35
44
  this.target = options.target;
36
45
  this.zoom = options.zoom;
37
46
 
47
+ if (this.correctionScrollSize) {
48
+ this.correctionScrollSize = {
49
+ ...this.correctionScrollSize,
50
+ ...options.correctionScrollSize,
51
+ };
52
+ }
53
+
38
54
  this.container.addEventListener('wheel', this.wheelHandler, false);
39
55
 
40
56
  this.setSize();
@@ -109,9 +125,9 @@ export class ScrollViewer extends EventEmitter {
109
125
 
110
126
  private setScrollSize = () => {
111
127
  const targetRect = this.target.getBoundingClientRect();
112
- this.scrollWidth = targetRect.width * this.zoom + 100;
128
+ this.scrollWidth = targetRect.width * this.zoom + this.correctionScrollSize.width;
113
129
  const targetMarginTop = Number(this.target.style.marginTop) || 0;
114
- this.scrollHeight = (targetRect.height + targetMarginTop) * this.zoom + 100;
130
+ this.scrollHeight = (targetRect.height + targetMarginTop) * this.zoom + this.correctionScrollSize.height;
115
131
 
116
132
  let left: number | undefined;
117
133
  let top: number | undefined;
@@ -46,6 +46,7 @@ export const useStage = (stageOptions: StageOptions) => {
46
46
  ]);
47
47
 
48
48
  stage.on('select', (el: HTMLElement) => {
49
+ if (`${editorService.get('node')?.id}` === el.id && editorService.get('nodes').length === 1) return;
49
50
  editorService.select(el.id);
50
51
  });
51
52
 
@@ -53,7 +54,7 @@ export const useStage = (stageOptions: StageOptions) => {
53
54
  editorService.highlight(el.id);
54
55
  });
55
56
 
56
- stage.on('multiSelect', (els: HTMLElement[]) => {
57
+ stage.on('multi-select', (els: HTMLElement[]) => {
57
58
  editorService.multiSelect(els.map((el) => el.id));
58
59
  });
59
60
 
@@ -72,7 +73,13 @@ export const useStage = (stageOptions: StageOptions) => {
72
73
  editorService.sort(ev.src, ev.dist);
73
74
  });
74
75
 
75
- stage.on('changeGuides', (e) => {
76
+ stage.on('select-parent', () => {
77
+ const parent = editorService.get('parent');
78
+ editorService.select(parent);
79
+ editorService.get<StageCore>('stage').select(parent.id);
80
+ });
81
+
82
+ stage.on('change-guides', (e) => {
76
83
  uiService.set('showGuides', true);
77
84
 
78
85
  if (!root.value || !page.value) return;