@tmagic/editor 1.0.0-rc.7 → 1.0.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 +4 -0
- package/dist/tmagic-editor.es.js +122 -104
- package/dist/tmagic-editor.es.js.map +1 -1
- package/dist/tmagic-editor.umd.js +123 -104
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/dist/types/src/Editor.vue.d.ts +10 -1
- package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +3 -31
- package/dist/types/src/services/editor.d.ts +6 -3
- package/dist/types/src/services/props.d.ts +8 -2
- package/dist/types/src/type.d.ts +11 -0
- package/dist/types/src/utils/editor.d.ts +1 -6
- package/dist/types/src/utils/props.d.ts +10 -1
- package/package.json +7 -7
- package/src/Editor.vue +18 -8
- package/src/layouts/workspace/Stage.vue +40 -35
- package/src/layouts/workspace/Workspace.vue +2 -28
- package/src/services/editor.ts +15 -9
- package/src/services/ui.ts +4 -2
- package/src/theme/page-bar.scss +1 -0
- package/src/theme/workspace.scss +4 -0
- package/src/type.ts +13 -0
- package/src/utils/editor.ts +15 -0
- package/src/utils/props.ts +16 -6
|
@@ -69,6 +69,7 @@ declare const _default: DefineComponent<{
|
|
|
69
69
|
};
|
|
70
70
|
canSelect: {
|
|
71
71
|
type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
|
|
72
|
+
default: (el: HTMLElement) => boolean;
|
|
72
73
|
};
|
|
73
74
|
stageRect: {
|
|
74
75
|
type: PropType<StageRect>;
|
|
@@ -77,6 +78,9 @@ declare const _default: DefineComponent<{
|
|
|
77
78
|
type: ObjectConstructor;
|
|
78
79
|
default: () => {};
|
|
79
80
|
};
|
|
81
|
+
updateDragEl: {
|
|
82
|
+
type: PropType<(el: HTMLDivElement, target: HTMLElement) => void>;
|
|
83
|
+
};
|
|
80
84
|
}, Services, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, ("props-panel-mounted" | "update:modelValue")[], "props-panel-mounted" | "update:modelValue", VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly<ExtractPropTypes<{
|
|
81
85
|
/** 页面初始值 */
|
|
82
86
|
modelValue: {
|
|
@@ -142,6 +146,7 @@ declare const _default: DefineComponent<{
|
|
|
142
146
|
};
|
|
143
147
|
canSelect: {
|
|
144
148
|
type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
|
|
149
|
+
default: (el: HTMLElement) => boolean;
|
|
145
150
|
};
|
|
146
151
|
stageRect: {
|
|
147
152
|
type: PropType<StageRect>;
|
|
@@ -150,6 +155,9 @@ declare const _default: DefineComponent<{
|
|
|
150
155
|
type: ObjectConstructor;
|
|
151
156
|
default: () => {};
|
|
152
157
|
};
|
|
158
|
+
updateDragEl: {
|
|
159
|
+
type: PropType<(el: HTMLDivElement, target: HTMLElement) => void>;
|
|
160
|
+
};
|
|
153
161
|
}>> & {
|
|
154
162
|
"onProps-panel-mounted"?: ((...args: any[]) => any) | undefined;
|
|
155
163
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
@@ -157,12 +165,13 @@ declare const _default: DefineComponent<{
|
|
|
157
165
|
menu: MenuBarData;
|
|
158
166
|
layerContentMenu: MenuItem[];
|
|
159
167
|
stageContentMenu: MenuItem[];
|
|
160
|
-
autoScrollIntoView: boolean;
|
|
161
168
|
codeOptions: Record<string, any>;
|
|
162
169
|
modelValue: MApp;
|
|
163
170
|
componentGroupList: ComponentGroup[];
|
|
171
|
+
autoScrollIntoView: boolean;
|
|
164
172
|
propsConfigs: Record<string, FormConfig>;
|
|
165
173
|
propsValues: Record<string, MNode>;
|
|
166
174
|
eventMethodList: Record<string, any>;
|
|
175
|
+
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
|
167
176
|
}>;
|
|
168
177
|
export default _default;
|
|
@@ -1,35 +1,7 @@
|
|
|
1
|
-
import type { DefineComponent, Ref, ComputedRef, ComponentOptionsMixin, VNodeProps, AllowedComponentProps, ComponentCustomProps, ExtractPropTypes
|
|
1
|
+
import type { DefineComponent, Ref, ComputedRef, ComponentOptionsMixin, EmitsOptions, VNodeProps, AllowedComponentProps, ComponentCustomProps, ExtractPropTypes } from 'vue';
|
|
2
2
|
import type { MPage } from '@tmagic/schema';
|
|
3
|
-
|
|
4
|
-
import StageCore from '@tmagic/stage';
|
|
5
|
-
declare const _default: DefineComponent<{
|
|
6
|
-
runtimeUrl: StringConstructor;
|
|
7
|
-
autoScrollIntoView: BooleanConstructor;
|
|
8
|
-
render: {
|
|
9
|
-
type: PropType<() => HTMLDivElement>;
|
|
10
|
-
};
|
|
11
|
-
moveableOptions: {
|
|
12
|
-
type: PropType<MoveableOptions | ((core?: StageCore | undefined) => MoveableOptions)>;
|
|
13
|
-
};
|
|
14
|
-
canSelect: {
|
|
15
|
-
type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
|
|
16
|
-
};
|
|
17
|
-
}, {
|
|
3
|
+
declare const _default: DefineComponent<{}, {
|
|
18
4
|
workspace: Ref<HTMLDivElement | undefined>;
|
|
19
5
|
page: ComputedRef<MPage | undefined>;
|
|
20
|
-
},
|
|
21
|
-
runtimeUrl: StringConstructor;
|
|
22
|
-
autoScrollIntoView: BooleanConstructor;
|
|
23
|
-
render: {
|
|
24
|
-
type: PropType<() => HTMLDivElement>;
|
|
25
|
-
};
|
|
26
|
-
moveableOptions: {
|
|
27
|
-
type: PropType<MoveableOptions | ((core?: StageCore | undefined) => MoveableOptions)>;
|
|
28
|
-
};
|
|
29
|
-
canSelect: {
|
|
30
|
-
type: PropType<(el: HTMLElement) => boolean | Promise<boolean>>;
|
|
31
|
-
};
|
|
32
|
-
}>>, {
|
|
33
|
-
autoScrollIntoView: boolean;
|
|
34
|
-
}>;
|
|
6
|
+
}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly<ExtractPropTypes<{}>>, {}>;
|
|
35
7
|
export default _default;
|
|
@@ -23,21 +23,24 @@ declare class Editor extends BaseService {
|
|
|
23
23
|
/**
|
|
24
24
|
* 根据id获取组件、组件的父组件以及组件所属的页面节点
|
|
25
25
|
* @param {number | string} id 组件id
|
|
26
|
+
* @param {boolean} raw 是否使用toRaw
|
|
26
27
|
* @returns {EditorNodeInfo}
|
|
27
28
|
*/
|
|
28
|
-
getNodeInfo(id: Id): EditorNodeInfo;
|
|
29
|
+
getNodeInfo(id: Id, raw?: boolean): EditorNodeInfo;
|
|
29
30
|
/**
|
|
30
31
|
* 根据ID获取指点节点配置
|
|
31
32
|
* @param id 组件ID
|
|
33
|
+
* @param {boolean} raw 是否使用toRaw
|
|
32
34
|
* @returns 组件节点配置
|
|
33
35
|
*/
|
|
34
|
-
getNodeById(id: Id): MNode | undefined;
|
|
36
|
+
getNodeById(id: Id, raw?: boolean): MNode | undefined;
|
|
35
37
|
/**
|
|
36
38
|
* 根据ID获取指点节点的父节点配置
|
|
37
39
|
* @param id 组件ID
|
|
40
|
+
* @param {boolean} raw 是否使用toRaw
|
|
38
41
|
* @returns 指点组件的父节点配置
|
|
39
42
|
*/
|
|
40
|
-
getParentById(id: Id): MContainer | undefined;
|
|
43
|
+
getParentById(id: Id, raw?: boolean): MContainer | undefined;
|
|
41
44
|
/**
|
|
42
45
|
* 只有容器拥有布局
|
|
43
46
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FormConfig } from '@tmagic/form';
|
|
2
|
-
import type { MNode } from '@tmagic/schema';
|
|
2
|
+
import type { MNode, MPage } from '@tmagic/schema';
|
|
3
3
|
import BaseService from './BaseService';
|
|
4
4
|
declare class Props extends BaseService {
|
|
5
5
|
private state;
|
|
@@ -29,7 +29,13 @@ declare class Props extends BaseService {
|
|
|
29
29
|
* @param type 组件类型
|
|
30
30
|
* @returns 组件初始值
|
|
31
31
|
*/
|
|
32
|
-
getPropsValue(type: string, defaultValue?:
|
|
32
|
+
getPropsValue(type: string, defaultValue?: Record<string, any>): Promise<any>;
|
|
33
|
+
createId(type: string | number): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* 将组件与组件的子元素配置中的id都设置成一个新的ID
|
|
36
|
+
* @param {Object} config 组件配置
|
|
37
|
+
*/
|
|
38
|
+
setNewItemId(config: MNode, parent?: MPage): Promise<void>;
|
|
33
39
|
}
|
|
34
40
|
export declare type PropsService = Props;
|
|
35
41
|
declare const _default: Props;
|
package/dist/types/src/type.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Component } from 'vue';
|
|
|
2
2
|
import type { FormConfig } from '@tmagic/form';
|
|
3
3
|
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
4
4
|
import type StageCore from '@tmagic/stage';
|
|
5
|
+
import type { MoveableOptions } from '@tmagic/stage';
|
|
5
6
|
import type { ComponentListService } from './services/componentList';
|
|
6
7
|
import type { EditorService } from './services/editor';
|
|
7
8
|
import type { EventsService } from './services/events';
|
|
@@ -21,6 +22,14 @@ export interface Services {
|
|
|
21
22
|
componentListService: ComponentListService;
|
|
22
23
|
uiService: UiService;
|
|
23
24
|
}
|
|
25
|
+
export interface StageOptions {
|
|
26
|
+
runtimeUrl: string;
|
|
27
|
+
autoScrollIntoView: boolean;
|
|
28
|
+
render: () => HTMLDivElement;
|
|
29
|
+
moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
|
|
30
|
+
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
|
31
|
+
updateDragEl: (el: HTMLDivElement) => void;
|
|
32
|
+
}
|
|
24
33
|
export interface StoreState {
|
|
25
34
|
root: MApp | null;
|
|
26
35
|
page: MPage | null;
|
|
@@ -197,3 +206,5 @@ export declare enum Layout {
|
|
|
197
206
|
export declare enum Keys {
|
|
198
207
|
ESCAPE = "Space"
|
|
199
208
|
}
|
|
209
|
+
export declare const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
|
|
210
|
+
export declare const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
|
|
@@ -2,7 +2,6 @@ import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
|
2
2
|
import type StageCore from '@tmagic/stage';
|
|
3
3
|
import { Layout } from '../type';
|
|
4
4
|
export declare const COPY_STORAGE_KEY = "$MagicEditorCopyData";
|
|
5
|
-
export declare const generateId: (type: string | number) => string;
|
|
6
5
|
/**
|
|
7
6
|
* 获取所有页面配置
|
|
8
7
|
* @param app DSL跟节点
|
|
@@ -27,11 +26,6 @@ export declare const generatePageName: (pageNameList: string[]) => string;
|
|
|
27
26
|
* @returns {string}
|
|
28
27
|
*/
|
|
29
28
|
export declare const generatePageNameByApp: (app: MApp) => string;
|
|
30
|
-
/**
|
|
31
|
-
* 将组件与组件的子元素配置中的id都设置成一个新的ID
|
|
32
|
-
* @param {Object} config 组件配置
|
|
33
|
-
*/
|
|
34
|
-
export declare const setNewItemId: (config: MNode, parent?: MPage | undefined) => void;
|
|
35
29
|
/**
|
|
36
30
|
* @param {Object} node
|
|
37
31
|
* @returns {boolean}
|
|
@@ -43,3 +37,4 @@ export declare const initPosition: (node: MNode, layout: Layout, parentNode: MNo
|
|
|
43
37
|
export declare const setLayout: (node: MNode, layout: Layout) => MNode;
|
|
44
38
|
export declare const change2Fixed: (node: MNode, root: MApp) => MNode;
|
|
45
39
|
export declare const Fixed2Other: (node: MNode, root: MApp, getLayout: (parent: MNode, node?: MNode | undefined) => Promise<Layout>) => Promise<MNode>;
|
|
40
|
+
export declare const getGuideLineFromCache: (key: string) => number[];
|
|
@@ -41,9 +41,18 @@ export declare const DEFAULT_CONFIG: FormConfig;
|
|
|
41
41
|
* @param type 组件类型
|
|
42
42
|
* @returns Object
|
|
43
43
|
*/
|
|
44
|
-
export declare const getDefaultPropsValue: (type: string) => {
|
|
44
|
+
export declare const getDefaultPropsValue: (type: string, id: string) => {
|
|
45
45
|
type: string;
|
|
46
46
|
id: string;
|
|
47
|
+
layout: string;
|
|
47
48
|
style: {};
|
|
48
49
|
name: string;
|
|
50
|
+
items: never[];
|
|
51
|
+
} | {
|
|
52
|
+
type: string;
|
|
53
|
+
id: string;
|
|
54
|
+
style: {};
|
|
55
|
+
name: string;
|
|
56
|
+
layout?: undefined;
|
|
57
|
+
items?: undefined;
|
|
49
58
|
};
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.0.0
|
|
2
|
+
"version": "1.0.0",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"dist/*",
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@babel/core": "^7.18.0",
|
|
45
45
|
"@element-plus/icons": "0.0.11",
|
|
46
|
-
"@tmagic/core": "1.0.0
|
|
47
|
-
"@tmagic/form": "1.0.0
|
|
48
|
-
"@tmagic/schema": "1.0.0
|
|
49
|
-
"@tmagic/stage": "1.0.0
|
|
50
|
-
"@tmagic/utils": "1.0.0
|
|
46
|
+
"@tmagic/core": "1.0.0",
|
|
47
|
+
"@tmagic/form": "1.0.0",
|
|
48
|
+
"@tmagic/schema": "1.0.0",
|
|
49
|
+
"@tmagic/stage": "1.0.0",
|
|
50
|
+
"@tmagic/utils": "1.0.0",
|
|
51
51
|
"buffer": "^6.0.3",
|
|
52
52
|
"color": "^3.1.3",
|
|
53
53
|
"element-plus": "^2.2.0",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"vue": "^3.2.0"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@tmagic/form": "1.0.0
|
|
63
|
+
"@tmagic/form": "1.0.0",
|
|
64
64
|
"element-plus": "^2.2.0",
|
|
65
65
|
"monaco-editor": "^0.32.1",
|
|
66
66
|
"vue": "^3.2.0"
|
package/src/Editor.vue
CHANGED
|
@@ -12,13 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
<template #workspace :editorService="editorService">
|
|
14
14
|
<slot name="workspace">
|
|
15
|
-
<workspace
|
|
16
|
-
:runtime-url="runtimeUrl"
|
|
17
|
-
:auto-scroll-into-view="autoScrollIntoView"
|
|
18
|
-
:render="render"
|
|
19
|
-
:moveable-options="moveableOptions"
|
|
20
|
-
:can-select="canSelect"
|
|
21
|
-
>
|
|
15
|
+
<workspace>
|
|
22
16
|
<template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
|
|
23
17
|
<template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
|
|
24
18
|
<template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
|
|
@@ -37,7 +31,7 @@
|
|
|
37
31
|
</template>
|
|
38
32
|
|
|
39
33
|
<script lang="ts">
|
|
40
|
-
import { defineComponent, onUnmounted, PropType, provide, toRaw, watch } from 'vue';
|
|
34
|
+
import { defineComponent, onUnmounted, PropType, provide, reactive, toRaw, watch } from 'vue';
|
|
41
35
|
|
|
42
36
|
import { EventOption } from '@tmagic/core';
|
|
43
37
|
import type { FormConfig } from '@tmagic/form';
|
|
@@ -145,6 +139,7 @@ export default defineComponent({
|
|
|
145
139
|
|
|
146
140
|
canSelect: {
|
|
147
141
|
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
|
142
|
+
default: (el: HTMLElement) => Boolean(el.id),
|
|
148
143
|
},
|
|
149
144
|
|
|
150
145
|
stageRect: {
|
|
@@ -155,6 +150,10 @@ export default defineComponent({
|
|
|
155
150
|
type: Object,
|
|
156
151
|
default: () => ({}),
|
|
157
152
|
},
|
|
153
|
+
|
|
154
|
+
updateDragEl: {
|
|
155
|
+
type: Function as PropType<(el: HTMLDivElement, target: HTMLElement) => void>,
|
|
156
|
+
},
|
|
158
157
|
},
|
|
159
158
|
|
|
160
159
|
emits: ['props-panel-mounted', 'update:modelValue'],
|
|
@@ -249,6 +248,17 @@ export default defineComponent({
|
|
|
249
248
|
|
|
250
249
|
provide('layerContentMenu', props.layerContentMenu);
|
|
251
250
|
provide('stageContentMenu', props.stageContentMenu);
|
|
251
|
+
provide(
|
|
252
|
+
'stageOptions',
|
|
253
|
+
reactive({
|
|
254
|
+
runtimeUrl: props.runtimeUrl,
|
|
255
|
+
autoScrollIntoView: props.autoScrollIntoView,
|
|
256
|
+
render: props.render,
|
|
257
|
+
moveableOptions: props.moveableOptions,
|
|
258
|
+
canSelect: props.canSelect,
|
|
259
|
+
updateDragEl: props.updateDragEl,
|
|
260
|
+
}),
|
|
261
|
+
);
|
|
252
262
|
|
|
253
263
|
return services;
|
|
254
264
|
},
|
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
markRaw,
|
|
29
29
|
onMounted,
|
|
30
30
|
onUnmounted,
|
|
31
|
-
PropType,
|
|
32
31
|
ref,
|
|
33
32
|
toRaw,
|
|
34
33
|
watch,
|
|
@@ -37,11 +36,18 @@ import {
|
|
|
37
36
|
import { cloneDeep } from 'lodash-es';
|
|
38
37
|
|
|
39
38
|
import type { MApp, MNode, MPage } from '@tmagic/schema';
|
|
40
|
-
import
|
|
41
|
-
import StageCore from '@tmagic/stage';
|
|
39
|
+
import StageCore, { GuidesType, Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
|
|
42
40
|
|
|
43
41
|
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
|
44
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
H_GUIDE_LINE_STORAGE_KEY,
|
|
44
|
+
Layout,
|
|
45
|
+
Services,
|
|
46
|
+
StageOptions,
|
|
47
|
+
StageRect,
|
|
48
|
+
V_GUIDE_LINE_STORAGE_KEY,
|
|
49
|
+
} from '@editor/type';
|
|
50
|
+
import { getGuideLineFromCache } from '@editor/utils';
|
|
45
51
|
|
|
46
52
|
import ViewerMenu from './ViewerMenu.vue';
|
|
47
53
|
|
|
@@ -53,29 +59,9 @@ export default defineComponent({
|
|
|
53
59
|
ScrollViewer,
|
|
54
60
|
},
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
render: {
|
|
58
|
-
type: Function as PropType<() => HTMLDivElement>,
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
runtimeUrl: String,
|
|
62
|
-
autoScrollIntoView: Boolean,
|
|
63
|
-
|
|
64
|
-
canSelect: {
|
|
65
|
-
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
|
66
|
-
default: (el: HTMLElement) => Boolean(el.id),
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
moveableOptions: {
|
|
70
|
-
type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
|
|
71
|
-
default: () => (core?: StageCore) => ({
|
|
72
|
-
container: core?.renderer?.contentWindow?.document.getElementById('app'),
|
|
73
|
-
}),
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
setup(props) {
|
|
62
|
+
setup() {
|
|
78
63
|
const services = inject<Services>('services');
|
|
64
|
+
const stageOptions = inject<StageOptions>('stageOptions');
|
|
79
65
|
|
|
80
66
|
const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
|
|
81
67
|
const stageContainer = ref<HTMLDivElement>();
|
|
@@ -91,19 +77,21 @@ export default defineComponent({
|
|
|
91
77
|
let stage: StageCore | null = null;
|
|
92
78
|
let runtime: Runtime | null = null;
|
|
93
79
|
|
|
80
|
+
const getGuideLineKey = (key: string) => `${key}_${root.value?.id}_${page.value?.id}`;
|
|
81
|
+
|
|
94
82
|
watchEffect(() => {
|
|
95
83
|
if (stage) return;
|
|
96
84
|
|
|
97
85
|
if (!stageContainer.value) return;
|
|
98
|
-
if (!(
|
|
86
|
+
if (!(stageOptions?.runtimeUrl || stageOptions?.render) || !root.value) return;
|
|
99
87
|
|
|
100
88
|
stage = new StageCore({
|
|
101
|
-
render:
|
|
102
|
-
runtimeUrl:
|
|
89
|
+
render: stageOptions.render,
|
|
90
|
+
runtimeUrl: stageOptions.runtimeUrl,
|
|
103
91
|
zoom: zoom.value,
|
|
104
|
-
autoScrollIntoView:
|
|
92
|
+
autoScrollIntoView: stageOptions.autoScrollIntoView,
|
|
105
93
|
canSelect: (el, event, stop) => {
|
|
106
|
-
const elCanSelect =
|
|
94
|
+
const elCanSelect = stageOptions.canSelect(el);
|
|
107
95
|
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
|
108
96
|
if (uiSelectMode.value && elCanSelect && event.type === 'mousedown') {
|
|
109
97
|
document.dispatchEvent(new CustomEvent('ui-select', { detail: el }));
|
|
@@ -112,13 +100,19 @@ export default defineComponent({
|
|
|
112
100
|
|
|
113
101
|
return elCanSelect;
|
|
114
102
|
},
|
|
115
|
-
moveableOptions:
|
|
103
|
+
moveableOptions: stageOptions.moveableOptions,
|
|
104
|
+
updateDragEl: stageOptions.updateDragEl,
|
|
116
105
|
});
|
|
117
106
|
|
|
118
107
|
services?.editorService.set('stage', markRaw(stage));
|
|
119
108
|
|
|
120
109
|
stage?.mount(stageContainer.value);
|
|
121
110
|
|
|
111
|
+
stage.mask.setGuides([
|
|
112
|
+
getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY)),
|
|
113
|
+
getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY)),
|
|
114
|
+
]);
|
|
115
|
+
|
|
122
116
|
stage?.on('select', (el: HTMLElement) => {
|
|
123
117
|
services?.editorService.select(el.id);
|
|
124
118
|
});
|
|
@@ -135,15 +129,26 @@ export default defineComponent({
|
|
|
135
129
|
services?.editorService.sort(ev.src, ev.dist);
|
|
136
130
|
});
|
|
137
131
|
|
|
138
|
-
stage?.on('changeGuides', () => {
|
|
132
|
+
stage?.on('changeGuides', (e) => {
|
|
139
133
|
services?.uiService.set('showGuides', true);
|
|
134
|
+
|
|
135
|
+
if (!root.value || !page.value) return;
|
|
136
|
+
|
|
137
|
+
const storageKey = getGuideLineKey(
|
|
138
|
+
e.type === GuidesType.HORIZONTAL ? H_GUIDE_LINE_STORAGE_KEY : V_GUIDE_LINE_STORAGE_KEY,
|
|
139
|
+
);
|
|
140
|
+
if (e.guides.length) {
|
|
141
|
+
globalThis.localStorage.setItem(storageKey, JSON.stringify(e.guides));
|
|
142
|
+
} else {
|
|
143
|
+
globalThis.localStorage.removeItem(storageKey);
|
|
144
|
+
}
|
|
140
145
|
});
|
|
141
146
|
|
|
142
147
|
if (!node.value?.id) return;
|
|
143
148
|
stage?.on('runtime-ready', (rt) => {
|
|
144
149
|
runtime = rt;
|
|
145
150
|
// toRaw返回的值是一个引用而非快照,需要cloneDeep
|
|
146
|
-
root.value && runtime?.updateRootConfig(cloneDeep(toRaw(root.value)));
|
|
151
|
+
root.value && runtime?.updateRootConfig?.(cloneDeep(toRaw(root.value)));
|
|
147
152
|
page.value?.id && runtime?.updatePageId?.(page.value.id);
|
|
148
153
|
setTimeout(() => {
|
|
149
154
|
node.value && stage?.select(toRaw(node.value.id));
|
|
@@ -158,7 +163,7 @@ export default defineComponent({
|
|
|
158
163
|
|
|
159
164
|
watch(root, (root) => {
|
|
160
165
|
if (runtime && root) {
|
|
161
|
-
runtime.updateRootConfig(cloneDeep(toRaw(root)));
|
|
166
|
+
runtime.updateRootConfig?.(cloneDeep(toRaw(root)));
|
|
162
167
|
}
|
|
163
168
|
});
|
|
164
169
|
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-editor-workspace" tabindex="1" ref="workspace">
|
|
3
|
-
<magic-stage
|
|
4
|
-
:key="page?.id"
|
|
5
|
-
:runtime-url="runtimeUrl"
|
|
6
|
-
:auto-scroll-into-view="autoScrollIntoView"
|
|
7
|
-
:render="render"
|
|
8
|
-
:moveable-options="moveableOptions"
|
|
9
|
-
:can-select="canSelect"
|
|
10
|
-
></magic-stage>
|
|
3
|
+
<magic-stage :key="page?.id"></magic-stage>
|
|
11
4
|
|
|
12
5
|
<slot name="workspace-content"></slot>
|
|
13
6
|
|
|
@@ -19,12 +12,10 @@
|
|
|
19
12
|
</template>
|
|
20
13
|
|
|
21
14
|
<script lang="ts">
|
|
22
|
-
import { computed, defineComponent, inject, onMounted, onUnmounted,
|
|
15
|
+
import { computed, defineComponent, inject, onMounted, onUnmounted, ref } from 'vue';
|
|
23
16
|
import KeyController from 'keycon';
|
|
24
17
|
|
|
25
18
|
import type { MNode, MPage } from '@tmagic/schema';
|
|
26
|
-
import type { MoveableOptions } from '@tmagic/stage';
|
|
27
|
-
import StageCore from '@tmagic/stage';
|
|
28
19
|
import { isPage } from '@tmagic/utils';
|
|
29
20
|
|
|
30
21
|
import type { Services } from '@editor/type';
|
|
@@ -40,23 +31,6 @@ export default defineComponent({
|
|
|
40
31
|
MagicStage,
|
|
41
32
|
},
|
|
42
33
|
|
|
43
|
-
props: {
|
|
44
|
-
runtimeUrl: String,
|
|
45
|
-
autoScrollIntoView: Boolean,
|
|
46
|
-
|
|
47
|
-
render: {
|
|
48
|
-
type: Function as PropType<() => HTMLDivElement>,
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
moveableOptions: {
|
|
52
|
-
type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
canSelect: {
|
|
56
|
-
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
|
|
60
34
|
setup() {
|
|
61
35
|
const services = inject<Services>('services');
|
|
62
36
|
const workspace = ref<HTMLDivElement>();
|
package/src/services/editor.ts
CHANGED
|
@@ -108,10 +108,14 @@ class Editor extends BaseService {
|
|
|
108
108
|
/**
|
|
109
109
|
* 根据id获取组件、组件的父组件以及组件所属的页面节点
|
|
110
110
|
* @param {number | string} id 组件id
|
|
111
|
+
* @param {boolean} raw 是否使用toRaw
|
|
111
112
|
* @returns {EditorNodeInfo}
|
|
112
113
|
*/
|
|
113
|
-
public getNodeInfo(id: Id): EditorNodeInfo {
|
|
114
|
-
|
|
114
|
+
public getNodeInfo(id: Id, raw = true): EditorNodeInfo {
|
|
115
|
+
let root = this.get<MApp | null>('root');
|
|
116
|
+
if (raw) {
|
|
117
|
+
root = toRaw(root);
|
|
118
|
+
}
|
|
115
119
|
if (!root) return {};
|
|
116
120
|
|
|
117
121
|
if (id === root.id) {
|
|
@@ -141,21 +145,23 @@ class Editor extends BaseService {
|
|
|
141
145
|
/**
|
|
142
146
|
* 根据ID获取指点节点配置
|
|
143
147
|
* @param id 组件ID
|
|
148
|
+
* @param {boolean} raw 是否使用toRaw
|
|
144
149
|
* @returns 组件节点配置
|
|
145
150
|
*/
|
|
146
|
-
public getNodeById(id: Id): MNode | undefined {
|
|
147
|
-
const { node } = this.getNodeInfo(id);
|
|
151
|
+
public getNodeById(id: Id, raw = true): MNode | undefined {
|
|
152
|
+
const { node } = this.getNodeInfo(id, raw);
|
|
148
153
|
return node;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
/**
|
|
152
157
|
* 根据ID获取指点节点的父节点配置
|
|
153
158
|
* @param id 组件ID
|
|
159
|
+
* @param {boolean} raw 是否使用toRaw
|
|
154
160
|
* @returns 指点组件的父节点配置
|
|
155
161
|
*/
|
|
156
|
-
public getParentById(id: Id): MContainer | undefined {
|
|
162
|
+
public getParentById(id: Id, raw = true): MContainer | undefined {
|
|
157
163
|
if (!this.get<MApp | null>('root')) return;
|
|
158
|
-
const { parent } = this.getNodeInfo(id);
|
|
164
|
+
const { parent } = this.getNodeInfo(id, raw);
|
|
159
165
|
return parent;
|
|
160
166
|
}
|
|
161
167
|
|
|
@@ -279,7 +285,7 @@ class Editor extends BaseService {
|
|
|
279
285
|
} else if (curNode.items) {
|
|
280
286
|
parentNode = curNode;
|
|
281
287
|
} else {
|
|
282
|
-
parentNode = this.getParentById(curNode.id);
|
|
288
|
+
parentNode = this.getParentById(curNode.id, false);
|
|
283
289
|
}
|
|
284
290
|
|
|
285
291
|
if (!parentNode) throw new Error('未找到父元素');
|
|
@@ -332,7 +338,7 @@ class Editor extends BaseService {
|
|
|
332
338
|
|
|
333
339
|
if (!root) throw new Error('没有root');
|
|
334
340
|
|
|
335
|
-
const { parent, node: curNode } = this.getNodeInfo(node.id);
|
|
341
|
+
const { parent, node: curNode } = this.getNodeInfo(node.id, false);
|
|
336
342
|
|
|
337
343
|
if (!parent || !curNode) throw new Error('找不要删除的节点');
|
|
338
344
|
|
|
@@ -384,7 +390,7 @@ class Editor extends BaseService {
|
|
|
384
390
|
public async update(config: MNode): Promise<MNode> {
|
|
385
391
|
if (!config?.id) throw new Error('没有配置或者配置缺少id值');
|
|
386
392
|
|
|
387
|
-
const info = this.getNodeInfo(config.id);
|
|
393
|
+
const info = this.getNodeInfo(config.id, false);
|
|
388
394
|
|
|
389
395
|
if (!info.node) throw new Error(`获取不到id为${config.id}的节点`);
|
|
390
396
|
|
package/src/services/ui.ts
CHANGED
|
@@ -26,7 +26,9 @@ import type { GetColumnWidth, SetColumnWidth, StageRect, UiState } from '@editor
|
|
|
26
26
|
import BaseService from './BaseService';
|
|
27
27
|
|
|
28
28
|
const DEFAULT_LEFT_COLUMN_WIDTH = 310;
|
|
29
|
+
const MIN_LEFT_COLUMN_WIDTH = 45;
|
|
29
30
|
const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
|
|
31
|
+
const MIN_RIGHT_COLUMN_WIDTH = 1;
|
|
30
32
|
|
|
31
33
|
const COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorColumnWidthData';
|
|
32
34
|
|
|
@@ -117,11 +119,11 @@ class Ui extends BaseService {
|
|
|
117
119
|
};
|
|
118
120
|
|
|
119
121
|
if (left) {
|
|
120
|
-
columnWidth.left = left;
|
|
122
|
+
columnWidth.left = Math.max(left, MIN_LEFT_COLUMN_WIDTH);
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
if (right) {
|
|
124
|
-
columnWidth.right = right;
|
|
126
|
+
columnWidth.right = Math.max(right, MIN_RIGHT_COLUMN_WIDTH);
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
if (!center || center === 'auto') {
|
package/src/theme/page-bar.scss
CHANGED
package/src/theme/workspace.scss
CHANGED
package/src/type.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type { Component } from 'vue';
|
|
|
21
21
|
import type { FormConfig } from '@tmagic/form';
|
|
22
22
|
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
23
23
|
import type StageCore from '@tmagic/stage';
|
|
24
|
+
import type { MoveableOptions } from '@tmagic/stage';
|
|
24
25
|
|
|
25
26
|
import type { ComponentListService } from '@editor/services/componentList';
|
|
26
27
|
import type { EditorService } from '@editor/services/editor';
|
|
@@ -45,6 +46,15 @@ export interface Services {
|
|
|
45
46
|
uiService: UiService;
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
export interface StageOptions {
|
|
50
|
+
runtimeUrl: string;
|
|
51
|
+
autoScrollIntoView: boolean;
|
|
52
|
+
render: () => HTMLDivElement;
|
|
53
|
+
moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
|
|
54
|
+
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
|
55
|
+
updateDragEl: (el: HTMLDivElement) => void;
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
export interface StoreState {
|
|
49
59
|
root: MApp | null;
|
|
50
60
|
page: MPage | null;
|
|
@@ -253,3 +263,6 @@ export enum Layout {
|
|
|
253
263
|
export enum Keys {
|
|
254
264
|
ESCAPE = 'Space',
|
|
255
265
|
}
|
|
266
|
+
|
|
267
|
+
export const H_GUIDE_LINE_STORAGE_KEY = '$MagicStageHorizontalGuidelinesData';
|
|
268
|
+
export const V_GUIDE_LINE_STORAGE_KEY = '$MagicStageVerticalGuidelinesData';
|
package/src/utils/editor.ts
CHANGED
|
@@ -204,3 +204,18 @@ export const Fixed2Other = async (
|
|
|
204
204
|
|
|
205
205
|
return toRelative(node);
|
|
206
206
|
};
|
|
207
|
+
|
|
208
|
+
export const getGuideLineFromCache = (key: string): number[] => {
|
|
209
|
+
if (!key) return [];
|
|
210
|
+
|
|
211
|
+
const guideLineCacheData = globalThis.localStorage.getItem(key);
|
|
212
|
+
if (guideLineCacheData) {
|
|
213
|
+
try {
|
|
214
|
+
return JSON.parse(guideLineCacheData) || [];
|
|
215
|
+
} catch (e) {
|
|
216
|
+
console.error(e);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return [];
|
|
221
|
+
};
|