@tmagic/editor 1.0.0-beta.13 → 1.0.0-beta.14
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/coverage/clover.xml +646 -550
- package/coverage/coverage-final.json +19 -18
- package/coverage/lcov-report/index.html +55 -55
- package/coverage/lcov-report/src/Editor.vue.html +1 -1
- package/coverage/lcov-report/{layouts/sidebar/LayerMenu.vue.html → src/components/ContentMenu.vue.html} +137 -95
- package/coverage/lcov-report/src/components/Icon.vue.html +5 -5
- package/coverage/lcov-report/src/components/ScrollViewer.vue.html +1 -1
- package/coverage/lcov-report/src/components/ToolButton.vue.html +180 -63
- package/coverage/lcov-report/src/components/index.html +34 -19
- package/coverage/lcov-report/src/index.html +1 -1
- package/coverage/lcov-report/src/layouts/AddPageBox.vue.html +1 -1
- package/coverage/lcov-report/src/layouts/Framework.vue.html +13 -13
- package/coverage/lcov-report/src/layouts/NavMenu.vue.html +1 -1
- package/coverage/lcov-report/src/layouts/PropsPanel.vue.html +1 -1
- package/coverage/lcov-report/src/layouts/Resizer.vue.html +1 -1
- package/coverage/lcov-report/src/layouts/index.html +15 -15
- package/coverage/lcov-report/src/layouts/sidebar/ComponentListPanel.vue.html +78 -12
- package/coverage/lcov-report/src/layouts/sidebar/LayerMenu.vue.html +149 -92
- package/coverage/lcov-report/src/layouts/sidebar/LayerPanel.vue.html +43 -121
- package/coverage/lcov-report/src/layouts/sidebar/Sidebar.vue.html +1 -1
- package/coverage/lcov-report/src/layouts/sidebar/index.html +40 -40
- package/coverage/lcov-report/src/layouts/workspace/PageBar.vue.html +99 -12
- package/coverage/lcov-report/src/layouts/workspace/Stage.vue.html +86 -95
- package/coverage/lcov-report/src/layouts/workspace/ViewerMenu.vue.html +208 -97
- package/coverage/lcov-report/src/layouts/workspace/Workspace.vue.html +3 -3
- package/coverage/lcov-report/src/layouts/workspace/index.html +35 -35
- package/coverage/lcov-report/src/services/BaseService.ts.html +11 -11
- package/coverage/lcov-report/src/services/componentList.ts.html +1 -1
- package/coverage/lcov-report/src/services/editor.ts.html +102 -9
- package/coverage/lcov-report/src/services/events.ts.html +1 -1
- package/coverage/lcov-report/src/services/history.ts.html +29 -8
- package/coverage/lcov-report/src/services/index.html +25 -25
- package/coverage/lcov-report/src/services/props.ts.html +4 -7
- package/coverage/lcov-report/src/services/ui.ts.html +1 -1
- package/coverage/lcov-report/src/type.ts.html +8 -14
- package/coverage/lcov-report/src/utils/compose.ts.html +4 -4
- package/coverage/lcov-report/src/utils/config.ts.html +1 -1
- package/coverage/lcov-report/src/utils/editor.ts.html +2 -2
- package/coverage/lcov-report/src/utils/index.html +1 -1
- package/coverage/lcov-report/src/utils/index.ts.html +1 -1
- package/coverage/lcov-report/src/utils/logger.ts.html +1 -1
- package/coverage/lcov-report/src/utils/props.ts.html +59 -2
- package/coverage/lcov-report/src/utils/scroll-viewer.ts.html +1 -1
- package/coverage/lcov-report/src/utils/undo-redo.ts.html +1 -1
- package/coverage/lcov.info +1623 -1354
- package/dist/style.css +39 -18
- package/dist/tmagic-editor.es.js +598 -412
- package/dist/tmagic-editor.es.js.map +1 -1
- package/dist/tmagic-editor.umd.js +595 -408
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/dist/types/src/Editor.vue.d.ts +1 -1
- package/dist/types/src/components/ToolButton.vue.d.ts +12 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -0
- package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +2 -0
- package/dist/types/src/services/history.d.ts +1 -0
- package/dist/types/src/services/props.d.ts +2 -2
- package/dist/types/src/type.d.ts +6 -8
- package/dist/types/src/utils/polyfills.d.ts +0 -0
- package/package.json +8 -7
- package/src/components/ContentMenu.vue +107 -0
- package/src/components/ToolButton.vue +66 -27
- package/src/index.ts +2 -0
- package/src/layouts/Framework.vue +6 -6
- package/src/layouts/sidebar/ComponentListPanel.vue +23 -1
- package/src/layouts/sidebar/LayerMenu.vue +91 -72
- package/src/layouts/sidebar/LayerPanel.vue +23 -49
- package/src/layouts/workspace/PageBar.vue +35 -6
- package/src/layouts/workspace/Stage.vue +41 -44
- package/src/layouts/workspace/ViewerMenu.vue +104 -67
- package/src/layouts/workspace/Workspace.vue +2 -2
- package/src/services/editor.ts +32 -1
- package/src/services/history.ts +7 -0
- package/src/services/props.ts +2 -3
- package/src/theme/common/var.scss +1 -0
- package/src/theme/component-list-panel.scss +2 -0
- package/src/theme/content-menu.scss +33 -26
- package/src/theme/layer-panel.scss +1 -1
- package/src/theme/page-bar.scss +22 -1
- package/src/type.ts +6 -8
- package/src/utils/editor.ts +1 -1
- package/src/utils/polyfills.ts +22 -0
- package/src/utils/props.ts +19 -0
- package/coverage/lcov-report/Icon.vue.html +0 -172
- package/coverage/lcov-report/ToolButton.vue.html +0 -655
- package/coverage/lcov-report/layouts/sidebar/index.html +0 -116
- package/coverage/lcov-report/utils/index.html +0 -116
- package/coverage/lcov-report/utils/undo-redo.ts.html +0 -313
- package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -980
- package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -188
- package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
|
@@ -1,91 +1,110 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<div
|
|
4
|
-
v-if="node.items"
|
|
5
|
-
class="magic-editor-content-menu-item"
|
|
6
|
-
@mouseenter="setSubVisitable(true)"
|
|
7
|
-
@mouseleave="setSubVisitable(false)"
|
|
8
|
-
>
|
|
9
|
-
新增
|
|
10
|
-
</div>
|
|
11
|
-
<div v-if="node.type !== 'app'" class="magic-editor-content-menu-item" @click="() => copy(node)">复制</div>
|
|
12
|
-
<div
|
|
13
|
-
v-if="node.type !== 'app' && node.type !== 'page'"
|
|
14
|
-
class="magic-editor-content-menu-item"
|
|
15
|
-
@click="() => remove()"
|
|
16
|
-
>
|
|
17
|
-
删除
|
|
18
|
-
</div>
|
|
19
|
-
<div class="subMenu" v-show="subVisible" @mouseenter="setSubVisitable(true)" @mouseleave="setSubVisitable(false)">
|
|
20
|
-
<el-scrollbar>
|
|
21
|
-
<template v-if="node.type === 'tabs'">
|
|
22
|
-
<div
|
|
23
|
-
class="magic-editor-content-menu-item"
|
|
24
|
-
@click="
|
|
25
|
-
() =>
|
|
26
|
-
append({
|
|
27
|
-
type: 'tab-pane',
|
|
28
|
-
})
|
|
29
|
-
"
|
|
30
|
-
>
|
|
31
|
-
标签
|
|
32
|
-
</div>
|
|
33
|
-
</template>
|
|
34
|
-
<template v-else-if="node.items">
|
|
35
|
-
<div v-for="list in componentGroupList" :key="list.title">
|
|
36
|
-
<template v-for="item in list.items">
|
|
37
|
-
<div class="magic-editor-content-menu-item" v-if="item" :key="item.type" @click="() => append(item)">
|
|
38
|
-
{{ item.text }}
|
|
39
|
-
</div>
|
|
40
|
-
</template>
|
|
41
|
-
<div class="separation"></div>
|
|
42
|
-
</div>
|
|
43
|
-
</template>
|
|
44
|
-
</el-scrollbar>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
2
|
+
<content-menu :menu-data="menuData" ref="menu" style="overflow: initial"></content-menu>
|
|
47
3
|
</template>
|
|
48
4
|
|
|
49
5
|
<script lang="ts">
|
|
50
|
-
import { computed, defineComponent, inject, ref } from 'vue';
|
|
6
|
+
import { computed, defineComponent, inject, markRaw, ref } from 'vue';
|
|
7
|
+
import { Delete, DocumentCopy, Files, Plus } from '@element-plus/icons';
|
|
51
8
|
|
|
52
|
-
import
|
|
9
|
+
import { NodeType } from '@tmagic/schema';
|
|
53
10
|
|
|
54
|
-
import
|
|
11
|
+
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
12
|
+
import type { ComponentGroup, MenuButton, MenuItem, Services } from '@editor/type';
|
|
55
13
|
|
|
56
14
|
export default defineComponent({
|
|
57
|
-
|
|
15
|
+
components: { ContentMenu },
|
|
58
16
|
|
|
59
17
|
setup() {
|
|
60
18
|
const services = inject<Services>('services');
|
|
61
|
-
const
|
|
19
|
+
const menu = ref<InstanceType<typeof ContentMenu>>();
|
|
62
20
|
const node = computed(() => services?.editorService.get('node'));
|
|
21
|
+
const isRoot = computed(() => node.value?.type === NodeType.ROOT);
|
|
22
|
+
const isPage = computed(() => node.value?.type === NodeType.PAGE);
|
|
23
|
+
const componentList = computed(() => services?.componentListService.getList() || []);
|
|
63
24
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
},
|
|
25
|
+
const createMenuItems = (group: ComponentGroup): MenuButton[] =>
|
|
26
|
+
group.items.map((component) => ({
|
|
27
|
+
text: component.text,
|
|
28
|
+
type: 'button',
|
|
29
|
+
icon: component.icon,
|
|
30
|
+
handler: () => {
|
|
31
|
+
services?.editorService.add({
|
|
32
|
+
name: component.text,
|
|
33
|
+
type: component.type,
|
|
34
|
+
...(component.data || {}),
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
}));
|
|
78
38
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
39
|
+
const getSubMenuData = computed<MenuButton[]>(() => {
|
|
40
|
+
if (node.value?.type === 'tabs') {
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
text: '标签页',
|
|
44
|
+
type: 'button',
|
|
45
|
+
icon: Files,
|
|
46
|
+
handler: () => {
|
|
47
|
+
services?.editorService.add({
|
|
48
|
+
type: 'tab-pane',
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
if (node.value?.items) {
|
|
55
|
+
return (
|
|
56
|
+
componentList.value.reduce(
|
|
57
|
+
(subMenuData: MenuButton[], group: ComponentGroup, index) =>
|
|
58
|
+
subMenuData.concat(
|
|
59
|
+
createMenuItems(group),
|
|
60
|
+
index < componentList.value.length - 1
|
|
61
|
+
? [
|
|
62
|
+
{
|
|
63
|
+
type: 'divider',
|
|
64
|
+
direction: 'horizontal',
|
|
65
|
+
},
|
|
66
|
+
]
|
|
67
|
+
: [],
|
|
68
|
+
),
|
|
69
|
+
[],
|
|
70
|
+
) || []
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return [];
|
|
74
|
+
});
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
return {
|
|
77
|
+
menu,
|
|
78
|
+
menuData: computed<MenuItem[]>(() => [
|
|
79
|
+
{
|
|
80
|
+
type: 'button',
|
|
81
|
+
text: '新增',
|
|
82
|
+
icon: markRaw(Plus),
|
|
83
|
+
display: () => node.value?.items,
|
|
84
|
+
items: getSubMenuData.value,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
type: 'button',
|
|
88
|
+
text: '复制',
|
|
89
|
+
icon: markRaw(DocumentCopy),
|
|
90
|
+
display: () => !isRoot.value,
|
|
91
|
+
handler: () => {
|
|
92
|
+
node.value && services?.editorService.copy(node.value);
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'button',
|
|
97
|
+
text: '删除',
|
|
98
|
+
icon: markRaw(Delete),
|
|
99
|
+
display: () => !isRoot.value && !isPage.value,
|
|
100
|
+
handler: () => {
|
|
101
|
+
node.value && services?.editorService.remove(node.value);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
]),
|
|
86
105
|
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
show(e: MouseEvent) {
|
|
107
|
+
menu.value?.show(e);
|
|
89
108
|
},
|
|
90
109
|
};
|
|
91
110
|
},
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
<div
|
|
34
34
|
:id="data.id"
|
|
35
35
|
class="cus-tree-node"
|
|
36
|
-
@mousedown="
|
|
37
|
-
@mouseup="
|
|
36
|
+
@mousedown="toggleClickFlag"
|
|
37
|
+
@mouseup="toggleClickFlag"
|
|
38
38
|
@mouseenter="highlightHandler(data)"
|
|
39
39
|
:class="{ 'cus-tree-node-hover': canHighlight && data.id === highlightNode?.id }"
|
|
40
40
|
>
|
|
@@ -48,13 +48,13 @@
|
|
|
48
48
|
</el-tree>
|
|
49
49
|
|
|
50
50
|
<teleport to="body">
|
|
51
|
-
<layer-menu
|
|
51
|
+
<layer-menu ref="menu"></layer-menu>
|
|
52
52
|
</teleport>
|
|
53
53
|
</el-scrollbar>
|
|
54
54
|
</template>
|
|
55
55
|
|
|
56
56
|
<script lang="ts">
|
|
57
|
-
import { computed, defineComponent, inject,
|
|
57
|
+
import { computed, defineComponent, inject, Ref, ref, watchEffect } from 'vue';
|
|
58
58
|
import type { ElTree } from 'element-plus';
|
|
59
59
|
import { throttle } from 'lodash-es';
|
|
60
60
|
|
|
@@ -169,46 +169,6 @@ const useFilter = (tree: Ref<InstanceType<typeof ElTree> | undefined>) => ({
|
|
|
169
169
|
},
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
-
const useContentMenu = (editorService?: EditorService) => {
|
|
173
|
-
const menuStyle = ref({
|
|
174
|
-
position: 'absolute',
|
|
175
|
-
left: '0',
|
|
176
|
-
top: '0',
|
|
177
|
-
display: 'none',
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
onMounted(() => {
|
|
181
|
-
document.addEventListener(
|
|
182
|
-
'click',
|
|
183
|
-
() => {
|
|
184
|
-
menuStyle.value.display = 'none';
|
|
185
|
-
},
|
|
186
|
-
true,
|
|
187
|
-
);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
return {
|
|
191
|
-
menuStyle,
|
|
192
|
-
|
|
193
|
-
contextmenu(event: MouseEvent, data: MNode) {
|
|
194
|
-
const bodyHeight = globalThis.document.body.clientHeight;
|
|
195
|
-
|
|
196
|
-
const left = `${event.clientX + 20}px`;
|
|
197
|
-
let top = `${event.clientY - 10}px`;
|
|
198
|
-
|
|
199
|
-
if (event.clientY + 300 > bodyHeight) {
|
|
200
|
-
top = `${bodyHeight - 300}px`;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
menuStyle.value.left = left;
|
|
204
|
-
menuStyle.value.top = top;
|
|
205
|
-
menuStyle.value.display = '';
|
|
206
|
-
|
|
207
|
-
select(data, editorService);
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
};
|
|
211
|
-
|
|
212
172
|
export default defineComponent({
|
|
213
173
|
name: 'magic-editor-layer-panel',
|
|
214
174
|
|
|
@@ -217,13 +177,14 @@ export default defineComponent({
|
|
|
217
177
|
setup() {
|
|
218
178
|
const services = inject<Services>('services');
|
|
219
179
|
const tree = ref<InstanceType<typeof ElTree>>();
|
|
180
|
+
const menu = ref<InstanceType<typeof LayerMenu>>();
|
|
220
181
|
const clicked = ref(false);
|
|
221
182
|
const editorService = services?.editorService;
|
|
222
183
|
const highlightHandler = throttle((data: MNode) => {
|
|
223
184
|
highlight(data, editorService);
|
|
224
185
|
}, throttleTime);
|
|
225
186
|
|
|
226
|
-
const
|
|
187
|
+
const toggleClickFlag = () => {
|
|
227
188
|
clicked.value = !clicked.value;
|
|
228
189
|
};
|
|
229
190
|
|
|
@@ -232,12 +193,22 @@ export default defineComponent({
|
|
|
232
193
|
() => statusData.highlightNode.value?.id !== statusData.clickNode.value?.id && !clicked.value,
|
|
233
194
|
);
|
|
234
195
|
|
|
196
|
+
editorService?.on('remove', () => {
|
|
197
|
+
setTimeout(() => {
|
|
198
|
+
tree.value?.getNode(editorService.get('node').id)?.updateChildren();
|
|
199
|
+
}, 0);
|
|
200
|
+
});
|
|
201
|
+
|
|
235
202
|
return {
|
|
236
203
|
tree,
|
|
204
|
+
menu,
|
|
237
205
|
...statusData,
|
|
238
206
|
...useDrop(tree, editorService),
|
|
239
207
|
...useFilter(tree),
|
|
240
|
-
|
|
208
|
+
|
|
209
|
+
highlightHandler,
|
|
210
|
+
toggleClickFlag,
|
|
211
|
+
canHighlight,
|
|
241
212
|
|
|
242
213
|
clickHandler(data: MNode): void {
|
|
243
214
|
if (services?.uiService.get<boolean>('uiSelectMode')) {
|
|
@@ -247,9 +218,12 @@ export default defineComponent({
|
|
|
247
218
|
tree.value?.setCurrentKey(data.id);
|
|
248
219
|
select(data, editorService);
|
|
249
220
|
},
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
221
|
+
|
|
222
|
+
async contextmenu(event: MouseEvent, data: MNode) {
|
|
223
|
+
event.preventDefault();
|
|
224
|
+
await select(data, editorService);
|
|
225
|
+
menu.value?.show(event);
|
|
226
|
+
},
|
|
253
227
|
};
|
|
254
228
|
},
|
|
255
229
|
});
|
|
@@ -22,11 +22,25 @@
|
|
|
22
22
|
</slot>
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
|
-
<el-popover placement="top" :width="160" trigger="hover">
|
|
25
|
+
<el-popover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
|
|
26
26
|
<div>
|
|
27
27
|
<slot name="page-bar-popover" :page="item">
|
|
28
|
-
<
|
|
29
|
-
|
|
28
|
+
<tool-button
|
|
29
|
+
:data="{
|
|
30
|
+
type: 'button',
|
|
31
|
+
text: '复制',
|
|
32
|
+
icon: DocumentCopy,
|
|
33
|
+
handler: () => copy(item),
|
|
34
|
+
}"
|
|
35
|
+
></tool-button>
|
|
36
|
+
<tool-button
|
|
37
|
+
:data="{
|
|
38
|
+
type: 'button',
|
|
39
|
+
text: '删除',
|
|
40
|
+
icon: Delete,
|
|
41
|
+
handler: () => remove(item),
|
|
42
|
+
}"
|
|
43
|
+
></tool-button>
|
|
30
44
|
</slot>
|
|
31
45
|
</div>
|
|
32
46
|
<template #reference>
|
|
@@ -44,12 +58,24 @@
|
|
|
44
58
|
</template>
|
|
45
59
|
|
|
46
60
|
<script lang="ts">
|
|
47
|
-
import {
|
|
48
|
-
|
|
61
|
+
import {
|
|
62
|
+
computed,
|
|
63
|
+
ComputedRef,
|
|
64
|
+
defineComponent,
|
|
65
|
+
inject,
|
|
66
|
+
markRaw,
|
|
67
|
+
onMounted,
|
|
68
|
+
onUnmounted,
|
|
69
|
+
ref,
|
|
70
|
+
toRaw,
|
|
71
|
+
watch,
|
|
72
|
+
} from 'vue';
|
|
73
|
+
import { ArrowLeftBold, ArrowRightBold, CaretBottom, Delete, DocumentCopy, Plus } from '@element-plus/icons';
|
|
49
74
|
|
|
50
75
|
import type { MApp, MPage } from '@tmagic/schema';
|
|
51
76
|
import { NodeType } from '@tmagic/schema';
|
|
52
77
|
|
|
78
|
+
import ToolButton from '@editor/components/ToolButton.vue';
|
|
53
79
|
import type { Services } from '@editor/type';
|
|
54
80
|
import { generatePageNameByApp } from '@editor/utils/editor';
|
|
55
81
|
|
|
@@ -138,7 +164,7 @@ const useScroll = (root: ComputedRef<MApp | undefined>) => {
|
|
|
138
164
|
};
|
|
139
165
|
|
|
140
166
|
export default defineComponent({
|
|
141
|
-
components: { ArrowLeftBold, ArrowRightBold, CaretBottom, Plus },
|
|
167
|
+
components: { ArrowLeftBold, ArrowRightBold, CaretBottom, Plus, ToolButton },
|
|
142
168
|
|
|
143
169
|
setup() {
|
|
144
170
|
const services = inject<Services>('services');
|
|
@@ -147,6 +173,9 @@ export default defineComponent({
|
|
|
147
173
|
const root = computed(() => editorService?.get<MApp>('root'));
|
|
148
174
|
|
|
149
175
|
return {
|
|
176
|
+
Delete: markRaw(Delete),
|
|
177
|
+
DocumentCopy: markRaw(DocumentCopy),
|
|
178
|
+
|
|
150
179
|
...useScroll(root),
|
|
151
180
|
|
|
152
181
|
root,
|
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
<div
|
|
10
10
|
class="m-editor-stage-container"
|
|
11
11
|
ref="stageContainer"
|
|
12
|
-
@contextmenu="contextmenuHandler"
|
|
13
12
|
:style="`transform: scale(${zoom})`"
|
|
13
|
+
@contextmenu="contextmenuHandler"
|
|
14
|
+
@drop="dropHandler"
|
|
15
|
+
@dragover="dragoverHandler"
|
|
14
16
|
></div>
|
|
15
17
|
<teleport to="body">
|
|
16
|
-
<viewer-menu ref="menu"
|
|
18
|
+
<viewer-menu ref="menu"></viewer-menu>
|
|
17
19
|
</teleport>
|
|
18
20
|
</scroll-viewer>
|
|
19
21
|
</template>
|
|
@@ -39,49 +41,10 @@ import type { MoveableOptions, Runtime, SortEventData, UpdateEventData } from '@
|
|
|
39
41
|
import StageCore from '@tmagic/stage';
|
|
40
42
|
|
|
41
43
|
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
|
42
|
-
import
|
|
44
|
+
import { Layout, Services, StageRect } from '@editor/type';
|
|
43
45
|
|
|
44
46
|
import ViewerMenu from './ViewerMenu.vue';
|
|
45
47
|
|
|
46
|
-
const useMenu = () => {
|
|
47
|
-
const menu = ref<InstanceType<typeof ViewerMenu>>();
|
|
48
|
-
const menuStyle = ref({
|
|
49
|
-
display: 'none',
|
|
50
|
-
left: '0',
|
|
51
|
-
top: '0',
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
onMounted(() => {
|
|
55
|
-
document.addEventListener(
|
|
56
|
-
'click',
|
|
57
|
-
() => {
|
|
58
|
-
menuStyle.value.display = 'none';
|
|
59
|
-
},
|
|
60
|
-
true,
|
|
61
|
-
);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
menu,
|
|
66
|
-
menuStyle,
|
|
67
|
-
|
|
68
|
-
contextmenuHandler(e: MouseEvent) {
|
|
69
|
-
e.preventDefault();
|
|
70
|
-
|
|
71
|
-
const menuHeight = menu.value?.$el.clientHeight;
|
|
72
|
-
let top = e.clientY;
|
|
73
|
-
if (menuHeight + e.clientY > document.body.clientHeight) {
|
|
74
|
-
top = document.body.clientHeight - menuHeight;
|
|
75
|
-
}
|
|
76
|
-
menuStyle.value = {
|
|
77
|
-
display: 'block',
|
|
78
|
-
top: `${top}px`,
|
|
79
|
-
left: `${e.clientX}px`,
|
|
80
|
-
};
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
|
|
85
48
|
export default defineComponent({
|
|
86
49
|
name: 'magic-stage',
|
|
87
50
|
|
|
@@ -115,12 +78,13 @@ export default defineComponent({
|
|
|
115
78
|
|
|
116
79
|
const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
|
|
117
80
|
const stageContainer = ref<HTMLDivElement>();
|
|
81
|
+
const menu = ref<InstanceType<typeof ViewerMenu>>();
|
|
118
82
|
|
|
119
83
|
const stageRect = computed(() => services?.uiService.get<StageRect>('stageRect'));
|
|
120
84
|
const uiSelectMode = computed(() => services?.uiService.get<boolean>('uiSelectMode'));
|
|
121
85
|
const root = computed(() => services?.editorService.get<MApp>('root'));
|
|
122
86
|
const page = computed(() => services?.editorService.get<MPage>('page'));
|
|
123
|
-
const zoom = computed(() => services?.uiService.get<number>('zoom'));
|
|
87
|
+
const zoom = computed(() => services?.uiService.get<number>('zoom') || 1);
|
|
124
88
|
const node = computed(() => services?.editorService.get<MNode>('node'));
|
|
125
89
|
|
|
126
90
|
let stage: StageCore | null = null;
|
|
@@ -218,9 +182,42 @@ export default defineComponent({
|
|
|
218
182
|
return {
|
|
219
183
|
stageWrap,
|
|
220
184
|
stageContainer,
|
|
185
|
+
menu,
|
|
221
186
|
stageRect,
|
|
222
187
|
zoom,
|
|
223
|
-
|
|
188
|
+
|
|
189
|
+
contextmenuHandler(e: MouseEvent) {
|
|
190
|
+
e.preventDefault();
|
|
191
|
+
menu.value?.show(e);
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
dragoverHandler(e: DragEvent) {
|
|
195
|
+
e.preventDefault();
|
|
196
|
+
if (e.dataTransfer) {
|
|
197
|
+
e.dataTransfer.dropEffect = 'move';
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
async dropHandler(e: DragEvent) {
|
|
202
|
+
e.preventDefault();
|
|
203
|
+
if (e.dataTransfer && page.value && stageContainer.value && stage) {
|
|
204
|
+
// eslint-disable-next-line no-eval
|
|
205
|
+
const config = eval(`(${e.dataTransfer.getData('data')})`);
|
|
206
|
+
const layout = await services?.editorService.getLayout(page.value);
|
|
207
|
+
|
|
208
|
+
const containerRect = stageContainer.value.getBoundingClientRect();
|
|
209
|
+
const { scrollTop, scrollLeft } = stage.mask;
|
|
210
|
+
if (layout === Layout.ABSOLUTE) {
|
|
211
|
+
config.style = {
|
|
212
|
+
position: 'absolute',
|
|
213
|
+
top: e.clientY - containerRect.top + scrollTop,
|
|
214
|
+
left: e.clientX - containerRect.left + scrollLeft,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
services?.editorService.add(config, page.value);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
224
221
|
};
|
|
225
222
|
},
|
|
226
223
|
});
|