@tmagic/editor 1.3.0-alpha.6 → 1.3.0-alpha.7
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 +3 -0
- package/dist/tmagic-editor.js +407 -243
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +409 -244
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +10 -10
- package/src/Editor.vue +3 -0
- package/src/components/ContentMenu.vue +15 -8
- package/src/components/FunctionEditor.vue +6 -4
- package/src/fields/CodeLink.vue +4 -2
- package/src/index.ts +3 -2
- package/src/initService.ts +2 -0
- package/src/layouts/Framework.vue +3 -2
- package/src/layouts/sidebar/LayerPanel.vue +50 -31
- package/src/layouts/workspace/Stage.vue +13 -3
- package/src/layouts/workspace/Workspace.vue +2 -2
- package/src/services/codeBlock.ts +3 -2
- package/src/services/keybinding.ts +148 -203
- package/src/services/storage.ts +3 -2
- package/src/theme/stage.scss +4 -0
- package/src/type.ts +56 -0
- package/src/utils/config.ts +1 -1
- package/src/utils/keybinding-config.ts +120 -0
- package/types/components/ContentMenu.vue.d.ts +2 -0
- package/types/index.d.ts +1 -1
- package/types/initService.d.ts +1 -1
- package/types/layouts/workspace/Workspace.vue.d.ts +1 -1
- package/types/services/keybinding.d.ts +13 -5
- package/types/type.d.ts +53 -0
- package/types/utils/config.d.ts +1 -1
- package/types/utils/keybinding-config.d.ts +3 -0
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.3.0-alpha.
|
|
2
|
+
"version": "1.3.0-alpha.7",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@babel/core": "^7.18.0",
|
|
48
48
|
"@element-plus/icons-vue": "^2.0.9",
|
|
49
|
-
"@tmagic/core": "1.3.0-alpha.
|
|
50
|
-
"@tmagic/design": "1.3.0-alpha.
|
|
51
|
-
"@tmagic/form": "1.3.0-alpha.
|
|
52
|
-
"@tmagic/schema": "1.3.0-alpha.
|
|
53
|
-
"@tmagic/stage": "1.3.0-alpha.
|
|
54
|
-
"@tmagic/table": "1.3.0-alpha.
|
|
55
|
-
"@tmagic/utils": "1.3.0-alpha.
|
|
49
|
+
"@tmagic/core": "1.3.0-alpha.7",
|
|
50
|
+
"@tmagic/design": "1.3.0-alpha.7",
|
|
51
|
+
"@tmagic/form": "1.3.0-alpha.7",
|
|
52
|
+
"@tmagic/schema": "1.3.0-alpha.7",
|
|
53
|
+
"@tmagic/stage": "1.3.0-alpha.7",
|
|
54
|
+
"@tmagic/table": "1.3.0-alpha.7",
|
|
55
|
+
"@tmagic/utils": "1.3.0-alpha.7",
|
|
56
56
|
"buffer": "^6.0.3",
|
|
57
57
|
"color": "^3.1.3",
|
|
58
58
|
"events": "^3.3.0",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"vue": "^3.3.4"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@tmagic/design": "1.3.0-alpha.
|
|
68
|
-
"@tmagic/form": "1.3.0-alpha.
|
|
67
|
+
"@tmagic/design": "1.3.0-alpha.7",
|
|
68
|
+
"@tmagic/form": "1.3.0-alpha.7",
|
|
69
69
|
"monaco-editor": "^0.34.0",
|
|
70
70
|
"vue": "^3.3.4"
|
|
71
71
|
},
|
package/src/Editor.vue
CHANGED
|
@@ -100,6 +100,7 @@ import keybindingService from './services/keybinding';
|
|
|
100
100
|
import propsService from './services/props';
|
|
101
101
|
import storageService from './services/storage';
|
|
102
102
|
import uiService from './services/ui';
|
|
103
|
+
import keybindingConfig from './utils/keybinding-config';
|
|
103
104
|
import editorProps from './editorProps';
|
|
104
105
|
import { initServiceEvents, initServiceState } from './initService';
|
|
105
106
|
import type { Services } from './type';
|
|
@@ -136,6 +137,8 @@ export default defineComponent({
|
|
|
136
137
|
|
|
137
138
|
initServiceEvents(props, emit, services);
|
|
138
139
|
initServiceState(props, services);
|
|
140
|
+
keybindingService.registe(keybindingConfig);
|
|
141
|
+
keybindingService.registeEl('global');
|
|
139
142
|
|
|
140
143
|
provide('services', services);
|
|
141
144
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
<teleport to="body">
|
|
14
14
|
<content-menu
|
|
15
|
+
v-if="subMenuData.length"
|
|
15
16
|
class="sub-menu"
|
|
16
17
|
ref="subMenu"
|
|
17
18
|
:menu-data="subMenuData"
|
|
@@ -55,6 +56,8 @@ const menuStyle = ref({
|
|
|
55
56
|
top: '0',
|
|
56
57
|
});
|
|
57
58
|
|
|
59
|
+
const contains = (el: HTMLElement) => menu.value?.contains(el) || subMenu.value?.contains(el);
|
|
60
|
+
|
|
58
61
|
const hide = () => {
|
|
59
62
|
if (!visible.value) return;
|
|
60
63
|
|
|
@@ -69,7 +72,7 @@ const hideHandler = (e: MouseEvent) => {
|
|
|
69
72
|
if (!visible.value || !target) {
|
|
70
73
|
return;
|
|
71
74
|
}
|
|
72
|
-
if (
|
|
75
|
+
if (contains(target)) {
|
|
73
76
|
return;
|
|
74
77
|
}
|
|
75
78
|
hide();
|
|
@@ -104,13 +107,15 @@ const showSubMenu = (item: MenuButton | MenuComponent) => {
|
|
|
104
107
|
return;
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
subMenuData.value = menuItem.items;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
subMenuData.value = menuItem.items || [];
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
if (menu.value) {
|
|
113
|
+
subMenu.value?.show({
|
|
114
|
+
clientX: menu.value.offsetLeft + menu.value.clientWidth,
|
|
115
|
+
clientY: menu.value.offsetTop,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}, 0);
|
|
114
119
|
};
|
|
115
120
|
|
|
116
121
|
onMounted(() => {
|
|
@@ -126,7 +131,9 @@ onUnmounted(() => {
|
|
|
126
131
|
});
|
|
127
132
|
|
|
128
133
|
defineExpose({
|
|
134
|
+
menu,
|
|
129
135
|
hide,
|
|
130
136
|
show,
|
|
137
|
+
contains,
|
|
131
138
|
});
|
|
132
139
|
</script>
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
</TMagicCard>
|
|
34
34
|
</template>
|
|
35
35
|
<script lang="ts" setup>
|
|
36
|
-
import { inject, ref, watchEffect } from 'vue';
|
|
36
|
+
import { inject, provide, ref, watchEffect } from 'vue';
|
|
37
37
|
import { cloneDeep } from 'lodash-es';
|
|
38
38
|
|
|
39
39
|
import { TMagicCard, TMagicInput, tMagicMessage } from '@tmagic/design';
|
|
@@ -41,6 +41,7 @@ import { ColumnConfig, TableConfig } from '@tmagic/form';
|
|
|
41
41
|
import { CodeParam, Id } from '@tmagic/schema';
|
|
42
42
|
|
|
43
43
|
import type { Services } from '@editor/type';
|
|
44
|
+
import { getConfig } from '@editor/utils/config';
|
|
44
45
|
|
|
45
46
|
import CodeDraftEditor from './CodeDraftEditor.vue';
|
|
46
47
|
|
|
@@ -48,6 +49,8 @@ defineOptions({
|
|
|
48
49
|
name: 'MEditorFunctionEditor',
|
|
49
50
|
});
|
|
50
51
|
|
|
52
|
+
provide('mForm', {});
|
|
53
|
+
|
|
51
54
|
const defaultParamColConfig: ColumnConfig = {
|
|
52
55
|
type: 'row',
|
|
53
56
|
label: '参数类型',
|
|
@@ -147,9 +150,8 @@ initTableModel();
|
|
|
147
150
|
// 保存前钩子
|
|
148
151
|
const beforeSave = (codeValue: string): boolean => {
|
|
149
152
|
try {
|
|
150
|
-
//
|
|
151
|
-
|
|
152
|
-
eval(codeValue);
|
|
153
|
+
// 检测js代码是否存在语法错误
|
|
154
|
+
getConfig('parseDSL')(codeValue);
|
|
153
155
|
return true;
|
|
154
156
|
} catch (e: any) {
|
|
155
157
|
tMagicMessage.error(e.stack);
|
package/src/fields/CodeLink.vue
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
import { computed, reactive, watch } from 'vue';
|
|
7
7
|
import serialize from 'serialize-javascript';
|
|
8
8
|
|
|
9
|
+
import { getConfig } from '@editor/utils/config';
|
|
10
|
+
|
|
9
11
|
defineOptions({
|
|
10
12
|
name: 'MEditorCodeLink',
|
|
11
13
|
});
|
|
@@ -69,8 +71,8 @@ const changeHandler = (v: Record<string, any>) => {
|
|
|
69
71
|
if (!props.name || !props.model) return;
|
|
70
72
|
|
|
71
73
|
try {
|
|
72
|
-
|
|
73
|
-
props.model[props.name] =
|
|
74
|
+
const parseDSL = getConfig('parseDSL');
|
|
75
|
+
props.model[props.name] = parseDSL(`(${v[props.name]})`);
|
|
74
76
|
emit('change', props.model[props.name]);
|
|
75
77
|
} catch (e) {
|
|
76
78
|
console.error(e);
|
package/src/index.ts
CHANGED
|
@@ -64,11 +64,12 @@ export { default as LayoutContainer } from './components/SplitView.vue';
|
|
|
64
64
|
export { default as SplitView } from './components/SplitView.vue';
|
|
65
65
|
|
|
66
66
|
const defaultInstallOpt: InstallOptions = {
|
|
67
|
-
//
|
|
67
|
+
// eslint-disable-next-line no-eval
|
|
68
|
+
parseDSL: (dsl: string) => eval(dsl),
|
|
68
69
|
};
|
|
69
70
|
|
|
70
71
|
export default {
|
|
71
|
-
install: (app: App, opt?: InstallOptions): void => {
|
|
72
|
+
install: (app: App, opt?: Partial<InstallOptions>): void => {
|
|
72
73
|
const option = Object.assign(defaultInstallOpt, opt || {});
|
|
73
74
|
|
|
74
75
|
// eslint-disable-next-line no-param-reassign
|
package/src/initService.ts
CHANGED
|
@@ -25,6 +25,7 @@ export const initServiceState = (
|
|
|
25
25
|
eventsService,
|
|
26
26
|
uiService,
|
|
27
27
|
codeBlockService,
|
|
28
|
+
keybindingService,
|
|
28
29
|
}: Services,
|
|
29
30
|
) => {
|
|
30
31
|
// 初始值变化,重新设置节点信息
|
|
@@ -104,6 +105,7 @@ export const initServiceState = (
|
|
|
104
105
|
uiService.resetState();
|
|
105
106
|
componentListService.resetState();
|
|
106
107
|
codeBlockService.resetState();
|
|
108
|
+
keybindingService.reset();
|
|
107
109
|
});
|
|
108
110
|
};
|
|
109
111
|
|
|
@@ -52,6 +52,7 @@ import { TMagicScrollbar } from '@tmagic/design';
|
|
|
52
52
|
|
|
53
53
|
import SplitView from '@editor/components/SplitView.vue';
|
|
54
54
|
import type { GetColumnWidth, Services } from '@editor/type';
|
|
55
|
+
import { getConfig } from '@editor/utils/config';
|
|
55
56
|
|
|
56
57
|
import AddPageBox from './AddPageBox.vue';
|
|
57
58
|
import CodeEditor from './CodeEditor.vue';
|
|
@@ -131,8 +132,8 @@ const columnWidthChange = (columnW: GetColumnWidth) => {
|
|
|
131
132
|
|
|
132
133
|
const saveCode = (value: string) => {
|
|
133
134
|
try {
|
|
134
|
-
|
|
135
|
-
editorService?.set('root',
|
|
135
|
+
const parseDSL = getConfig('parseDSL');
|
|
136
|
+
editorService?.set('root', parseDSL(value));
|
|
136
137
|
} catch (e: any) {
|
|
137
138
|
console.error(e);
|
|
138
139
|
}
|
|
@@ -50,8 +50,7 @@
|
|
|
50
50
|
</template>
|
|
51
51
|
|
|
52
52
|
<script lang="ts" setup>
|
|
53
|
-
import { computed, inject, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
54
|
-
import KeyController from 'keycon';
|
|
53
|
+
import { computed, inject, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
55
54
|
import { difference, throttle, union } from 'lodash-es';
|
|
56
55
|
|
|
57
56
|
import { TMagicScrollbar, TMagicTree } from '@tmagic/design';
|
|
@@ -248,51 +247,71 @@ const windowBlurHandler = () => {
|
|
|
248
247
|
isCtrlKeyDown.value = false;
|
|
249
248
|
};
|
|
250
249
|
|
|
251
|
-
|
|
252
|
-
if (
|
|
250
|
+
keybindingService?.registeCommand('layer-panel-not-ctrl-keydown', (e) => {
|
|
251
|
+
if (e.key !== keybindingService.ctrlKey) {
|
|
253
252
|
isCtrlKeyDown.value = false;
|
|
254
253
|
}
|
|
255
|
-
};
|
|
254
|
+
});
|
|
256
255
|
|
|
257
|
-
|
|
256
|
+
keybindingService?.registeCommand('layer-panel-ctrl-keydown', () => {
|
|
257
|
+
isCtrlKeyDown.value = true;
|
|
258
|
+
});
|
|
258
259
|
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
keybindingService?.registeCommand('layer-panel-ctrl-keyup', () => {
|
|
261
|
+
isCtrlKeyDown.value = false;
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
keybindingService?.registeCommand('layer-panel-global-keydwon', () => {
|
|
265
|
+
if (!tree.value?.$el.contains(document.activeElement)) {
|
|
266
|
+
isCtrlKeyDown.value = false;
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
keybindingService?.registe([
|
|
271
|
+
{
|
|
272
|
+
command: 'layer-panel-not-ctrl-keydown',
|
|
273
|
+
when: [['layer-panel', 'keydown']],
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
command: 'layer-panel-ctrl-keydown',
|
|
277
|
+
keybinding: 'ctrl',
|
|
278
|
+
when: [['layer-panel', 'keydown']],
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
command: 'layer-panel-ctrl-keyup',
|
|
282
|
+
keybinding: 'ctrl',
|
|
283
|
+
when: [['layer-panel', 'keyup']],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
command: 'layer-panel-global-keydwon',
|
|
287
|
+
keybinding: 'ctrl',
|
|
288
|
+
when: [['global', 'keydown']],
|
|
289
|
+
},
|
|
290
|
+
]);
|
|
261
291
|
|
|
292
|
+
watch(tree, () => {
|
|
262
293
|
if (tree.value?.$el) {
|
|
263
|
-
|
|
264
|
-
keybindingService?.on('keyup', globalKeyupHandler);
|
|
265
|
-
|
|
266
|
-
keycon = new KeyController(tree.value.$el);
|
|
267
|
-
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
|
268
|
-
const ctrl = isMac ? 'meta' : 'ctrl';
|
|
269
|
-
|
|
270
|
-
keycon
|
|
271
|
-
.keydown((e) => {
|
|
272
|
-
if (e.key !== ctrl) {
|
|
273
|
-
isCtrlKeyDown.value = false;
|
|
274
|
-
}
|
|
275
|
-
})
|
|
276
|
-
.keydown(ctrl, () => {
|
|
277
|
-
isCtrlKeyDown.value = true;
|
|
278
|
-
})
|
|
279
|
-
.keyup(ctrl, () => {
|
|
280
|
-
isCtrlKeyDown.value = false;
|
|
281
|
-
});
|
|
294
|
+
keybindingService?.registeEl('layer-panel', tree.value.$el);
|
|
282
295
|
|
|
283
296
|
tree.value.$el.addEventListener('blur', windowBlurHandler);
|
|
297
|
+
} else {
|
|
298
|
+
keybindingService?.unregisteEl('layer-panel');
|
|
284
299
|
}
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
onMounted(() => {
|
|
303
|
+
editorService?.on('remove', editorServiceRemoveHandler);
|
|
285
304
|
|
|
286
305
|
globalThis.addEventListener('blur', windowBlurHandler);
|
|
287
306
|
});
|
|
288
307
|
|
|
289
|
-
|
|
290
|
-
|
|
308
|
+
onBeforeUnmount(() => {
|
|
309
|
+
tree.value?.$el.removeEventListener('blur', windowBlurHandler);
|
|
310
|
+
});
|
|
291
311
|
|
|
312
|
+
onUnmounted(() => {
|
|
292
313
|
editorService?.off('remove', editorServiceRemoveHandler);
|
|
293
|
-
keybindingService?.off('keyup', globalKeyupHandler);
|
|
294
314
|
globalThis.removeEventListener('blur', windowBlurHandler);
|
|
295
|
-
tree.value?.$el.removeEventListener('blur', windowBlurHandler);
|
|
296
315
|
});
|
|
297
316
|
|
|
298
317
|
// 鼠标在组件树移动触发高亮
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<ScrollViewer
|
|
3
3
|
class="m-editor-stage"
|
|
4
4
|
ref="stageWrap"
|
|
5
|
+
tabindex="-1"
|
|
5
6
|
:width="stageRect?.width"
|
|
6
7
|
:height="stageRect?.height"
|
|
7
8
|
:wrap-width="stageContainerRect?.width"
|
|
@@ -35,6 +36,7 @@ import StageCore, { calcValueByFontsize, getOffset, Runtime } from '@tmagic/stag
|
|
|
35
36
|
|
|
36
37
|
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
|
37
38
|
import { Layout, MenuButton, MenuComponent, Services, StageOptions } from '@editor/type';
|
|
39
|
+
import { getConfig } from '@editor/utils/config';
|
|
38
40
|
import { useStage } from '@editor/utils/stage';
|
|
39
41
|
|
|
40
42
|
import ViewerMenu from './ViewerMenu.vue';
|
|
@@ -74,6 +76,10 @@ watchEffect(() => {
|
|
|
74
76
|
|
|
75
77
|
stage = useStage(stageOptions);
|
|
76
78
|
|
|
79
|
+
stage.on('select', () => {
|
|
80
|
+
stageWrap.value?.container?.focus();
|
|
81
|
+
});
|
|
82
|
+
|
|
77
83
|
services?.editorService.set('stage', markRaw(stage));
|
|
78
84
|
|
|
79
85
|
stage?.mount(stageContainer.value);
|
|
@@ -120,13 +126,17 @@ const resizeObserver = new ResizeObserver((entries) => {
|
|
|
120
126
|
});
|
|
121
127
|
|
|
122
128
|
onMounted(() => {
|
|
123
|
-
|
|
129
|
+
if (stageWrap.value?.container) {
|
|
130
|
+
resizeObserver.observe(stageWrap.value.container);
|
|
131
|
+
services?.keybindingService.registeEl('stage', stageWrap.value.container);
|
|
132
|
+
}
|
|
124
133
|
});
|
|
125
134
|
|
|
126
135
|
onUnmounted(() => {
|
|
127
136
|
stage?.destroy();
|
|
128
137
|
resizeObserver.disconnect();
|
|
129
138
|
services?.editorService.set('stage', null);
|
|
139
|
+
services?.keybindingService.unregisteEl('stage');
|
|
130
140
|
});
|
|
131
141
|
|
|
132
142
|
const contextmenuHandler = (e: MouseEvent) => {
|
|
@@ -153,8 +163,8 @@ const dropHandler = async (e: DragEvent) => {
|
|
|
153
163
|
}
|
|
154
164
|
|
|
155
165
|
if (e.dataTransfer && parent && stageContainer.value && stage) {
|
|
156
|
-
|
|
157
|
-
const config =
|
|
166
|
+
const parseDSL = getConfig('parseDSL');
|
|
167
|
+
const config = parseDSL(`(${e.dataTransfer.getData('data')})`);
|
|
158
168
|
const layout = await services?.editorService.getLayout(parent);
|
|
159
169
|
|
|
160
170
|
const containerRect = stageContainer.value.getBoundingClientRect();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor-workspace"
|
|
2
|
+
<div class="m-editor-workspace">
|
|
3
3
|
<Breadcrumb></Breadcrumb>
|
|
4
4
|
|
|
5
5
|
<slot name="stage">
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<script lang="ts" setup>
|
|
19
19
|
import { computed, inject } from 'vue';
|
|
20
20
|
|
|
21
|
-
import
|
|
21
|
+
import { MenuButton, MenuComponent, Services } from '@editor/type';
|
|
22
22
|
|
|
23
23
|
import Breadcrumb from './Breadcrumb.vue';
|
|
24
24
|
import PageBar from './PageBar.vue';
|
|
@@ -23,6 +23,7 @@ import { CodeBlockContent, CodeBlockDSL, Id } from '@tmagic/schema';
|
|
|
23
23
|
|
|
24
24
|
import type { CodeState } from '@editor/type';
|
|
25
25
|
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
|
|
26
|
+
import { getConfig } from '@editor/utils/config';
|
|
26
27
|
|
|
27
28
|
import BaseService from './BaseService';
|
|
28
29
|
|
|
@@ -95,8 +96,8 @@ class CodeBlock extends BaseService {
|
|
|
95
96
|
const codeConfigProcessed = codeConfig;
|
|
96
97
|
if (codeConfig.content) {
|
|
97
98
|
// 在保存的时候转换代码内容
|
|
98
|
-
|
|
99
|
-
codeConfigProcessed.content =
|
|
99
|
+
const parseDSL = getConfig('parseDSL');
|
|
100
|
+
codeConfigProcessed.content = parseDSL(codeConfig.content);
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
const existContent = codeDsl[id] || {};
|