@tmagic/editor 1.2.0-beta.8 → 1.2.0
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 +59 -35
- package/dist/{tmagic-editor.mjs → tmagic-editor.js} +1473 -1161
- package/dist/tmagic-editor.js.map +1 -0
- package/dist/{tmagic-editor.umd.js → tmagic-editor.umd.cjs} +1483 -1166
- package/dist/tmagic-editor.umd.cjs.map +1 -0
- package/package.json +16 -14
- package/src/Editor.vue +66 -40
- package/src/components/CodeDraftEditor.vue +145 -0
- package/src/components/ContentMenu.vue +2 -2
- package/src/components/FunctionEditor.vue +145 -0
- package/src/components/Icon.vue +1 -1
- package/src/{layouts → components}/Layout.vue +54 -15
- package/src/components/ScrollBar.vue +1 -1
- package/src/components/ScrollViewer.vue +10 -1
- package/src/components/ToolButton.vue +1 -1
- package/src/fields/Code.vue +1 -1
- package/src/fields/CodeLink.vue +1 -1
- package/src/fields/CodeSelect.vue +84 -110
- package/src/fields/UISelect.vue +1 -1
- package/src/index.ts +1 -0
- package/src/layouts/AddPageBox.vue +1 -1
- package/src/layouts/CodeEditor.vue +2 -3
- package/src/layouts/Framework.vue +2 -2
- package/src/layouts/NavMenu.vue +2 -2
- package/src/layouts/PropsPanel.vue +13 -6
- package/src/layouts/Resizer.vue +1 -1
- package/src/layouts/sidebar/ComponentListPanel.vue +1 -1
- package/src/layouts/sidebar/LayerMenu.vue +9 -7
- package/src/layouts/sidebar/LayerPanel.vue +127 -174
- package/src/layouts/sidebar/Sidebar.vue +110 -26
- package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +27 -83
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +90 -122
- package/src/layouts/workspace/Breadcrumb.vue +1 -1
- package/src/layouts/workspace/PageBar.vue +1 -1
- package/src/layouts/workspace/PageBarScrollContainer.vue +1 -1
- package/src/layouts/workspace/Stage.vue +26 -9
- package/src/layouts/workspace/ViewerMenu.vue +11 -9
- package/src/layouts/workspace/Workspace.vue +7 -3
- package/src/services/BaseService.ts +10 -1
- package/src/services/codeBlock.ts +124 -125
- package/src/services/componentList.ts +6 -1
- package/src/services/editor.ts +54 -18
- package/src/services/events.ts +6 -1
- package/src/services/history.ts +7 -16
- package/src/services/props.ts +7 -2
- package/src/services/storage.ts +1 -0
- package/src/services/ui.ts +12 -0
- package/src/theme/code-block.scss +43 -24
- package/src/theme/component-list-panel.scss +8 -5
- package/src/type.ts +77 -50
- package/src/utils/editor.ts +9 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/props.ts +2 -2
- package/src/utils/scroll-viewer.ts +18 -2
- package/src/utils/stage.ts +4 -3
- package/types/Editor.vue.d.ts +47 -27
- package/types/components/CodeDraftEditor.vue.d.ts +56 -0
- package/types/components/ContentMenu.vue.d.ts +11 -87
- package/types/components/FunctionEditor.vue.d.ts +43 -0
- package/types/components/Icon.vue.d.ts +4 -50
- package/types/{layouts → components}/Layout.vue.d.ts +12 -1
- package/types/components/ScrollBar.vue.d.ts +7 -65
- package/types/components/ScrollViewer.vue.d.ts +45 -1
- package/types/components/ToolButton.vue.d.ts +12 -78
- package/types/fields/Code.vue.d.ts +11 -77
- package/types/fields/CodeLink.vue.d.ts +12 -82
- package/types/fields/CodeSelect.vue.d.ts +13 -77
- package/types/fields/UISelect.vue.d.ts +7 -65
- package/types/index.d.ts +1 -0
- package/types/layouts/AddPageBox.vue.d.ts +1 -43
- package/types/layouts/CodeEditor.vue.d.ts +22 -130
- package/types/layouts/NavMenu.vue.d.ts +9 -69
- package/types/layouts/sidebar/LayerMenu.vue.d.ts +16 -48
- package/types/layouts/sidebar/LayerPanel.vue.d.ts +24 -7
- package/types/layouts/sidebar/Sidebar.vue.d.ts +10 -5
- package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +1 -1
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +6 -5
- package/types/layouts/workspace/Breadcrumb.vue.d.ts +1 -43
- package/types/layouts/workspace/Stage.vue.d.ts +15 -43
- package/types/layouts/workspace/ViewerMenu.vue.d.ts +11 -66
- package/types/layouts/workspace/Workspace.vue.d.ts +23 -5
- package/types/services/BaseService.d.ts +2 -1
- package/types/services/codeBlock.d.ts +57 -36
- package/types/services/componentList.d.ts +1 -0
- package/types/services/editor.d.ts +5 -6
- package/types/services/events.d.ts +1 -0
- package/types/services/history.d.ts +5 -15
- package/types/services/props.d.ts +3 -2
- package/types/services/ui.d.ts +2 -1
- package/types/type.d.ts +65 -48
- package/types/utils/editor.d.ts +1 -0
- package/types/utils/index.d.ts +1 -0
- package/types/utils/props.d.ts +1 -1
- package/types/utils/scroll-viewer.d.ts +5 -0
- package/dist/tmagic-editor.mjs.map +0 -1
- package/dist/tmagic-editor.umd.js.map +0 -1
- package/src/layouts/sidebar/TabPane.vue +0 -118
- package/types/layouts/sidebar/TabPane.vue.d.ts +0 -82
package/src/services/history.ts
CHANGED
|
@@ -18,25 +18,13 @@
|
|
|
18
18
|
|
|
19
19
|
import { reactive } from 'vue';
|
|
20
20
|
|
|
21
|
-
import type {
|
|
21
|
+
import type { MPage } from '@tmagic/schema';
|
|
22
22
|
|
|
23
|
+
import { HistoryState, StepValue } from '../type';
|
|
23
24
|
import { UndoRedo } from '../utils/undo-redo';
|
|
24
25
|
|
|
25
26
|
import BaseService from './BaseService';
|
|
26
27
|
|
|
27
|
-
export interface StepValue {
|
|
28
|
-
data: MPage;
|
|
29
|
-
modifiedNodeIds: Map<Id, Id>;
|
|
30
|
-
nodeId: Id;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface HistoryState {
|
|
34
|
-
pageId?: Id;
|
|
35
|
-
pageSteps: Record<Id, UndoRedo<StepValue>>;
|
|
36
|
-
canRedo: boolean;
|
|
37
|
-
canUndo: boolean;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
28
|
class History extends BaseService {
|
|
41
29
|
public state = reactive<HistoryState>({
|
|
42
30
|
pageSteps: {},
|
|
@@ -76,9 +64,11 @@ class History extends BaseService {
|
|
|
76
64
|
}
|
|
77
65
|
|
|
78
66
|
this.setCanUndoRedo();
|
|
67
|
+
|
|
68
|
+
this.emit('page-change', this.state.pageSteps[this.state.pageId]);
|
|
79
69
|
}
|
|
80
70
|
|
|
81
|
-
public
|
|
71
|
+
public resetState(): void {
|
|
82
72
|
this.state.pageId = undefined;
|
|
83
73
|
this.state.pageSteps = {};
|
|
84
74
|
this.state.canRedo = false;
|
|
@@ -110,8 +100,9 @@ class History extends BaseService {
|
|
|
110
100
|
}
|
|
111
101
|
|
|
112
102
|
public destroy(): void {
|
|
113
|
-
this.
|
|
103
|
+
this.resetState();
|
|
114
104
|
this.removeAllListeners();
|
|
105
|
+
this.removeAllPlugins();
|
|
115
106
|
}
|
|
116
107
|
|
|
117
108
|
private getUndoRedo() {
|
package/src/services/props.ts
CHANGED
|
@@ -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
|
|
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
|
/**
|
package/src/services/storage.ts
CHANGED
package/src/services/ui.ts
CHANGED
|
@@ -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) {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
.m-editor-code-block-list {
|
|
2
|
+
height: 100%;
|
|
2
3
|
margin-top: 5px;
|
|
4
|
+
|
|
3
5
|
.el-tree-node__content {
|
|
4
6
|
height: auto;
|
|
5
7
|
}
|
|
8
|
+
.el-tree-node__label {
|
|
9
|
+
width: 100%;
|
|
10
|
+
}
|
|
6
11
|
.code-header-wrapper {
|
|
7
12
|
display: flex;
|
|
8
13
|
align-items: center;
|
|
@@ -32,9 +37,7 @@
|
|
|
32
37
|
display: flex;
|
|
33
38
|
align-items: center;
|
|
34
39
|
.right-tool {
|
|
35
|
-
|
|
36
|
-
right: 15px;
|
|
37
|
-
padding-left: 5px;
|
|
40
|
+
width: fit-content !important;
|
|
38
41
|
display: flex;
|
|
39
42
|
align-items: center;
|
|
40
43
|
.edit-icon {
|
|
@@ -47,7 +50,8 @@
|
|
|
47
50
|
white-space: nowrap;
|
|
48
51
|
text-overflow: ellipsis;
|
|
49
52
|
padding: 10px 15px;
|
|
50
|
-
|
|
53
|
+
width: 0 !important;
|
|
54
|
+
flex: 1;
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
.code-comp-map-wrapper {
|
|
@@ -74,30 +78,30 @@
|
|
|
74
78
|
|
|
75
79
|
.m-fields-code-select {
|
|
76
80
|
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
81
|
}
|
|
82
|
+
|
|
83
|
+
.el-dialog.is-fullscreen.code-editor-dialog {
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
}
|
|
86
|
+
|
|
91
87
|
.code-editor-dialog {
|
|
92
|
-
.
|
|
88
|
+
.tmagic-design-card {
|
|
89
|
+
.t-card__header {
|
|
90
|
+
display: block;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.el-dialog__body,
|
|
95
|
+
.t-dialog__body {
|
|
93
96
|
height: 90%;
|
|
94
97
|
padding-top: 10px;
|
|
95
98
|
}
|
|
96
|
-
.
|
|
99
|
+
.tmagic-design-card {
|
|
97
100
|
height: 100%;
|
|
98
101
|
background: #fff;
|
|
99
|
-
.el-card__body
|
|
100
|
-
|
|
102
|
+
.el-card__body,
|
|
103
|
+
.t-card__body {
|
|
104
|
+
height: 100%;
|
|
101
105
|
background: #fff;
|
|
102
106
|
}
|
|
103
107
|
}
|
|
@@ -109,6 +113,9 @@
|
|
|
109
113
|
.side-tree {
|
|
110
114
|
height: 100%;
|
|
111
115
|
overflow: auto;
|
|
116
|
+
.el-tree-node__label {
|
|
117
|
+
width: 100%;
|
|
118
|
+
}
|
|
112
119
|
|
|
113
120
|
.list-container {
|
|
114
121
|
width: 100%;
|
|
@@ -134,6 +141,7 @@
|
|
|
134
141
|
display: flex;
|
|
135
142
|
align-items: center;
|
|
136
143
|
font-size: 16px;
|
|
144
|
+
margin-bottom: 10px;
|
|
137
145
|
.code-name-label {
|
|
138
146
|
margin-right: 10px;
|
|
139
147
|
}
|
|
@@ -166,18 +174,29 @@
|
|
|
166
174
|
|
|
167
175
|
.m-editor-wrapper {
|
|
168
176
|
height: 100%;
|
|
177
|
+
&.fullScreen {
|
|
178
|
+
height: 100%;
|
|
179
|
+
width: 100%;
|
|
180
|
+
position: fixed;
|
|
181
|
+
top: 0;
|
|
182
|
+
left: 0;
|
|
183
|
+
z-index: 100;
|
|
184
|
+
}
|
|
169
185
|
.m-editor-container {
|
|
170
|
-
height: calc(100% -
|
|
186
|
+
height: calc(100% - 45px);
|
|
171
187
|
}
|
|
172
188
|
.m-editor-content-bottom {
|
|
173
|
-
height:
|
|
189
|
+
height: 45px;
|
|
174
190
|
width: 100%;
|
|
175
191
|
display: flex;
|
|
176
192
|
justify-content: end;
|
|
177
193
|
background: #fff;
|
|
194
|
+
position: absolute;
|
|
195
|
+
right: 20px;
|
|
196
|
+
bottom: 0;
|
|
178
197
|
> button {
|
|
179
198
|
height: 30px;
|
|
180
|
-
margin-top:
|
|
199
|
+
margin-top: 5px;
|
|
181
200
|
}
|
|
182
201
|
}
|
|
183
202
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.ui-component-panel {
|
|
1
|
+
.ui-component-panel.tmagic-design-collapse {
|
|
2
2
|
height: 100%;
|
|
3
3
|
border-top: 0 !important;
|
|
4
4
|
margin-top: 48px;
|
|
@@ -19,14 +19,15 @@
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
.
|
|
22
|
+
.tmagic-design-collapse-item {
|
|
23
23
|
> div:first-of-type {
|
|
24
24
|
border-bottom: 1px solid $--border-color;
|
|
25
25
|
margin-bottom: 10px;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
.el-collapse-item__header
|
|
29
|
+
.el-collapse-item__header,
|
|
30
|
+
.t-collapse-panel__header {
|
|
30
31
|
background: $--sidebar-content-background-color;
|
|
31
32
|
color: $--font-color;
|
|
32
33
|
height: 25px;
|
|
@@ -40,11 +41,13 @@
|
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
.el-collapse-item__wrap
|
|
44
|
+
.el-collapse-item__wrap,
|
|
45
|
+
.t-collapse-panel__body {
|
|
44
46
|
background: $--sidebar-content-background-color;
|
|
45
47
|
border-bottom: 0;
|
|
46
48
|
|
|
47
|
-
.el-collapse-item__content
|
|
49
|
+
.el-collapse-item__content,
|
|
50
|
+
.t-collapse-panel__content {
|
|
48
51
|
padding: 10px;
|
|
49
52
|
display: flex;
|
|
50
53
|
flex-wrap: wrap;
|
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 {
|
|
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,12 @@ export interface StageOptions {
|
|
|
56
62
|
containerHighlightClassName: string;
|
|
57
63
|
containerHighlightDuration: number;
|
|
58
64
|
containerHighlightType: ContainerHighlightType;
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
disabledDragStart?: boolean;
|
|
66
|
+
render: (stage: StageCore) => HTMLDivElement | Promise<HTMLDivElement>;
|
|
67
|
+
moveableOptions: MoveableOptions | ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions);
|
|
61
68
|
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
|
62
69
|
isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
|
|
63
|
-
updateDragEl:
|
|
70
|
+
updateDragEl: UpdateDragEl;
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
export interface StoreState {
|
|
@@ -164,18 +171,17 @@ export interface MenuButton {
|
|
|
164
171
|
* 按钮类型
|
|
165
172
|
* button: 只有文字不带边框的按钮
|
|
166
173
|
* text: 纯文本
|
|
174
|
+
* divider: 分割线
|
|
167
175
|
* dropdown: 下拉菜单
|
|
168
|
-
* divider: 分隔线
|
|
169
|
-
* zoom: 放大缩小
|
|
170
176
|
*/
|
|
171
|
-
type: 'button' | '
|
|
177
|
+
type: 'button' | 'text' | 'divider' | 'dropdown';
|
|
172
178
|
/** 当type为divider时有效,分割线方向, 默认vertical */
|
|
173
179
|
direction?: 'horizontal' | 'vertical';
|
|
174
180
|
/** 展示的文案 */
|
|
175
181
|
text?: string;
|
|
176
182
|
/** 鼠标悬浮是显示的气泡中的文案 */
|
|
177
183
|
tooltip?: string;
|
|
178
|
-
/**
|
|
184
|
+
/** Vue组件或url */
|
|
179
185
|
icon?: string | Component<{}, {}, any>;
|
|
180
186
|
/** 是否置灰,默认为false */
|
|
181
187
|
disabled?: boolean | ((data?: Services) => boolean);
|
|
@@ -183,8 +189,8 @@ export interface MenuButton {
|
|
|
183
189
|
display?: boolean | ((data?: Services) => boolean);
|
|
184
190
|
/** type为button/dropdown时点击运行的方法 */
|
|
185
191
|
handler?: (data: Services, event: MouseEvent) => Promise<any> | any;
|
|
186
|
-
/** type为dropdown时,下拉的菜单列表, 或者有子菜单时 */
|
|
187
192
|
className?: string;
|
|
193
|
+
/** type为dropdown时,下拉的菜单列表, 或者有子菜单时 */
|
|
188
194
|
items?: MenuButton[];
|
|
189
195
|
}
|
|
190
196
|
|
|
@@ -200,6 +206,7 @@ export interface MenuComponent {
|
|
|
200
206
|
/** 是否显示,默认为true */
|
|
201
207
|
className?: string;
|
|
202
208
|
display?: boolean | ((data?: Services) => Promise<boolean> | boolean);
|
|
209
|
+
[key: string]: any;
|
|
203
210
|
}
|
|
204
211
|
|
|
205
212
|
/**
|
|
@@ -207,8 +214,13 @@ export interface MenuComponent {
|
|
|
207
214
|
* 'delete': 删除按钮
|
|
208
215
|
* 'undo': 撤销按钮
|
|
209
216
|
* 'redo': 恢复按钮
|
|
217
|
+
* 'zoom': 'zoom-in', 'zoom-out', 'scale-to-original', 'scale-to-fit' 的集合
|
|
210
218
|
* 'zoom-in': 放大按钮
|
|
211
219
|
* 'zoom-out': 缩小按钮
|
|
220
|
+
* 'guides': 显示隐藏参考线
|
|
221
|
+
* 'rule': 显示隐藏标尺
|
|
222
|
+
* 'scale-to-original': 缩放到实际大小
|
|
223
|
+
* 'scale-to-fit': 缩放以适应
|
|
212
224
|
*/
|
|
213
225
|
export type MenuItem =
|
|
214
226
|
| '/'
|
|
@@ -220,6 +232,8 @@ export type MenuItem =
|
|
|
220
232
|
| 'zoom-out'
|
|
221
233
|
| 'guides'
|
|
222
234
|
| 'rule'
|
|
235
|
+
| 'scale-to-original'
|
|
236
|
+
| 'scale-to-fit'
|
|
223
237
|
| MenuButton
|
|
224
238
|
| MenuComponent
|
|
225
239
|
| string;
|
|
@@ -237,13 +251,14 @@ export interface MenuBarData {
|
|
|
237
251
|
export interface SideComponent extends MenuComponent {
|
|
238
252
|
/** 显示文案 */
|
|
239
253
|
text: string;
|
|
240
|
-
/**
|
|
254
|
+
/** vue组件或url */
|
|
241
255
|
icon: Component<{}, {}, any>;
|
|
242
256
|
}
|
|
243
257
|
|
|
244
258
|
/**
|
|
245
259
|
* component-list: 组件列表
|
|
246
260
|
* layer: 已选组件树
|
|
261
|
+
* code-block: 代码块
|
|
247
262
|
*/
|
|
248
263
|
export type SideItem = 'component-list' | 'layer' | 'code-block' | SideComponent;
|
|
249
264
|
|
|
@@ -262,8 +277,9 @@ export interface ComponentItem {
|
|
|
262
277
|
text: string;
|
|
263
278
|
/** 组件类型 */
|
|
264
279
|
type: string;
|
|
265
|
-
/**
|
|
266
|
-
icon?: string | Component
|
|
280
|
+
/** Vue组件或url */
|
|
281
|
+
icon?: string | Component<{}, {}, any>;
|
|
282
|
+
/** 新增组件时需要透传到组价节点上的数据 */
|
|
267
283
|
data?: {
|
|
268
284
|
[key: string]: any;
|
|
269
285
|
};
|
|
@@ -308,28 +324,13 @@ export interface ScrollViewerEvent {
|
|
|
308
324
|
scrollWidth: number;
|
|
309
325
|
}
|
|
310
326
|
|
|
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
327
|
export type CodeState = {
|
|
327
328
|
/** 是否展示代码块编辑区 */
|
|
328
329
|
isShowCodeEditor: boolean;
|
|
329
330
|
/** 代码块DSL数据源 */
|
|
330
331
|
codeDsl: CodeBlockDSL | null;
|
|
331
332
|
/** 当前选中的代码块id */
|
|
332
|
-
id:
|
|
333
|
+
id: Id;
|
|
333
334
|
/** 代码块是否可编辑 */
|
|
334
335
|
editable: boolean;
|
|
335
336
|
/** 代码编辑面板的展示模式 */
|
|
@@ -337,12 +338,23 @@ export type CodeState = {
|
|
|
337
338
|
/** list模式下左侧展示的代码列表 */
|
|
338
339
|
combineIds: string[];
|
|
339
340
|
/** 为业务逻辑预留的不可删除的代码块列表,由业务逻辑维护(如代码块上线后不可删除) */
|
|
340
|
-
undeletableList:
|
|
341
|
+
undeletableList: Id[];
|
|
342
|
+
/** 代码块和组件的绑定关系 */
|
|
343
|
+
relations: CodeRelation;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
export type HookData = {
|
|
347
|
+
/** 代码块id */
|
|
348
|
+
codeId: Id;
|
|
349
|
+
/** 参数 */
|
|
350
|
+
params?: object;
|
|
341
351
|
};
|
|
342
352
|
|
|
343
353
|
export type CodeRelation = {
|
|
344
|
-
|
|
345
|
-
|
|
354
|
+
[codeId: Id]: {
|
|
355
|
+
/** 组件id:['created'] */
|
|
356
|
+
[compId: Id]: string[];
|
|
357
|
+
};
|
|
346
358
|
};
|
|
347
359
|
|
|
348
360
|
export enum CodeEditorMode {
|
|
@@ -352,28 +364,29 @@ export enum CodeEditorMode {
|
|
|
352
364
|
EDITOR = 'editor',
|
|
353
365
|
}
|
|
354
366
|
|
|
355
|
-
export interface
|
|
367
|
+
export interface CodeDslItem {
|
|
356
368
|
/** 代码块id */
|
|
357
|
-
id:
|
|
369
|
+
id: Id;
|
|
358
370
|
/** 代码块名称 */
|
|
359
371
|
name: string;
|
|
360
372
|
/** 代码块函数内容 */
|
|
361
373
|
codeBlockContent?: CodeBlockContent;
|
|
362
374
|
/** 是否展示代码绑定关系 */
|
|
363
375
|
showRelation?: boolean;
|
|
376
|
+
/** 代码块对应绑定的组件信息 */
|
|
377
|
+
combineInfo?: CombineInfo[];
|
|
364
378
|
}
|
|
365
379
|
|
|
366
|
-
export interface
|
|
367
|
-
/**
|
|
368
|
-
|
|
380
|
+
export interface CombineInfo {
|
|
381
|
+
/** 组件id */
|
|
382
|
+
compId: Id;
|
|
383
|
+
/** 组件名称 */
|
|
384
|
+
compName: string;
|
|
369
385
|
}
|
|
370
386
|
|
|
371
|
-
export interface
|
|
372
|
-
/**
|
|
373
|
-
|
|
374
|
-
/** 代码块id : 组件信息 */
|
|
375
|
-
[id: string]: MNode[];
|
|
376
|
-
};
|
|
387
|
+
export interface ListState {
|
|
388
|
+
/** 代码块列表 */
|
|
389
|
+
codeList: CodeDslItem[];
|
|
377
390
|
}
|
|
378
391
|
|
|
379
392
|
export enum CodeDeleteErrorType {
|
|
@@ -383,11 +396,25 @@ export enum CodeDeleteErrorType {
|
|
|
383
396
|
BIND = 'bind',
|
|
384
397
|
}
|
|
385
398
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
399
|
+
// 代码块草稿localStorage key
|
|
400
|
+
export const CODE_DRAFT_STORAGE_KEY = 'magicCodeDraft';
|
|
401
|
+
|
|
402
|
+
export interface CodeParamStatement {
|
|
403
|
+
/** 参数名称 */
|
|
404
|
+
name: string;
|
|
405
|
+
/** 参数类型 */
|
|
406
|
+
type?: string;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface StepValue {
|
|
410
|
+
data: MPage;
|
|
411
|
+
modifiedNodeIds: Map<Id, Id>;
|
|
412
|
+
nodeId: Id;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export interface HistoryState {
|
|
416
|
+
pageId?: Id;
|
|
417
|
+
pageSteps: Record<Id, UndoRedo<StepValue>>;
|
|
418
|
+
canRedo: boolean;
|
|
419
|
+
canUndo: boolean;
|
|
393
420
|
}
|
package/src/utils/editor.ts
CHANGED
|
@@ -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: ');
|
package/src/utils/index.ts
CHANGED
package/src/utils/props.ts
CHANGED
|
@@ -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 +
|
|
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 +
|
|
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;
|
package/src/utils/stage.ts
CHANGED
|
@@ -26,6 +26,7 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
26
26
|
containerHighlightClassName: stageOptions.containerHighlightClassName,
|
|
27
27
|
containerHighlightDuration: stageOptions.containerHighlightDuration,
|
|
28
28
|
containerHighlightType: stageOptions.containerHighlightType,
|
|
29
|
+
disabledDragStart: stageOptions.disabledDragStart,
|
|
29
30
|
canSelect: (el, event, stop) => {
|
|
30
31
|
const elCanSelect = stageOptions.canSelect(el);
|
|
31
32
|
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
|
@@ -46,7 +47,7 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
46
47
|
]);
|
|
47
48
|
|
|
48
49
|
stage.on('select', (el: HTMLElement) => {
|
|
49
|
-
if (`${editorService.get('node')?.id}` === el.id) return;
|
|
50
|
+
if (`${editorService.get('node')?.id}` === el.id && editorService.get('nodes').length === 1) return;
|
|
50
51
|
editorService.select(el.id);
|
|
51
52
|
});
|
|
52
53
|
|
|
@@ -54,7 +55,7 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
54
55
|
editorService.highlight(el.id);
|
|
55
56
|
});
|
|
56
57
|
|
|
57
|
-
stage.on('
|
|
58
|
+
stage.on('multi-select', (els: HTMLElement[]) => {
|
|
58
59
|
editorService.multiSelect(els.map((el) => el.id));
|
|
59
60
|
});
|
|
60
61
|
|
|
@@ -79,7 +80,7 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
79
80
|
editorService.get<StageCore>('stage').select(parent.id);
|
|
80
81
|
});
|
|
81
82
|
|
|
82
|
-
stage.on('
|
|
83
|
+
stage.on('change-guides', (e) => {
|
|
83
84
|
uiService.set('showGuides', true);
|
|
84
85
|
|
|
85
86
|
if (!root.value || !page.value) return;
|