@tmagic/editor 1.5.2 → 1.5.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/style.css +366 -6
- package/dist/tmagic-editor.js +1749 -829
- package/dist/tmagic-editor.umd.cjs +1764 -843
- package/package.json +7 -7
- package/src/components/CodeBlockEditor.vue +3 -3
- package/src/components/CodeParams.vue +2 -2
- package/src/components/ContentMenu.vue +13 -13
- package/src/components/FloatingBox.vue +9 -9
- package/src/components/Resizer.vue +2 -2
- package/src/components/ScrollBar.vue +6 -7
- package/src/components/ScrollViewer.vue +6 -6
- package/src/components/SplitView.vue +3 -3
- package/src/fields/DataSourceInput.vue +3 -3
- package/src/fields/DataSourceMethods.vue +4 -4
- package/src/fields/DisplayConds.vue +2 -1
- package/src/fields/StyleSetter/Index.vue +69 -0
- package/src/fields/StyleSetter/components/BackgroundPosition.vue +71 -0
- package/src/fields/StyleSetter/components/Border.vue +104 -0
- package/src/fields/StyleSetter/components/Box.vue +73 -0
- package/src/fields/StyleSetter/components/Position.vue +54 -0
- package/src/fields/StyleSetter/icons/background-position/LeftBottom.vue +7 -0
- package/src/fields/StyleSetter/icons/background-position/LeftCenter.vue +7 -0
- package/src/fields/StyleSetter/icons/background-position/LeftTop.vue +12 -0
- package/src/fields/StyleSetter/icons/background-position/index.ts +3 -0
- package/src/fields/StyleSetter/icons/background-repeat/NoRepeat.vue +8 -0
- package/src/fields/StyleSetter/icons/background-repeat/Repeat.vue +31 -0
- package/src/fields/StyleSetter/icons/background-repeat/RepeatX.vue +8 -0
- package/src/fields/StyleSetter/icons/background-repeat/RepeatY.vue +8 -0
- package/src/fields/StyleSetter/icons/background-repeat/index.ts +4 -0
- package/src/fields/StyleSetter/icons/display/Block.vue +7 -0
- package/src/fields/StyleSetter/icons/display/Flex.vue +7 -0
- package/src/fields/StyleSetter/icons/display/Inline.vue +7 -0
- package/src/fields/StyleSetter/icons/display/InlineBlock.vue +7 -0
- package/src/fields/StyleSetter/icons/display/None.vue +7 -0
- package/src/fields/StyleSetter/icons/display/index.ts +5 -0
- package/src/fields/StyleSetter/icons/flex-direction/Column.vue +7 -0
- package/src/fields/StyleSetter/icons/flex-direction/ColumnReverse.vue +7 -0
- package/src/fields/StyleSetter/icons/flex-direction/Row.vue +7 -0
- package/src/fields/StyleSetter/icons/flex-direction/RowReverse.vue +7 -0
- package/src/fields/StyleSetter/icons/flex-direction/index.ts +4 -0
- package/src/fields/StyleSetter/icons/justify-content/Center.vue +5 -0
- package/src/fields/StyleSetter/icons/justify-content/FlexEnd.vue +5 -0
- package/src/fields/StyleSetter/icons/justify-content/FlexStart.vue +5 -0
- package/src/fields/StyleSetter/icons/justify-content/SpaceAround.vue +7 -0
- package/src/fields/StyleSetter/icons/justify-content/SpaceBetween.vue +5 -0
- package/src/fields/StyleSetter/icons/justify-content/index.ts +5 -0
- package/src/fields/StyleSetter/icons/text-align/Center.vue +7 -0
- package/src/fields/StyleSetter/icons/text-align/Left.vue +7 -0
- package/src/fields/StyleSetter/icons/text-align/Right.vue +7 -0
- package/src/fields/StyleSetter/icons/text-align/index.ts +3 -0
- package/src/fields/StyleSetter/pro/Background.vue +78 -0
- package/src/fields/StyleSetter/pro/Border.vue +35 -0
- package/src/fields/StyleSetter/pro/Font.vue +90 -0
- package/src/fields/StyleSetter/pro/Layout.vue +164 -0
- package/src/fields/StyleSetter/pro/Position.vue +48 -0
- package/src/fields/StyleSetter/pro/index.ts +5 -0
- package/src/hooks/use-code-block-edit.ts +5 -5
- package/src/index.ts +3 -0
- package/src/initService.ts +104 -66
- package/src/layouts/CodeEditor.vue +6 -6
- package/src/layouts/Framework.vue +5 -5
- package/src/layouts/NavMenu.vue +6 -3
- package/src/layouts/page-bar/PageBar.vue +13 -13
- package/src/layouts/page-bar/PageBarScrollContainer.vue +12 -11
- package/src/layouts/props-panel/FormPanel.vue +7 -7
- package/src/layouts/props-panel/PropsPanel.vue +36 -4
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +3 -3
- package/src/layouts/sidebar/layer/LayerMenu.vue +2 -2
- package/src/layouts/sidebar/layer/LayerPanel.vue +5 -4
- package/src/layouts/sidebar/layer/use-click.ts +4 -6
- package/src/layouts/workspace/viewer/NodeListMenu.vue +5 -5
- package/src/layouts/workspace/viewer/Stage.vue +13 -13
- package/src/layouts/workspace/viewer/StageOverlay.vue +2 -2
- package/src/layouts/workspace/viewer/ViewerMenu.vue +3 -3
- package/src/services/componentList.ts +2 -2
- package/src/services/dep.ts +8 -2
- package/src/services/editor.ts +2 -2
- package/src/services/stageOverlay.ts +2 -2
- package/src/services/ui.ts +2 -2
- package/src/theme/props-panel.scss +13 -0
- package/src/theme/resizer.scss +2 -2
- package/src/theme/style-setter/background.scss +113 -0
- package/src/theme/style-setter/border.scss +53 -0
- package/src/theme/style-setter/index.scss +28 -0
- package/src/theme/style-setter/layout.scss +199 -0
- package/src/theme/theme.scss +1 -0
- package/src/utils/idle-task.ts +26 -10
- package/src/utils/props.ts +52 -297
- package/types/index.d.ts +432 -170
|
@@ -144,40 +144,40 @@ const remove = (node: MPage | MPageFragment) => {
|
|
|
144
144
|
editorService?.remove(node);
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
-
const
|
|
148
|
-
const
|
|
147
|
+
const pageBarScrollContainerRef = useTemplateRef<InstanceType<typeof PageBarScrollContainer>>('pageBarScrollContainer');
|
|
148
|
+
const pageBarItemEls = useTemplateRef<HTMLDivElement[]>('pageBarItems');
|
|
149
149
|
watch(page, (page) => {
|
|
150
150
|
if (
|
|
151
151
|
!page ||
|
|
152
|
-
!
|
|
153
|
-
!
|
|
154
|
-
|
|
152
|
+
!pageBarScrollContainerRef.value?.itemsContainerWidth ||
|
|
153
|
+
!pageBarItemEls.value ||
|
|
154
|
+
pageBarItemEls.value.length < 2
|
|
155
155
|
) {
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
const firstItem =
|
|
160
|
-
const lastItem =
|
|
159
|
+
const firstItem = pageBarItemEls.value[0];
|
|
160
|
+
const lastItem = pageBarItemEls.value[pageBarItemEls.value.length - 1];
|
|
161
161
|
|
|
162
162
|
if (page.id === firstItem.dataset.pageId) {
|
|
163
|
-
|
|
163
|
+
pageBarScrollContainerRef.value.scroll('start');
|
|
164
164
|
} else if (page.id === lastItem.dataset.pageId) {
|
|
165
|
-
|
|
165
|
+
pageBarScrollContainerRef.value.scroll('end');
|
|
166
166
|
} else {
|
|
167
|
-
const pageItem =
|
|
167
|
+
const pageItem = pageBarItemEls.value.find((item) => item.dataset.pageId === page.id);
|
|
168
168
|
if (!pageItem) {
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
const pageItemRect = pageItem.getBoundingClientRect();
|
|
173
173
|
const offsetLeft = pageItemRect.left - firstItem.getBoundingClientRect().left;
|
|
174
|
-
const { itemsContainerWidth } =
|
|
174
|
+
const { itemsContainerWidth } = pageBarScrollContainerRef.value;
|
|
175
175
|
|
|
176
176
|
const left = itemsContainerWidth - offsetLeft - pageItemRect.width;
|
|
177
177
|
|
|
178
|
-
const translateLeft =
|
|
178
|
+
const translateLeft = pageBarScrollContainerRef.value.getTranslateLeft();
|
|
179
179
|
if (offsetLeft + translateLeft < 0 || offsetLeft + pageItemRect.width > itemsContainerWidth - translateLeft) {
|
|
180
|
-
|
|
180
|
+
pageBarScrollContainerRef.value.scrollTo(left);
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
});
|
|
@@ -46,7 +46,7 @@ const services = inject<Services>('services');
|
|
|
46
46
|
const editorService = services?.editorService;
|
|
47
47
|
const uiService = services?.uiService;
|
|
48
48
|
|
|
49
|
-
const
|
|
49
|
+
const itemsContainerEl = useTemplateRef<HTMLElement>('itemsContainer');
|
|
50
50
|
const canScroll = ref(false);
|
|
51
51
|
|
|
52
52
|
const showAddPageButton = computed(() => uiService?.get('showAddPageButton'));
|
|
@@ -54,19 +54,21 @@ const showPageListButton = computed(() => uiService?.get('showPageListButton'));
|
|
|
54
54
|
|
|
55
55
|
const itemsContainerWidth = ref(0);
|
|
56
56
|
|
|
57
|
+
const pageBarEl = useTemplateRef<HTMLDivElement>('pageBar');
|
|
58
|
+
|
|
57
59
|
const setCanScroll = () => {
|
|
58
60
|
// 减去新增、搜索、页面列表、左移、右移5个按钮的宽度
|
|
59
61
|
// 37 = icon width 16 + padding 10 * 2 + border-right 1
|
|
60
62
|
itemsContainerWidth.value =
|
|
61
|
-
(
|
|
63
|
+
(pageBarEl.value?.clientWidth || 0) -
|
|
62
64
|
37 * 2 -
|
|
63
65
|
37 -
|
|
64
66
|
(showAddPageButton.value ? 37 : 21) -
|
|
65
67
|
(showPageListButton.value ? 37 : 0);
|
|
66
68
|
|
|
67
69
|
nextTick(() => {
|
|
68
|
-
if (
|
|
69
|
-
canScroll.value =
|
|
70
|
+
if (itemsContainerEl.value) {
|
|
71
|
+
canScroll.value = itemsContainerEl.value.scrollWidth - itemsContainerWidth.value > 1;
|
|
70
72
|
}
|
|
71
73
|
});
|
|
72
74
|
};
|
|
@@ -75,9 +77,8 @@ const resizeObserver = new ResizeObserver(() => {
|
|
|
75
77
|
setCanScroll();
|
|
76
78
|
});
|
|
77
79
|
|
|
78
|
-
const pageBar = useTemplateRef<HTMLDivElement>('pageBar');
|
|
79
80
|
onMounted(() => {
|
|
80
|
-
|
|
81
|
+
pageBarEl.value && resizeObserver.observe(pageBarEl.value);
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
onBeforeUnmount(() => {
|
|
@@ -87,9 +88,9 @@ onBeforeUnmount(() => {
|
|
|
87
88
|
let translateLeft = 0;
|
|
88
89
|
|
|
89
90
|
const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
|
|
90
|
-
if (!
|
|
91
|
+
if (!itemsContainerEl.value || !canScroll.value) return;
|
|
91
92
|
|
|
92
|
-
const maxScrollLeft =
|
|
93
|
+
const maxScrollLeft = itemsContainerEl.value.scrollWidth - itemsContainerWidth.value;
|
|
93
94
|
|
|
94
95
|
if (type === 'left') {
|
|
95
96
|
scrollTo(translateLeft + 200);
|
|
@@ -103,8 +104,8 @@ const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
|
|
|
103
104
|
};
|
|
104
105
|
|
|
105
106
|
const scrollTo = (value: number) => {
|
|
106
|
-
if (!
|
|
107
|
-
const maxScrollLeft =
|
|
107
|
+
if (!itemsContainerEl.value || !canScroll.value) return;
|
|
108
|
+
const maxScrollLeft = itemsContainerEl.value.scrollWidth - itemsContainerWidth.value;
|
|
108
109
|
|
|
109
110
|
if (value >= 0) {
|
|
110
111
|
value = 0;
|
|
@@ -116,7 +117,7 @@ const scrollTo = (value: number) => {
|
|
|
116
117
|
|
|
117
118
|
translateLeft = value;
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
itemsContainerEl.value.style.transform = `translate(${translateLeft}px, 0px)`;
|
|
120
121
|
};
|
|
121
122
|
|
|
122
123
|
watch(
|
|
@@ -88,23 +88,23 @@ const propsPanelSize = computed(() => services?.uiService.get('propsPanelSize')
|
|
|
88
88
|
const { height: editorContentHeight } = useEditorContentHeight();
|
|
89
89
|
const stage = computed(() => services?.editorService.get('stage'));
|
|
90
90
|
|
|
91
|
-
const
|
|
91
|
+
const configFormRef = useTemplateRef<InstanceType<typeof MForm>>('configForm');
|
|
92
92
|
|
|
93
93
|
watchEffect(() => {
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
if (configFormRef.value) {
|
|
95
|
+
configFormRef.value.formState.stage = stage.value;
|
|
96
|
+
configFormRef.value.formState.services = services;
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
const internalInstance = getCurrentInstance();
|
|
101
101
|
onMounted(() => {
|
|
102
|
-
emit('mounted', internalInstance);
|
|
102
|
+
emit('mounted', internalInstance?.proxy);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
const submit = async (v: FormValue, eventData: ContainerChangeEventData) => {
|
|
106
106
|
try {
|
|
107
|
-
const values = await
|
|
107
|
+
const values = await configFormRef.value?.submitForm();
|
|
108
108
|
emit('submit', values, eventData);
|
|
109
109
|
} catch (e: any) {
|
|
110
110
|
emit('submit-error', e);
|
|
@@ -119,5 +119,5 @@ const saveCode = (values: any) => {
|
|
|
119
119
|
emit('submit', props.codeValueKey ? { [props.codeValueKey]: values } : values);
|
|
120
120
|
};
|
|
121
121
|
|
|
122
|
-
defineExpose({ configForm, submit });
|
|
122
|
+
defineExpose({ configForm: configFormRef, submit });
|
|
123
123
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor-props-panel" v-show="nodes.length === 1">
|
|
2
|
+
<div ref="propsPanel" class="m-editor-props-panel" v-show="nodes.length === 1">
|
|
3
3
|
<slot name="props-panel-header"></slot>
|
|
4
4
|
<FormPanel
|
|
5
5
|
ref="propertyFormPanel"
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
@mounted="mountedHandler"
|
|
16
16
|
></FormPanel>
|
|
17
17
|
|
|
18
|
+
<Resizer v-if="showStylePanel" @change="widthChange"></Resizer>
|
|
19
|
+
|
|
18
20
|
<FormPanel
|
|
19
21
|
v-if="showStylePanel"
|
|
20
22
|
class="m-editor-props-style-panel"
|
|
@@ -53,12 +55,14 @@
|
|
|
53
55
|
<script lang="ts" setup>
|
|
54
56
|
import { computed, inject, onBeforeUnmount, ref, useTemplateRef, watchEffect } from 'vue';
|
|
55
57
|
import { Close, Sugar } from '@element-plus/icons-vue';
|
|
58
|
+
import type { OnDrag } from 'gesto';
|
|
56
59
|
|
|
57
60
|
import type { MNode } from '@tmagic/core';
|
|
58
61
|
import { TMagicButton } from '@tmagic/design';
|
|
59
62
|
import type { ContainerChangeEventData, FormState, FormValue } from '@tmagic/form';
|
|
60
63
|
|
|
61
64
|
import MIcon from '@editor/components/Icon.vue';
|
|
65
|
+
import Resizer from '@editor/components/Resizer.vue';
|
|
62
66
|
import type { PropsPanelSlots, Services } from '@editor/type';
|
|
63
67
|
import { styleTabConfig } from '@editor/utils';
|
|
64
68
|
|
|
@@ -120,7 +124,21 @@ const submit = async (v: MNode, eventData?: ContainerChangeEventData) => {
|
|
|
120
124
|
if (!v.id) {
|
|
121
125
|
v.id = values.value.id;
|
|
122
126
|
}
|
|
123
|
-
|
|
127
|
+
|
|
128
|
+
const newValue: MNode = {
|
|
129
|
+
...v,
|
|
130
|
+
style: {},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
if (v.style) {
|
|
134
|
+
Object.entries(v.style).forEach(([key, value]) => {
|
|
135
|
+
if (value !== '' && newValue.style) {
|
|
136
|
+
newValue.style[key] = value;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
services?.editorService.update(newValue, { changeRecords: eventData?.changeRecords });
|
|
124
142
|
} catch (e: any) {
|
|
125
143
|
emit('submit-error', e);
|
|
126
144
|
}
|
|
@@ -130,8 +148,22 @@ const errorHandler = (e: any) => {
|
|
|
130
148
|
emit('form-error', e);
|
|
131
149
|
};
|
|
132
150
|
|
|
133
|
-
const mountedHandler = (
|
|
134
|
-
|
|
151
|
+
const mountedHandler = () => {
|
|
152
|
+
if (propertyFormPanelRef.value) {
|
|
153
|
+
emit('mounted', propertyFormPanelRef.value);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const propsPanelEl = useTemplateRef('propsPanel');
|
|
158
|
+
const widthChange = ({ deltaX }: OnDrag) => {
|
|
159
|
+
if (!propsPanelEl.value) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const width = globalThis.parseFloat(
|
|
164
|
+
getComputedStyle(propsPanelEl.value).getPropertyValue('--props-style-panel-width'),
|
|
165
|
+
);
|
|
166
|
+
propsPanelEl.value.style.setProperty('--props-style-panel-width', `${width - deltaX}px`);
|
|
135
167
|
};
|
|
136
168
|
|
|
137
169
|
const { showStylePanel, showStylePanelHandler, closeStylePanelHandler } = useStylePanel(services);
|
|
@@ -89,10 +89,10 @@ const editable = computed(() => codeBlockService?.getEditStatus());
|
|
|
89
89
|
const { codeBlockEditor, codeConfig, editCode, deleteCode, createCodeBlock, submitCodeBlockHandler } =
|
|
90
90
|
useCodeBlockEdit(codeBlockService);
|
|
91
91
|
|
|
92
|
-
const
|
|
92
|
+
const codeBlockListRef = useTemplateRef<InstanceType<typeof CodeBlockList>>('codeBlockList');
|
|
93
93
|
|
|
94
94
|
const filterTextChangeHandler = (val: string) => {
|
|
95
|
-
|
|
95
|
+
codeBlockListRef.value?.filter(val);
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
eventBus?.on('edit-code', (id: string) => {
|
|
@@ -104,7 +104,7 @@ const {
|
|
|
104
104
|
menuData: contentMenuData,
|
|
105
105
|
contentMenuHideHandler,
|
|
106
106
|
} = useContentMenu((id: string) => {
|
|
107
|
-
|
|
107
|
+
codeBlockListRef.value?.deleteCode(id);
|
|
108
108
|
});
|
|
109
109
|
const menuData = computed<(MenuButton | MenuComponent)[]>(() => props.customContentMenu(contentMenuData, 'code-block'));
|
|
110
110
|
</script>
|
|
@@ -27,7 +27,7 @@ const emit = defineEmits<{
|
|
|
27
27
|
}>();
|
|
28
28
|
|
|
29
29
|
const services = inject<Services>('services');
|
|
30
|
-
const
|
|
30
|
+
const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
|
|
31
31
|
const node = computed(() => services?.editorService.get('node'));
|
|
32
32
|
const nodes = computed(() => services?.editorService.get('nodes'));
|
|
33
33
|
const componentList = computed(() => services?.componentListService.getList() || []);
|
|
@@ -113,7 +113,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
113
113
|
);
|
|
114
114
|
|
|
115
115
|
const show = (e: MouseEvent) => {
|
|
116
|
-
|
|
116
|
+
menuRef.value?.show(e);
|
|
117
117
|
};
|
|
118
118
|
|
|
119
119
|
defineExpose({
|
|
@@ -87,13 +87,13 @@ defineProps<{
|
|
|
87
87
|
const services = inject<Services>('services');
|
|
88
88
|
const editorService = services?.editorService;
|
|
89
89
|
|
|
90
|
-
const
|
|
90
|
+
const treeRef = useTemplateRef<InstanceType<typeof Tree>>('tree');
|
|
91
91
|
|
|
92
92
|
const page = computed(() => editorService?.get('page'));
|
|
93
93
|
const nodeData = computed<TreeNodeData[]>(() => (!page.value ? [] : [page.value]));
|
|
94
94
|
|
|
95
95
|
const { nodeStatusMap } = useNodeStatus(services);
|
|
96
|
-
const { isCtrlKeyDown } = useKeybinding(services,
|
|
96
|
+
const { isCtrlKeyDown } = useKeybinding(services, treeRef);
|
|
97
97
|
|
|
98
98
|
const filterNodeMethod = (v: string, data: MNode): boolean => {
|
|
99
99
|
let name = '';
|
|
@@ -121,10 +121,11 @@ const collapseAllHandler = () => {
|
|
|
121
121
|
|
|
122
122
|
const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useDrag(services);
|
|
123
123
|
|
|
124
|
+
// 右键菜单
|
|
125
|
+
const menuRef = useTemplateRef<InstanceType<typeof LayerMenu>>('menu');
|
|
124
126
|
const {
|
|
125
|
-
menu,
|
|
126
127
|
nodeClickHandler,
|
|
127
128
|
nodeContentMenuHandler,
|
|
128
129
|
highlightHandler: mouseenterHandler,
|
|
129
|
-
} = useClick(services, isCtrlKeyDown, nodeStatusMap);
|
|
130
|
+
} = useClick(services, isCtrlKeyDown, nodeStatusMap, menuRef);
|
|
130
131
|
</script>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, type ComputedRef, nextTick, type Ref,
|
|
1
|
+
import { computed, type ComputedRef, nextTick, type Ref, type ShallowRef } from 'vue';
|
|
2
2
|
import { throttle } from 'lodash-es';
|
|
3
3
|
|
|
4
4
|
import { Id, MNode } from '@tmagic/core';
|
|
@@ -13,6 +13,7 @@ export const useClick = (
|
|
|
13
13
|
services: Services | undefined,
|
|
14
14
|
isCtrlKeyDown: Ref<boolean>,
|
|
15
15
|
nodeStatusMap: ComputedRef<Map<Id, LayerNodeStatus> | undefined>,
|
|
16
|
+
menuRef: ShallowRef<InstanceType<typeof LayerMenu> | null>,
|
|
16
17
|
) => {
|
|
17
18
|
const isMultiSelect = computed(() => isCtrlKeyDown.value && !services?.editorService.get('disabledMultiSelect'));
|
|
18
19
|
|
|
@@ -98,11 +99,8 @@ export const useClick = (
|
|
|
98
99
|
});
|
|
99
100
|
};
|
|
100
101
|
|
|
101
|
-
// 右键菜单
|
|
102
|
-
const menu = useTemplateRef<InstanceType<typeof LayerMenu>>('menu');
|
|
103
|
-
|
|
104
102
|
return {
|
|
105
|
-
|
|
103
|
+
menuRef,
|
|
106
104
|
|
|
107
105
|
nodeClickHandler,
|
|
108
106
|
|
|
@@ -114,7 +112,7 @@ export const useClick = (
|
|
|
114
112
|
nodeClickHandler(event, data);
|
|
115
113
|
}
|
|
116
114
|
|
|
117
|
-
|
|
115
|
+
menuRef.value?.show(event);
|
|
118
116
|
},
|
|
119
117
|
|
|
120
118
|
highlightHandler,
|
|
@@ -39,8 +39,8 @@ const editorService = services?.editorService;
|
|
|
39
39
|
|
|
40
40
|
const visible = ref(false);
|
|
41
41
|
const buttonVisible = ref(false);
|
|
42
|
-
const
|
|
43
|
-
const
|
|
42
|
+
const buttonEl = useTemplateRef<HTMLDivElement>('button');
|
|
43
|
+
const boxRef = useTemplateRef<InstanceType<typeof FloatingBox>>('box');
|
|
44
44
|
|
|
45
45
|
const stage = computed(() => editorService?.get('stage'));
|
|
46
46
|
const page = computed(() => editorService?.get('page'));
|
|
@@ -99,14 +99,14 @@ const menuPosition = ref({
|
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
watch(visible, async (visible) => {
|
|
102
|
-
if (!
|
|
102
|
+
if (!buttonEl.value || !visible) {
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
await nextTick();
|
|
107
107
|
|
|
108
|
-
const rect =
|
|
109
|
-
const height =
|
|
108
|
+
const rect = buttonEl.value.getBoundingClientRect();
|
|
109
|
+
const height = boxRef.value?.target?.clientHeight || 0;
|
|
110
110
|
|
|
111
111
|
menuPosition.value = {
|
|
112
112
|
left: rect.left + rect.width + 5,
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
width: 60,
|
|
15
15
|
height: 50,
|
|
16
16
|
}"
|
|
17
|
-
@click="
|
|
17
|
+
@click="stageWrapRef?.container?.focus()"
|
|
18
18
|
>
|
|
19
19
|
<div
|
|
20
20
|
class="m-editor-stage-container"
|
|
@@ -95,9 +95,9 @@ const services = inject<Services>('services');
|
|
|
95
95
|
|
|
96
96
|
const stageLoading = computed(() => services?.editorService.get('stageLoading') || false);
|
|
97
97
|
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const
|
|
98
|
+
const stageWrapRef = useTemplateRef<InstanceType<typeof ScrollViewer>>('stageWrap');
|
|
99
|
+
const stageContainerEl = useTemplateRef<HTMLDivElement>('stageContainer');
|
|
100
|
+
const menuRef = useTemplateRef<InstanceType<typeof ViewerMenu>>('menu');
|
|
101
101
|
|
|
102
102
|
const nodes = computed(() => services?.editorService.get('nodes') || []);
|
|
103
103
|
const isMultiSelect = computed(() => nodes.value.length > 1);
|
|
@@ -111,18 +111,18 @@ const node = computed(() => services?.editorService.get('node'));
|
|
|
111
111
|
watchEffect(() => {
|
|
112
112
|
if (stage || !page.value) return;
|
|
113
113
|
|
|
114
|
-
if (!
|
|
114
|
+
if (!stageContainerEl.value) return;
|
|
115
115
|
if (!(props.stageOptions?.runtimeUrl || props.stageOptions?.render) || !root.value) return;
|
|
116
116
|
|
|
117
117
|
stage = useStage(props.stageOptions);
|
|
118
118
|
|
|
119
119
|
stage.on('select', () => {
|
|
120
|
-
|
|
120
|
+
stageWrapRef.value?.container?.focus();
|
|
121
121
|
});
|
|
122
122
|
|
|
123
123
|
services?.editorService.set('stage', markRaw(stage));
|
|
124
124
|
|
|
125
|
-
stage.mount(
|
|
125
|
+
stage.mount(stageContainerEl.value);
|
|
126
126
|
|
|
127
127
|
if (!node.value?.id) {
|
|
128
128
|
return;
|
|
@@ -188,9 +188,9 @@ const resizeObserver = new ResizeObserver((entries) => {
|
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
onMounted(() => {
|
|
191
|
-
if (
|
|
192
|
-
resizeObserver.observe(
|
|
193
|
-
services?.keybindingService.registerEl(KeyBindingContainerKey.STAGE,
|
|
191
|
+
if (stageWrapRef.value?.container) {
|
|
192
|
+
resizeObserver.observe(stageWrapRef.value.container);
|
|
193
|
+
services?.keybindingService.registerEl(KeyBindingContainerKey.STAGE, stageWrapRef.value.container);
|
|
194
194
|
}
|
|
195
195
|
});
|
|
196
196
|
|
|
@@ -206,7 +206,7 @@ const parseDSL = getEditorConfig('parseDSL');
|
|
|
206
206
|
|
|
207
207
|
const contextmenuHandler = (e: MouseEvent) => {
|
|
208
208
|
e.preventDefault();
|
|
209
|
-
|
|
209
|
+
menuRef.value?.show(e);
|
|
210
210
|
};
|
|
211
211
|
|
|
212
212
|
const dragoverHandler = (e: DragEvent) => {
|
|
@@ -239,10 +239,10 @@ const dropHandler = async (e: DragEvent) => {
|
|
|
239
239
|
parent = services?.editorService.getNodeById(parentId, false) as MContainer;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
if (parent &&
|
|
242
|
+
if (parent && stageContainerEl.value && stage) {
|
|
243
243
|
const layout = await services?.editorService.getLayout(parent);
|
|
244
244
|
|
|
245
|
-
const containerRect =
|
|
245
|
+
const containerRect = stageContainerEl.value.getBoundingClientRect();
|
|
246
246
|
const { scrollTop, scrollLeft } = stage.mask!;
|
|
247
247
|
const { style = {} } = config.data;
|
|
248
248
|
|
|
@@ -19,7 +19,7 @@ const services = inject<Services>('services');
|
|
|
19
19
|
|
|
20
20
|
const stageOptions = inject<StageOptions>('stageOptions');
|
|
21
21
|
|
|
22
|
-
const
|
|
22
|
+
const stageOverlayEl = useTemplateRef<HTMLDivElement>('stageOverlay');
|
|
23
23
|
|
|
24
24
|
const stageOverlayVisible = computed(() => services?.stageOverlayService.get('stageOverlayVisible'));
|
|
25
25
|
const wrapWidth = computed(() => services?.stageOverlayService.get('wrapWidth') || 0);
|
|
@@ -42,7 +42,7 @@ watch(stage, (stage) => {
|
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
watch(
|
|
45
|
+
watch(stageOverlayEl, (stageOverlay) => {
|
|
46
46
|
if (!services) return;
|
|
47
47
|
|
|
48
48
|
const subStage = services.stageOverlayService.createStage(stageOptions);
|
|
@@ -31,7 +31,7 @@ const props = withDefaults(
|
|
|
31
31
|
|
|
32
32
|
const services = inject<Services>('services');
|
|
33
33
|
const editorService = services?.editorService;
|
|
34
|
-
const
|
|
34
|
+
const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
|
|
35
35
|
const canCenter = ref(false);
|
|
36
36
|
|
|
37
37
|
const node = computed(() => editorService?.get('node'));
|
|
@@ -52,7 +52,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
52
52
|
},
|
|
53
53
|
},
|
|
54
54
|
useCopyMenu(),
|
|
55
|
-
usePasteMenu(
|
|
55
|
+
usePasteMenu(menuRef),
|
|
56
56
|
{
|
|
57
57
|
type: 'divider',
|
|
58
58
|
direction: 'horizontal',
|
|
@@ -136,7 +136,7 @@ watch(
|
|
|
136
136
|
);
|
|
137
137
|
|
|
138
138
|
const show = (e: MouseEvent) => {
|
|
139
|
-
|
|
139
|
+
menuRef.value?.show(e);
|
|
140
140
|
};
|
|
141
141
|
|
|
142
142
|
defineExpose({ show });
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { shallowReactive } from 'vue';
|
|
20
20
|
|
|
21
21
|
import type { ComponentGroup, ComponentGroupState } from '@editor/type';
|
|
22
22
|
|
|
23
23
|
import BaseService from './BaseService';
|
|
24
24
|
|
|
25
25
|
class ComponentList extends BaseService {
|
|
26
|
-
private state =
|
|
26
|
+
private state = shallowReactive<ComponentGroupState>({
|
|
27
27
|
list: [],
|
|
28
28
|
});
|
|
29
29
|
|
package/src/services/dep.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
import { reactive } from 'vue';
|
|
18
|
+
import { reactive, shallowReactive } from 'vue';
|
|
19
19
|
|
|
20
20
|
import type { DepExtendedData, Id, MNode, Target, TargetNode } from '@tmagic/core';
|
|
21
21
|
import { DepTargetType, Watcher } from '@tmagic/core';
|
|
@@ -29,6 +29,7 @@ export interface DepEvents {
|
|
|
29
29
|
'add-target': [target: Target];
|
|
30
30
|
'remove-target': [id: string | number];
|
|
31
31
|
collected: [nodes: MNode[], deep: boolean];
|
|
32
|
+
'ds-collected': [nodes: MNode[], deep: boolean];
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
interface State {
|
|
@@ -40,7 +41,7 @@ type StateKey = keyof State;
|
|
|
40
41
|
const idleTask = new IdleTask<{ node: TargetNode; deep: boolean; target: Target }>();
|
|
41
42
|
|
|
42
43
|
class Dep extends BaseService {
|
|
43
|
-
private state =
|
|
44
|
+
private state = shallowReactive<State>({
|
|
44
45
|
collecting: false,
|
|
45
46
|
});
|
|
46
47
|
|
|
@@ -96,6 +97,7 @@ class Dep extends BaseService {
|
|
|
96
97
|
this.set('collecting', false);
|
|
97
98
|
|
|
98
99
|
this.emit('collected', nodes, deep);
|
|
100
|
+
this.emit('ds-collected', nodes, deep);
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
public collectIdle(nodes: MNode[], depExtendedData: DepExtendedData = {}, deep = false, type?: DepTargetType) {
|
|
@@ -119,6 +121,9 @@ class Dep extends BaseService {
|
|
|
119
121
|
this.set('collecting', false);
|
|
120
122
|
resolve();
|
|
121
123
|
});
|
|
124
|
+
idleTask.once('hight-level-finish', () => {
|
|
125
|
+
this.emit('ds-collected', nodes, deep);
|
|
126
|
+
});
|
|
122
127
|
});
|
|
123
128
|
}
|
|
124
129
|
|
|
@@ -185,6 +190,7 @@ class Dep extends BaseService {
|
|
|
185
190
|
deep: false,
|
|
186
191
|
target,
|
|
187
192
|
},
|
|
193
|
+
target.type === DepTargetType.DATA_SOURCE,
|
|
188
194
|
);
|
|
189
195
|
|
|
190
196
|
if (deep && Array.isArray(node.items) && node.items.length) {
|
package/src/services/editor.ts
CHANGED
|
@@ -527,8 +527,8 @@ class Editor extends BaseService {
|
|
|
527
527
|
|
|
528
528
|
let newConfig = await this.toggleFixedPosition(toRaw(config), node, root);
|
|
529
529
|
|
|
530
|
-
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue, key) => {
|
|
531
|
-
if (typeof srcValue === 'undefined' && Object.hasOwn(
|
|
530
|
+
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue, key, object: any, source: any) => {
|
|
531
|
+
if (typeof srcValue === 'undefined' && Object.hasOwn(source, key)) {
|
|
532
532
|
return '';
|
|
533
533
|
}
|
|
534
534
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { shallowReactive } from 'vue';
|
|
2
2
|
import type { Writable } from 'type-fest';
|
|
3
3
|
|
|
4
4
|
import StageCore from '@tmagic/stage';
|
|
@@ -17,7 +17,7 @@ const canUsePluginMethods = {
|
|
|
17
17
|
type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
|
|
18
18
|
|
|
19
19
|
class StageOverlay extends BaseService {
|
|
20
|
-
private state: StageOverlayState =
|
|
20
|
+
private state: StageOverlayState = shallowReactive({
|
|
21
21
|
wrapDiv: document.createElement('div'),
|
|
22
22
|
sourceEl: null,
|
|
23
23
|
contentEl: null,
|
package/src/services/ui.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { shallowReactive } from 'vue';
|
|
20
20
|
import type { Writable } from 'type-fest';
|
|
21
21
|
|
|
22
22
|
import { convertToNumber } from '@tmagic/utils';
|
|
@@ -26,7 +26,7 @@ import type { AsyncHookPlugin, StageRect, UiState } from '@editor/type';
|
|
|
26
26
|
|
|
27
27
|
import BaseService from './BaseService';
|
|
28
28
|
|
|
29
|
-
const state =
|
|
29
|
+
const state = shallowReactive<UiState>({
|
|
30
30
|
uiSelectMode: false,
|
|
31
31
|
showSrc: false,
|
|
32
32
|
showStylePanel: true,
|
|
@@ -72,6 +72,11 @@
|
|
|
72
72
|
align-items: center;
|
|
73
73
|
border-bottom: 2px solid $border-color;
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
.tmagic-design-form {
|
|
77
|
+
padding-right: 10px;
|
|
78
|
+
padding-left: 10px;
|
|
79
|
+
}
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
.m-editor-props-panel-src-icon {
|
|
@@ -95,6 +100,14 @@
|
|
|
95
100
|
z-index: 10;
|
|
96
101
|
}
|
|
97
102
|
|
|
103
|
+
.m-editor-resizer {
|
|
104
|
+
position: absolute;
|
|
105
|
+
display: block;
|
|
106
|
+
top: 0;
|
|
107
|
+
right: var(--props-style-panel-width);
|
|
108
|
+
z-index: 13;
|
|
109
|
+
}
|
|
110
|
+
|
|
98
111
|
&.small {
|
|
99
112
|
.el-form-item__label {
|
|
100
113
|
font-size: 12px;
|
package/src/theme/resizer.scss
CHANGED