@tmagic/editor 1.4.0-beta.1 → 1.4.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/dist/style.css +22 -26
- package/dist/tmagic-editor.js +977 -798
- package/dist/tmagic-editor.umd.cjs +981 -800
- package/package.json +11 -11
- package/src/components/CodeBlockEditor.vue +75 -101
- package/src/components/FloatingBox.vue +58 -38
- package/src/components/SplitView.vue +46 -35
- package/src/fields/DataSourceFieldSelect.vue +2 -1
- package/src/fields/DataSourceFields.vue +55 -30
- package/src/fields/DataSourceInput.vue +6 -2
- package/src/fields/DataSourceMocks.vue +35 -17
- package/src/hooks/index.ts +2 -0
- package/src/hooks/use-code-block-edit.ts +1 -1
- package/src/hooks/use-editor-content-height.ts +20 -0
- package/src/hooks/use-float-box.ts +21 -15
- package/src/hooks/use-next-float-box-position.ts +29 -0
- package/src/hooks/use-window-rect.ts +20 -0
- package/src/layouts/CodeEditor.vue +3 -6
- package/src/layouts/Framework.vue +33 -34
- package/src/layouts/PropsPanel.vue +37 -0
- package/src/layouts/sidebar/Sidebar.vue +17 -15
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -3
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +36 -22
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -6
- package/src/layouts/workspace/viewer/NodeListMenu.vue +1 -0
- package/src/layouts/workspace/viewer/StageOverlay.vue +3 -1
- package/src/services/stageOverlay.ts +2 -2
- package/src/services/ui.ts +6 -0
- package/src/theme/code-block.scss +0 -19
- package/src/theme/component-list-panel.scss +0 -1
- package/src/theme/floating-box.scss +2 -2
- package/src/theme/icon.scss +7 -1
- package/src/theme/layer-panel.scss +0 -1
- package/src/theme/props-panel.scss +14 -0
- package/src/theme/sidebar.scss +0 -7
- package/src/type.ts +6 -6
- package/types/components/CodeBlockEditor.vue.d.ts +39 -25
- package/types/components/FloatingBox.vue.d.ts +42 -57
- package/types/components/SplitView.vue.d.ts +2 -0
- package/types/fields/DataSourceFields.vue.d.ts +84 -28
- package/types/fields/DataSourceMocks.vue.d.ts +80 -28
- package/types/hooks/index.d.ts +2 -0
- package/types/hooks/use-code-block-edit.d.ts +16 -11
- package/types/hooks/use-data-source-method.d.ts +16 -11
- package/types/hooks/use-editor-content-height.d.ts +3 -0
- package/types/hooks/use-next-float-box-position.d.ts +9 -0
- package/types/hooks/use-window-rect.d.ts +6 -0
- package/types/layouts/sidebar/Sidebar.vue.d.ts +1 -1
- package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +1 -3
- package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +34 -22
- package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +2 -15
- package/types/services/stageOverlay.d.ts +1 -1
- package/types/services/ui.d.ts +6 -0
- package/types/type.d.ts +6 -5
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.4.0
|
|
2
|
+
"version": "1.4.0",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@babel/core": "^7.18.0",
|
|
44
44
|
"@element-plus/icons-vue": "^2.3.1",
|
|
45
|
-
"@tmagic/core": "1.4.0
|
|
46
|
-
"@tmagic/dep": "1.4.0
|
|
47
|
-
"@tmagic/design": "1.4.0
|
|
48
|
-
"@tmagic/form": "1.4.0
|
|
49
|
-
"@tmagic/schema": "1.4.0
|
|
50
|
-
"@tmagic/stage": "1.4.0
|
|
51
|
-
"@tmagic/table": "1.4.0
|
|
52
|
-
"@tmagic/utils": "1.4.0
|
|
45
|
+
"@tmagic/core": "1.4.0",
|
|
46
|
+
"@tmagic/dep": "1.4.0",
|
|
47
|
+
"@tmagic/design": "1.4.0",
|
|
48
|
+
"@tmagic/form": "1.4.0",
|
|
49
|
+
"@tmagic/schema": "1.4.0",
|
|
50
|
+
"@tmagic/stage": "1.4.0",
|
|
51
|
+
"@tmagic/table": "1.4.0",
|
|
52
|
+
"@tmagic/utils": "1.4.0",
|
|
53
53
|
"buffer": "^6.0.3",
|
|
54
54
|
"color": "^3.1.3",
|
|
55
55
|
"emmet-monaco-es": "^5.3.0",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"vue": "^3.4.21"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
-
"@tmagic/design": "1.4.0
|
|
67
|
-
"@tmagic/form": "1.4.0
|
|
66
|
+
"@tmagic/design": "1.4.0",
|
|
67
|
+
"@tmagic/form": "1.4.0",
|
|
68
68
|
"monaco-editor": "^0.47.0",
|
|
69
69
|
"vue": "^3.4.21"
|
|
70
70
|
},
|
|
@@ -1,81 +1,90 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<!-- 代码块编辑区 -->
|
|
3
|
-
<FloatingBox
|
|
3
|
+
<FloatingBox
|
|
4
|
+
v-model:visible="boxVisible"
|
|
5
|
+
v-model:width="width"
|
|
6
|
+
v-model:height="codeBlockEditorHeight"
|
|
7
|
+
:title="content.name ? `${disabled ? '查看' : '编辑'}${content.name}` : '新增代码'"
|
|
8
|
+
:position="boxPosition"
|
|
9
|
+
:before-close="beforeClose"
|
|
10
|
+
>
|
|
4
11
|
<template #body>
|
|
5
|
-
<
|
|
12
|
+
<MFormBox
|
|
13
|
+
class="m-editor-code-block-editor"
|
|
14
|
+
ref="formBox"
|
|
15
|
+
label-width="80px"
|
|
16
|
+
:close-on-press-escape="false"
|
|
17
|
+
:title="content.name"
|
|
18
|
+
:config="functionConfig"
|
|
19
|
+
:values="content"
|
|
20
|
+
:disabled="disabled"
|
|
21
|
+
style="height: 100%"
|
|
22
|
+
@change="changeHandler"
|
|
23
|
+
@submit="submitForm"
|
|
24
|
+
@error="errorHandler"
|
|
25
|
+
@closed="closedHandler"
|
|
26
|
+
>
|
|
27
|
+
<template #left>
|
|
28
|
+
<TMagicButton v-if="!disabled" type="primary" link @click="difVisible = true">查看修改</TMagicButton>
|
|
29
|
+
</template>
|
|
30
|
+
</MFormBox>
|
|
6
31
|
</template>
|
|
7
32
|
</FloatingBox>
|
|
8
33
|
|
|
9
|
-
<Teleport
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<template #
|
|
27
|
-
<
|
|
34
|
+
<Teleport to="body">
|
|
35
|
+
<TMagicDialog title="查看修改" v-model="difVisible" fullscreen>
|
|
36
|
+
<div style="display: flex; margin-bottom: 10px">
|
|
37
|
+
<div style="flex: 1"><TMagicTag size="small" type="info">修改前</TMagicTag></div>
|
|
38
|
+
<div style="flex: 1"><TMagicTag size="small" type="success">修改后</TMagicTag></div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<CodeEditor
|
|
42
|
+
v-if="difVisible"
|
|
43
|
+
ref="magicVsEditor"
|
|
44
|
+
type="diff"
|
|
45
|
+
language="json"
|
|
46
|
+
:initValues="content.content"
|
|
47
|
+
:modifiedValues="formBox?.form?.values.content"
|
|
48
|
+
:style="`height: ${windowRect.height - 150}px`"
|
|
49
|
+
></CodeEditor>
|
|
50
|
+
|
|
51
|
+
<template #footer>
|
|
52
|
+
<span class="dialog-footer">
|
|
53
|
+
<TMagicButton size="small" @click="difVisible = false">取消</TMagicButton>
|
|
54
|
+
<TMagicButton size="small" type="primary" @click="diffChange">确定</TMagicButton>
|
|
55
|
+
</span>
|
|
28
56
|
</template>
|
|
29
|
-
</
|
|
57
|
+
</TMagicDialog>
|
|
30
58
|
</Teleport>
|
|
31
|
-
|
|
32
|
-
<TMagicDialog v-model="difVisible" title="查看修改" fullscreen>
|
|
33
|
-
<div style="display: flex; margin-bottom: 10px">
|
|
34
|
-
<div style="flex: 1"><TMagicTag size="small" type="info">修改前</TMagicTag></div>
|
|
35
|
-
<div style="flex: 1"><TMagicTag size="small" type="success">修改后</TMagicTag></div>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
<CodeEditor
|
|
39
|
-
v-if="difVisible"
|
|
40
|
-
ref="magicVsEditor"
|
|
41
|
-
type="diff"
|
|
42
|
-
language="json"
|
|
43
|
-
:initValues="content.content"
|
|
44
|
-
:modifiedValues="fomDrawer?.form?.values.content"
|
|
45
|
-
:style="`height: ${height - 200}px`"
|
|
46
|
-
></CodeEditor>
|
|
47
|
-
|
|
48
|
-
<template #footer>
|
|
49
|
-
<span class="dialog-footer">
|
|
50
|
-
<TMagicButton size="small" @click="difVisible = false">取消</TMagicButton>
|
|
51
|
-
<TMagicButton size="small" type="primary" @click="diffChange">确定</TMagicButton>
|
|
52
|
-
</span>
|
|
53
|
-
</template>
|
|
54
|
-
</TMagicDialog>
|
|
55
59
|
</template>
|
|
56
60
|
|
|
57
61
|
<script lang="ts" setup>
|
|
58
|
-
import { computed, inject,
|
|
62
|
+
import { computed, inject, Ref, ref } from 'vue';
|
|
59
63
|
|
|
60
64
|
import { TMagicButton, TMagicDialog, tMagicMessage, tMagicMessageBox, TMagicTag } from '@tmagic/design';
|
|
61
|
-
import { ColumnConfig, FormConfig, FormState, MFormBox
|
|
65
|
+
import { ColumnConfig, FormConfig, FormState, MFormBox } from '@tmagic/form';
|
|
62
66
|
import type { CodeBlockContent } from '@tmagic/schema';
|
|
63
67
|
|
|
64
68
|
import FloatingBox from '@editor/components/FloatingBox.vue';
|
|
69
|
+
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
|
70
|
+
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
|
71
|
+
import { useWindowRect } from '@editor/hooks/use-window-rect';
|
|
65
72
|
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
|
66
|
-
import type { Services
|
|
73
|
+
import type { Services } from '@editor/type';
|
|
67
74
|
import { getConfig } from '@editor/utils/config';
|
|
68
75
|
|
|
69
76
|
defineOptions({
|
|
70
77
|
name: 'MEditorCodeBlockEditor',
|
|
71
78
|
});
|
|
72
79
|
|
|
80
|
+
const width = defineModel<number>('width', { default: 670 });
|
|
81
|
+
const boxVisible = defineModel<boolean>('visible', { default: false });
|
|
82
|
+
|
|
73
83
|
const props = defineProps<{
|
|
74
84
|
content: CodeBlockContent;
|
|
75
85
|
disabled?: boolean;
|
|
76
86
|
isDataSource?: boolean;
|
|
77
87
|
dataSourceType?: string;
|
|
78
|
-
slideType?: SlideType;
|
|
79
88
|
}>();
|
|
80
89
|
|
|
81
90
|
const emit = defineEmits<{
|
|
@@ -84,38 +93,23 @@ const emit = defineEmits<{
|
|
|
84
93
|
|
|
85
94
|
const services = inject<Services>('services');
|
|
86
95
|
|
|
87
|
-
const
|
|
88
|
-
const height = ref(globalThis.innerHeight);
|
|
89
|
-
|
|
90
|
-
const windowReizehandler = () => {
|
|
91
|
-
height.value = globalThis.innerHeight;
|
|
92
|
-
};
|
|
96
|
+
const { height: codeBlockEditorHeight } = useEditorContentHeight();
|
|
93
97
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
onBeforeUnmount(() => {
|
|
97
|
-
globalThis.removeEventListener('resize', windowReizehandler);
|
|
98
|
-
});
|
|
98
|
+
const difVisible = ref(false);
|
|
99
|
+
const { rect: windowRect } = useWindowRect();
|
|
99
100
|
|
|
100
101
|
const magicVsEditor = ref<InstanceType<typeof CodeEditor>>();
|
|
101
102
|
|
|
102
103
|
const diffChange = () => {
|
|
103
|
-
if (!magicVsEditor.value || !
|
|
104
|
+
if (!magicVsEditor.value || !formBox.value?.form) {
|
|
104
105
|
return;
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
formBox.value.form.values.content = magicVsEditor.value.getEditorValue();
|
|
108
109
|
|
|
109
110
|
difVisible.value = false;
|
|
110
111
|
};
|
|
111
112
|
|
|
112
|
-
const columnWidth = computed(() => services?.uiService.get('columnWidth'));
|
|
113
|
-
const size = computed(() =>
|
|
114
|
-
columnWidth.value ? columnWidth.value.center + columnWidth.value.right - (props.isDataSource ? 100 : 0) : 600,
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
const codeEditorHeight = ref('600px');
|
|
118
|
-
|
|
119
113
|
const defaultParamColConfig: ColumnConfig = {
|
|
120
114
|
type: 'row',
|
|
121
115
|
label: '参数类型',
|
|
@@ -199,7 +193,7 @@ const functionConfig = computed<FormConfig>(() => [
|
|
|
199
193
|
name: 'content',
|
|
200
194
|
type: 'vs-code',
|
|
201
195
|
options: inject('codeOptions', {}),
|
|
202
|
-
height:
|
|
196
|
+
height: '500px',
|
|
203
197
|
onChange: (formState: FormState | undefined, code: string) => {
|
|
204
198
|
try {
|
|
205
199
|
// 检测js代码是否存在语法错误
|
|
@@ -216,6 +210,7 @@ const functionConfig = computed<FormConfig>(() => [
|
|
|
216
210
|
]);
|
|
217
211
|
|
|
218
212
|
const submitForm = (values: CodeBlockContent) => {
|
|
213
|
+
changedValue.value = undefined;
|
|
219
214
|
emit('submit', values);
|
|
220
215
|
};
|
|
221
216
|
|
|
@@ -223,16 +218,7 @@ const errorHandler = (error: any) => {
|
|
|
223
218
|
tMagicMessage.error(error.message);
|
|
224
219
|
};
|
|
225
220
|
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
const openHandler = () => {
|
|
229
|
-
setTimeout(() => {
|
|
230
|
-
if (fomDrawer.value) {
|
|
231
|
-
const height = fomDrawer.value?.bodyHeight - 348 - (props.isDataSource ? 50 : 0);
|
|
232
|
-
codeEditorHeight.value = `${height > 100 ? height : 600}px`;
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
};
|
|
221
|
+
const formBox = ref<InstanceType<typeof MFormBox>>();
|
|
236
222
|
|
|
237
223
|
const changedValue = ref<CodeBlockContent>();
|
|
238
224
|
const changeHandler = (values: CodeBlockContent) => {
|
|
@@ -256,6 +242,8 @@ const beforeClose = (done: (cancel?: boolean) => void) => {
|
|
|
256
242
|
done();
|
|
257
243
|
})
|
|
258
244
|
.catch((action: string) => {
|
|
245
|
+
if (action === 'cancel') {
|
|
246
|
+
}
|
|
259
247
|
done(action === 'cancel');
|
|
260
248
|
});
|
|
261
249
|
};
|
|
@@ -264,31 +252,17 @@ const closedHandler = () => {
|
|
|
264
252
|
changedValue.value = undefined;
|
|
265
253
|
};
|
|
266
254
|
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
const floatingBoxBody = ref<HTMLDivElement>();
|
|
270
|
-
|
|
271
|
-
const boxPosition = computed(() => {
|
|
272
|
-
const columnWidth = services?.uiService?.get('columnWidth');
|
|
273
|
-
const navMenuRect = services?.uiService?.get('navMenuRect');
|
|
274
|
-
return {
|
|
275
|
-
left: columnWidth?.left ?? 0,
|
|
276
|
-
top: (navMenuRect?.top ?? 0) + (navMenuRect?.height ?? 0),
|
|
277
|
-
};
|
|
278
|
-
});
|
|
255
|
+
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
|
256
|
+
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
|
|
279
257
|
|
|
280
258
|
defineExpose({
|
|
281
259
|
async show() {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
285
|
-
await nextTick();
|
|
286
|
-
editVisible.value = true;
|
|
287
|
-
fomDrawer.value?.show();
|
|
260
|
+
calcBoxPosition();
|
|
261
|
+
boxVisible.value = true;
|
|
288
262
|
},
|
|
289
263
|
|
|
290
|
-
hide() {
|
|
291
|
-
|
|
264
|
+
async hide() {
|
|
265
|
+
boxVisible.value = false;
|
|
292
266
|
},
|
|
293
267
|
});
|
|
294
268
|
</script>
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Teleport to="body" v-if="visible">
|
|
3
3
|
<div ref="target" class="m-editor-float-box" :style="{ ...style, zIndex: curZIndex }" @mousedown="nextZIndex">
|
|
4
|
-
<div ref="
|
|
4
|
+
<div ref="titleEl" class="m-editor-float-box-title">
|
|
5
5
|
<slot name="title">
|
|
6
6
|
<span>{{ title }}</span>
|
|
7
7
|
</slot>
|
|
8
8
|
<div>
|
|
9
|
-
<TMagicButton link size="small"
|
|
9
|
+
<TMagicButton link size="small" @click="closeHandler"><MIcon :icon="Close"></MIcon></TMagicButton>
|
|
10
10
|
</div>
|
|
11
11
|
</div>
|
|
12
|
-
<div class="m-editor-float-box-body">
|
|
12
|
+
<div class="m-editor-float-box-body" :style="{ height: `${bodyHeight}px` }">
|
|
13
13
|
<slot name="body"></slot>
|
|
14
14
|
</div>
|
|
15
15
|
</div>
|
|
@@ -17,67 +17,71 @@
|
|
|
17
17
|
</template>
|
|
18
18
|
|
|
19
19
|
<script setup lang="ts">
|
|
20
|
-
import { computed, nextTick, onBeforeUnmount, ref, watch
|
|
20
|
+
import { computed, inject, nextTick, onBeforeUnmount, provide, ref, watch } from 'vue';
|
|
21
21
|
import { Close } from '@element-plus/icons-vue';
|
|
22
22
|
import VanillaMoveable from 'moveable';
|
|
23
23
|
|
|
24
24
|
import { TMagicButton, useZIndex } from '@tmagic/design';
|
|
25
25
|
|
|
26
|
+
import MIcon from '@editor/components/Icon.vue';
|
|
27
|
+
import type { Services } from '@editor/type';
|
|
28
|
+
|
|
26
29
|
interface Position {
|
|
27
30
|
left: number;
|
|
28
31
|
top: number;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
34
|
+
const width = defineModel<number>('width', { default: 0 });
|
|
35
|
+
const height = defineModel<number>('height', { default: 0 });
|
|
36
|
+
const visible = defineModel<boolean>('visible', { default: false });
|
|
35
37
|
|
|
36
38
|
const props = withDefaults(
|
|
37
39
|
defineProps<{
|
|
38
|
-
visible: boolean;
|
|
39
40
|
position?: Position;
|
|
40
|
-
rect?: Rect;
|
|
41
41
|
title?: string;
|
|
42
42
|
beforeClose?: (done: (cancel?: boolean) => void) => void;
|
|
43
43
|
}>(),
|
|
44
44
|
{
|
|
45
|
-
visible: false,
|
|
46
45
|
title: '',
|
|
47
46
|
position: () => ({ left: 0, top: 0 }),
|
|
48
|
-
rect: () => ({ width: 'auto', height: 'auto' }),
|
|
49
47
|
},
|
|
50
48
|
);
|
|
51
49
|
|
|
52
|
-
const emit = defineEmits<{
|
|
53
|
-
'update:visible': [boolean];
|
|
54
|
-
}>();
|
|
55
|
-
|
|
56
50
|
const target = ref<HTMLDivElement>();
|
|
57
|
-
const
|
|
51
|
+
const titleEl = ref<HTMLDivElement>();
|
|
58
52
|
|
|
59
53
|
const zIndex = useZIndex();
|
|
60
|
-
const curZIndex = ref<number>(
|
|
54
|
+
const curZIndex = ref<number>(0);
|
|
61
55
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
height
|
|
56
|
+
const titleHeight = ref(0);
|
|
57
|
+
const bodyHeight = computed(() => {
|
|
58
|
+
if (height.value) {
|
|
59
|
+
return height.value - titleHeight.value;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (target.value) {
|
|
63
|
+
return target.value.clientHeight - titleHeight.value;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return 'auto';
|
|
65
67
|
});
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
const services = inject<Services>('services');
|
|
70
|
+
const frameworkWidth = computed(() => services?.uiService.get('frameworkRect').width || 0);
|
|
71
|
+
const style = computed(() => {
|
|
72
|
+
let { left } = props.position;
|
|
73
|
+
if (width.value) {
|
|
74
|
+
left = left + width.value > frameworkWidth.value ? frameworkWidth.value - width.value : left;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
left: `${left}px`,
|
|
79
|
+
top: `${props.position.top}px`,
|
|
80
|
+
width: width.value ? `${width.value}px` : 'auto',
|
|
81
|
+
height: height.value ? `${height.value}px` : 'auto',
|
|
71
82
|
};
|
|
72
83
|
});
|
|
73
84
|
|
|
74
|
-
const style = computed(() => ({
|
|
75
|
-
left: `${props.position.left}px`,
|
|
76
|
-
top: `${props.position.top}px`,
|
|
77
|
-
width: typeof rect.value.width === 'string' ? rect.value.width : `${rect.value.width}px`,
|
|
78
|
-
height: typeof rect.value.height === 'string' ? rect.value.height : `${rect.value.height}px`,
|
|
79
|
-
}));
|
|
80
|
-
|
|
81
85
|
let moveable: VanillaMoveable | null = null;
|
|
82
86
|
|
|
83
87
|
const initMoveable = () => {
|
|
@@ -90,7 +94,7 @@ const initMoveable = () => {
|
|
|
90
94
|
keepRatio: false,
|
|
91
95
|
origin: false,
|
|
92
96
|
snappable: true,
|
|
93
|
-
dragTarget:
|
|
97
|
+
dragTarget: titleEl.value,
|
|
94
98
|
dragTargetSelf: false,
|
|
95
99
|
linePadding: 10,
|
|
96
100
|
controlPadding: 10,
|
|
@@ -102,8 +106,8 @@ const initMoveable = () => {
|
|
|
102
106
|
});
|
|
103
107
|
|
|
104
108
|
moveable.on('resize', (e) => {
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
width.value = e.width;
|
|
110
|
+
height.value = e.height;
|
|
107
111
|
e.target.style.width = `${e.width}px`;
|
|
108
112
|
e.target.style.height = `${e.height}px`;
|
|
109
113
|
e.target.style.transform = e.drag.transform;
|
|
@@ -116,11 +120,23 @@ const destroyMoveable = () => {
|
|
|
116
120
|
};
|
|
117
121
|
|
|
118
122
|
watch(
|
|
119
|
-
|
|
123
|
+
visible,
|
|
120
124
|
async (visible) => {
|
|
121
125
|
if (visible) {
|
|
122
126
|
await nextTick();
|
|
123
|
-
|
|
127
|
+
curZIndex.value = zIndex.nextZIndex();
|
|
128
|
+
|
|
129
|
+
const targetRect = target.value?.getBoundingClientRect();
|
|
130
|
+
if (targetRect) {
|
|
131
|
+
width.value = targetRect.width;
|
|
132
|
+
height.value = targetRect.height;
|
|
133
|
+
initMoveable();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (titleEl.value) {
|
|
137
|
+
const titleRect = titleEl.value.getBoundingClientRect();
|
|
138
|
+
titleHeight.value = titleRect.height;
|
|
139
|
+
}
|
|
124
140
|
} else {
|
|
125
141
|
destroyMoveable();
|
|
126
142
|
}
|
|
@@ -136,7 +152,7 @@ onBeforeUnmount(() => {
|
|
|
136
152
|
|
|
137
153
|
const hide = (cancel?: boolean) => {
|
|
138
154
|
if (cancel !== false) {
|
|
139
|
-
|
|
155
|
+
visible.value = false;
|
|
140
156
|
}
|
|
141
157
|
};
|
|
142
158
|
|
|
@@ -152,7 +168,11 @@ const nextZIndex = () => {
|
|
|
152
168
|
curZIndex.value = zIndex.nextZIndex();
|
|
153
169
|
};
|
|
154
170
|
|
|
171
|
+
provide('parentFloating', target);
|
|
172
|
+
|
|
155
173
|
defineExpose({
|
|
174
|
+
bodyHeight,
|
|
156
175
|
target,
|
|
176
|
+
titleEl,
|
|
157
177
|
});
|
|
158
178
|
</script>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
</template>
|
|
22
22
|
|
|
23
23
|
<script lang="ts" setup>
|
|
24
|
-
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
|
|
24
|
+
import { computed, onBeforeUnmount, onMounted, ref, watchEffect } from 'vue';
|
|
25
25
|
import { OnDrag } from 'gesto';
|
|
26
26
|
|
|
27
27
|
import Resizer from './Resizer.vue';
|
|
@@ -34,6 +34,7 @@ const emit = defineEmits(['update:left', 'change', 'update:right']);
|
|
|
34
34
|
|
|
35
35
|
const props = withDefaults(
|
|
36
36
|
defineProps<{
|
|
37
|
+
width?: number;
|
|
37
38
|
left?: number;
|
|
38
39
|
right?: number;
|
|
39
40
|
minLeft?: number;
|
|
@@ -54,8 +55,11 @@ const el = ref<HTMLElement>();
|
|
|
54
55
|
|
|
55
56
|
const hasLeft = computed(() => typeof props.left !== 'undefined');
|
|
56
57
|
const hasRight = computed(() => typeof props.right !== 'undefined');
|
|
58
|
+
const center = ref(0);
|
|
59
|
+
|
|
60
|
+
let clientWidth = 0;
|
|
57
61
|
|
|
58
|
-
const getCenterWidth = (
|
|
62
|
+
const getCenterWidth = (l = 0, r = 0) => {
|
|
59
63
|
let right = r > 0 ? r : 0;
|
|
60
64
|
let left = l > 0 ? l : 0;
|
|
61
65
|
let center = clientWidth - left - right;
|
|
@@ -76,45 +80,51 @@ const getCenterWidth = (clientWidth: number, l = 0, r = 0) => {
|
|
|
76
80
|
};
|
|
77
81
|
};
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
const widthChange = (width: number) => {
|
|
84
|
+
if (width <= 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
83
87
|
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
clientWidth = width;
|
|
89
|
+
let left = props.left || 0;
|
|
90
|
+
let right = props.right || 0;
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
if (left > clientWidth) {
|
|
93
|
+
left = clientWidth / 3;
|
|
94
|
+
}
|
|
90
95
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
if (right > clientWidth) {
|
|
97
|
+
right = clientWidth / 3;
|
|
98
|
+
}
|
|
94
99
|
|
|
95
|
-
|
|
100
|
+
const columnWidth = getCenterWidth(left, right);
|
|
96
101
|
|
|
97
|
-
|
|
102
|
+
center.value = columnWidth.center;
|
|
98
103
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
center: center.value,
|
|
102
|
-
right: columnWidth.right,
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
});
|
|
104
|
+
emit('change', columnWidth);
|
|
105
|
+
};
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
107
|
+
if (typeof props.width !== 'number') {
|
|
108
|
+
const resizerObserver = new ResizeObserver((entries) => {
|
|
109
|
+
for (const { contentRect } of entries) {
|
|
110
|
+
widthChange(contentRect.width);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
onMounted(() => {
|
|
115
|
+
if (el.value) {
|
|
116
|
+
resizerObserver.observe(el.value);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
onBeforeUnmount(() => {
|
|
121
|
+
resizerObserver.disconnect();
|
|
122
|
+
});
|
|
123
|
+
} else {
|
|
124
|
+
watchEffect(() => {
|
|
125
|
+
if (typeof props.width === 'number') widthChange(props.width);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
118
128
|
|
|
119
129
|
const changeLeft = ({ deltaX }: OnDrag) => {
|
|
120
130
|
if (typeof props.left === 'undefined') return;
|
|
@@ -125,7 +135,7 @@ const changeLeft = ({ deltaX }: OnDrag) => {
|
|
|
125
135
|
left = props.left;
|
|
126
136
|
}
|
|
127
137
|
|
|
128
|
-
const columnWidth = getCenterWidth(
|
|
138
|
+
const columnWidth = getCenterWidth(left, props.right || 0);
|
|
129
139
|
|
|
130
140
|
center.value = columnWidth.center;
|
|
131
141
|
|
|
@@ -145,7 +155,7 @@ const changeRight = ({ deltaX }: OnDrag) => {
|
|
|
145
155
|
right = props.right;
|
|
146
156
|
}
|
|
147
157
|
|
|
148
|
-
const columnWidth = getCenterWidth(
|
|
158
|
+
const columnWidth = getCenterWidth(props.left, right);
|
|
149
159
|
|
|
150
160
|
center.value = columnWidth.center;
|
|
151
161
|
|
|
@@ -158,7 +168,8 @@ const changeRight = ({ deltaX }: OnDrag) => {
|
|
|
158
168
|
|
|
159
169
|
defineExpose({
|
|
160
170
|
updateWidth() {
|
|
161
|
-
|
|
171
|
+
clientWidth = props.width ?? el.value?.clientWidth ?? clientWidth;
|
|
172
|
+
const columnWidth = getCenterWidth(props.left, props.right);
|
|
162
173
|
|
|
163
174
|
emit('change', {
|
|
164
175
|
left: columnWidth.left,
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
style="margin-left: 5px"
|
|
20
20
|
link
|
|
21
21
|
:type="showDataSourceFieldSelect ? 'primary' : 'default'"
|
|
22
|
-
:icon="Coin"
|
|
23
22
|
:size="size"
|
|
24
23
|
@click="showDataSourceFieldSelect = !showDataSourceFieldSelect"
|
|
24
|
+
><MIcon :icon="Coin"></MIcon
|
|
25
25
|
></TMagicButton>
|
|
26
26
|
</div>
|
|
27
27
|
</template>
|
|
@@ -36,6 +36,7 @@ import { MCascader } from '@tmagic/form';
|
|
|
36
36
|
import type { DataSchema, DataSourceFieldType } from '@tmagic/schema';
|
|
37
37
|
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
|
38
38
|
|
|
39
|
+
import MIcon from '@editor/components/Icon.vue';
|
|
39
40
|
import type { DataSourceFieldSelectConfig, Services } from '@editor/type';
|
|
40
41
|
|
|
41
42
|
defineOptions({
|