@tmagic/editor 1.0.0-beta.1
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 +505 -0
- package/dist/tmagic-editor.es.js +4233 -0
- package/dist/tmagic-editor.es.js.map +1 -0
- package/dist/tmagic-editor.umd.js +4276 -0
- package/dist/tmagic-editor.umd.js.map +1 -0
- package/dist/types/src/Editor.vue.d.ts +136 -0
- package/dist/types/src/components/Icon.vue.d.ts +13 -0
- package/dist/types/src/components/ToolButton.vue.d.ts +35 -0
- package/dist/types/src/fields/Code.vue.d.ts +24 -0
- package/dist/types/src/fields/CodeLink.vue.d.ts +54 -0
- package/dist/types/src/fields/UISelect.vue.d.ts +32 -0
- package/dist/types/src/index.d.ts +19 -0
- package/dist/types/src/layouts/AddPageBox.vue.d.ts +5 -0
- package/dist/types/src/layouts/CodeEditor.vue.d.ts +46 -0
- package/dist/types/src/layouts/Framework.vue.d.ts +11 -0
- package/dist/types/src/layouts/NavMenu.vue.d.ts +24 -0
- package/dist/types/src/layouts/PropsPanel.vue.d.ts +13 -0
- package/dist/types/src/layouts/Resizer.vue.d.ts +13 -0
- package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +12 -0
- package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +31 -0
- package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +973 -0
- package/dist/types/src/layouts/sidebar/Sidebar.vue.d.ts +27 -0
- package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +11 -0
- package/dist/types/src/layouts/workspace/Stage.vue.d.ts +153 -0
- package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +18 -0
- package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +37 -0
- package/dist/types/src/services/BaseService.d.ts +56 -0
- package/dist/types/src/services/editor.d.ts +122 -0
- package/dist/types/src/services/events.d.ts +16 -0
- package/dist/types/src/services/history.d.ts +51 -0
- package/dist/types/src/services/props.d.ts +36 -0
- package/dist/types/src/services/ui.d.ts +26 -0
- package/dist/types/src/shims-vue.d.ts +6 -0
- package/dist/types/src/type.d.ts +183 -0
- package/dist/types/src/utils/compose.d.ts +5 -0
- package/dist/types/src/utils/config.d.ts +4 -0
- package/dist/types/src/utils/editor.d.ts +45 -0
- package/dist/types/src/utils/index.d.ts +4 -0
- package/dist/types/src/utils/logger.d.ts +5 -0
- package/dist/types/src/utils/props.d.ts +49 -0
- package/dist/types/src/utils/undo-redo.d.ts +12 -0
- package/dist/types/src/vite-env.d.ts +1 -0
- package/package.json +57 -0
- package/src/Editor.vue +234 -0
- package/src/components/Icon.vue +29 -0
- package/src/components/ToolButton.vue +188 -0
- package/src/fields/Code.vue +35 -0
- package/src/fields/CodeLink.vue +81 -0
- package/src/fields/UISelect.vue +100 -0
- package/src/index.ts +63 -0
- package/src/layouts/AddPageBox.vue +41 -0
- package/src/layouts/CodeEditor.vue +188 -0
- package/src/layouts/Framework.vue +73 -0
- package/src/layouts/NavMenu.vue +37 -0
- package/src/layouts/PropsPanel.vue +81 -0
- package/src/layouts/Resizer.vue +61 -0
- package/src/layouts/sidebar/ComponentListPanel.vue +69 -0
- package/src/layouts/sidebar/LayerMenu.vue +117 -0
- package/src/layouts/sidebar/LayerPanel.vue +209 -0
- package/src/layouts/sidebar/Sidebar.vue +86 -0
- package/src/layouts/workspace/PageBar.vue +83 -0
- package/src/layouts/workspace/Stage.vue +221 -0
- package/src/layouts/workspace/ViewerMenu.vue +110 -0
- package/src/layouts/workspace/Workspace.vue +98 -0
- package/src/services/BaseService.ts +138 -0
- package/src/services/componentList.ts +48 -0
- package/src/services/editor.ts +521 -0
- package/src/services/events.ts +82 -0
- package/src/services/history.ts +124 -0
- package/src/services/props.ts +110 -0
- package/src/services/ui.ts +101 -0
- package/src/shims-vue.d.ts +6 -0
- package/src/theme/code-editor.scss +7 -0
- package/src/theme/common/var.scss +13 -0
- package/src/theme/component-list-panel.scss +102 -0
- package/src/theme/content-menu.scss +39 -0
- package/src/theme/framework.scss +72 -0
- package/src/theme/index.scss +13 -0
- package/src/theme/layer-panel.scss +68 -0
- package/src/theme/nav-menu.scss +69 -0
- package/src/theme/page-bar.scss +31 -0
- package/src/theme/props-panel.scss +17 -0
- package/src/theme/resizer.scss +51 -0
- package/src/theme/ruler.scss +38 -0
- package/src/theme/sidebar.scss +97 -0
- package/src/theme/stage.scss +22 -0
- package/src/theme/workspace.scss +5 -0
- package/src/type.ts +236 -0
- package/src/utils/compose.ts +33 -0
- package/src/utils/config.ts +29 -0
- package/src/utils/editor.ts +244 -0
- package/src/utils/index.ts +22 -0
- package/src/utils/logger.ts +47 -0
- package/src/utils/props.ts +218 -0
- package/src/utils/undo-redo.ts +76 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +9 -0
- package/vite.config.ts +30 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { cloneDeep, random } from 'lodash-es';
|
|
20
|
+
|
|
21
|
+
import { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
22
|
+
import { getNodePath, isPop } from '@tmagic/utils';
|
|
23
|
+
|
|
24
|
+
import { Layout } from '@editor/type';
|
|
25
|
+
|
|
26
|
+
export const COPY_STORAGE_KEY = '$MagicEditorCopyData';
|
|
27
|
+
|
|
28
|
+
export const generateId = (type: string | number): string => `${type}_${random(10000, false)}`;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 获取所有页面配置
|
|
32
|
+
* @param app DSL跟节点
|
|
33
|
+
* @returns 所有页面配置
|
|
34
|
+
*/
|
|
35
|
+
export const getPageList = (app: MApp): MPage[] => {
|
|
36
|
+
if (app.items && Array.isArray(app.items)) {
|
|
37
|
+
return app.items.filter((item: MPage) => item.type === 'page');
|
|
38
|
+
}
|
|
39
|
+
return [];
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 获取所有页面名称
|
|
44
|
+
* @param pages 所有页面配置
|
|
45
|
+
* @returns 所有页面名称
|
|
46
|
+
*/
|
|
47
|
+
export const getPageNameList = (pages: MPage[]): string[] => pages.map((page: MPage) => page.name || 'index');
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 新增页面时,生成页面名称
|
|
51
|
+
* @param {Object} pageNameList 所有页面名称
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
export const generatePageName = (pageNameList: string[]): string => {
|
|
55
|
+
let pageLength = pageNameList.length;
|
|
56
|
+
|
|
57
|
+
if (!pageLength) return 'index';
|
|
58
|
+
|
|
59
|
+
let pageName = `page_${pageLength}`;
|
|
60
|
+
while (pageNameList.includes(pageName)) {
|
|
61
|
+
pageLength += 1;
|
|
62
|
+
pageName = `page_${pageLength}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return pageName;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 新增页面时,生成页面名称
|
|
70
|
+
* @param {Object} app 所有页面配置
|
|
71
|
+
* @returns {string}
|
|
72
|
+
*/
|
|
73
|
+
export const generatePageNameByApp = (app: MApp): string => generatePageName(getPageNameList(getPageList(app)));
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 复制页面时,需要把组件下关联的弹窗id换测复制出来的弹窗的id
|
|
77
|
+
* @param {number} oldId 复制的源弹窗id
|
|
78
|
+
* @param {number} popId 新的弹窗id
|
|
79
|
+
* @param {Object} pageConfig 页面配置
|
|
80
|
+
*/
|
|
81
|
+
const updatePopId = (oldId: Id, popId: Id, pageConfig: MPage) => {
|
|
82
|
+
pageConfig.items?.forEach((config) => {
|
|
83
|
+
if (config.pop === oldId) {
|
|
84
|
+
config.pop = popId;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (config.popId === oldId) {
|
|
89
|
+
config.popId = popId;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (Array.isArray(config.items)) {
|
|
94
|
+
updatePopId(oldId, popId, config as MPage);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 将组件与组件的子元素配置中的id都设置成一个新的ID
|
|
101
|
+
* @param {Object} config 组件配置
|
|
102
|
+
*/
|
|
103
|
+
/* eslint no-param-reassign: ["error", { "props": false }] */
|
|
104
|
+
export const setNewItemId = (config: MNode, parent?: MPage) => {
|
|
105
|
+
const oldId = config.id;
|
|
106
|
+
|
|
107
|
+
config.id = generateId(config.type);
|
|
108
|
+
config.name = `${config.name?.replace(/_(\d+)$/, '')}_${config.id}`;
|
|
109
|
+
|
|
110
|
+
// 只有弹窗在页面下的一级子元素才有效
|
|
111
|
+
if (isPop(config) && parent?.type === 'page') {
|
|
112
|
+
updatePopId(oldId, config.id, parent);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (config.items && Array.isArray(config.items)) {
|
|
116
|
+
config.items.forEach((item) => setNewItemId(item, config as MPage));
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {Object} node
|
|
122
|
+
* @returns {boolean}
|
|
123
|
+
*/
|
|
124
|
+
export const isFixed = (node: MNode): boolean => node.style?.position === 'fixed';
|
|
125
|
+
|
|
126
|
+
export const getNodeIndex = (node: MNode, parent: MContainer): number => {
|
|
127
|
+
const items = parent?.items || [];
|
|
128
|
+
return items.findIndex((item: MNode) => `${item.id}` === `${node.id}`);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const toRelative = (node: MNode) => {
|
|
132
|
+
node.style = {
|
|
133
|
+
...(node.style || {}),
|
|
134
|
+
position: 'relative',
|
|
135
|
+
top: 0,
|
|
136
|
+
left: 0,
|
|
137
|
+
};
|
|
138
|
+
return node;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export const initPosition = (node: MNode, layout: Layout) => {
|
|
142
|
+
if (layout === Layout.ABSOLUTE) {
|
|
143
|
+
node.style = {
|
|
144
|
+
position: 'absolute',
|
|
145
|
+
...(node.style || {}),
|
|
146
|
+
};
|
|
147
|
+
return node;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (layout === Layout.RELATIVE) {
|
|
151
|
+
return toRelative(node);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return node;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export const setLayout = (node: MNode, layout: Layout) => {
|
|
158
|
+
node.items?.forEach((child: MNode) => {
|
|
159
|
+
if (isPop(child)) return;
|
|
160
|
+
|
|
161
|
+
child.style = child.style || {};
|
|
162
|
+
|
|
163
|
+
// 是 fixed 不做处理
|
|
164
|
+
if (child.style.position === 'fixed') return;
|
|
165
|
+
|
|
166
|
+
if (layout !== Layout.RELATIVE) {
|
|
167
|
+
child.style.position = 'absolute';
|
|
168
|
+
} else {
|
|
169
|
+
toRelative(child);
|
|
170
|
+
child.style.right = 'auto';
|
|
171
|
+
child.style.bottom = 'auto';
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return node;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export const change2Fixed = (node: MNode, root: MApp) => {
|
|
178
|
+
const path = getNodePath(node.id, root.items);
|
|
179
|
+
const offset = {
|
|
180
|
+
left: 0,
|
|
181
|
+
top: 0,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
path.forEach((value) => {
|
|
185
|
+
offset.left = offset.left + globalThis.parseFloat(value.style?.left || 0);
|
|
186
|
+
offset.top = offset.top + globalThis.parseFloat(value.style?.top || 0);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
node.style = {
|
|
190
|
+
...(node.style || {}),
|
|
191
|
+
...offset,
|
|
192
|
+
};
|
|
193
|
+
return node;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export const Fixed2Other = async (node: MNode, root: MApp, getLayout: (node: MNode) => Promise<Layout>) => {
|
|
197
|
+
const path = getNodePath(node.id, root.items);
|
|
198
|
+
const cur = path.pop();
|
|
199
|
+
const offset = {
|
|
200
|
+
left: cur?.style?.left || 0,
|
|
201
|
+
top: cur?.style?.top || 0,
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
path.forEach((value) => {
|
|
205
|
+
offset.left = offset.left - globalThis.parseFloat(value.style?.left || 0);
|
|
206
|
+
offset.top = offset.top - globalThis.parseFloat(value.style?.top || 0);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const parent = path.pop();
|
|
210
|
+
if (!parent) {
|
|
211
|
+
return toRelative(node);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const layout = await getLayout(parent);
|
|
215
|
+
if (layout !== Layout.RELATIVE) {
|
|
216
|
+
node.style = {
|
|
217
|
+
...(node.style || {}),
|
|
218
|
+
...offset,
|
|
219
|
+
position: 'absolute',
|
|
220
|
+
};
|
|
221
|
+
return node;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return toRelative(node);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export const defaults = (object: any, source: any) => {
|
|
228
|
+
let o = source;
|
|
229
|
+
if (Array.isArray(object)) {
|
|
230
|
+
o = object;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
Object.entries(o).forEach(([key, value]: [string, any]) => {
|
|
234
|
+
if (typeof object[key] === 'undefined') {
|
|
235
|
+
object[key] = value;
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (value && typeof value !== 'string' && Object.keys(value).length) {
|
|
240
|
+
object[key] = defaults(cloneDeep(object[key]), value);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
return object;
|
|
244
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export * from './config';
|
|
20
|
+
export * from './props';
|
|
21
|
+
export * from './logger';
|
|
22
|
+
export * from './editor';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export const log = (...args: any[]) => {
|
|
20
|
+
if (process.env.NODE_ENV === 'development') {
|
|
21
|
+
console.log('magic editor: ', ...args);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const info = (...args: any[]) => {
|
|
26
|
+
if (process.env.NODE_ENV === 'development') {
|
|
27
|
+
console.info('magic editor: ', ...args);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const warn = (...args: any[]) => {
|
|
32
|
+
if (process.env.NODE_ENV === 'development') {
|
|
33
|
+
console.warn('magic editor: ', ...args);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const debug = (...args: any[]) => {
|
|
38
|
+
if (process.env.NODE_ENV === 'development') {
|
|
39
|
+
console.debug('magic editor: ', ...args);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const error = (...args: any[]) => {
|
|
44
|
+
if (process.env.NODE_ENV === 'development') {
|
|
45
|
+
console.error('magic editor: ', ...args);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { FormConfig, FormState } from '@tmagic/form';
|
|
20
|
+
|
|
21
|
+
import editorService from '@editor/services/editor';
|
|
22
|
+
import eventsService from '@editor/services/events';
|
|
23
|
+
import { generateId } from '@editor/utils/editor';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 统一为组件属性表单加上事件、高级、样式配置
|
|
27
|
+
* @param config 组件属性配置
|
|
28
|
+
* @returns Object
|
|
29
|
+
*/
|
|
30
|
+
export const fillConfig = (config: FormConfig = []) => [
|
|
31
|
+
{
|
|
32
|
+
type: 'tab',
|
|
33
|
+
items: [
|
|
34
|
+
{
|
|
35
|
+
title: '属性',
|
|
36
|
+
labelWidth: '80px',
|
|
37
|
+
items: [
|
|
38
|
+
// 组件类型,必须要有
|
|
39
|
+
{
|
|
40
|
+
text: 'type',
|
|
41
|
+
name: 'type',
|
|
42
|
+
type: 'hidden',
|
|
43
|
+
},
|
|
44
|
+
// 组件id,必须要有
|
|
45
|
+
{
|
|
46
|
+
name: 'id',
|
|
47
|
+
type: 'display',
|
|
48
|
+
text: 'id',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'name',
|
|
52
|
+
text: '组件名称',
|
|
53
|
+
},
|
|
54
|
+
...config,
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
title: '样式',
|
|
59
|
+
labelWidth: '80px',
|
|
60
|
+
items: [
|
|
61
|
+
{
|
|
62
|
+
name: 'style',
|
|
63
|
+
items: [
|
|
64
|
+
{
|
|
65
|
+
type: 'fieldset',
|
|
66
|
+
legend: '位置',
|
|
67
|
+
items: [
|
|
68
|
+
{
|
|
69
|
+
name: 'position',
|
|
70
|
+
type: 'checkbox',
|
|
71
|
+
activeValue: 'fixed',
|
|
72
|
+
inactiveValue: 'absolute',
|
|
73
|
+
defaultValue: 'absolute',
|
|
74
|
+
text: '固定定位',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'left',
|
|
78
|
+
text: 'left',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'top',
|
|
82
|
+
text: 'top',
|
|
83
|
+
disabled: (vm: FormState, { model }: any) =>
|
|
84
|
+
model.position === 'fixed' && model._magic_position === 'fixedBottom',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'right',
|
|
88
|
+
text: 'right',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'bottom',
|
|
92
|
+
text: 'bottom',
|
|
93
|
+
disabled: (vm: FormState, { model }: any) =>
|
|
94
|
+
model.position === 'fixed' && model._magic_position === 'fixedTop',
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
type: 'fieldset',
|
|
100
|
+
legend: '盒子',
|
|
101
|
+
items: [
|
|
102
|
+
{
|
|
103
|
+
name: 'width',
|
|
104
|
+
text: '宽度',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'height',
|
|
108
|
+
text: '高度',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'fieldset',
|
|
114
|
+
legend: '背景',
|
|
115
|
+
items: [
|
|
116
|
+
{
|
|
117
|
+
name: 'backgroundImage',
|
|
118
|
+
text: '背景图',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'backgroundColor',
|
|
122
|
+
text: '背景颜色',
|
|
123
|
+
type: 'colorPicker',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'backgroundRepeat',
|
|
127
|
+
text: '背景图重复',
|
|
128
|
+
type: 'select',
|
|
129
|
+
defaultValue: 'no-repeat',
|
|
130
|
+
options: [
|
|
131
|
+
{ text: 'repeat', value: 'repeat' },
|
|
132
|
+
{ text: 'repeat-x', value: 'repeat-x' },
|
|
133
|
+
{ text: 'repeat-y', value: 'repeat-y' },
|
|
134
|
+
{ text: 'no-repeat', value: 'no-repeat' },
|
|
135
|
+
{ text: 'inherit', value: 'inherit' },
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'backgroundSize',
|
|
140
|
+
text: '背景图大小',
|
|
141
|
+
defaultValue: '100% 100%',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
title: '事件',
|
|
151
|
+
items: [
|
|
152
|
+
{
|
|
153
|
+
type: 'table',
|
|
154
|
+
name: 'events',
|
|
155
|
+
items: [
|
|
156
|
+
{
|
|
157
|
+
name: 'name',
|
|
158
|
+
label: '事件名',
|
|
159
|
+
type: 'select',
|
|
160
|
+
options: (mForm: FormState, { formValue }: any) =>
|
|
161
|
+
eventsService.getEvent(formValue.type).map((option) => ({
|
|
162
|
+
text: option.label,
|
|
163
|
+
value: option.value,
|
|
164
|
+
})),
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'to',
|
|
168
|
+
label: '联动组件',
|
|
169
|
+
type: 'ui-select',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'method',
|
|
173
|
+
label: '动作',
|
|
174
|
+
type: 'select',
|
|
175
|
+
options: (mForm: FormState, { model }: any) => {
|
|
176
|
+
const node = editorService.getNodeById(model.to);
|
|
177
|
+
if (!node) return [];
|
|
178
|
+
|
|
179
|
+
return eventsService.getMethod(node.type).map((option) => ({
|
|
180
|
+
text: option.label,
|
|
181
|
+
value: option.value,
|
|
182
|
+
}));
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
title: '高级',
|
|
191
|
+
labelWidth: '80px',
|
|
192
|
+
items: [
|
|
193
|
+
{
|
|
194
|
+
type: 'code-link',
|
|
195
|
+
name: 'created',
|
|
196
|
+
text: 'created',
|
|
197
|
+
formTitle: 'created',
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
// 默认组件属性表单配置
|
|
206
|
+
export const DEFAULT_CONFIG: FormConfig = fillConfig([]);
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 获取默认属性配置
|
|
210
|
+
* @param type 组件类型
|
|
211
|
+
* @returns Object
|
|
212
|
+
*/
|
|
213
|
+
export const getDefaultPropsValue = (type: string) => ({
|
|
214
|
+
type,
|
|
215
|
+
id: generateId(type),
|
|
216
|
+
style: {},
|
|
217
|
+
name: type,
|
|
218
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { cloneDeep } from 'lodash-es';
|
|
20
|
+
|
|
21
|
+
export class UndoRedo<T = any> {
|
|
22
|
+
private elementList: T[];
|
|
23
|
+
private listCursor: number;
|
|
24
|
+
private listMaxSize: number;
|
|
25
|
+
|
|
26
|
+
constructor(listMaxSize = 200) {
|
|
27
|
+
const minListMaxSize = 2;
|
|
28
|
+
this.elementList = [];
|
|
29
|
+
this.listCursor = 0;
|
|
30
|
+
this.listMaxSize = listMaxSize > minListMaxSize ? listMaxSize : minListMaxSize;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public pushElement(element: T): void {
|
|
34
|
+
// 新元素进来时,把游标之外的元素全部丢弃,并把新元素放进来
|
|
35
|
+
this.elementList.splice(this.listCursor, this.elementList.length - this.listCursor, cloneDeep(element));
|
|
36
|
+
this.listCursor += 1;
|
|
37
|
+
// 如果list中的元素超过maxSize,则移除第一个元素
|
|
38
|
+
if (this.elementList.length > this.listMaxSize) {
|
|
39
|
+
this.elementList.shift();
|
|
40
|
+
this.listCursor -= 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public canUndo(): boolean {
|
|
45
|
+
return this.listCursor > 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 返回undo后的当前元素
|
|
49
|
+
public undo(): T | null {
|
|
50
|
+
if (!this.canUndo()) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
this.listCursor -= 1;
|
|
54
|
+
return this.getCurrentElement();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public canRedo() {
|
|
58
|
+
return this.elementList.length > this.listCursor;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 返回redo后的当前元素
|
|
62
|
+
public redo(): T | null {
|
|
63
|
+
if (!this.canRedo()) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
this.listCursor += 1;
|
|
67
|
+
return this.getCurrentElement();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public getCurrentElement(): T | null {
|
|
71
|
+
if (this.listCursor < 1) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return cloneDeep(this.elementList[this.listCursor - 1]);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
package/tsconfig.json
ADDED
package/vite.config.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import path from 'path';
|
|
20
|
+
|
|
21
|
+
import { defineConfig } from 'vite';
|
|
22
|
+
|
|
23
|
+
import { getBaseConfig } from '../vite-config';
|
|
24
|
+
|
|
25
|
+
import pkg from './package.json';
|
|
26
|
+
|
|
27
|
+
const deps = Object.keys(pkg.dependencies);
|
|
28
|
+
const alias = [{ find: /@editor/, replacement: path.join(__dirname, './src') }];
|
|
29
|
+
|
|
30
|
+
export default defineConfig(getBaseConfig(deps, 'TMagicEditor', alias));
|