@tmagic/editor 1.1.2 → 1.1.4
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/tmagic-editor.mjs +43 -57
- package/dist/tmagic-editor.mjs.map +1 -1
- package/dist/tmagic-editor.umd.js +43 -57
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/package.json +7 -7
- package/src/layouts/NavMenu.vue +1 -1
- package/src/layouts/sidebar/ComponentListPanel.vue +1 -1
- package/src/layouts/workspace/PageBarScrollContainer.vue +46 -43
- package/src/layouts/workspace/Workspace.vue +3 -3
- package/src/services/editor.ts +10 -4
- package/src/services/ui.ts +6 -6
- package/src/utils/scroll-viewer.ts +1 -0
- package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +2 -1
- package/types/services/ui.d.ts +3 -3
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.
|
|
2
|
+
"version": "1.1.4",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"dist/*",
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@babel/core": "^7.18.0",
|
|
47
47
|
"@element-plus/icons-vue": "^2.0.9",
|
|
48
|
-
"@tmagic/core": "1.1.
|
|
49
|
-
"@tmagic/form": "1.1.
|
|
50
|
-
"@tmagic/schema": "1.1.
|
|
51
|
-
"@tmagic/stage": "1.1.
|
|
52
|
-
"@tmagic/utils": "1.1.
|
|
48
|
+
"@tmagic/core": "1.1.4",
|
|
49
|
+
"@tmagic/form": "1.1.4",
|
|
50
|
+
"@tmagic/schema": "1.1.4",
|
|
51
|
+
"@tmagic/stage": "1.1.4",
|
|
52
|
+
"@tmagic/utils": "1.1.4",
|
|
53
53
|
"buffer": "^6.0.3",
|
|
54
54
|
"color": "^3.1.3",
|
|
55
55
|
"element-plus": "^2.2.6",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"vue": "^3.2.37"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@tmagic/form": "1.1.
|
|
65
|
+
"@tmagic/form": "1.1.4",
|
|
66
66
|
"element-plus": "^2.2.6",
|
|
67
67
|
"monaco-editor": "^0.34.0",
|
|
68
68
|
"vue": "^3.2.37"
|
package/src/layouts/NavMenu.vue
CHANGED
|
@@ -123,7 +123,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
|
|
|
123
123
|
className: 'scale-to-fit',
|
|
124
124
|
icon: markRaw(FullScreen),
|
|
125
125
|
tooltip: `缩放以适应(${ctrl}+0)`,
|
|
126
|
-
handler: () => uiService?.set('zoom', uiService.calcZoom()),
|
|
126
|
+
handler: async () => uiService?.set('zoom', await uiService.calcZoom()),
|
|
127
127
|
});
|
|
128
128
|
break;
|
|
129
129
|
case 'rule':
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
<el-collapse-item v-if="group.items && group.items.length" :key="index" :name="index">
|
|
16
16
|
<template #title><i class="el-icon-s-grid"></i>{{ group.title }}</template>
|
|
17
17
|
<div
|
|
18
|
-
class="component-item"
|
|
19
18
|
v-for="item in group.items"
|
|
19
|
+
class="component-item"
|
|
20
20
|
draggable="true"
|
|
21
21
|
:key="item.type"
|
|
22
22
|
@click="appendComponent(item)"
|
|
@@ -6,27 +6,33 @@
|
|
|
6
6
|
class="m-editor-page-bar-item m-editor-page-bar-item-icon"
|
|
7
7
|
@click="addPage"
|
|
8
8
|
>
|
|
9
|
-
<
|
|
9
|
+
<Icon :icon="Plus"></Icon>
|
|
10
10
|
</div>
|
|
11
11
|
<div v-else style="width: 21px"></div>
|
|
12
12
|
<div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('left')">
|
|
13
|
-
<
|
|
13
|
+
<Icon :icon="ArrowLeftBold"></Icon>
|
|
14
14
|
</div>
|
|
15
|
-
<div
|
|
15
|
+
<div
|
|
16
|
+
v-if="pageLength"
|
|
17
|
+
class="m-editor-page-bar-items"
|
|
18
|
+
ref="itemsContainer"
|
|
19
|
+
:style="`width: ${itemsContainerWidth}px`"
|
|
20
|
+
>
|
|
16
21
|
<slot></slot>
|
|
17
22
|
</div>
|
|
18
23
|
<div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('right')">
|
|
19
|
-
<
|
|
24
|
+
<Icon :icon="ArrowRightBold"></Icon>
|
|
20
25
|
</div>
|
|
21
26
|
</div>
|
|
22
27
|
</template>
|
|
23
28
|
|
|
24
29
|
<script setup lang="ts">
|
|
25
|
-
import { computed, inject, onMounted, onUnmounted, ref, toRaw, watch } from 'vue';
|
|
30
|
+
import { computed, inject, nextTick, onMounted, onUnmounted, ref, toRaw, watch } from 'vue';
|
|
26
31
|
import { ArrowLeftBold, ArrowRightBold, Plus } from '@element-plus/icons-vue';
|
|
27
32
|
|
|
28
|
-
import {
|
|
33
|
+
import { NodeType } from '@tmagic/schema';
|
|
29
34
|
|
|
35
|
+
import Icon from '../../components/Icon.vue';
|
|
30
36
|
import type { Services } from '../../type';
|
|
31
37
|
import { generatePageNameByApp } from '../../utils/editor';
|
|
32
38
|
|
|
@@ -34,31 +40,39 @@ const services = inject<Services>('services');
|
|
|
34
40
|
const editorService = services?.editorService;
|
|
35
41
|
const uiService = services?.uiService;
|
|
36
42
|
|
|
37
|
-
const pageBar = ref<HTMLDivElement>();
|
|
38
43
|
const itemsContainer = ref<HTMLDivElement>();
|
|
39
|
-
const pageBarWidth = ref(0);
|
|
40
44
|
const canScroll = ref(false);
|
|
41
45
|
|
|
42
46
|
const showAddPageButton = computed(() => uiService?.get('showAddPageButton'));
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
const itemsContainerWidth = computed(() => pageBarWidth.value - 35 * 2 - (showAddPageButton.value ? 35 : 21));
|
|
48
|
+
const itemsContainerWidth = ref(0);
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
pageBarWidth.value = width || 0;
|
|
50
|
+
const setCanScroll = () => {
|
|
51
|
+
// 减去新增、左移、右移三个按钮的宽度
|
|
52
|
+
// 37 = icon width 16 + padding 10 * 2 + border-right 1
|
|
53
|
+
itemsContainerWidth.value = (pageBar.value?.clientWidth || 0) - 37 * 2 - (showAddPageButton.value ? 37 : 21);
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
nextTick(() => {
|
|
56
|
+
if (itemsContainer.value) {
|
|
57
|
+
canScroll.value = itemsContainer.value.scrollWidth - itemsContainerWidth.value > 1;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
63
|
+
setCanScroll();
|
|
55
64
|
});
|
|
56
65
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
const pageBar = ref<HTMLDivElement>();
|
|
67
|
+
onMounted(() => {
|
|
68
|
+
pageBar.value && resizeObserver.observe(pageBar.value);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
onUnmounted(() => {
|
|
72
|
+
resizeObserver.disconnect();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
let translateLeft = 0;
|
|
62
76
|
|
|
63
77
|
const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
|
|
64
78
|
if (!itemsContainer.value) return;
|
|
@@ -86,30 +100,19 @@ const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
|
|
|
86
100
|
itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
|
|
87
101
|
};
|
|
88
102
|
|
|
89
|
-
|
|
90
|
-
pageBar.value && resizeObserver.observe(pageBar.value);
|
|
91
|
-
});
|
|
103
|
+
const pageLength = computed(() => editorService?.get<number>('pageLength'));
|
|
92
104
|
|
|
93
|
-
|
|
94
|
-
|
|
105
|
+
watch(pageLength, (length = 0, preLength = 0) => {
|
|
106
|
+
setTimeout(() => {
|
|
107
|
+
setCanScroll();
|
|
108
|
+
if (length < preLength) {
|
|
109
|
+
scroll('start');
|
|
110
|
+
} else {
|
|
111
|
+
scroll('end');
|
|
112
|
+
}
|
|
113
|
+
});
|
|
95
114
|
});
|
|
96
115
|
|
|
97
|
-
const root = computed(() => editorService?.get<MApp>('root'));
|
|
98
|
-
|
|
99
|
-
watch(
|
|
100
|
-
() => root.value?.items.length,
|
|
101
|
-
(length = 0, preLength = 0) => {
|
|
102
|
-
setTimeout(() => {
|
|
103
|
-
setCanScroll();
|
|
104
|
-
if (length < preLength) {
|
|
105
|
-
scroll('start');
|
|
106
|
-
} else {
|
|
107
|
-
scroll('end');
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
},
|
|
111
|
-
);
|
|
112
|
-
|
|
113
116
|
const addPage = () => {
|
|
114
117
|
if (!editorService) return;
|
|
115
118
|
const pageConfig = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor-workspace" tabindex="1" ref="workspace">
|
|
2
|
+
<div class="m-editor-workspace" tabindex="-1" ref="workspace">
|
|
3
3
|
<slot name="stage">
|
|
4
4
|
<MagicStage :key="page?.id"></MagicStage>
|
|
5
5
|
</slot>
|
|
@@ -139,9 +139,9 @@ onMounted(() => {
|
|
|
139
139
|
e.inputEvent.preventDefault();
|
|
140
140
|
services?.uiService.zoom(-0.1);
|
|
141
141
|
})
|
|
142
|
-
.keydown([ctrl, '0'], (e) => {
|
|
142
|
+
.keydown([ctrl, '0'], async (e) => {
|
|
143
143
|
e.inputEvent.preventDefault();
|
|
144
|
-
services?.uiService.set('zoom', services.uiService.calcZoom());
|
|
144
|
+
services?.uiService.set('zoom', await services.uiService.calcZoom());
|
|
145
145
|
})
|
|
146
146
|
.keydown([ctrl, '1'], (e) => {
|
|
147
147
|
e.inputEvent.preventDefault();
|
package/src/services/editor.ts
CHANGED
|
@@ -297,7 +297,7 @@ class Editor extends BaseService {
|
|
|
297
297
|
throw new Error('app下不能添加组件');
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
if (parent.id !== curNode.id) {
|
|
300
|
+
if (parent.id !== curNode.id && node.type !== NodeType.PAGE) {
|
|
301
301
|
const index = parent.items.indexOf(curNode);
|
|
302
302
|
parent?.items?.splice(index + 1, 0, node);
|
|
303
303
|
} else {
|
|
@@ -629,12 +629,18 @@ class Editor extends BaseService {
|
|
|
629
629
|
const brothers: MNode[] = parent?.items || [];
|
|
630
630
|
const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
|
|
631
631
|
|
|
632
|
+
// 流式布局与绝对定位布局操作的相反的
|
|
633
|
+
const layout = await this.getLayout(parent, node);
|
|
634
|
+
const isRelative = layout === Layout.RELATIVE;
|
|
635
|
+
|
|
636
|
+
brothers.splice(index, 1);
|
|
637
|
+
|
|
632
638
|
if (offset === LayerOffset.TOP) {
|
|
633
|
-
brothers.splice(brothers.length - 1, 0,
|
|
639
|
+
brothers.splice(isRelative ? 0 : brothers.length - 1, 0, node);
|
|
634
640
|
} else if (offset === LayerOffset.BOTTOM) {
|
|
635
|
-
brothers.splice(
|
|
641
|
+
brothers.splice(isRelative ? brothers.length - 1 : 0, 0, node);
|
|
636
642
|
} else {
|
|
637
|
-
brothers.splice(index +
|
|
643
|
+
brothers.splice(index + (isRelative ? -offset : offset), 0, node);
|
|
638
644
|
}
|
|
639
645
|
|
|
640
646
|
const grandparent = this.getParentById(parent.id);
|
package/src/services/ui.ts
CHANGED
|
@@ -59,7 +59,7 @@ const state = reactive<UiState>({
|
|
|
59
59
|
|
|
60
60
|
class Ui extends BaseService {
|
|
61
61
|
constructor() {
|
|
62
|
-
super([]);
|
|
62
|
+
super(['initColumnWidth', 'zoom', 'calcZoom']);
|
|
63
63
|
globalThis.addEventListener('resize', () => {
|
|
64
64
|
this.setColumnWidth({
|
|
65
65
|
center: 'auto',
|
|
@@ -95,7 +95,7 @@ class Ui extends BaseService {
|
|
|
95
95
|
return (state as any)[name];
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
public initColumnWidth() {
|
|
98
|
+
public async initColumnWidth() {
|
|
99
99
|
const columnWidthCacheData = globalThis.localStorage.getItem(COLUMN_WIDTH_STORAGE_KEY);
|
|
100
100
|
if (columnWidthCacheData) {
|
|
101
101
|
try {
|
|
@@ -107,12 +107,12 @@ class Ui extends BaseService {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
public zoom(zoom: number) {
|
|
110
|
+
public async zoom(zoom: number) {
|
|
111
111
|
this.set('zoom', (this.get<number>('zoom') * 100 + zoom * 100) / 100);
|
|
112
112
|
if (this.get<number>('zoom') < 0.1) this.set('zoom', 0.1);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
public calcZoom() {
|
|
115
|
+
public async calcZoom() {
|
|
116
116
|
const { stageRect, stageContainerRect } = state;
|
|
117
117
|
const { height, width } = stageContainerRect;
|
|
118
118
|
if (!width || !height) return 1;
|
|
@@ -162,12 +162,12 @@ class Ui extends BaseService {
|
|
|
162
162
|
state.columnWidth = columnWidth;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
private setStageRect(value: StageRect) {
|
|
165
|
+
private async setStageRect(value: StageRect) {
|
|
166
166
|
state.stageRect = {
|
|
167
167
|
...state.stageRect,
|
|
168
168
|
...value,
|
|
169
169
|
};
|
|
170
|
-
state.zoom = this.calcZoom();
|
|
170
|
+
state.zoom = await this.calcZoom();
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nextTick } from 'vue';
|
|
1
2
|
declare const _default: {
|
|
2
3
|
new (...args: any[]): {
|
|
3
4
|
$: import("vue").ComponentInternalInstance;
|
|
@@ -34,7 +35,7 @@ declare const _default: {
|
|
|
34
35
|
errorCaptured?: (((err: unknown, instance: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}>> | null, info: string) => boolean | void) | ((err: unknown, instance: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}>> | null, info: string) => boolean | void)[]) | undefined;
|
|
35
36
|
};
|
|
36
37
|
$forceUpdate: () => void;
|
|
37
|
-
$nextTick: typeof
|
|
38
|
+
$nextTick: typeof nextTick;
|
|
38
39
|
$watch(source: string | Function, cb: Function, options?: import("vue").WatchOptions<boolean> | undefined): import("vue").WatchStopHandle;
|
|
39
40
|
} & Readonly<import("vue").ExtractPropTypes<{}>> & import("vue").ShallowUnwrapRef<{}> & {} & import("vue").ComponentCustomProperties;
|
|
40
41
|
__isFragment?: undefined;
|
package/types/services/ui.d.ts
CHANGED
|
@@ -26,9 +26,9 @@ declare class Ui extends BaseService {
|
|
|
26
26
|
constructor();
|
|
27
27
|
set<T = any>(name: keyof UiState, value: T): void;
|
|
28
28
|
get<T>(name: keyof typeof state): T;
|
|
29
|
-
initColumnWidth(): void
|
|
30
|
-
zoom(zoom: number): void
|
|
31
|
-
calcZoom(): number
|
|
29
|
+
initColumnWidth(): Promise<void>;
|
|
30
|
+
zoom(zoom: number): Promise<void>;
|
|
31
|
+
calcZoom(): Promise<number>;
|
|
32
32
|
destroy(): void;
|
|
33
33
|
private setColumnWidth;
|
|
34
34
|
private setStageRect;
|