@tmagic/editor 1.5.4 → 1.5.6
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 → tmagic-editor.css} +1 -1
- package/dist/tmagic-editor.js +2983 -2076
- package/dist/tmagic-editor.umd.cjs +7933 -2135
- package/package.json +8 -18
- package/src/components/SplitView.vue +16 -7
- package/src/fields/StyleSetter/Index.vue +4 -1
- package/src/fields/StyleSetter/pro/Layout.vue +37 -21
- package/src/fields/StyleSetter/pro/Position.vue +47 -4
- package/src/initService.ts +301 -238
- package/src/layouts/Framework.vue +26 -27
- package/src/layouts/props-panel/PropsPanel.vue +52 -7
- package/src/layouts/props-panel/use-style-panel.ts +12 -1
- package/src/services/dep.ts +20 -3
- package/src/services/ui.ts +8 -2
- package/src/theme/style-setter/layout.scss +1 -1
- package/src/utils/const.ts +5 -0
- package/src/utils/idle-task.ts +2 -1
- package/types/index.d.ts +10435 -2685
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor" ref="content" style="min-width:
|
|
2
|
+
<div class="m-editor" ref="content" style="min-width: 900px">
|
|
3
3
|
<slot name="header"></slot>
|
|
4
4
|
|
|
5
5
|
<slot name="nav"></slot>
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
left-class="m-editor-framework-left"
|
|
18
18
|
center-class="m-editor-framework-center"
|
|
19
19
|
right-class="m-editor-framework-right"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
:min-left="
|
|
23
|
-
:min-right="
|
|
24
|
-
:min-center="
|
|
20
|
+
:left="columnWidth.left"
|
|
21
|
+
:right="columnWidth.right"
|
|
22
|
+
:min-left="200"
|
|
23
|
+
:min-right="300"
|
|
24
|
+
:min-center="400"
|
|
25
25
|
:width="frameworkRect?.width || 0"
|
|
26
26
|
@change="columnWidthChange"
|
|
27
27
|
>
|
|
@@ -60,13 +60,18 @@
|
|
|
60
60
|
</template>
|
|
61
61
|
|
|
62
62
|
<script lang="ts" setup>
|
|
63
|
-
import { computed, inject, onBeforeUnmount, onMounted,
|
|
63
|
+
import { computed, inject, onBeforeUnmount, onMounted, useTemplateRef, watch } from 'vue';
|
|
64
64
|
|
|
65
65
|
import type { MPage, MPageFragment } from '@tmagic/core';
|
|
66
66
|
|
|
67
67
|
import SplitView from '@editor/components/SplitView.vue';
|
|
68
68
|
import type { FrameworkSlots, GetColumnWidth, PageBarSortOptions, Services } from '@editor/type';
|
|
69
69
|
import { getEditorConfig } from '@editor/utils/config';
|
|
70
|
+
import {
|
|
71
|
+
DEFAULT_LEFT_COLUMN_WIDTH,
|
|
72
|
+
LEFT_COLUMN_WIDTH_STORAGE_KEY,
|
|
73
|
+
RIGHT_COLUMN_WIDTH_STORAGE_KEY,
|
|
74
|
+
} from '@editor/utils/const';
|
|
70
75
|
|
|
71
76
|
import PageBar from './page-bar/PageBar.vue';
|
|
72
77
|
import AddPageBox from './AddPageBox.vue';
|
|
@@ -84,9 +89,6 @@ defineProps<{
|
|
|
84
89
|
pageFilterFunction?: (page: MPage | MPageFragment, keyword: string) => boolean;
|
|
85
90
|
}>();
|
|
86
91
|
|
|
87
|
-
const DEFAULT_LEFT_COLUMN_WIDTH = 310;
|
|
88
|
-
const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
|
|
89
|
-
|
|
90
92
|
const codeOptions = inject('codeOptions', {});
|
|
91
93
|
const { editorService, uiService } = inject<Services>('services') || {};
|
|
92
94
|
|
|
@@ -99,20 +101,14 @@ const page = computed(() => editorService?.get('page'));
|
|
|
99
101
|
const pageLength = computed(() => editorService?.get('pageLength') || 0);
|
|
100
102
|
const showSrc = computed(() => uiService?.get('showSrc'));
|
|
101
103
|
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const columnWidth = ref<Partial<GetColumnWidth>>({
|
|
112
|
-
left: getLeftColumnWidthCacheData(),
|
|
113
|
-
center: 0,
|
|
114
|
-
right: getRightColumnWidthCacheData(),
|
|
115
|
-
});
|
|
104
|
+
const columnWidth = computed(
|
|
105
|
+
() =>
|
|
106
|
+
uiService?.get('columnWidth') || {
|
|
107
|
+
left: 0,
|
|
108
|
+
center: 0,
|
|
109
|
+
right: 0,
|
|
110
|
+
},
|
|
111
|
+
);
|
|
116
112
|
|
|
117
113
|
watch(pageLength, () => {
|
|
118
114
|
splitViewRef.value?.updateWidth();
|
|
@@ -121,13 +117,16 @@ watch(pageLength, () => {
|
|
|
121
117
|
watch(
|
|
122
118
|
() => uiService?.get('hideSlideBar'),
|
|
123
119
|
(hideSlideBar) => {
|
|
124
|
-
columnWidth
|
|
120
|
+
uiService?.set('columnWidth', {
|
|
121
|
+
...columnWidth.value,
|
|
122
|
+
left: hideSlideBar
|
|
123
|
+
? 0
|
|
124
|
+
: Number(globalThis.localStorage.getItem(LEFT_COLUMN_WIDTH_STORAGE_KEY)) || DEFAULT_LEFT_COLUMN_WIDTH,
|
|
125
|
+
});
|
|
125
126
|
},
|
|
126
127
|
);
|
|
127
128
|
|
|
128
129
|
const columnWidthChange = (columnW: GetColumnWidth) => {
|
|
129
|
-
columnWidth.value = columnW;
|
|
130
|
-
|
|
131
130
|
globalThis.localStorage.setItem(LEFT_COLUMN_WIDTH_STORAGE_KEY, `${columnW.left}`);
|
|
132
131
|
globalThis.localStorage.setItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY, `${columnW.right}`);
|
|
133
132
|
uiService?.set('columnWidth', columnW);
|
|
@@ -41,10 +41,9 @@
|
|
|
41
41
|
</FormPanel>
|
|
42
42
|
|
|
43
43
|
<TMagicButton
|
|
44
|
-
v-if="!showStylePanel"
|
|
44
|
+
v-if="showStylePanelToggleButton && !showStylePanel"
|
|
45
45
|
class="m-editor-props-panel-style-icon"
|
|
46
46
|
circle
|
|
47
|
-
:type="showStylePanel ? 'primary' : ''"
|
|
48
47
|
@click="showStylePanelHandler"
|
|
49
48
|
>
|
|
50
49
|
<MIcon :icon="Sugar"></MIcon>
|
|
@@ -53,18 +52,20 @@
|
|
|
53
52
|
</template>
|
|
54
53
|
|
|
55
54
|
<script lang="ts" setup>
|
|
56
|
-
import { computed, inject, onBeforeUnmount, ref, useTemplateRef, watchEffect } from 'vue';
|
|
55
|
+
import { computed, inject, onBeforeUnmount, ref, useTemplateRef, watch, watchEffect } from 'vue';
|
|
57
56
|
import { Close, Sugar } from '@element-plus/icons-vue';
|
|
58
57
|
import type { OnDrag } from 'gesto';
|
|
59
58
|
|
|
60
|
-
import type
|
|
59
|
+
import { type MNode } from '@tmagic/core';
|
|
61
60
|
import { TMagicButton } from '@tmagic/design';
|
|
62
61
|
import type { ContainerChangeEventData, FormState, FormValue } from '@tmagic/form';
|
|
62
|
+
import { setValueByKeyPath } from '@tmagic/utils';
|
|
63
63
|
|
|
64
64
|
import MIcon from '@editor/components/Icon.vue';
|
|
65
65
|
import Resizer from '@editor/components/Resizer.vue';
|
|
66
66
|
import type { PropsPanelSlots, Services } from '@editor/type';
|
|
67
67
|
import { styleTabConfig } from '@editor/utils';
|
|
68
|
+
import { RIGHT_COLUMN_WIDTH_STORAGE_KEY } from '@editor/utils/const';
|
|
68
69
|
|
|
69
70
|
import FormPanel from './FormPanel.vue';
|
|
70
71
|
import { useStylePanel } from './use-style-panel';
|
|
@@ -136,6 +137,12 @@ const submit = async (v: MNode, eventData?: ContainerChangeEventData) => {
|
|
|
136
137
|
newValue.style[key] = value;
|
|
137
138
|
}
|
|
138
139
|
});
|
|
140
|
+
|
|
141
|
+
eventData?.changeRecords?.forEach((record) => {
|
|
142
|
+
if (record.propPath?.startsWith('style') && record.value === '') {
|
|
143
|
+
setValueByKeyPath(record.propPath, record.value, newValue);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
139
146
|
}
|
|
140
147
|
|
|
141
148
|
services?.editorService.update(newValue, { changeRecords: eventData?.changeRecords });
|
|
@@ -156,17 +163,55 @@ const mountedHandler = () => {
|
|
|
156
163
|
|
|
157
164
|
const propsPanelEl = useTemplateRef('propsPanel');
|
|
158
165
|
const widthChange = ({ deltaX }: OnDrag) => {
|
|
159
|
-
if (!propsPanelEl.value) {
|
|
166
|
+
if (!propsPanelEl.value || !services) {
|
|
160
167
|
return;
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
const width = globalThis.parseFloat(
|
|
164
171
|
getComputedStyle(propsPanelEl.value).getPropertyValue('--props-style-panel-width'),
|
|
165
172
|
);
|
|
166
|
-
|
|
173
|
+
|
|
174
|
+
let value = width - deltaX;
|
|
175
|
+
if (value > services.uiService.get('columnWidth').right) {
|
|
176
|
+
value = services.uiService.get('columnWidth').right - 40;
|
|
177
|
+
}
|
|
178
|
+
propsPanelEl.value.style.setProperty('--props-style-panel-width', `${value}px`);
|
|
167
179
|
};
|
|
168
180
|
|
|
169
|
-
const { showStylePanel, showStylePanelHandler, closeStylePanelHandler } =
|
|
181
|
+
const { showStylePanel, showStylePanelToggleButton, showStylePanelHandler, closeStylePanelHandler } =
|
|
182
|
+
useStylePanel(services);
|
|
183
|
+
|
|
184
|
+
watch(showStylePanel, (showStylePanel) => {
|
|
185
|
+
if (!propsPanelEl.value || !services) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const columnWidth = {
|
|
190
|
+
...services.uiService.get('columnWidth'),
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const width = globalThis.parseFloat(
|
|
194
|
+
getComputedStyle(propsPanelEl.value).getPropertyValue('--props-style-panel-width'),
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
if (showStylePanel) {
|
|
198
|
+
columnWidth.right += width;
|
|
199
|
+
columnWidth.center -= width;
|
|
200
|
+
} else {
|
|
201
|
+
columnWidth.right -= width;
|
|
202
|
+
columnWidth.center += width;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (columnWidth.center < 0) {
|
|
206
|
+
columnWidth.right = columnWidth.right + columnWidth.center - 400;
|
|
207
|
+
columnWidth.center = 400;
|
|
208
|
+
|
|
209
|
+
propsPanelEl.value.style.setProperty('--props-style-panel-width', `${columnWidth.right / 2}px`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
globalThis.localStorage.setItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY, `${columnWidth.right}`);
|
|
213
|
+
services.uiService.set('columnWidth', columnWidth);
|
|
214
|
+
});
|
|
170
215
|
|
|
171
216
|
const propertyFormPanelRef = useTemplateRef<InstanceType<typeof FormPanel>>('propertyFormPanel');
|
|
172
217
|
defineExpose({
|
|
@@ -8,14 +8,24 @@ export const useStylePanel = (services?: Services) => {
|
|
|
8
8
|
const showStylePanelStorageValue = services?.storageService.getItem(showStylePanelStorageKey, {
|
|
9
9
|
protocol: Protocol.BOOLEAN,
|
|
10
10
|
});
|
|
11
|
+
|
|
11
12
|
if (typeof showStylePanelStorageValue === 'boolean') {
|
|
12
13
|
services?.uiService.set('showStylePanel', showStylePanelStorageValue);
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
const showStylePanel = computed(
|
|
17
|
+
() => showStylePanelToggleButton.value && (services?.uiService.get('showStylePanel') ?? true),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const showStylePanelToggleButton = computed(
|
|
21
|
+
() => !(services && services.uiService.get('frameworkRect').width < 1280),
|
|
22
|
+
);
|
|
23
|
+
|
|
15
24
|
const showStylePanelHandler = () => {
|
|
16
25
|
services?.uiService.set('showStylePanel', true);
|
|
17
26
|
services?.storageService.setItem(showStylePanelStorageKey, true, { protocol: Protocol.BOOLEAN });
|
|
18
27
|
};
|
|
28
|
+
|
|
19
29
|
const closeStylePanelHandler = () => {
|
|
20
30
|
services?.uiService.set('showStylePanel', false);
|
|
21
31
|
services?.storageService.setItem(showStylePanelStorageKey, false, { protocol: Protocol.BOOLEAN });
|
|
@@ -23,6 +33,7 @@ export const useStylePanel = (services?: Services) => {
|
|
|
23
33
|
|
|
24
34
|
return {
|
|
25
35
|
showStylePanel,
|
|
36
|
+
showStylePanelToggleButton,
|
|
26
37
|
showStylePanelHandler,
|
|
27
38
|
closeStylePanelHandler,
|
|
28
39
|
};
|
package/src/services/dep.ts
CHANGED
|
@@ -119,10 +119,10 @@ class Dep extends BaseService {
|
|
|
119
119
|
idleTask.once('finish', () => {
|
|
120
120
|
this.emit('collected', nodes, deep);
|
|
121
121
|
this.set('collecting', false);
|
|
122
|
-
resolve();
|
|
123
122
|
});
|
|
124
123
|
idleTask.once('hight-level-finish', () => {
|
|
125
124
|
this.emit('ds-collected', nodes, deep);
|
|
125
|
+
resolve();
|
|
126
126
|
});
|
|
127
127
|
});
|
|
128
128
|
}
|
|
@@ -130,11 +130,11 @@ class Dep extends BaseService {
|
|
|
130
130
|
public collectNode(node: MNode, target: Target, depExtendedData: DepExtendedData = {}, deep = false) {
|
|
131
131
|
// 先删除原有依赖,重新收集
|
|
132
132
|
if (isPage(node)) {
|
|
133
|
-
Object.entries(target.deps)
|
|
133
|
+
for (const [depKey, dep] of Object.entries(target.deps)) {
|
|
134
134
|
if (dep.data?.pageId && dep.data.pageId === depExtendedData.pageId) {
|
|
135
135
|
delete target.deps[depKey];
|
|
136
136
|
}
|
|
137
|
-
}
|
|
137
|
+
}
|
|
138
138
|
} else {
|
|
139
139
|
this.watcher.removeTargetDep(target, node);
|
|
140
140
|
}
|
|
@@ -176,6 +176,23 @@ class Dep extends BaseService {
|
|
|
176
176
|
return super.once(eventName, listener as any);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
public reset() {
|
|
180
|
+
idleTask.removeAllListeners();
|
|
181
|
+
idleTask.clearTasks();
|
|
182
|
+
|
|
183
|
+
for (const type of Object.keys(this.watcher.getTargetsList())) {
|
|
184
|
+
this.removeTargets(type);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.set('collecting', false);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public destroy() {
|
|
191
|
+
this.removeAllListeners();
|
|
192
|
+
this.reset();
|
|
193
|
+
this.removeAllPlugins();
|
|
194
|
+
}
|
|
195
|
+
|
|
179
196
|
public emit<Name extends keyof DepEvents, Param extends DepEvents[Name]>(eventName: Name, ...args: Param) {
|
|
180
197
|
return super.emit(eventName, ...args);
|
|
181
198
|
}
|
package/src/services/ui.ts
CHANGED
|
@@ -23,6 +23,12 @@ import { convertToNumber } from '@tmagic/utils';
|
|
|
23
23
|
|
|
24
24
|
import editorService from '@editor/services/editor';
|
|
25
25
|
import type { AsyncHookPlugin, StageRect, UiState } from '@editor/type';
|
|
26
|
+
import {
|
|
27
|
+
DEFAULT_LEFT_COLUMN_WIDTH,
|
|
28
|
+
DEFAULT_RIGHT_COLUMN_WIDTH,
|
|
29
|
+
LEFT_COLUMN_WIDTH_STORAGE_KEY,
|
|
30
|
+
RIGHT_COLUMN_WIDTH_STORAGE_KEY,
|
|
31
|
+
} from '@editor/utils/const';
|
|
26
32
|
|
|
27
33
|
import BaseService from './BaseService';
|
|
28
34
|
|
|
@@ -40,9 +46,9 @@ const state = shallowReactive<UiState>({
|
|
|
40
46
|
height: 817,
|
|
41
47
|
},
|
|
42
48
|
columnWidth: {
|
|
43
|
-
left:
|
|
44
|
-
right: 0,
|
|
49
|
+
left: Number(globalThis.localStorage.getItem(LEFT_COLUMN_WIDTH_STORAGE_KEY)) || DEFAULT_LEFT_COLUMN_WIDTH,
|
|
45
50
|
center: 0,
|
|
51
|
+
right: Number(globalThis.localStorage.getItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY)) || DEFAULT_RIGHT_COLUMN_WIDTH,
|
|
46
52
|
},
|
|
47
53
|
showGuides: true,
|
|
48
54
|
showRule: true,
|
package/src/utils/idle-task.ts
CHANGED
|
@@ -54,6 +54,7 @@ export class IdleTask<T = any> extends EventEmitter {
|
|
|
54
54
|
|
|
55
55
|
this.hightLevelTaskList = [];
|
|
56
56
|
this.taskList = [];
|
|
57
|
+
this.taskHandle = null;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
public on<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(
|
|
@@ -80,7 +81,7 @@ export class IdleTask<T = any> extends EventEmitter {
|
|
|
80
81
|
// 动画会占用空闲时间,当任务一直无法执行时,看看是否有动画正在播放
|
|
81
82
|
// 根据空闲时间的多少来决定执行的任务数,保证页面不卡死的情况下尽量多执行任务,不然当任务数巨大时,执行时间会很久
|
|
82
83
|
// 执行不完不会影响配置,但是会影响画布渲染
|
|
83
|
-
while (deadline.timeRemaining() > 0 && taskList.length) {
|
|
84
|
+
while (deadline.timeRemaining() > 0 && (taskList.length || hightLevelTaskList.length)) {
|
|
84
85
|
const timeRemaining = deadline.timeRemaining();
|
|
85
86
|
let times = 0;
|
|
86
87
|
if (timeRemaining <= 5) {
|