@tmagic/editor 1.5.22 → 1.6.0-beta.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/LICENSE +1 -1
- package/dist/style.css +2 -9
- package/dist/tmagic-editor.js +3662 -1728
- package/dist/tmagic-editor.umd.cjs +3655 -1721
- package/package.json +10 -10
- package/src/Editor.vue +5 -0
- package/src/editorProps.ts +2 -3
- package/src/fields/DataSourceFields.vue +1 -1
- package/src/fields/DataSourceMethods.vue +1 -1
- package/src/hooks/index.ts +1 -1
- package/src/hooks/use-filter.ts +6 -4
- package/src/hooks/use-stage.ts +1 -0
- package/src/index.ts +1 -1
- package/src/initService.ts +64 -11
- package/src/layouts/page-bar/PageBarScrollContainer.vue +2 -1
- package/src/layouts/props-panel/FormPanel.vue +6 -1
- package/src/layouts/props-panel/PropsPanel.vue +6 -0
- package/src/layouts/workspace/viewer/Stage.vue +4 -29
- package/src/layouts/workspace/viewer/StageOverlay.vue +25 -6
- package/src/services/BaseService.ts +18 -9
- package/src/services/codeBlock.ts +1 -1
- package/src/services/componentList.ts +1 -1
- package/src/services/dep.ts +1 -1
- package/src/services/editor.ts +1 -1
- package/src/services/events.ts +1 -1
- package/src/services/history.ts +1 -1
- package/src/services/keybinding.ts +12 -0
- package/src/services/props.ts +1 -1
- package/src/services/stageOverlay.ts +1 -1
- package/src/services/ui.ts +1 -1
- package/src/theme/stage.scss +6 -11
- package/src/type.ts +4 -4
- package/src/utils/config.ts +1 -1
- package/src/utils/editor.ts +1 -1
- package/src/utils/index.ts +1 -1
- package/src/utils/logger.ts +1 -1
- package/src/utils/props.ts +16 -2
- package/src/utils/undo-redo.ts +1 -1
- package/types/index.d.ts +65 -145
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.6.0-beta.0",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
"moveable": "^0.53.0",
|
|
59
59
|
"serialize-javascript": "^6.0.2",
|
|
60
60
|
"sortablejs": "^1.15.6",
|
|
61
|
-
"@tmagic/design": "1.
|
|
62
|
-
"@tmagic/form": "1.
|
|
63
|
-
"@tmagic/
|
|
64
|
-
"@tmagic/
|
|
65
|
-
"@tmagic/
|
|
61
|
+
"@tmagic/design": "1.6.0-beta.0",
|
|
62
|
+
"@tmagic/form": "1.6.0-beta.0",
|
|
63
|
+
"@tmagic/stage": "1.6.0-beta.0",
|
|
64
|
+
"@tmagic/table": "1.6.0-beta.0",
|
|
65
|
+
"@tmagic/utils": "1.6.0-beta.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@types/events": "^3.0.
|
|
68
|
+
"@types/events": "^3.0.3",
|
|
69
69
|
"@types/lodash-es": "^4.17.4",
|
|
70
70
|
"@types/serialize-javascript": "^5.0.4",
|
|
71
71
|
"@types/sortablejs": "^1.15.8",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"monaco-editor": "^0.48.0",
|
|
77
|
-
"typescript": "
|
|
78
|
-
"vue": "
|
|
79
|
-
"@tmagic/core": "1.
|
|
77
|
+
"typescript": "^5.8.3",
|
|
78
|
+
"vue": "^3.5.17",
|
|
79
|
+
"@tmagic/core": "1.6.0-beta.0"
|
|
80
80
|
},
|
|
81
81
|
"peerDependenciesMeta": {
|
|
82
82
|
"typescript": {
|
package/src/Editor.vue
CHANGED
|
@@ -97,6 +97,7 @@
|
|
|
97
97
|
:extend-state="extendFormState"
|
|
98
98
|
:disabled-show-src="disabledShowSrc"
|
|
99
99
|
@mounted="propsPanelMountedHandler"
|
|
100
|
+
@unmounted="propsPanelUnmountedHandler"
|
|
100
101
|
@form-error="propsPanelFormErrorHandler"
|
|
101
102
|
@submit-error="propsPanelSubmitErrorHandler"
|
|
102
103
|
>
|
|
@@ -163,6 +164,7 @@ defineOptions({
|
|
|
163
164
|
|
|
164
165
|
const emit = defineEmits<{
|
|
165
166
|
'props-panel-mounted': [instance: InstanceType<typeof FormPanel>];
|
|
167
|
+
'props-panel-unmounted': [];
|
|
166
168
|
'update:modelValue': [value: MApp | null];
|
|
167
169
|
'props-form-error': [e: any];
|
|
168
170
|
'props-submit-error': [e: any];
|
|
@@ -235,6 +237,9 @@ provide<EventBus>('eventBus', new EventEmitter());
|
|
|
235
237
|
const propsPanelMountedHandler = (e: InstanceType<typeof FormPanel>) => {
|
|
236
238
|
emit('props-panel-mounted', e);
|
|
237
239
|
};
|
|
240
|
+
const propsPanelUnmountedHandler = () => {
|
|
241
|
+
emit('props-panel-unmounted');
|
|
242
|
+
};
|
|
238
243
|
|
|
239
244
|
const propsPanelSubmitErrorHandler = (e: any) => {
|
|
240
245
|
emit('props-submit-error', e);
|
package/src/editorProps.ts
CHANGED
|
@@ -3,9 +3,8 @@ import type { FormConfig, FormState } from '@tmagic/form';
|
|
|
3
3
|
import StageCore, {
|
|
4
4
|
CONTAINER_HIGHLIGHT_CLASS_NAME,
|
|
5
5
|
ContainerHighlightType,
|
|
6
|
-
type
|
|
6
|
+
type CustomizeMoveableOptions,
|
|
7
7
|
type GuidesOptions,
|
|
8
|
-
type MoveableOptions,
|
|
9
8
|
RenderType,
|
|
10
9
|
type UpdateDragEl,
|
|
11
10
|
} from '@tmagic/stage';
|
|
@@ -56,7 +55,7 @@ export interface EditorProps {
|
|
|
56
55
|
datasourceConfigs?: Record<string, FormConfig>;
|
|
57
56
|
datasourceEventMethodList?: Record<string, { events: EventOption[]; methods: EventOption[] }>;
|
|
58
57
|
/** 画布中组件选中框的移动范围 */
|
|
59
|
-
moveableOptions?:
|
|
58
|
+
moveableOptions?: CustomizeMoveableOptions;
|
|
60
59
|
/** 编辑器初始化时默认选中的组件ID */
|
|
61
60
|
defaultSelected?: Id;
|
|
62
61
|
/** 拖入画布中容器时,识别到容器后给容器根dom加上的class */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-editor-data-source-fields">
|
|
3
|
-
<MagicTable :data="model[name]" :columns="fieldColumns"></MagicTable>
|
|
3
|
+
<MagicTable :data="model[name]" :columns="fieldColumns" :border="true"></MagicTable>
|
|
4
4
|
|
|
5
5
|
<div class="m-editor-data-source-fields-footer">
|
|
6
6
|
<TMagicButton size="small" :disabled="disabled" plain @click="newFromJsonHandler()">快速添加</TMagicButton>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-editor-data-source-methods">
|
|
3
|
-
<MagicTable :data="model[name]" :columns="methodColumns"></MagicTable>
|
|
3
|
+
<MagicTable :data="model[name]" :columns="methodColumns" :border="true"></MagicTable>
|
|
4
4
|
|
|
5
5
|
<div class="m-editor-data-source-methods-footer">
|
|
6
6
|
<TMagicButton size="small" type="primary" :disabled="disabled" plain @click="createCodeHandler"
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
package/src/hooks/use-filter.ts
CHANGED
|
@@ -32,10 +32,12 @@ export const useFilter = (
|
|
|
32
32
|
const visible = filterIsMatch(text, node);
|
|
33
33
|
if (visible && parents.length) {
|
|
34
34
|
parents.forEach((parent) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
if (text || text.length) {
|
|
36
|
+
updateStatus(nodeStatusMap.value!, parent.id, {
|
|
37
|
+
visible,
|
|
38
|
+
expand: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
43
|
|
package/src/hooks/use-stage.ts
CHANGED
|
@@ -45,6 +45,7 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
45
45
|
updateDragEl: stageOptions.updateDragEl,
|
|
46
46
|
guidesOptions: stageOptions.guidesOptions,
|
|
47
47
|
disabledMultiSelect: stageOptions.disabledMultiSelect,
|
|
48
|
+
disabledRule: stageOptions.disabledRule,
|
|
48
49
|
});
|
|
49
50
|
|
|
50
51
|
watch(
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
package/src/initService.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { onBeforeUnmount, reactive, toRaw, watch } from 'vue';
|
|
1
|
+
import { nextTick, onBeforeUnmount, reactive, toRaw, watch } from 'vue';
|
|
2
2
|
import { cloneDeep } from 'lodash-es';
|
|
3
3
|
|
|
4
4
|
import type TMagicCore from '@tmagic/core';
|
|
@@ -21,9 +21,11 @@ import {
|
|
|
21
21
|
NODE_CONDS_KEY,
|
|
22
22
|
NodeType,
|
|
23
23
|
Target,
|
|
24
|
+
updateNode,
|
|
24
25
|
} from '@tmagic/core';
|
|
25
26
|
import { ChangeRecord } from '@tmagic/form';
|
|
26
|
-
import
|
|
27
|
+
import StageCore from '@tmagic/stage';
|
|
28
|
+
import { getDepNodeIds, getNodes, isPage, isValueIncludeDataSource } from '@tmagic/utils';
|
|
27
29
|
|
|
28
30
|
import PropsPanel from './layouts/PropsPanel.vue';
|
|
29
31
|
import { isIncludeDataSource } from './utils/editor';
|
|
@@ -233,14 +235,15 @@ export const initServiceEvents = (
|
|
|
233
235
|
) => {
|
|
234
236
|
let getTMagicAppPrimise: Promise<TMagicCore | undefined> | null = null;
|
|
235
237
|
|
|
236
|
-
const getTMagicApp = (): Promise<TMagicCore | undefined> => {
|
|
237
|
-
const
|
|
238
|
+
const getTMagicApp = async (): Promise<TMagicCore | undefined> => {
|
|
239
|
+
const stage = await getStage();
|
|
240
|
+
const { renderer } = stage;
|
|
238
241
|
if (!renderer) {
|
|
239
|
-
return
|
|
242
|
+
return void 0;
|
|
240
243
|
}
|
|
241
244
|
|
|
242
245
|
if (renderer.runtime) {
|
|
243
|
-
return
|
|
246
|
+
return renderer.runtime.getApp?.();
|
|
244
247
|
}
|
|
245
248
|
|
|
246
249
|
if (getTMagicAppPrimise) {
|
|
@@ -344,6 +347,60 @@ export const initServiceEvents = (
|
|
|
344
347
|
},
|
|
345
348
|
);
|
|
346
349
|
|
|
350
|
+
const getStage = (): Promise<StageCore> => {
|
|
351
|
+
const stage = editorService.get('stage');
|
|
352
|
+
if (stage) {
|
|
353
|
+
return Promise.resolve(stage);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return new Promise<StageCore>((resolve) => {
|
|
357
|
+
const unWatch = watch(
|
|
358
|
+
() => editorService.get('stage'),
|
|
359
|
+
(stage) => {
|
|
360
|
+
if (stage) {
|
|
361
|
+
resolve(stage);
|
|
362
|
+
nextTick(() => {
|
|
363
|
+
unWatch();
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
);
|
|
368
|
+
});
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
const updateStageDsl = async (value: MApp | null) => {
|
|
372
|
+
const stage = await getStage();
|
|
373
|
+
|
|
374
|
+
const runtime = await stage.renderer?.getRuntime();
|
|
375
|
+
const app = await getTMagicApp();
|
|
376
|
+
|
|
377
|
+
if (!app?.dataSourceManager) {
|
|
378
|
+
runtime?.updateRootConfig?.(cloneDeep(toRaw(value))!);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const page = editorService.get('page');
|
|
382
|
+
const node = editorService.get('node');
|
|
383
|
+
page?.id && runtime?.updatePageId?.(page.id);
|
|
384
|
+
setTimeout(() => {
|
|
385
|
+
node && stage?.select(toRaw(node.id));
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
if (value) {
|
|
389
|
+
depService.clearIdleTasks();
|
|
390
|
+
|
|
391
|
+
await (typeof Worker === 'undefined' ? collectIdle(value.items, true) : depService.collectByWorker(value));
|
|
392
|
+
|
|
393
|
+
const dsl = cloneDeep(toRaw(value));
|
|
394
|
+
if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) {
|
|
395
|
+
for (const node of getNodes(getDepNodeIds(dsl.dataSourceDeps), dsl.items)) {
|
|
396
|
+
updateNode(app.dataSourceManager.compiledNode(node), dsl);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
runtime?.updateRootConfig?.(dsl);
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
|
|
347
404
|
const initDataSourceDepTarget = (ds: DataSourceSchema) => {
|
|
348
405
|
depService.addTarget(createDataSourceTarget(ds, reactive({})));
|
|
349
406
|
depService.addTarget(createDataSourceMethodTarget(ds, reactive({})));
|
|
@@ -370,11 +427,7 @@ export const initServiceEvents = (
|
|
|
370
427
|
}
|
|
371
428
|
|
|
372
429
|
if (Array.isArray(value.items)) {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
(typeof Worker === 'undefined' ? collectIdle(value.items, true) : depService.collectByWorker(value)).then(() => {
|
|
376
|
-
updateStageNodes(value.items);
|
|
377
|
-
});
|
|
430
|
+
updateStageDsl(value);
|
|
378
431
|
} else {
|
|
379
432
|
depService.clear();
|
|
380
433
|
delete value.dataSourceDeps;
|
|
@@ -78,6 +78,7 @@ const resizeObserver = new ResizeObserver(() => {
|
|
|
78
78
|
|
|
79
79
|
onMounted(() => {
|
|
80
80
|
pageBarEl.value && resizeObserver.observe(pageBarEl.value);
|
|
81
|
+
itemsContainerEl.value && resizeObserver.observe(itemsContainerEl.value);
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
onBeforeUnmount(() => {
|
|
@@ -136,7 +137,7 @@ watch(
|
|
|
136
137
|
let beforeDragList: Id[] = [];
|
|
137
138
|
const options = {
|
|
138
139
|
...{
|
|
139
|
-
dataIdAttr: 'page-id', // 获取排序后的数据
|
|
140
|
+
dataIdAttr: 'data-page-id', // 获取排序后的数据
|
|
140
141
|
onStart: async (event: SortableEvent) => {
|
|
141
142
|
if (typeof props.pageBarSortOptions?.beforeStart === 'function') {
|
|
142
143
|
await props.pageBarSortOptions.beforeStart(event, sortable);
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
</template>
|
|
43
43
|
|
|
44
44
|
<script setup lang="ts">
|
|
45
|
-
import { computed, getCurrentInstance, inject, onMounted, ref, useTemplateRef, watchEffect } from 'vue';
|
|
45
|
+
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef, watchEffect } from 'vue';
|
|
46
46
|
import { Document as DocumentIcon } from '@element-plus/icons-vue';
|
|
47
47
|
|
|
48
48
|
import { TMagicButton, TMagicScrollbar } from '@tmagic/design';
|
|
@@ -78,6 +78,7 @@ const emit = defineEmits<{
|
|
|
78
78
|
'submit-error': [e: any];
|
|
79
79
|
'form-error': [e: any];
|
|
80
80
|
mounted: [internalInstance: any];
|
|
81
|
+
unmounted: [];
|
|
81
82
|
}>();
|
|
82
83
|
|
|
83
84
|
const services = useServices();
|
|
@@ -104,6 +105,10 @@ onMounted(() => {
|
|
|
104
105
|
emit('mounted', internalInstance?.proxy);
|
|
105
106
|
});
|
|
106
107
|
|
|
108
|
+
onUnmounted(() => {
|
|
109
|
+
emit('unmounted');
|
|
110
|
+
});
|
|
111
|
+
|
|
107
112
|
const submit = async (v: FormValue, eventData: ContainerChangeEventData) => {
|
|
108
113
|
try {
|
|
109
114
|
const values = await configFormRef.value?.submitForm();
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
@submit-error="errorHandler"
|
|
14
14
|
@form-error="errorHandler"
|
|
15
15
|
@mounted="mountedHandler"
|
|
16
|
+
@unmounted="unmountedHandler"
|
|
16
17
|
></FormPanel>
|
|
17
18
|
|
|
18
19
|
<Resizer v-if="showStylePanel" @change="widthChange"></Resizer>
|
|
@@ -89,6 +90,7 @@ const emit = defineEmits<{
|
|
|
89
90
|
'submit-error': [e: any];
|
|
90
91
|
'form-error': [e: any];
|
|
91
92
|
mounted: [internalInstance: InstanceType<typeof FormPanel>];
|
|
93
|
+
unmounted: [];
|
|
92
94
|
}>();
|
|
93
95
|
|
|
94
96
|
const { editorService, uiService, propsService, storageService } = useServices();
|
|
@@ -165,6 +167,10 @@ const mountedHandler = () => {
|
|
|
165
167
|
}
|
|
166
168
|
};
|
|
167
169
|
|
|
170
|
+
const unmountedHandler = () => {
|
|
171
|
+
emit('unmounted');
|
|
172
|
+
};
|
|
173
|
+
|
|
168
174
|
const propsPanelEl = useTemplateRef('propsPanel');
|
|
169
175
|
const propsPanelWidth = ref(
|
|
170
176
|
storageService.getItem(PROPS_PANEL_WIDTH_STORAGE_KEY, { protocol: Protocol.NUMBER }) || 300,
|
|
@@ -43,20 +43,9 @@
|
|
|
43
43
|
</template>
|
|
44
44
|
|
|
45
45
|
<script lang="ts" setup>
|
|
46
|
-
import {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
nextTick,
|
|
50
|
-
onBeforeUnmount,
|
|
51
|
-
onMounted,
|
|
52
|
-
toRaw,
|
|
53
|
-
useTemplateRef,
|
|
54
|
-
watch,
|
|
55
|
-
watchEffect,
|
|
56
|
-
} from 'vue';
|
|
57
|
-
import { cloneDeep } from 'lodash-es';
|
|
58
|
-
|
|
59
|
-
import type { MApp, MContainer } from '@tmagic/core';
|
|
46
|
+
import { computed, markRaw, nextTick, onBeforeUnmount, onMounted, useTemplateRef, watch, watchEffect } from 'vue';
|
|
47
|
+
|
|
48
|
+
import type { MContainer } from '@tmagic/core';
|
|
60
49
|
import StageCore, { getOffset, Runtime } from '@tmagic/stage';
|
|
61
50
|
import { calcValueByFontsize, getIdFromEl } from '@tmagic/utils';
|
|
62
51
|
|
|
@@ -130,12 +119,6 @@ watchEffect(() => {
|
|
|
130
119
|
|
|
131
120
|
stage.on('runtime-ready', (rt) => {
|
|
132
121
|
runtime = rt;
|
|
133
|
-
// toRaw返回的值是一个引用而非快照,需要cloneDeep
|
|
134
|
-
root.value && runtime?.updateRootConfig?.(cloneDeep(toRaw(root.value)));
|
|
135
|
-
page.value?.id && runtime?.updatePageId?.(page.value.id);
|
|
136
|
-
setTimeout(() => {
|
|
137
|
-
node.value && stage?.select(toRaw(node.value.id));
|
|
138
|
-
});
|
|
139
122
|
});
|
|
140
123
|
});
|
|
141
124
|
|
|
@@ -184,14 +167,6 @@ watch(page, (page) => {
|
|
|
184
167
|
}
|
|
185
168
|
});
|
|
186
169
|
|
|
187
|
-
const rootChangeHandler = (root: MApp) => {
|
|
188
|
-
if (runtime && root) {
|
|
189
|
-
runtime.updateRootConfig?.(cloneDeep(toRaw(root)));
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
editorService.on('root-change', rootChangeHandler);
|
|
194
|
-
|
|
195
170
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
196
171
|
for (const { contentRect } of entries) {
|
|
197
172
|
uiService.set('stageContainerRect', {
|
|
@@ -210,10 +185,10 @@ onMounted(() => {
|
|
|
210
185
|
|
|
211
186
|
onBeforeUnmount(() => {
|
|
212
187
|
stage?.destroy();
|
|
188
|
+
stage = null;
|
|
213
189
|
resizeObserver.disconnect();
|
|
214
190
|
editorService.set('stage', null);
|
|
215
191
|
keybindingService.unregisterEl('stage');
|
|
216
|
-
editorService.off('root-change', rootChangeHandler);
|
|
217
192
|
});
|
|
218
193
|
|
|
219
194
|
const parseDSL = getEditorConfig('parseDSL');
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-if="stageOverlayVisible" class="m-editor-stage-overlay"
|
|
3
|
-
<TMagicIcon class="m-editor-stage-overlay-close" :size="'
|
|
2
|
+
<div v-if="stageOverlayVisible" class="m-editor-stage-overlay">
|
|
3
|
+
<TMagicIcon class="m-editor-stage-overlay-close" :size="'30'" @click="closeOverlayHandler"
|
|
4
4
|
><CloseBold
|
|
5
5
|
/></TMagicIcon>
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
<ScrollViewer
|
|
8
|
+
class="m-editor-stage"
|
|
9
|
+
:width="wrapWidth"
|
|
10
|
+
:height="wrapHeight"
|
|
11
|
+
:wrap-width="columnWidth.center"
|
|
12
|
+
:wrap-height="frameworkRect.height"
|
|
13
|
+
:zoom="zoom"
|
|
14
|
+
>
|
|
15
|
+
<div ref="stageOverlay" class="m-editor-stage-container" :style="style"></div>
|
|
16
|
+
</ScrollViewer>
|
|
7
17
|
</div>
|
|
8
18
|
</template>
|
|
9
19
|
|
|
@@ -13,10 +23,11 @@ import { CloseBold } from '@element-plus/icons-vue';
|
|
|
13
23
|
|
|
14
24
|
import { TMagicIcon } from '@tmagic/design';
|
|
15
25
|
|
|
26
|
+
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
|
16
27
|
import { useServices } from '@editor/hooks/use-services';
|
|
17
28
|
import type { StageOptions } from '@editor/type';
|
|
18
29
|
|
|
19
|
-
const { stageOverlayService, editorService } = useServices();
|
|
30
|
+
const { stageOverlayService, editorService, uiService } = useServices();
|
|
20
31
|
|
|
21
32
|
const stageOptions = inject<StageOptions>('stageOptions');
|
|
22
33
|
|
|
@@ -26,10 +37,12 @@ const stageOverlayVisible = computed(() => stageOverlayService.get('stageOverlay
|
|
|
26
37
|
const wrapWidth = computed(() => stageOverlayService.get('wrapWidth'));
|
|
27
38
|
const wrapHeight = computed(() => stageOverlayService.get('wrapHeight'));
|
|
28
39
|
const stage = computed(() => editorService.get('stage'));
|
|
40
|
+
const zoom = computed(() => uiService.get('zoom'));
|
|
41
|
+
const columnWidth = computed(() => uiService.get('columnWidth'));
|
|
42
|
+
const frameworkRect = computed(() => uiService.get('frameworkRect'));
|
|
29
43
|
|
|
30
44
|
const style = computed(() => ({
|
|
31
|
-
|
|
32
|
-
height: `${wrapHeight.value}px`,
|
|
45
|
+
transform: `scale(${zoom.value})`,
|
|
33
46
|
}));
|
|
34
47
|
|
|
35
48
|
watch(stage, (stage) => {
|
|
@@ -43,6 +56,12 @@ watch(stage, (stage) => {
|
|
|
43
56
|
}
|
|
44
57
|
});
|
|
45
58
|
|
|
59
|
+
watch(zoom, (zoom) => {
|
|
60
|
+
const stage = stageOverlayService.get('stage');
|
|
61
|
+
if (!stage || !zoom) return;
|
|
62
|
+
stage.setZoom(zoom);
|
|
63
|
+
});
|
|
64
|
+
|
|
46
65
|
watch(stageOverlayEl, (stageOverlay) => {
|
|
47
66
|
const subStage = stageOverlayService.createStage(stageOptions);
|
|
48
67
|
stageOverlayService.set('stage', subStage);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/*
|
|
3
3
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
4
4
|
*
|
|
5
|
-
* Copyright (C)
|
|
5
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
6
6
|
*
|
|
7
7
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
8
|
* you may not use this file except in compliance with the License.
|
|
@@ -199,24 +199,33 @@ export default class extends EventEmitter {
|
|
|
199
199
|
* @deprecated 请使用usePlugin代替
|
|
200
200
|
*/
|
|
201
201
|
public use(options: Record<string, Function>) {
|
|
202
|
-
|
|
202
|
+
for (const [methodName, method] of Object.entries(options)) {
|
|
203
203
|
if (typeof method === 'function') this.middleware[methodName].push(method);
|
|
204
|
-
}
|
|
204
|
+
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
public usePlugin(options: Record<string, Function>) {
|
|
208
|
-
|
|
208
|
+
for (const [methodName, method] of Object.entries(options)) {
|
|
209
209
|
if (typeof method === 'function') this.pluginOptionsList[methodName].push(method);
|
|
210
|
-
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public removePlugin(options: Record<string, Function>) {
|
|
214
|
+
for (const [methodName, method] of Object.entries(options)) {
|
|
215
|
+
if (Array.isArray(this.pluginOptionsList[methodName])) {
|
|
216
|
+
this.pluginOptionsList[methodName] = this.pluginOptionsList[methodName].filter((item) => item !== method);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
211
219
|
}
|
|
212
220
|
|
|
213
221
|
public removeAllPlugins() {
|
|
214
|
-
Object.keys(this.pluginOptionsList)
|
|
222
|
+
for (const key of Object.keys(this.pluginOptionsList)) {
|
|
215
223
|
this.pluginOptionsList[key] = [];
|
|
216
|
-
}
|
|
217
|
-
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const key of Object.keys(this.middleware)) {
|
|
218
227
|
this.middleware[key] = [];
|
|
219
|
-
}
|
|
228
|
+
}
|
|
220
229
|
}
|
|
221
230
|
|
|
222
231
|
private async doTask() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
package/src/services/dep.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
package/src/services/editor.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
package/src/services/events.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
package/src/services/history.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -145,6 +145,18 @@ class Keybinding extends BaseService {
|
|
|
145
145
|
for (const [type = '', eventType = 'keydown'] of when) {
|
|
146
146
|
const cacheItem: KeyBindingCacheItem = { type, command, keybinding, eventType, bound: false };
|
|
147
147
|
|
|
148
|
+
if (
|
|
149
|
+
this.bindingList.find(
|
|
150
|
+
(item) =>
|
|
151
|
+
item.command === command &&
|
|
152
|
+
item.eventType === eventType &&
|
|
153
|
+
item.type === type &&
|
|
154
|
+
item.keybinding === keybinding,
|
|
155
|
+
)
|
|
156
|
+
) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
148
160
|
this.bindingList.push(cacheItem);
|
|
149
161
|
}
|
|
150
162
|
}
|
package/src/services/props.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -97,9 +97,9 @@ class StageOverlay extends BaseService {
|
|
|
97
97
|
public createStage(stageOptions: StageOptions = {}) {
|
|
98
98
|
return useStage({
|
|
99
99
|
...stageOptions,
|
|
100
|
-
zoom: 1,
|
|
101
100
|
runtimeUrl: '',
|
|
102
101
|
autoScrollIntoView: false,
|
|
102
|
+
disabledRule: true,
|
|
103
103
|
render: async (stage: StageCore) => {
|
|
104
104
|
this.copyDocumentElement();
|
|
105
105
|
|
package/src/services/ui.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|