@tmagic/editor 1.5.7 → 1.5.8
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 +17 -0
- package/dist/tmagic-editor.js +463 -470
- package/dist/tmagic-editor.umd.cjs +471 -469
- package/package.json +7 -7
- package/src/components/CodeBlockEditor.vue +4 -4
- package/src/components/FloatingBox.vue +4 -4
- package/src/components/ToolButton.vue +6 -4
- package/src/components/TreeNode.vue +2 -2
- package/src/fields/CodeSelect.vue +6 -6
- package/src/fields/CodeSelectCol.vue +5 -4
- package/src/fields/CondOpSelect.vue +5 -4
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +6 -5
- package/src/fields/DataSourceFieldSelect/Index.vue +4 -3
- package/src/fields/DataSourceFields.vue +3 -3
- package/src/fields/DataSourceInput.vue +4 -4
- package/src/fields/DataSourceMethodSelect.vue +8 -9
- package/src/fields/DataSourceMocks.vue +3 -3
- package/src/fields/DataSourceSelect.vue +6 -5
- package/src/fields/DisplayConds.vue +4 -4
- package/src/fields/EventSelect.vue +17 -23
- package/src/fields/PageFragmentSelect.vue +6 -5
- package/src/fields/UISelect.vue +16 -19
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-code-block-edit.ts +5 -10
- package/src/hooks/use-data-source-edit.ts +6 -6
- package/src/hooks/use-editor-content-height.ts +5 -5
- package/src/hooks/use-float-box.ts +5 -5
- package/src/hooks/use-next-float-box-position.ts +9 -9
- package/src/hooks/use-services.ts +13 -0
- package/src/hooks/use-stage.ts +2 -6
- package/src/layouts/AddPageBox.vue +3 -7
- package/src/layouts/Framework.vue +27 -27
- package/src/layouts/NavMenu.vue +16 -16
- package/src/layouts/page-bar/AddButton.vue +4 -7
- package/src/layouts/page-bar/PageBar.vue +10 -10
- package/src/layouts/page-bar/PageBarScrollContainer.vue +7 -8
- package/src/layouts/page-bar/PageList.vue +6 -8
- package/src/layouts/props-panel/FormPanel.vue +6 -4
- package/src/layouts/props-panel/PropsPanel.vue +39 -49
- package/src/layouts/props-panel/use-style-panel.ts +35 -19
- package/src/layouts/sidebar/ComponentListPanel.vue +5 -5
- package/src/layouts/sidebar/Sidebar.vue +15 -9
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +13 -18
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +4 -3
- package/src/layouts/sidebar/code-block/useContentMenu.ts +3 -3
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +5 -5
- package/src/layouts/sidebar/data-source/DataSourceList.vue +13 -17
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +6 -12
- package/src/layouts/sidebar/data-source/useContentMenu.ts +3 -3
- package/src/layouts/sidebar/layer/LayerMenu.vue +11 -8
- package/src/layouts/sidebar/layer/LayerNodeTool.vue +2 -6
- package/src/layouts/sidebar/layer/LayerPanel.vue +6 -12
- package/src/layouts/sidebar/layer/use-click.ts +16 -15
- package/src/layouts/sidebar/layer/use-drag.ts +6 -6
- package/src/layouts/sidebar/layer/use-keybinding.ts +6 -8
- package/src/layouts/sidebar/layer/use-node-status.ts +16 -7
- package/src/layouts/workspace/Breadcrumb.vue +8 -9
- package/src/layouts/workspace/Workspace.vue +4 -10
- package/src/layouts/workspace/viewer/NodeListMenu.vue +9 -8
- package/src/layouts/workspace/viewer/Stage.vue +24 -24
- package/src/layouts/workspace/viewer/StageOverlay.vue +15 -16
- package/src/layouts/workspace/viewer/ViewerMenu.vue +15 -14
- package/src/services/dep.ts +23 -8
- package/src/services/ui.ts +6 -2
- package/src/theme/common/var.scss +1 -0
- package/src/theme/sidebar.scss +20 -1
- package/src/type.ts +3 -9
- package/src/utils/const.ts +11 -0
- package/src/utils/content-menu.ts +28 -30
- package/src/utils/idle-task.ts +11 -0
- package/src/utils/index.ts +1 -0
- package/types/index.d.ts +28 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, ref, watch } from 'vue';
|
|
1
|
+
import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
|
2
2
|
|
|
3
3
|
import type { Id, MNode, MPage, MPageFragment } from '@tmagic/core';
|
|
4
4
|
import { getNodePath, isPage, isPageFragment, traverseNode } from '@tmagic/utils';
|
|
@@ -33,9 +33,9 @@ const createPageNodeStatus = (page: MPage | MPageFragment, initialLayerNodeStatu
|
|
|
33
33
|
return map;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
export const useNodeStatus = (
|
|
37
|
-
const page = computed(() =>
|
|
38
|
-
const nodes = computed(() =>
|
|
36
|
+
export const useNodeStatus = ({ editorService }: Services) => {
|
|
37
|
+
const page = computed(() => editorService.get('page'));
|
|
38
|
+
const nodes = computed(() => editorService.get('nodes'));
|
|
39
39
|
|
|
40
40
|
/** 所有页面的节点状态 */
|
|
41
41
|
const nodeStatusMaps = ref(new Map<Id, Map<Id, LayerNodeStatus>>());
|
|
@@ -83,7 +83,7 @@ export const useNodeStatus = (services: Services | undefined) => {
|
|
|
83
83
|
},
|
|
84
84
|
);
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
const addHandler = (newNodes: MNode[]) => {
|
|
87
87
|
newNodes.forEach((node) => {
|
|
88
88
|
if (isPage(node) || isPageFragment(node)) return;
|
|
89
89
|
|
|
@@ -96,14 +96,23 @@ export const useNodeStatus = (services: Services | undefined) => {
|
|
|
96
96
|
});
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
|
-
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
editorService.on('add', addHandler);
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
const removeHandler = (nodes: MNode[]) => {
|
|
102
104
|
nodes.forEach((node) => {
|
|
103
105
|
traverseNode(node, (node: MNode) => {
|
|
104
106
|
nodeStatusMap.value?.delete(node.id);
|
|
105
107
|
});
|
|
106
108
|
});
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
editorService.on('remove', removeHandler);
|
|
112
|
+
|
|
113
|
+
onBeforeUnmount(() => {
|
|
114
|
+
editorService.off('remove', removeHandler);
|
|
115
|
+
editorService.off('add', addHandler);
|
|
107
116
|
});
|
|
108
117
|
|
|
109
118
|
return {
|
|
@@ -8,28 +8,27 @@
|
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script setup lang="ts">
|
|
11
|
-
import { computed
|
|
11
|
+
import { computed } from 'vue';
|
|
12
12
|
|
|
13
13
|
import type { MNode } from '@tmagic/core';
|
|
14
14
|
import { TMagicButton } from '@tmagic/design';
|
|
15
15
|
import { getNodePath } from '@tmagic/utils';
|
|
16
16
|
|
|
17
|
-
import
|
|
17
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
18
18
|
|
|
19
19
|
defineOptions({
|
|
20
20
|
name: 'MEditorBreadcrumb',
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
const
|
|
24
|
-
const editorService = services?.editorService;
|
|
23
|
+
const { editorService } = useServices();
|
|
25
24
|
|
|
26
|
-
const node = computed(() => editorService
|
|
27
|
-
const nodes = computed(() => editorService
|
|
28
|
-
const root = computed(() => editorService
|
|
25
|
+
const node = computed(() => editorService.get('node'));
|
|
26
|
+
const nodes = computed(() => editorService.get('nodes'));
|
|
27
|
+
const root = computed(() => editorService.get('root'));
|
|
29
28
|
const path = computed(() => getNodePath(node.value?.id || '', root.value?.items || []));
|
|
30
29
|
|
|
31
30
|
const select = async (node: MNode) => {
|
|
32
|
-
await editorService
|
|
33
|
-
editorService
|
|
31
|
+
await editorService.select(node);
|
|
32
|
+
editorService.get('stage')?.select(node.id);
|
|
34
33
|
};
|
|
35
34
|
</script>
|
|
@@ -19,14 +19,8 @@
|
|
|
19
19
|
<script lang="ts" setup>
|
|
20
20
|
import { computed, inject } from 'vue';
|
|
21
21
|
|
|
22
|
-
import
|
|
23
|
-
|
|
24
|
-
MenuButton,
|
|
25
|
-
MenuComponent,
|
|
26
|
-
Services,
|
|
27
|
-
StageOptions,
|
|
28
|
-
WorkspaceSlots,
|
|
29
|
-
} from '@editor/type';
|
|
22
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
23
|
+
import type { CustomContentMenuFunction, MenuButton, MenuComponent, StageOptions, WorkspaceSlots } from '@editor/type';
|
|
30
24
|
|
|
31
25
|
import MagicStage from './viewer/Stage.vue';
|
|
32
26
|
import Breadcrumb from './Breadcrumb.vue';
|
|
@@ -50,7 +44,7 @@ withDefaults(
|
|
|
50
44
|
|
|
51
45
|
const stageOptions = inject<StageOptions>('stageOptions');
|
|
52
46
|
|
|
53
|
-
const
|
|
47
|
+
const { editorService } = useServices();
|
|
54
48
|
|
|
55
|
-
const page = computed(() =>
|
|
49
|
+
const page = computed(() => editorService.get('page'));
|
|
56
50
|
</script>
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
</template>
|
|
23
23
|
|
|
24
24
|
<script lang="ts" setup>
|
|
25
|
-
import { computed,
|
|
25
|
+
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue';
|
|
26
26
|
|
|
27
27
|
import type { MNode } from '@tmagic/core';
|
|
28
28
|
import { TMagicTooltip } from '@tmagic/design';
|
|
@@ -31,20 +31,21 @@ import { getIdFromEl } from '@tmagic/utils';
|
|
|
31
31
|
import FloatingBox from '@editor/components/FloatingBox.vue';
|
|
32
32
|
import Tree from '@editor/components/Tree.vue';
|
|
33
33
|
import { useFilter } from '@editor/hooks/use-filter';
|
|
34
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
34
35
|
import { useNodeStatus } from '@editor/layouts/sidebar/layer/use-node-status';
|
|
35
|
-
import type {
|
|
36
|
+
import type { TreeNodeData } from '@editor/type';
|
|
36
37
|
|
|
37
|
-
const services =
|
|
38
|
-
const editorService = services
|
|
38
|
+
const services = useServices();
|
|
39
|
+
const { editorService } = services;
|
|
39
40
|
|
|
40
41
|
const visible = ref(false);
|
|
41
42
|
const buttonVisible = ref(false);
|
|
42
43
|
const buttonEl = useTemplateRef<HTMLDivElement>('button');
|
|
43
44
|
const boxRef = useTemplateRef<InstanceType<typeof FloatingBox>>('box');
|
|
44
45
|
|
|
45
|
-
const stage = computed(() => editorService
|
|
46
|
-
const page = computed(() => editorService
|
|
47
|
-
const nodes = computed(() => editorService
|
|
46
|
+
const stage = computed(() => editorService.get('stage'));
|
|
47
|
+
const page = computed(() => editorService.get('page'));
|
|
48
|
+
const nodes = computed(() => editorService.get('nodes'));
|
|
48
49
|
const nodeData = computed<TreeNodeData[]>(() => (!page.value ? [] : [page.value]));
|
|
49
50
|
|
|
50
51
|
const { nodeStatusMap } = useNodeStatus(services);
|
|
@@ -89,7 +90,7 @@ watch(
|
|
|
89
90
|
);
|
|
90
91
|
|
|
91
92
|
const clickHandler = async (event: MouseEvent, data: TreeNodeData) => {
|
|
92
|
-
await editorService
|
|
93
|
+
await editorService.select(data.id);
|
|
93
94
|
stage.value?.select(data.id);
|
|
94
95
|
};
|
|
95
96
|
|
|
@@ -45,7 +45,6 @@
|
|
|
45
45
|
<script lang="ts" setup>
|
|
46
46
|
import {
|
|
47
47
|
computed,
|
|
48
|
-
inject,
|
|
49
48
|
markRaw,
|
|
50
49
|
nextTick,
|
|
51
50
|
onBeforeUnmount,
|
|
@@ -62,8 +61,9 @@ import StageCore, { getOffset, Runtime } from '@tmagic/stage';
|
|
|
62
61
|
import { calcValueByFontsize, getIdFromEl } from '@tmagic/utils';
|
|
63
62
|
|
|
64
63
|
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
|
64
|
+
import { useServices } from '@editor/hooks';
|
|
65
65
|
import { useStage } from '@editor/hooks/use-stage';
|
|
66
|
-
import type { CustomContentMenuFunction, MenuButton, MenuComponent,
|
|
66
|
+
import type { CustomContentMenuFunction, MenuButton, MenuComponent, StageOptions } from '@editor/type';
|
|
67
67
|
import { DragType, Layout } from '@editor/type';
|
|
68
68
|
import { getEditorConfig } from '@editor/utils/config';
|
|
69
69
|
import { KeyBindingContainerKey } from '@editor/utils/keybinding-config';
|
|
@@ -91,22 +91,22 @@ const props = withDefaults(
|
|
|
91
91
|
let stage: StageCore | null = null;
|
|
92
92
|
let runtime: Runtime | null = null;
|
|
93
93
|
|
|
94
|
-
const
|
|
94
|
+
const { editorService, uiService, keybindingService } = useServices();
|
|
95
95
|
|
|
96
|
-
const stageLoading = computed(() =>
|
|
96
|
+
const stageLoading = computed(() => editorService.get('stageLoading'));
|
|
97
97
|
|
|
98
98
|
const stageWrapRef = useTemplateRef<InstanceType<typeof ScrollViewer>>('stageWrap');
|
|
99
99
|
const stageContainerEl = useTemplateRef<HTMLDivElement>('stageContainer');
|
|
100
100
|
const menuRef = useTemplateRef<InstanceType<typeof ViewerMenu>>('menu');
|
|
101
101
|
|
|
102
|
-
const nodes = computed(() =>
|
|
102
|
+
const nodes = computed(() => editorService.get('nodes'));
|
|
103
103
|
const isMultiSelect = computed(() => nodes.value.length > 1);
|
|
104
|
-
const stageRect = computed(() =>
|
|
105
|
-
const stageContainerRect = computed(() =>
|
|
106
|
-
const root = computed(() =>
|
|
107
|
-
const page = computed(() =>
|
|
108
|
-
const zoom = computed(() =>
|
|
109
|
-
const node = computed(() =>
|
|
104
|
+
const stageRect = computed(() => uiService.get('stageRect'));
|
|
105
|
+
const stageContainerRect = computed(() => uiService.get('stageContainerRect'));
|
|
106
|
+
const root = computed(() => editorService.get('root'));
|
|
107
|
+
const page = computed(() => editorService.get('page'));
|
|
108
|
+
const zoom = computed(() => uiService.get('zoom'));
|
|
109
|
+
const node = computed(() => editorService.get('node'));
|
|
110
110
|
|
|
111
111
|
watchEffect(() => {
|
|
112
112
|
if (stage || !page.value) return;
|
|
@@ -120,7 +120,7 @@ watchEffect(() => {
|
|
|
120
120
|
stageWrapRef.value?.container?.focus();
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
editorService.set('stage', markRaw(stage));
|
|
124
124
|
|
|
125
125
|
stage.mount(stageContainerEl.value);
|
|
126
126
|
|
|
@@ -141,7 +141,7 @@ watchEffect(() => {
|
|
|
141
141
|
|
|
142
142
|
onBeforeUnmount(() => {
|
|
143
143
|
stage?.destroy();
|
|
144
|
-
|
|
144
|
+
editorService.set('stage', null);
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
watch(zoom, (zoom) => {
|
|
@@ -152,14 +152,14 @@ watch(zoom, (zoom) => {
|
|
|
152
152
|
let timeoutId: NodeJS.Timeout | null = null;
|
|
153
153
|
watch(page, (page) => {
|
|
154
154
|
if (runtime && page) {
|
|
155
|
-
|
|
155
|
+
editorService.set('stageLoading', true);
|
|
156
156
|
|
|
157
157
|
if (timeoutId) {
|
|
158
158
|
globalThis.clearTimeout(timeoutId);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
timeoutId = globalThis.setTimeout(() => {
|
|
162
|
-
|
|
162
|
+
editorService.set('stageLoading', false);
|
|
163
163
|
timeoutId = null;
|
|
164
164
|
}, 3000);
|
|
165
165
|
|
|
@@ -176,11 +176,11 @@ const rootChangeHandler = (root: MApp) => {
|
|
|
176
176
|
}
|
|
177
177
|
};
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
editorService.on('root-change', rootChangeHandler);
|
|
180
180
|
|
|
181
181
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
182
182
|
for (const { contentRect } of entries) {
|
|
183
|
-
|
|
183
|
+
uiService.set('stageContainerRect', {
|
|
184
184
|
width: contentRect.width,
|
|
185
185
|
height: contentRect.height,
|
|
186
186
|
});
|
|
@@ -190,16 +190,16 @@ const resizeObserver = new ResizeObserver((entries) => {
|
|
|
190
190
|
onMounted(() => {
|
|
191
191
|
if (stageWrapRef.value?.container) {
|
|
192
192
|
resizeObserver.observe(stageWrapRef.value.container);
|
|
193
|
-
|
|
193
|
+
keybindingService.registerEl(KeyBindingContainerKey.STAGE, stageWrapRef.value.container);
|
|
194
194
|
}
|
|
195
195
|
});
|
|
196
196
|
|
|
197
197
|
onBeforeUnmount(() => {
|
|
198
198
|
stage?.destroy();
|
|
199
199
|
resizeObserver.disconnect();
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
200
|
+
editorService.set('stage', null);
|
|
201
|
+
keybindingService.unregisterEl('stage');
|
|
202
|
+
editorService.off('root-change', rootChangeHandler);
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
const parseDSL = getEditorConfig('parseDSL');
|
|
@@ -236,11 +236,11 @@ const dropHandler = async (e: DragEvent) => {
|
|
|
236
236
|
let parent: MContainer | undefined | null = page.value;
|
|
237
237
|
const parentId = getIdFromEl()(parentEl);
|
|
238
238
|
if (parentId) {
|
|
239
|
-
parent =
|
|
239
|
+
parent = editorService.getNodeById(parentId, false) as MContainer;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
if (parent && stageContainerEl.value && stage) {
|
|
243
|
-
const layout = await
|
|
243
|
+
const layout = await editorService.getLayout(parent);
|
|
244
244
|
|
|
245
245
|
const containerRect = stageContainerEl.value.getBoundingClientRect();
|
|
246
246
|
const { scrollTop, scrollLeft } = stage.mask!;
|
|
@@ -275,7 +275,7 @@ const dropHandler = async (e: DragEvent) => {
|
|
|
275
275
|
|
|
276
276
|
config.data.inputEvent = e;
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
editorService.add(config.data, parent);
|
|
279
279
|
}
|
|
280
280
|
};
|
|
281
281
|
</script>
|
|
@@ -13,18 +13,19 @@ import { CloseBold } from '@element-plus/icons-vue';
|
|
|
13
13
|
|
|
14
14
|
import { TMagicIcon } from '@tmagic/design';
|
|
15
15
|
|
|
16
|
-
import
|
|
16
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
17
|
+
import type { StageOptions } from '@editor/type';
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const { stageOverlayService, editorService } = useServices();
|
|
19
20
|
|
|
20
21
|
const stageOptions = inject<StageOptions>('stageOptions');
|
|
21
22
|
|
|
22
23
|
const stageOverlayEl = useTemplateRef<HTMLDivElement>('stageOverlay');
|
|
23
24
|
|
|
24
|
-
const stageOverlayVisible = computed(() =>
|
|
25
|
-
const wrapWidth = computed(() =>
|
|
26
|
-
const wrapHeight = computed(() =>
|
|
27
|
-
const stage = computed(() =>
|
|
25
|
+
const stageOverlayVisible = computed(() => stageOverlayService.get('stageOverlayVisible'));
|
|
26
|
+
const wrapWidth = computed(() => stageOverlayService.get('wrapWidth'));
|
|
27
|
+
const wrapHeight = computed(() => stageOverlayService.get('wrapHeight'));
|
|
28
|
+
const stage = computed(() => editorService.get('stage'));
|
|
28
29
|
|
|
29
30
|
const style = computed(() => ({
|
|
30
31
|
width: `${wrapWidth.value}px`,
|
|
@@ -35,18 +36,16 @@ watch(stage, (stage) => {
|
|
|
35
36
|
if (stage) {
|
|
36
37
|
stage.on('dblclick', async (event: MouseEvent) => {
|
|
37
38
|
const el = (await stage.actionManager?.getElementFromPoint(event)) || null;
|
|
38
|
-
|
|
39
|
+
stageOverlayService.openOverlay(el);
|
|
39
40
|
});
|
|
40
41
|
} else {
|
|
41
|
-
|
|
42
|
+
stageOverlayService.closeOverlay();
|
|
42
43
|
}
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
watch(stageOverlayEl, (stageOverlay) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const subStage = services.stageOverlayService.createStage(stageOptions);
|
|
49
|
-
services?.stageOverlayService.set('stage', subStage);
|
|
47
|
+
const subStage = stageOverlayService.createStage(stageOptions);
|
|
48
|
+
stageOverlayService.set('stage', subStage);
|
|
50
49
|
|
|
51
50
|
if (stageOverlay && subStage) {
|
|
52
51
|
subStage.mount(stageOverlay);
|
|
@@ -56,18 +55,18 @@ watch(stageOverlayEl, (stageOverlay) => {
|
|
|
56
55
|
const { contentWindow } = renderer!;
|
|
57
56
|
mask?.showRule(false);
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
stageOverlayService.updateOverlay();
|
|
60
59
|
|
|
61
60
|
contentWindow?.magic.onRuntimeReady({});
|
|
62
61
|
}
|
|
63
62
|
});
|
|
64
63
|
|
|
65
64
|
onBeforeUnmount(() => {
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
stageOverlayService.get('stage')?.destroy();
|
|
66
|
+
stageOverlayService.set('stage', null);
|
|
68
67
|
});
|
|
69
68
|
|
|
70
69
|
const closeOverlayHandler = () => {
|
|
71
|
-
|
|
70
|
+
stageOverlayService.closeOverlay();
|
|
72
71
|
};
|
|
73
72
|
</script>
|
|
@@ -3,15 +3,16 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script lang="ts" setup>
|
|
6
|
-
import { computed,
|
|
6
|
+
import { computed, markRaw, ref, useTemplateRef, watch } from 'vue';
|
|
7
7
|
import { Bottom, Top } from '@element-plus/icons-vue';
|
|
8
8
|
|
|
9
9
|
import { NodeType } from '@tmagic/core';
|
|
10
10
|
import { isPage, isPageFragment } from '@tmagic/utils';
|
|
11
11
|
|
|
12
12
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
13
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
13
14
|
import CenterIcon from '@editor/icons/CenterIcon.vue';
|
|
14
|
-
import { CustomContentMenuFunction, LayerOffset, Layout, MenuButton, MenuComponent
|
|
15
|
+
import { CustomContentMenuFunction, LayerOffset, Layout, MenuButton, MenuComponent } from '@editor/type';
|
|
15
16
|
import { useCopyMenu, useDeleteMenu, useMoveToMenu, usePasteMenu } from '@editor/utils/content-menu';
|
|
16
17
|
|
|
17
18
|
defineOptions({
|
|
@@ -29,14 +30,14 @@ const props = withDefaults(
|
|
|
29
30
|
},
|
|
30
31
|
);
|
|
31
32
|
|
|
32
|
-
const services =
|
|
33
|
-
const editorService = services
|
|
33
|
+
const services = useServices();
|
|
34
|
+
const { editorService } = services;
|
|
34
35
|
const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
|
|
35
36
|
const canCenter = ref(false);
|
|
36
37
|
|
|
37
|
-
const node = computed(() => editorService
|
|
38
|
-
const nodes = computed(() => editorService
|
|
39
|
-
const parent = computed(() => editorService
|
|
38
|
+
const node = computed(() => editorService.get('node'));
|
|
39
|
+
const nodes = computed(() => editorService.get('nodes'));
|
|
40
|
+
const parent = computed(() => editorService.get('parent'));
|
|
40
41
|
|
|
41
42
|
const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
42
43
|
props.customContentMenu(
|
|
@@ -48,7 +49,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
48
49
|
display: () => canCenter.value,
|
|
49
50
|
handler: () => {
|
|
50
51
|
if (!nodes.value) return;
|
|
51
|
-
editorService
|
|
52
|
+
editorService.alignCenter(nodes.value);
|
|
52
53
|
},
|
|
53
54
|
},
|
|
54
55
|
useCopyMenu(),
|
|
@@ -67,7 +68,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
67
68
|
icon: markRaw(Top),
|
|
68
69
|
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
69
70
|
handler: () => {
|
|
70
|
-
editorService
|
|
71
|
+
editorService.moveLayer(1);
|
|
71
72
|
},
|
|
72
73
|
},
|
|
73
74
|
{
|
|
@@ -76,7 +77,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
76
77
|
icon: markRaw(Bottom),
|
|
77
78
|
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
78
79
|
handler: () => {
|
|
79
|
-
editorService
|
|
80
|
+
editorService.moveLayer(-1);
|
|
80
81
|
},
|
|
81
82
|
},
|
|
82
83
|
{
|
|
@@ -85,7 +86,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
85
86
|
icon: markRaw(Top),
|
|
86
87
|
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
87
88
|
handler: () => {
|
|
88
|
-
editorService
|
|
89
|
+
editorService.moveLayer(LayerOffset.TOP);
|
|
89
90
|
},
|
|
90
91
|
},
|
|
91
92
|
{
|
|
@@ -94,7 +95,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
94
95
|
icon: markRaw(Bottom),
|
|
95
96
|
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
96
97
|
handler: () => {
|
|
97
|
-
editorService
|
|
98
|
+
editorService.moveLayer(LayerOffset.BOTTOM);
|
|
98
99
|
},
|
|
99
100
|
},
|
|
100
101
|
useMoveToMenu(services),
|
|
@@ -112,7 +113,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
112
113
|
type: 'button',
|
|
113
114
|
text: '清空参考线',
|
|
114
115
|
handler: () => {
|
|
115
|
-
editorService
|
|
116
|
+
editorService.get('stage')?.clearGuides();
|
|
116
117
|
},
|
|
117
118
|
},
|
|
118
119
|
...props.stageContentMenu,
|
|
@@ -124,7 +125,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
124
125
|
watch(
|
|
125
126
|
parent,
|
|
126
127
|
async () => {
|
|
127
|
-
if (!parent.value
|
|
128
|
+
if (!parent.value) return (canCenter.value = false);
|
|
128
129
|
const layout = await editorService.getLayout(parent.value);
|
|
129
130
|
const isLayoutConform = [Layout.ABSOLUTE, Layout.FIXED].includes(layout);
|
|
130
131
|
const isTypeConform = nodes.value?.every(
|
package/src/services/dep.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
import { reactive, shallowReactive } from 'vue';
|
|
19
|
+
import { throttle } from 'lodash-es';
|
|
19
20
|
|
|
20
21
|
import type { DepExtendedData, Id, MNode, Target, TargetNode } from '@tmagic/core';
|
|
21
22
|
import { DepTargetType, Watcher } from '@tmagic/core';
|
|
@@ -34,19 +35,32 @@ export interface DepEvents {
|
|
|
34
35
|
|
|
35
36
|
interface State {
|
|
36
37
|
collecting: boolean;
|
|
38
|
+
taskLength: number;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
type StateKey = keyof State;
|
|
40
42
|
|
|
41
|
-
const idleTask = new IdleTask<{ node: TargetNode; deep: boolean; target: Target }>();
|
|
42
|
-
|
|
43
43
|
class Dep extends BaseService {
|
|
44
44
|
private state = shallowReactive<State>({
|
|
45
45
|
collecting: false,
|
|
46
|
+
taskLength: 0,
|
|
46
47
|
});
|
|
47
48
|
|
|
49
|
+
private idleTask = new IdleTask<{ node: TargetNode; deep: boolean; target: Target }>();
|
|
50
|
+
|
|
48
51
|
private watcher = new Watcher({ initialTargets: reactive({}) });
|
|
49
52
|
|
|
53
|
+
constructor() {
|
|
54
|
+
super();
|
|
55
|
+
|
|
56
|
+
this.idleTask.on(
|
|
57
|
+
'update-task-length',
|
|
58
|
+
throttle(({ length }) => {
|
|
59
|
+
this.set('taskLength', length);
|
|
60
|
+
}, 1000),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
50
64
|
public set<K extends StateKey, T extends State[K]>(name: K, value: T) {
|
|
51
65
|
this.state[name] = value;
|
|
52
66
|
}
|
|
@@ -116,11 +130,11 @@ class Dep extends BaseService {
|
|
|
116
130
|
resolve();
|
|
117
131
|
return;
|
|
118
132
|
}
|
|
119
|
-
idleTask.once('finish', () => {
|
|
133
|
+
this.idleTask.once('finish', () => {
|
|
120
134
|
this.emit('collected', nodes, deep);
|
|
121
135
|
this.set('collecting', false);
|
|
122
136
|
});
|
|
123
|
-
idleTask.once('hight-level-finish', () => {
|
|
137
|
+
this.idleTask.once('hight-level-finish', () => {
|
|
124
138
|
this.emit('ds-collected', nodes, deep);
|
|
125
139
|
resolve();
|
|
126
140
|
});
|
|
@@ -159,7 +173,7 @@ class Dep extends BaseService {
|
|
|
159
173
|
}
|
|
160
174
|
|
|
161
175
|
public clearIdleTasks() {
|
|
162
|
-
idleTask.clearTasks();
|
|
176
|
+
this.idleTask.clearTasks();
|
|
163
177
|
}
|
|
164
178
|
|
|
165
179
|
public on<Name extends keyof DepEvents, Param extends DepEvents[Name]>(
|
|
@@ -177,8 +191,8 @@ class Dep extends BaseService {
|
|
|
177
191
|
}
|
|
178
192
|
|
|
179
193
|
public reset() {
|
|
180
|
-
idleTask.removeAllListeners();
|
|
181
|
-
idleTask.clearTasks();
|
|
194
|
+
this.idleTask.removeAllListeners();
|
|
195
|
+
this.idleTask.clearTasks();
|
|
182
196
|
|
|
183
197
|
for (const type of Object.keys(this.watcher.getTargetsList())) {
|
|
184
198
|
this.removeTargets(type);
|
|
@@ -191,6 +205,7 @@ class Dep extends BaseService {
|
|
|
191
205
|
this.removeAllListeners();
|
|
192
206
|
this.reset();
|
|
193
207
|
this.removeAllPlugins();
|
|
208
|
+
this.idleTask.removeAllListeners();
|
|
194
209
|
}
|
|
195
210
|
|
|
196
211
|
public emit<Name extends keyof DepEvents, Param extends DepEvents[Name]>(eventName: Name, ...args: Param) {
|
|
@@ -198,7 +213,7 @@ class Dep extends BaseService {
|
|
|
198
213
|
}
|
|
199
214
|
|
|
200
215
|
private enqueueTask(node: MNode, target: Target, depExtendedData: DepExtendedData, deep: boolean) {
|
|
201
|
-
idleTask.enqueueTask(
|
|
216
|
+
this.idleTask.enqueueTask(
|
|
202
217
|
({ node, deep, target }) => {
|
|
203
218
|
this.collectNode(node, target, depExtendedData, deep);
|
|
204
219
|
},
|
package/src/services/ui.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from '@editor/utils/const';
|
|
32
32
|
|
|
33
33
|
import BaseService from './BaseService';
|
|
34
|
+
import storageService, { Protocol } from './storage';
|
|
34
35
|
|
|
35
36
|
const state = shallowReactive<UiState>({
|
|
36
37
|
uiSelectMode: false,
|
|
@@ -46,9 +47,12 @@ const state = shallowReactive<UiState>({
|
|
|
46
47
|
height: 817,
|
|
47
48
|
},
|
|
48
49
|
columnWidth: {
|
|
49
|
-
left:
|
|
50
|
+
left:
|
|
51
|
+
storageService.getItem(LEFT_COLUMN_WIDTH_STORAGE_KEY, { protocol: Protocol.NUMBER }) || DEFAULT_LEFT_COLUMN_WIDTH,
|
|
50
52
|
center: 0,
|
|
51
|
-
right:
|
|
53
|
+
right:
|
|
54
|
+
storageService.getItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY, { protocol: Protocol.NUMBER }) ||
|
|
55
|
+
DEFAULT_RIGHT_COLUMN_WIDTH,
|
|
52
56
|
},
|
|
53
57
|
showGuides: true,
|
|
54
58
|
showRule: true,
|
package/src/theme/sidebar.scss
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
.m-editor-sidebar {
|
|
4
4
|
display: flex;
|
|
5
5
|
height: 100%;
|
|
6
|
+
position: relative;
|
|
6
7
|
|
|
7
8
|
.m-editor-sidebar-header {
|
|
8
9
|
background: $sidebar-heder-background-color;
|
|
9
10
|
height: 100%;
|
|
10
|
-
width:
|
|
11
|
+
width: $sidebar-heder-width;
|
|
11
12
|
|
|
12
13
|
.m-editor-sidebar-header-item {
|
|
13
14
|
line-height: 15px;
|
|
@@ -52,6 +53,24 @@
|
|
|
52
53
|
overflow: auto;
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
.m-editor-sidebar-tips {
|
|
57
|
+
position: absolute;
|
|
58
|
+
bottom: 0;
|
|
59
|
+
left: $sidebar-heder-width;
|
|
60
|
+
width: calc(100% - #{$sidebar-heder-width});
|
|
61
|
+
text-align: center;
|
|
62
|
+
background-color: rgba(252.5, 245.7, 235.5, 0.9);
|
|
63
|
+
color: #e6a23c;
|
|
64
|
+
padding: 5px 0;
|
|
65
|
+
font-size: 12px;
|
|
66
|
+
|
|
67
|
+
.close-icon {
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
position: absolute;
|
|
70
|
+
right: 15px;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
55
74
|
.fold-icon {
|
|
56
75
|
position: absolute;
|
|
57
76
|
bottom: 8px;
|