@tmagic/editor 1.0.0-beta.8 → 1.0.0-rc.10
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/README.md +1 -0
- package/dist/style.css +94 -45
- package/dist/tmagic-editor.es.js +1622 -2069
- package/dist/tmagic-editor.es.js.map +1 -1
- package/dist/tmagic-editor.umd.js +1621 -2071
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/dist/types/src/Editor.vue.d.ts +50 -2
- package/dist/types/src/fields/Code.vue.d.ts +4 -4
- package/dist/types/src/fields/CodeLink.vue.d.ts +1 -3
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/layouts/CodeEditor.vue.d.ts +13 -4
- package/dist/types/src/layouts/Framework.vue.d.ts +15 -3
- package/dist/types/src/layouts/PropsPanel.vue.d.ts +4 -5
- package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +2 -1
- package/dist/types/src/layouts/sidebar/Sidebar.vue.d.ts +2 -3
- package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +14 -0
- package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +5 -31
- package/dist/types/src/services/BaseService.d.ts +5 -2
- package/dist/types/src/services/editor.d.ts +16 -6
- package/dist/types/src/services/history.d.ts +2 -18
- package/dist/types/src/services/props.d.ts +8 -2
- package/dist/types/src/services/ui.d.ts +2 -0
- package/dist/types/src/type.d.ts +25 -9
- package/dist/types/src/utils/editor.d.ts +5 -10
- package/dist/types/src/utils/polyfills.d.ts +0 -0
- package/dist/types/src/utils/props.d.ts +8 -1
- package/package.json +35 -12
- package/src/Editor.vue +44 -9
- package/src/components/ContentMenu.vue +140 -0
- package/src/components/ScrollViewer.vue +1 -1
- package/src/components/ToolButton.vue +72 -31
- package/src/fields/UISelect.vue +14 -6
- package/src/index.ts +2 -0
- package/src/layouts/AddPageBox.vue +3 -1
- package/src/layouts/CodeEditor.vue +20 -13
- package/src/layouts/Framework.vue +20 -7
- package/src/layouts/PropsPanel.vue +5 -4
- package/src/layouts/sidebar/ComponentListPanel.vue +25 -3
- package/src/layouts/sidebar/LayerMenu.vue +93 -95
- package/src/layouts/sidebar/LayerPanel.vue +80 -59
- package/src/layouts/sidebar/Sidebar.vue +13 -52
- package/src/layouts/sidebar/TabPane.vue +68 -0
- package/src/layouts/workspace/PageBar.vue +145 -17
- package/src/layouts/workspace/Stage.vue +65 -91
- package/src/layouts/workspace/ViewerMenu.vue +122 -68
- package/src/layouts/workspace/Workspace.vue +125 -42
- package/src/services/BaseService.ts +71 -23
- package/src/services/editor.ts +231 -69
- package/src/services/history.ts +7 -0
- package/src/services/props.ts +64 -9
- package/src/services/ui.ts +35 -5
- package/src/theme/common/var.scss +3 -2
- package/src/theme/component-list-panel.scss +2 -0
- package/src/theme/content-menu.scss +33 -26
- package/src/theme/layer-panel.scss +10 -0
- package/src/theme/nav-menu.scss +6 -2
- package/src/theme/page-bar.scss +42 -2
- package/src/theme/props-panel.scss +19 -17
- package/src/theme/workspace.scss +4 -0
- package/src/type.ts +27 -9
- package/src/utils/editor.ts +37 -56
- package/src/utils/polyfills.ts +8 -0
- package/src/utils/props.ts +50 -8
- package/LICENSE +0 -5432
- package/dist/types/src/components/ToolButton.vue.d.ts +0 -35
- package/dist/types/src/fields/UISelect.vue.d.ts +0 -32
- package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +0 -31
- package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -973
- package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +0 -11
- package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -192
- package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
- package/tsconfig.json +0 -9
- package/vite.config.ts +0 -30
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.0.0-
|
|
2
|
+
"version": "1.0.0-rc.10",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
|
-
"sideEffects":
|
|
4
|
+
"sideEffects": [
|
|
5
|
+
"dist/*",
|
|
6
|
+
"src/theme/*"
|
|
7
|
+
],
|
|
5
8
|
"main": "dist/tmagic-editor.umd.js",
|
|
6
9
|
"module": "dist/tmagic-editor.es.js",
|
|
7
10
|
"style": "dist/style.css",
|
|
@@ -14,8 +17,10 @@
|
|
|
14
17
|
"./dist/style.css": {
|
|
15
18
|
"import": "./dist/style.css",
|
|
16
19
|
"require": "./dist/style.css"
|
|
17
|
-
}
|
|
20
|
+
},
|
|
21
|
+
"./*": "./*"
|
|
18
22
|
},
|
|
23
|
+
"license": "Apache-2.0",
|
|
19
24
|
"scripts": {
|
|
20
25
|
"build": "vite build"
|
|
21
26
|
},
|
|
@@ -26,21 +31,40 @@
|
|
|
26
31
|
"type": "git",
|
|
27
32
|
"url": "https://github.com/Tencent/tmagic-editor.git"
|
|
28
33
|
},
|
|
34
|
+
"homepage": "https://tencent.github.io/tmagic-editor/docs/",
|
|
35
|
+
"keywords": [
|
|
36
|
+
"editor",
|
|
37
|
+
"drag",
|
|
38
|
+
"resize",
|
|
39
|
+
"vue",
|
|
40
|
+
"vue3",
|
|
41
|
+
"typescript"
|
|
42
|
+
],
|
|
29
43
|
"dependencies": {
|
|
44
|
+
"@babel/core": "^7.18.0",
|
|
30
45
|
"@element-plus/icons": "0.0.11",
|
|
31
|
-
"@tmagic/core": "
|
|
32
|
-
"@tmagic/form": "
|
|
33
|
-
"@tmagic/schema": "
|
|
34
|
-
"@tmagic/stage": "
|
|
35
|
-
"@tmagic/utils": "
|
|
46
|
+
"@tmagic/core": "1.0.0-rc.10",
|
|
47
|
+
"@tmagic/form": "1.0.0-rc.10",
|
|
48
|
+
"@tmagic/schema": "1.0.0-rc.10",
|
|
49
|
+
"@tmagic/stage": "1.0.0-rc.10",
|
|
50
|
+
"@tmagic/utils": "1.0.0-rc.10",
|
|
51
|
+
"buffer": "^6.0.3",
|
|
36
52
|
"color": "^3.1.3",
|
|
37
|
-
"element-plus": "^2.
|
|
53
|
+
"element-plus": "^2.2.0",
|
|
38
54
|
"events": "^3.3.0",
|
|
55
|
+
"gesto": "^1.7.0",
|
|
56
|
+
"keycon": "^1.1.2",
|
|
39
57
|
"lodash-es": "^4.17.21",
|
|
40
58
|
"monaco-editor": "^0.32.1",
|
|
41
59
|
"serialize-javascript": "^6.0.0",
|
|
42
60
|
"vue": "^3.2.0"
|
|
43
61
|
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"@tmagic/form": "1.0.0-rc.10",
|
|
64
|
+
"element-plus": "^2.2.0",
|
|
65
|
+
"monaco-editor": "^0.32.1",
|
|
66
|
+
"vue": "^3.2.0"
|
|
67
|
+
},
|
|
44
68
|
"devDependencies": {
|
|
45
69
|
"@types/events": "^3.0.0",
|
|
46
70
|
"@types/lodash-es": "^4.17.4",
|
|
@@ -49,12 +73,11 @@
|
|
|
49
73
|
"@vitejs/plugin-vue": "^1.2.3",
|
|
50
74
|
"@vitejs/plugin-vue-jsx": "^1.1.6",
|
|
51
75
|
"@vue/compiler-sfc": "^3.2.0",
|
|
52
|
-
"@vue/test-utils": "^2.0.0
|
|
76
|
+
"@vue/test-utils": "^2.0.0",
|
|
53
77
|
"sass": "^1.35.1",
|
|
54
78
|
"typescript": "^4.3.4",
|
|
55
79
|
"vite": "^2.3.7",
|
|
56
80
|
"vite-plugin-dts": "^0.9.6",
|
|
57
81
|
"vue-tsc": "^0.0.24"
|
|
58
|
-
}
|
|
59
|
-
"gitHead": "ff8e32901775ecc145a82f906d6af6119652d61e"
|
|
82
|
+
}
|
|
60
83
|
}
|
package/src/Editor.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<framework>
|
|
2
|
+
<framework :code-options="codeOptions">
|
|
3
3
|
<template #nav>
|
|
4
4
|
<slot name="nav" :editorService="editorService"><nav-menu :data="menu"></nav-menu></slot>
|
|
5
5
|
</template>
|
|
@@ -12,12 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
<template #workspace :editorService="editorService">
|
|
14
14
|
<slot name="workspace">
|
|
15
|
-
<workspace
|
|
16
|
-
:runtime-url="runtimeUrl"
|
|
17
|
-
:render="render"
|
|
18
|
-
:moveable-options="moveableOptions"
|
|
19
|
-
:can-select="canSelect"
|
|
20
|
-
>
|
|
15
|
+
<workspace>
|
|
21
16
|
<template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
|
|
22
17
|
<template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
|
|
23
18
|
<template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
|
|
@@ -36,7 +31,7 @@
|
|
|
36
31
|
</template>
|
|
37
32
|
|
|
38
33
|
<script lang="ts">
|
|
39
|
-
import { defineComponent, onUnmounted, PropType, provide, toRaw, watch } from 'vue';
|
|
34
|
+
import { defineComponent, onUnmounted, PropType, provide, reactive, toRaw, watch } from 'vue';
|
|
40
35
|
|
|
41
36
|
import { EventOption } from '@tmagic/core';
|
|
42
37
|
import type { FormConfig } from '@tmagic/form';
|
|
@@ -55,7 +50,7 @@ import eventsService from '@editor/services/events';
|
|
|
55
50
|
import historyService from '@editor/services/history';
|
|
56
51
|
import propsService from '@editor/services/props';
|
|
57
52
|
import uiService from '@editor/services/ui';
|
|
58
|
-
import type { ComponentGroup, MenuBarData, Services, SideBarData, StageRect } from '@editor/type';
|
|
53
|
+
import type { ComponentGroup, MenuBarData, MenuItem, Services, SideBarData, StageRect } from '@editor/type';
|
|
59
54
|
|
|
60
55
|
export default defineComponent({
|
|
61
56
|
name: 'm-editor',
|
|
@@ -87,6 +82,16 @@ export default defineComponent({
|
|
|
87
82
|
type: Object as PropType<SideBarData>,
|
|
88
83
|
},
|
|
89
84
|
|
|
85
|
+
layerContentMenu: {
|
|
86
|
+
type: Array as PropType<MenuItem[]>,
|
|
87
|
+
default: () => [],
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
stageContentMenu: {
|
|
91
|
+
type: Array as PropType<MenuItem[]>,
|
|
92
|
+
default: () => [],
|
|
93
|
+
},
|
|
94
|
+
|
|
90
95
|
/** 顶部工具栏配置 */
|
|
91
96
|
menu: {
|
|
92
97
|
type: Object as PropType<MenuBarData>,
|
|
@@ -101,6 +106,9 @@ export default defineComponent({
|
|
|
101
106
|
/** 中间工作区域中画布通过iframe渲染时的页面url */
|
|
102
107
|
runtimeUrl: String,
|
|
103
108
|
|
|
109
|
+
/** 选中时是否自动滚动到可视区域 */
|
|
110
|
+
autoScrollIntoView: Boolean,
|
|
111
|
+
|
|
104
112
|
/** 组件的属性配置表单的dsl */
|
|
105
113
|
propsConfigs: {
|
|
106
114
|
type: Object as PropType<Record<string, FormConfig>>,
|
|
@@ -122,6 +130,9 @@ export default defineComponent({
|
|
|
122
130
|
/** 画布中组件选中框的移动范围 */
|
|
123
131
|
moveableOptions: {
|
|
124
132
|
type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
|
|
133
|
+
default: () => (core?: StageCore) => ({
|
|
134
|
+
container: core?.renderer?.contentWindow?.document.getElementById('app'),
|
|
135
|
+
}),
|
|
125
136
|
},
|
|
126
137
|
|
|
127
138
|
/** 编辑器初始化时默认选中的组件ID */
|
|
@@ -131,11 +142,21 @@ export default defineComponent({
|
|
|
131
142
|
|
|
132
143
|
canSelect: {
|
|
133
144
|
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
|
145
|
+
default: (el: HTMLElement) => Boolean(el.id),
|
|
134
146
|
},
|
|
135
147
|
|
|
136
148
|
stageRect: {
|
|
137
149
|
type: [String, Object] as PropType<StageRect>,
|
|
138
150
|
},
|
|
151
|
+
|
|
152
|
+
codeOptions: {
|
|
153
|
+
type: Object,
|
|
154
|
+
default: () => ({}),
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
updateDragEl: {
|
|
158
|
+
type: Function as PropType<(el: HTMLDivElement, target: HTMLElement) => void>,
|
|
159
|
+
},
|
|
139
160
|
},
|
|
140
161
|
|
|
141
162
|
emits: ['props-panel-mounted', 'update:modelValue'],
|
|
@@ -228,6 +249,20 @@ export default defineComponent({
|
|
|
228
249
|
|
|
229
250
|
provide('services', services);
|
|
230
251
|
|
|
252
|
+
provide('layerContentMenu', props.layerContentMenu);
|
|
253
|
+
provide('stageContentMenu', props.stageContentMenu);
|
|
254
|
+
provide(
|
|
255
|
+
'stageOptions',
|
|
256
|
+
reactive({
|
|
257
|
+
runtimeUrl: props.runtimeUrl,
|
|
258
|
+
autoScrollIntoView: props.autoScrollIntoView,
|
|
259
|
+
render: props.render,
|
|
260
|
+
moveableOptions: props.moveableOptions,
|
|
261
|
+
canSelect: props.canSelect,
|
|
262
|
+
updateDragEl: props.updateDragEl,
|
|
263
|
+
}),
|
|
264
|
+
);
|
|
265
|
+
|
|
231
266
|
return services;
|
|
232
267
|
},
|
|
233
268
|
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="menuData.length && visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
|
|
3
|
+
<div>
|
|
4
|
+
<tool-button
|
|
5
|
+
v-for="(item, index) in menuData"
|
|
6
|
+
event-type="mouseup"
|
|
7
|
+
:data="item"
|
|
8
|
+
:key="index"
|
|
9
|
+
@mouseup="hide"
|
|
10
|
+
@mouseenter="showSubMenu(item)"
|
|
11
|
+
></tool-button>
|
|
12
|
+
</div>
|
|
13
|
+
<teleport to="body">
|
|
14
|
+
<content-menu
|
|
15
|
+
class="sub-menu"
|
|
16
|
+
ref="subMenu"
|
|
17
|
+
:menu-data="subMenuData"
|
|
18
|
+
:is-sub-menu="true"
|
|
19
|
+
@hide="hide"
|
|
20
|
+
></content-menu>
|
|
21
|
+
</teleport>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script lang="ts">
|
|
26
|
+
import { defineComponent, nextTick, onMounted, onUnmounted, PropType, ref } from 'vue';
|
|
27
|
+
|
|
28
|
+
import { MenuButton, MenuItem } from '@editor/type';
|
|
29
|
+
|
|
30
|
+
import ToolButton from './ToolButton.vue';
|
|
31
|
+
|
|
32
|
+
export default defineComponent({
|
|
33
|
+
components: { ToolButton },
|
|
34
|
+
|
|
35
|
+
props: {
|
|
36
|
+
menuData: {
|
|
37
|
+
type: Array as PropType<MenuItem[]>,
|
|
38
|
+
default: () => [],
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
isSubMenu: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: false,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
emits: ['hide', 'show'],
|
|
48
|
+
|
|
49
|
+
setup(props, { emit }) {
|
|
50
|
+
const menu = ref<HTMLDivElement>();
|
|
51
|
+
const subMenu = ref<any>();
|
|
52
|
+
const visible = ref(false);
|
|
53
|
+
const subMenuData = ref<MenuItem[]>([]);
|
|
54
|
+
const menuStyle = ref({
|
|
55
|
+
left: '0',
|
|
56
|
+
top: '0',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const hide = () => {
|
|
60
|
+
if (!visible.value) return;
|
|
61
|
+
|
|
62
|
+
visible.value = false;
|
|
63
|
+
subMenu.value?.hide();
|
|
64
|
+
|
|
65
|
+
emit('hide');
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const hideHandler = (e: MouseEvent) => {
|
|
69
|
+
const target = e.target as HTMLElement | undefined;
|
|
70
|
+
if (!visible.value || !target) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (menu.value?.contains(target) || subMenu.value?.$el?.contains(target)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
hide();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
onMounted(() => {
|
|
80
|
+
if (props.isSubMenu) return;
|
|
81
|
+
|
|
82
|
+
globalThis.addEventListener('mousedown', hideHandler, true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
onUnmounted(() => {
|
|
86
|
+
if (props.isSubMenu) return;
|
|
87
|
+
|
|
88
|
+
globalThis.removeEventListener('mousedown', hideHandler, true);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
menu,
|
|
93
|
+
subMenu,
|
|
94
|
+
visible,
|
|
95
|
+
menuStyle,
|
|
96
|
+
subMenuData,
|
|
97
|
+
|
|
98
|
+
hide,
|
|
99
|
+
|
|
100
|
+
show(e: MouseEvent) {
|
|
101
|
+
// 加settimeout是以为,如果菜单中的按钮监听的是mouseup,那么菜单显示出来时鼠标如果正好在菜单上就会马上触发按钮的mouseup
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
visible.value = true;
|
|
104
|
+
|
|
105
|
+
nextTick(() => {
|
|
106
|
+
const menuHeight = menu.value?.clientHeight || 0;
|
|
107
|
+
|
|
108
|
+
let top = e.clientY;
|
|
109
|
+
if (menuHeight + e.clientY > document.body.clientHeight) {
|
|
110
|
+
top = document.body.clientHeight - menuHeight;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
menuStyle.value = {
|
|
114
|
+
top: `${top}px`,
|
|
115
|
+
left: `${e.clientX}px`,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
emit('show');
|
|
119
|
+
});
|
|
120
|
+
}, 300);
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
showSubMenu(item: MenuItem) {
|
|
124
|
+
const menuItem = item as MenuButton;
|
|
125
|
+
if (typeof item !== 'object' || !menuItem.items?.length) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
subMenuData.value = menuItem.items;
|
|
130
|
+
if (menu.value) {
|
|
131
|
+
subMenu.value.show({
|
|
132
|
+
clientX: menu.value.offsetLeft + menu.value.clientWidth,
|
|
133
|
+
clientY: menu.value.offsetTop,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
</script>
|
|
@@ -1,24 +1,37 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
2
|
+
<div
|
|
3
|
+
v-if="display"
|
|
4
|
+
class="menu-item"
|
|
5
|
+
:class="item.type"
|
|
6
|
+
@click="clickHandler(item, $event)"
|
|
7
|
+
@mousedown="mousedownHandler(item, $event)"
|
|
8
|
+
@mouseup="mouseupHandler(item, $event)"
|
|
9
|
+
>
|
|
10
|
+
<el-divider v-if="item.type === 'divider'" :direction="item.direction || 'vertical'"></el-divider>
|
|
4
11
|
<div v-else-if="item.type === 'text'" class="menu-item-text">{{ item.text }}</div>
|
|
5
12
|
|
|
6
13
|
<template v-else-if="item.type === 'zoom'">
|
|
7
|
-
<
|
|
14
|
+
<tool-button
|
|
15
|
+
:data="{ type: 'button', icon: ZoomOut, handler: zoomOutHandler, tooltip: '缩小' }"
|
|
16
|
+
:event-type="eventType"
|
|
17
|
+
></tool-button>
|
|
8
18
|
<span class="menu-item-text" style="margin: 0 5px">{{ parseInt(`${zoom * 100}`, 10) }}%</span>
|
|
9
|
-
<
|
|
19
|
+
<tool-button
|
|
20
|
+
:data="{ type: 'button', icon: ZoomIn, handler: zoomInHandler, tooltip: '放大' }"
|
|
21
|
+
:event-type="eventType"
|
|
22
|
+
></tool-button>
|
|
10
23
|
</template>
|
|
11
24
|
|
|
12
|
-
<
|
|
13
|
-
v-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<el-button size="small"
|
|
19
|
-
><m-icon :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
|
|
25
|
+
<template v-else-if="item.type === 'button'">
|
|
26
|
+
<el-tooltip v-if="item.tooltip" effect="dark" placement="bottom-start" :content="item.tooltip">
|
|
27
|
+
<el-button size="small" text :disabled="disabled"
|
|
28
|
+
><m-icon v-if="item.icon" :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
|
|
29
|
+
>
|
|
30
|
+
</el-tooltip>
|
|
31
|
+
<el-button v-else size="small" text :disabled="disabled"
|
|
32
|
+
><m-icon v-if="item.icon" :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
|
|
20
33
|
>
|
|
21
|
-
</
|
|
34
|
+
</template>
|
|
22
35
|
|
|
23
36
|
<el-dropdown v-else-if="item.type === 'dropdown'" trigger="click" :disabled="disabled" @command="dropdownHandler">
|
|
24
37
|
<span class="el-dropdown-link menubar-menu-button">
|
|
@@ -38,9 +51,11 @@
|
|
|
38
51
|
</template>
|
|
39
52
|
|
|
40
53
|
<script lang="ts">
|
|
41
|
-
import { computed, defineComponent, inject, PropType } from 'vue';
|
|
54
|
+
import { computed, defineComponent, inject, markRaw, PropType } from 'vue';
|
|
42
55
|
import { ArrowDown, Back, Delete, Grid, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons';
|
|
43
56
|
|
|
57
|
+
import { NodeType } from '@tmagic/schema';
|
|
58
|
+
|
|
44
59
|
import MIcon from '@editor/components/Icon.vue';
|
|
45
60
|
import type { MenuButton, MenuComponent, MenuItem, Services } from '@editor/type';
|
|
46
61
|
|
|
@@ -56,19 +71,24 @@ export default defineComponent({
|
|
|
56
71
|
display: false,
|
|
57
72
|
}),
|
|
58
73
|
},
|
|
74
|
+
|
|
75
|
+
eventType: {
|
|
76
|
+
type: String as PropType<'mousedown' | 'mouseup' | 'click'>,
|
|
77
|
+
default: 'click',
|
|
78
|
+
},
|
|
59
79
|
},
|
|
60
80
|
|
|
61
81
|
setup(props) {
|
|
62
82
|
const services = inject<Services>('services');
|
|
63
83
|
const uiService = services?.uiService;
|
|
64
84
|
|
|
65
|
-
const zoomInHandler = () => uiService?.set('zoom', zoom.value + 0.1);
|
|
66
|
-
const zoomOutHandler = () => uiService?.set('zoom', zoom.value - 0.1);
|
|
67
|
-
|
|
68
85
|
const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1);
|
|
69
86
|
const showGuides = computed((): boolean => uiService?.get<boolean>('showGuides') ?? true);
|
|
70
87
|
const showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
|
|
71
88
|
|
|
89
|
+
const zoomInHandler = () => uiService?.zoom(0.1);
|
|
90
|
+
const zoomOutHandler = () => uiService?.zoom(-0.1);
|
|
91
|
+
|
|
72
92
|
const item = computed((): MenuButton | MenuComponent => {
|
|
73
93
|
if (typeof props.data !== 'string') {
|
|
74
94
|
return props.data;
|
|
@@ -85,15 +105,15 @@ export default defineComponent({
|
|
|
85
105
|
case 'delete':
|
|
86
106
|
return {
|
|
87
107
|
type: 'button',
|
|
88
|
-
icon: Delete,
|
|
108
|
+
icon: markRaw(Delete),
|
|
89
109
|
tooltip: '刪除',
|
|
90
|
-
disabled: () => services?.editorService.get('node')?.type ===
|
|
110
|
+
disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
|
|
91
111
|
handler: () => services?.editorService.remove(services?.editorService.get('node')),
|
|
92
112
|
};
|
|
93
113
|
case 'undo':
|
|
94
114
|
return {
|
|
95
115
|
type: 'button',
|
|
96
|
-
icon: Back,
|
|
116
|
+
icon: markRaw(Back),
|
|
97
117
|
tooltip: '后退',
|
|
98
118
|
disabled: () => !services?.historyService.state.canUndo,
|
|
99
119
|
handler: () => services?.editorService.undo(),
|
|
@@ -101,7 +121,7 @@ export default defineComponent({
|
|
|
101
121
|
case 'redo':
|
|
102
122
|
return {
|
|
103
123
|
type: 'button',
|
|
104
|
-
icon: Right,
|
|
124
|
+
icon: markRaw(Right),
|
|
105
125
|
tooltip: '前进',
|
|
106
126
|
disabled: () => !services?.historyService.state.canRedo,
|
|
107
127
|
handler: () => services?.editorService.redo(),
|
|
@@ -109,28 +129,28 @@ export default defineComponent({
|
|
|
109
129
|
case 'zoom-in':
|
|
110
130
|
return {
|
|
111
131
|
type: 'button',
|
|
112
|
-
icon: ZoomIn,
|
|
132
|
+
icon: markRaw(ZoomIn),
|
|
113
133
|
tooltip: '放大',
|
|
114
134
|
handler: zoomInHandler,
|
|
115
135
|
};
|
|
116
136
|
case 'zoom-out':
|
|
117
137
|
return {
|
|
118
138
|
type: 'button',
|
|
119
|
-
icon: ZoomOut,
|
|
139
|
+
icon: markRaw(ZoomOut),
|
|
120
140
|
tooltip: '縮小',
|
|
121
141
|
handler: zoomOutHandler,
|
|
122
142
|
};
|
|
123
143
|
case 'rule':
|
|
124
144
|
return {
|
|
125
145
|
type: 'button',
|
|
126
|
-
icon: ScaleToOriginal,
|
|
146
|
+
icon: markRaw(ScaleToOriginal),
|
|
127
147
|
tooltip: showRule.value ? '隐藏标尺' : '显示标尺',
|
|
128
148
|
handler: () => uiService?.set('showRule', !showRule.value),
|
|
129
149
|
};
|
|
130
150
|
case 'guides':
|
|
131
151
|
return {
|
|
132
152
|
type: 'button',
|
|
133
|
-
icon: Grid,
|
|
153
|
+
icon: markRaw(Grid),
|
|
134
154
|
tooltip: showGuides.value ? '隐藏参考线' : '显示参考线',
|
|
135
155
|
handler: () => uiService?.set('showGuides', !showGuides.value),
|
|
136
156
|
};
|
|
@@ -151,9 +171,16 @@ export default defineComponent({
|
|
|
151
171
|
return item.value.disabled;
|
|
152
172
|
});
|
|
153
173
|
|
|
174
|
+
const buttonHandler = (item: MenuButton | MenuComponent, event: MouseEvent) => {
|
|
175
|
+
if (disabled.value) return;
|
|
176
|
+
if (typeof (item as MenuButton).handler === 'function' && services) {
|
|
177
|
+
(item as MenuButton).handler?.(services, event);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
154
181
|
return {
|
|
155
|
-
ZoomIn,
|
|
156
|
-
ZoomOut,
|
|
182
|
+
ZoomIn: markRaw(ZoomIn),
|
|
183
|
+
ZoomOut: markRaw(ZoomOut),
|
|
157
184
|
|
|
158
185
|
item,
|
|
159
186
|
zoom,
|
|
@@ -176,10 +203,24 @@ export default defineComponent({
|
|
|
176
203
|
}
|
|
177
204
|
},
|
|
178
205
|
|
|
179
|
-
|
|
180
|
-
if (
|
|
181
|
-
if (
|
|
182
|
-
(item
|
|
206
|
+
clickHandler(item: MenuButton | MenuComponent, event: MouseEvent) {
|
|
207
|
+
if (props.eventType !== 'click') return;
|
|
208
|
+
if (item.type === 'button') {
|
|
209
|
+
buttonHandler(item, event);
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
mousedownHandler(item: MenuButton | MenuComponent, event: MouseEvent) {
|
|
214
|
+
if (props.eventType !== 'mousedown') return;
|
|
215
|
+
if (item.type === 'button') {
|
|
216
|
+
buttonHandler(item, event);
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
mouseupHandler(item: MenuButton | MenuComponent, event: MouseEvent) {
|
|
221
|
+
if (props.eventType !== 'mouseup') return;
|
|
222
|
+
if (item.type === 'button') {
|
|
223
|
+
buttonHandler(item, event);
|
|
183
224
|
}
|
|
184
225
|
},
|
|
185
226
|
};
|
package/src/fields/UISelect.vue
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-fields-ui-select" v-if="uiSelectMode" @click="cancelHandler">
|
|
3
|
-
<
|
|
3
|
+
<el-button type="danger" :icon="Delete" text style="padding: 0">取消</el-button>
|
|
4
4
|
</div>
|
|
5
|
-
<div class="m-fields-ui-select" v-else @click="startSelect">
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
<div class="m-fields-ui-select" v-else @click="startSelect" style="display: flex">
|
|
6
|
+
<el-tooltip content="清除">
|
|
7
|
+
<el-button v-if="val" style="padding: 0" type="danger" :icon="Close" text @click.stop="deleteHandler"></el-button>
|
|
8
|
+
</el-tooltip>
|
|
9
|
+
<el-tooltip :content="val ? toName + '_' + val : '点击此处选择'">
|
|
10
|
+
<el-button text style="padding: 0; margin: 0">{{ val ? toName + '_' + val : '点击此处选择' }}</el-button>
|
|
11
|
+
</el-tooltip>
|
|
9
12
|
</div>
|
|
10
13
|
</template>
|
|
11
14
|
|
|
12
15
|
<script lang="ts">
|
|
13
|
-
import { computed, defineComponent, inject, ref } from 'vue';
|
|
16
|
+
import { computed, defineComponent, inject, markRaw, ref } from 'vue';
|
|
17
|
+
import { Close, Delete, Pointer } from '@element-plus/icons';
|
|
14
18
|
|
|
15
19
|
import { FormState } from '@tmagic/form';
|
|
16
20
|
|
|
@@ -60,6 +64,10 @@ export default defineComponent({
|
|
|
60
64
|
};
|
|
61
65
|
|
|
62
66
|
return {
|
|
67
|
+
Delete: markRaw(Delete),
|
|
68
|
+
Pointer: markRaw(Pointer),
|
|
69
|
+
Close: markRaw(Close),
|
|
70
|
+
|
|
63
71
|
val,
|
|
64
72
|
uiSelectMode,
|
|
65
73
|
toName: computed(() => {
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
+
import './utils/polyfills';
|
|
18
19
|
|
|
19
20
|
import { App } from 'vue';
|
|
20
21
|
|
|
@@ -41,6 +42,7 @@ export { default as uiService } from './services/ui';
|
|
|
41
42
|
export { default as ComponentListPanel } from './layouts/sidebar/ComponentListPanel.vue';
|
|
42
43
|
export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
|
|
43
44
|
export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
45
|
+
export { default as ToolButton } from './components/ToolButton.vue';
|
|
44
46
|
|
|
45
47
|
const defaultInstallOpt: InstallOptions = {
|
|
46
48
|
// @todo, 自定义图片上传方法等编辑器依赖的外部选项
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
import { defineComponent, inject, toRaw } from 'vue';
|
|
16
16
|
import { Plus } from '@element-plus/icons';
|
|
17
17
|
|
|
18
|
+
import { NodeType } from '@tmagic/schema';
|
|
19
|
+
|
|
18
20
|
import { Services } from '@editor/type';
|
|
19
21
|
import { generatePageNameByApp } from '@editor/utils';
|
|
20
22
|
|
|
@@ -31,7 +33,7 @@ export default defineComponent({
|
|
|
31
33
|
if (!editorService) return;
|
|
32
34
|
|
|
33
35
|
editorService.add({
|
|
34
|
-
type:
|
|
36
|
+
type: NodeType.PAGE,
|
|
35
37
|
name: generatePageNameByApp(toRaw(editorService.get('root'))),
|
|
36
38
|
});
|
|
37
39
|
},
|