@tmagic/editor 1.4.7 → 1.4.9
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 +1 -1
- package/dist/tmagic-editor.js +314 -452
- package/dist/tmagic-editor.umd.cjs +313 -450
- package/package.json +16 -12
- package/src/fields/DataSourceInput.vue +8 -0
- package/src/initService.ts +46 -41
- package/src/layouts/PropsPanel.vue +1 -0
- package/src/layouts/sidebar/layer/use-click.ts +8 -5
- package/src/layouts/sidebar/layer/use-drag.ts +7 -1
- package/src/services/editor.ts +61 -22
- package/src/services/props.ts +22 -7
- package/src/theme/props-panel.scss +1 -1
- package/src/type.ts +3 -0
- package/src/utils/editor.ts +20 -1
- package/types/layouts/sidebar/layer/use-click.d.ts +1 -1
- package/types/services/editor.d.ts +19 -2
- package/types/services/props.d.ts +5 -5
- package/types/type.d.ts +6 -0
- package/types/utils/editor.d.ts +1 -0
- package/tsconfig.build.json +0 -16
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.4.
|
|
2
|
+
"version": "1.4.9",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
6
|
-
"dist/*",
|
|
7
6
|
"src/theme/*"
|
|
8
7
|
],
|
|
9
8
|
"main": "dist/tmagic-editor.umd.cjs",
|
|
@@ -22,6 +21,11 @@
|
|
|
22
21
|
},
|
|
23
22
|
"./*": "./*"
|
|
24
23
|
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"types",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
25
29
|
"license": "Apache-2.0",
|
|
26
30
|
"engines": {
|
|
27
31
|
"node": ">=18"
|
|
@@ -50,8 +54,8 @@
|
|
|
50
54
|
"lodash-es": "^4.17.21",
|
|
51
55
|
"moveable": "^0.53.0",
|
|
52
56
|
"serialize-javascript": "^6.0.0",
|
|
53
|
-
"@tmagic/dep": "1.4.
|
|
54
|
-
"@tmagic/table": "1.4.
|
|
57
|
+
"@tmagic/dep": "1.4.9",
|
|
58
|
+
"@tmagic/table": "1.4.9"
|
|
55
59
|
},
|
|
56
60
|
"devDependencies": {
|
|
57
61
|
"@types/events": "^3.0.0",
|
|
@@ -65,19 +69,19 @@
|
|
|
65
69
|
"sass": "^1.77.0",
|
|
66
70
|
"tsc-alias": "^1.8.5",
|
|
67
71
|
"type-fest": "^4.10.3",
|
|
68
|
-
"vite": "^5.
|
|
69
|
-
"vue-tsc": "^2.0.
|
|
72
|
+
"vite": "^5.3.1",
|
|
73
|
+
"vue-tsc": "^2.0.19"
|
|
70
74
|
},
|
|
71
75
|
"peerDependencies": {
|
|
72
76
|
"monaco-editor": "^0.48.0",
|
|
73
77
|
"vue": "^3.4.27",
|
|
74
78
|
"typescript": "*",
|
|
75
|
-
"@tmagic/core": "1.4.
|
|
76
|
-
"@tmagic/
|
|
77
|
-
"@tmagic/
|
|
78
|
-
"@tmagic/schema": "1.4.
|
|
79
|
-
"@tmagic/
|
|
80
|
-
"@tmagic/
|
|
79
|
+
"@tmagic/core": "1.4.9",
|
|
80
|
+
"@tmagic/form": "1.4.9",
|
|
81
|
+
"@tmagic/design": "1.4.9",
|
|
82
|
+
"@tmagic/schema": "1.4.9",
|
|
83
|
+
"@tmagic/utils": "1.4.9",
|
|
84
|
+
"@tmagic/stage": "1.4.9"
|
|
81
85
|
},
|
|
82
86
|
"peerDependenciesMeta": {
|
|
83
87
|
"typescript": {
|
|
@@ -106,9 +106,17 @@ watch(
|
|
|
106
106
|
);
|
|
107
107
|
|
|
108
108
|
const mouseupHandler = async () => {
|
|
109
|
+
const selection = globalThis.document.getSelection();
|
|
110
|
+
const anchorOffset = selection?.anchorOffset || 0;
|
|
111
|
+
const focusOffset = selection?.focusOffset || 0;
|
|
112
|
+
|
|
109
113
|
isFocused.value = true;
|
|
110
114
|
await nextTick();
|
|
111
115
|
autocomplete.value?.focus();
|
|
116
|
+
|
|
117
|
+
if (focusOffset && input.value) {
|
|
118
|
+
input.value.setSelectionRange(anchorOffset, focusOffset);
|
|
119
|
+
}
|
|
112
120
|
};
|
|
113
121
|
|
|
114
122
|
const blurHandler = () => {
|
package/src/initService.ts
CHANGED
|
@@ -11,11 +11,12 @@ import {
|
|
|
11
11
|
Target,
|
|
12
12
|
} from '@tmagic/dep';
|
|
13
13
|
import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage, MPageFragment } from '@tmagic/schema';
|
|
14
|
-
import {
|
|
14
|
+
import { isPage } from '@tmagic/utils';
|
|
15
15
|
|
|
16
16
|
import PropsPanel from './layouts/PropsPanel.vue';
|
|
17
17
|
import { EditorProps } from './editorProps';
|
|
18
18
|
import { Services } from './type';
|
|
19
|
+
import { traverseNode } from './utils';
|
|
19
20
|
|
|
20
21
|
export declare type LooseRequired<T> = {
|
|
21
22
|
[P in string & keyof T]: T[P];
|
|
@@ -204,38 +205,6 @@ export const initServiceEvents = (
|
|
|
204
205
|
}
|
|
205
206
|
};
|
|
206
207
|
|
|
207
|
-
const updateNodeWhenDataSourceChange = (nodes: MNode[]) => {
|
|
208
|
-
const root = editorService.get('root');
|
|
209
|
-
const stage = editorService.get('stage');
|
|
210
|
-
|
|
211
|
-
if (!root || !stage) return;
|
|
212
|
-
|
|
213
|
-
const app = getApp();
|
|
214
|
-
|
|
215
|
-
if (!app) return;
|
|
216
|
-
|
|
217
|
-
if (app.dsl) {
|
|
218
|
-
app.dsl.dataSourceDeps = root.dataSourceDeps;
|
|
219
|
-
app.dsl.dataSourceCondDeps = root.dataSourceCondDeps;
|
|
220
|
-
app.dsl.dataSources = root.dataSources;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
updateDataSourceSchema();
|
|
224
|
-
|
|
225
|
-
nodes.forEach((node) => {
|
|
226
|
-
const deps = Object.values(root.dataSourceDeps || {});
|
|
227
|
-
deps.forEach((dep) => {
|
|
228
|
-
if (dep[node.id]) {
|
|
229
|
-
stage.update({
|
|
230
|
-
config: cloneDeep(node),
|
|
231
|
-
parentId: editorService.getParentById(node.id)?.id,
|
|
232
|
-
root: cloneDeep(root),
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
};
|
|
238
|
-
|
|
239
208
|
const targetAddHandler = (target: Target) => {
|
|
240
209
|
const root = editorService.get('root');
|
|
241
210
|
if (!root) return;
|
|
@@ -267,8 +236,50 @@ export const initServiceEvents = (
|
|
|
267
236
|
}
|
|
268
237
|
};
|
|
269
238
|
|
|
270
|
-
const collectedHandler = (nodes: MNode[]) => {
|
|
271
|
-
|
|
239
|
+
const collectedHandler = (nodes: MNode[], deep: boolean) => {
|
|
240
|
+
const root = editorService.get('root');
|
|
241
|
+
const stage = editorService.get('stage');
|
|
242
|
+
|
|
243
|
+
if (!root || !stage) return;
|
|
244
|
+
|
|
245
|
+
const app = getApp();
|
|
246
|
+
|
|
247
|
+
if (!app) return;
|
|
248
|
+
|
|
249
|
+
if (app.dsl) {
|
|
250
|
+
app.dsl.dataSourceDeps = root.dataSourceDeps;
|
|
251
|
+
app.dsl.dataSourceCondDeps = root.dataSourceCondDeps;
|
|
252
|
+
app.dsl.dataSources = root.dataSources;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
updateDataSourceSchema();
|
|
256
|
+
|
|
257
|
+
const allNodes: MNode[] = [];
|
|
258
|
+
|
|
259
|
+
if (deep) {
|
|
260
|
+
nodes.forEach((node) => {
|
|
261
|
+
traverseNode<MNode>(node, (node) => {
|
|
262
|
+
if (!allNodes.includes(node)) {
|
|
263
|
+
allNodes.push(node);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
} else {
|
|
268
|
+
allNodes.push(...nodes);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const deps = Object.values(root.dataSourceDeps || {});
|
|
272
|
+
deps.forEach((dep) => {
|
|
273
|
+
Object.keys(dep).forEach((id) => {
|
|
274
|
+
const node = allNodes.find((node) => node.id === id);
|
|
275
|
+
node &&
|
|
276
|
+
stage.update({
|
|
277
|
+
config: cloneDeep(node),
|
|
278
|
+
parentId: editorService.getParentById(node.id)?.id,
|
|
279
|
+
root: cloneDeep(root),
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
});
|
|
272
283
|
};
|
|
273
284
|
|
|
274
285
|
depService.on('add-target', targetAddHandler);
|
|
@@ -399,12 +410,6 @@ export const initServiceEvents = (
|
|
|
399
410
|
(root?.items || []).forEach((page) => {
|
|
400
411
|
depService.collectIdle([page], { pageId: page.id }, true);
|
|
401
412
|
});
|
|
402
|
-
|
|
403
|
-
const targets = depService.getTargets(DepTargetType.DATA_SOURCE);
|
|
404
|
-
|
|
405
|
-
const nodes = getNodes(Object.keys(targets[config.id].deps), root?.items);
|
|
406
|
-
|
|
407
|
-
updateNodeWhenDataSourceChange(nodes);
|
|
408
413
|
};
|
|
409
414
|
|
|
410
415
|
const removeDataSourceTarget = (id: string) => {
|
|
@@ -56,9 +56,12 @@ export const useClick = (
|
|
|
56
56
|
|
|
57
57
|
const throttleTime = 300;
|
|
58
58
|
// 鼠标在组件树移动触发高亮
|
|
59
|
-
const highlightHandler
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
const highlightHandler: (event: MouseEvent, data: TreeNodeData) => void = throttle(
|
|
60
|
+
(event: MouseEvent, data: TreeNodeData) => {
|
|
61
|
+
highlight(data);
|
|
62
|
+
},
|
|
63
|
+
throttleTime,
|
|
64
|
+
);
|
|
62
65
|
|
|
63
66
|
// 触发画布高亮
|
|
64
67
|
const highlight = (data: TreeNodeData) => {
|
|
@@ -67,7 +70,7 @@ export const useClick = (
|
|
|
67
70
|
services?.stageOverlayService?.get('stage')?.highlight(data.id);
|
|
68
71
|
};
|
|
69
72
|
|
|
70
|
-
const nodeClickHandler = (event: MouseEvent, data: TreeNodeData) => {
|
|
73
|
+
const nodeClickHandler = (event: MouseEvent, data: TreeNodeData): void => {
|
|
71
74
|
if (!nodeStatusMap?.value) return;
|
|
72
75
|
|
|
73
76
|
if (services?.uiService.get('uiSelectMode')) {
|
|
@@ -94,7 +97,7 @@ export const useClick = (
|
|
|
94
97
|
|
|
95
98
|
nodeClickHandler,
|
|
96
99
|
|
|
97
|
-
nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData) {
|
|
100
|
+
nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData): void {
|
|
98
101
|
event.preventDefault();
|
|
99
102
|
|
|
100
103
|
const nodes = services?.editorService.get('nodes') || [];
|
|
@@ -144,7 +144,13 @@ export const useDrag = (services: Services | undefined) => {
|
|
|
144
144
|
targetIndex += 1;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
services
|
|
147
|
+
const selectedNodes = services.editorService.get('nodes');
|
|
148
|
+
|
|
149
|
+
if (selectedNodes.find((n) => `${n.id}` === `${node.id}`)) {
|
|
150
|
+
services.editorService.dragTo(selectedNodes, targetParent, targetIndex);
|
|
151
|
+
} else {
|
|
152
|
+
services.editorService.dragTo([node], targetParent, targetIndex);
|
|
153
|
+
}
|
|
148
154
|
}
|
|
149
155
|
|
|
150
156
|
dragState.dragOverNodeId = '';
|
package/src/services/editor.ts
CHANGED
|
@@ -49,11 +49,23 @@ import {
|
|
|
49
49
|
getPageFragmentList,
|
|
50
50
|
getPageList,
|
|
51
51
|
isFixed,
|
|
52
|
+
moveItemsInContainer,
|
|
52
53
|
setChildrenLayout,
|
|
53
54
|
setLayout,
|
|
54
55
|
} from '@editor/utils/editor';
|
|
55
56
|
import { beforePaste, getAddParent } from '@editor/utils/operator';
|
|
56
57
|
|
|
58
|
+
export interface EditorEvents {
|
|
59
|
+
'root-change': [value: StoreState['root'], preValue?: StoreState['root']];
|
|
60
|
+
select: [node: MNode | null];
|
|
61
|
+
add: [nodes: MNode[]];
|
|
62
|
+
remove: [nodes: MNode[]];
|
|
63
|
+
update: [nodes: MNode[]];
|
|
64
|
+
'move-layer': [offset: number | LayerOffset];
|
|
65
|
+
'drag-to': [data: { targetIndex: number; configs: MNode | MNode[]; targetParent: MContainer }];
|
|
66
|
+
'history-change': [data: MPage | MPageFragment];
|
|
67
|
+
}
|
|
68
|
+
|
|
57
69
|
const canUsePluginMethods = {
|
|
58
70
|
async: [
|
|
59
71
|
'getLayout',
|
|
@@ -139,7 +151,7 @@ class Editor extends BaseService {
|
|
|
139
151
|
this.state.stageLoading = false;
|
|
140
152
|
}
|
|
141
153
|
|
|
142
|
-
this.emit('root-change', value, preValue);
|
|
154
|
+
this.emit('root-change', value as StoreState['root'], preValue as StoreState['root']);
|
|
143
155
|
}
|
|
144
156
|
}
|
|
145
157
|
|
|
@@ -877,34 +889,46 @@ class Editor extends BaseService {
|
|
|
877
889
|
}
|
|
878
890
|
}
|
|
879
891
|
|
|
880
|
-
public async dragTo(config: MNode, targetParent: MContainer, targetIndex: number) {
|
|
892
|
+
public async dragTo(config: MNode | MNode[], targetParent: MContainer, targetIndex: number) {
|
|
881
893
|
if (!targetParent || !Array.isArray(targetParent.items)) return;
|
|
882
894
|
|
|
883
|
-
const
|
|
884
|
-
if (!parent || !curNode) throw new Error('找不要删除的节点');
|
|
895
|
+
const configs = Array.isArray(config) ? config : [config];
|
|
885
896
|
|
|
886
|
-
const
|
|
897
|
+
const sourceIndicesInTargetParent: number[] = [];
|
|
898
|
+
const sourceOutTargetParent: MNode[] = [];
|
|
887
899
|
|
|
888
|
-
|
|
900
|
+
const newLayout = await this.getLayout(targetParent);
|
|
889
901
|
|
|
890
|
-
|
|
891
|
-
|
|
902
|
+
for (const config of configs) {
|
|
903
|
+
const { parent, node: curNode } = this.getNodeInfo(config.id, false);
|
|
904
|
+
if (!parent || !curNode) throw new Error('找不要删除的节点');
|
|
892
905
|
|
|
893
|
-
|
|
894
|
-
targetIndex -= 1;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
906
|
+
const index = getNodeIndex(curNode.id, parent);
|
|
897
907
|
|
|
898
|
-
|
|
899
|
-
|
|
908
|
+
if (parent.id === targetParent.id) {
|
|
909
|
+
if (typeof index !== 'number' || index === -1) {
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
sourceIndicesInTargetParent.push(index);
|
|
913
|
+
} else {
|
|
914
|
+
const layout = await this.getLayout(parent);
|
|
915
|
+
|
|
916
|
+
if (newLayout !== layout) {
|
|
917
|
+
setLayout(config, newLayout);
|
|
918
|
+
}
|
|
900
919
|
|
|
901
|
-
|
|
902
|
-
|
|
920
|
+
parent.items?.splice(index, 1);
|
|
921
|
+
sourceOutTargetParent.push(config);
|
|
922
|
+
this.addModifiedNodeId(parent.id);
|
|
923
|
+
}
|
|
903
924
|
}
|
|
904
925
|
|
|
905
|
-
|
|
926
|
+
moveItemsInContainer(sourceIndicesInTargetParent, targetParent, targetIndex);
|
|
906
927
|
|
|
907
|
-
|
|
928
|
+
sourceOutTargetParent.forEach((config, index) => {
|
|
929
|
+
targetParent.items?.splice(targetIndex + index, 0, config);
|
|
930
|
+
this.addModifiedNodeId(config.id);
|
|
931
|
+
});
|
|
908
932
|
|
|
909
933
|
const page = this.get('page');
|
|
910
934
|
const root = this.get('root');
|
|
@@ -918,12 +942,9 @@ class Editor extends BaseService {
|
|
|
918
942
|
});
|
|
919
943
|
}
|
|
920
944
|
|
|
921
|
-
this.addModifiedNodeId(config.id);
|
|
922
|
-
this.addModifiedNodeId(parent.id);
|
|
923
|
-
|
|
924
945
|
this.pushHistoryState();
|
|
925
946
|
|
|
926
|
-
this.emit('drag-to', {
|
|
947
|
+
this.emit('drag-to', { targetIndex, configs, targetParent });
|
|
927
948
|
}
|
|
928
949
|
|
|
929
950
|
/**
|
|
@@ -1019,6 +1040,24 @@ class Editor extends BaseService {
|
|
|
1019
1040
|
super.usePlugin(options);
|
|
1020
1041
|
}
|
|
1021
1042
|
|
|
1043
|
+
public on<Name extends keyof EditorEvents, Param extends EditorEvents[Name]>(
|
|
1044
|
+
eventName: Name,
|
|
1045
|
+
listener: (...args: Param) => void | Promise<void>,
|
|
1046
|
+
) {
|
|
1047
|
+
return super.on(eventName, listener as any);
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
public once<Name extends keyof EditorEvents, Param extends EditorEvents[Name]>(
|
|
1051
|
+
eventName: Name,
|
|
1052
|
+
listener: (...args: Param) => void | Promise<void>,
|
|
1053
|
+
) {
|
|
1054
|
+
return super.once(eventName, listener as any);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
public emit<Name extends keyof EditorEvents, Param extends EditorEvents[Name]>(eventName: Name, ...args: Param) {
|
|
1058
|
+
return super.emit(eventName, ...args);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1022
1061
|
private addModifiedNodeId(id: Id) {
|
|
1023
1062
|
if (!this.isHistoryStateChange) {
|
|
1024
1063
|
this.get('modifiedNodeIds').set(id, id);
|
package/src/services/props.ts
CHANGED
|
@@ -26,7 +26,13 @@ import type { Id, MComponent, MNode } from '@tmagic/schema';
|
|
|
26
26
|
import { getNodePath, getValueByKeyPath, guid, setValueByKeyPath, toLine } from '@tmagic/utils';
|
|
27
27
|
|
|
28
28
|
import editorService from '@editor/services/editor';
|
|
29
|
-
import type {
|
|
29
|
+
import type {
|
|
30
|
+
AsyncHookPlugin,
|
|
31
|
+
PropsFormConfigFunction,
|
|
32
|
+
PropsFormValueFunction,
|
|
33
|
+
PropsState,
|
|
34
|
+
SyncHookPlugin,
|
|
35
|
+
} from '@editor/type';
|
|
30
36
|
import { fillConfig } from '@editor/utils/props';
|
|
31
37
|
|
|
32
38
|
import BaseService from './BaseService';
|
|
@@ -60,7 +66,7 @@ class Props extends BaseService {
|
|
|
60
66
|
]);
|
|
61
67
|
}
|
|
62
68
|
|
|
63
|
-
public setPropsConfigs(configs: Record<string, FormConfig>) {
|
|
69
|
+
public setPropsConfigs(configs: Record<string, FormConfig | PropsFormConfigFunction>) {
|
|
64
70
|
Object.keys(configs).forEach((type: string) => {
|
|
65
71
|
this.setPropsConfig(toLine(type), configs[type]);
|
|
66
72
|
});
|
|
@@ -71,8 +77,13 @@ class Props extends BaseService {
|
|
|
71
77
|
return fillConfig(config, typeof labelWidth !== 'function' ? labelWidth : '80px');
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
public async setPropsConfig(type: string, config: FormConfig) {
|
|
75
|
-
|
|
80
|
+
public async setPropsConfig(type: string, config: FormConfig | PropsFormConfigFunction) {
|
|
81
|
+
let c = config;
|
|
82
|
+
if (typeof config === 'function') {
|
|
83
|
+
c = config({ editorService });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.state.propsConfigMap[toLine(type)] = await this.fillConfig(Array.isArray(c) ? c : [c]);
|
|
76
87
|
}
|
|
77
88
|
|
|
78
89
|
/**
|
|
@@ -88,7 +99,7 @@ class Props extends BaseService {
|
|
|
88
99
|
return cloneDeep(this.state.propsConfigMap[toLine(type)] || (await this.fillConfig([])));
|
|
89
100
|
}
|
|
90
101
|
|
|
91
|
-
public setPropsValues(values: Record<string, Partial<MNode
|
|
102
|
+
public setPropsValues(values: Record<string, Partial<MNode> | PropsFormValueFunction>) {
|
|
92
103
|
Object.keys(values).forEach((type: string) => {
|
|
93
104
|
this.setPropsValue(toLine(type), values[type]);
|
|
94
105
|
});
|
|
@@ -99,8 +110,12 @@ class Props extends BaseService {
|
|
|
99
110
|
* @param type 组件类型
|
|
100
111
|
* @param value 组件初始值
|
|
101
112
|
*/
|
|
102
|
-
public async setPropsValue(type: string, value: Partial<MNode>) {
|
|
103
|
-
|
|
113
|
+
public async setPropsValue(type: string, value: Partial<MNode> | PropsFormValueFunction) {
|
|
114
|
+
let v = value;
|
|
115
|
+
if (typeof value === 'function') {
|
|
116
|
+
v = value({ editorService });
|
|
117
|
+
}
|
|
118
|
+
this.state.propsValueMap[toLine(type)] = v;
|
|
104
119
|
}
|
|
105
120
|
|
|
106
121
|
/**
|
package/src/type.ts
CHANGED
|
@@ -744,3 +744,6 @@ export interface EventBus extends EventEmitter {
|
|
|
744
744
|
): this;
|
|
745
745
|
emit<Name extends keyof EventBusEvent, Param extends EventBusEvent[Name]>(eventName: Name, ...args: Param): boolean;
|
|
746
746
|
}
|
|
747
|
+
|
|
748
|
+
export type PropsFormConfigFunction = (data: { editorService: EditorService }) => FormConfig;
|
|
749
|
+
export type PropsFormValueFunction = (data: { editorService: EditorService }) => Partial<MNode>;
|
package/src/utils/editor.ts
CHANGED
|
@@ -285,10 +285,29 @@ export const traverseNode = <T extends NodeItem = NodeItem>(
|
|
|
285
285
|
) => {
|
|
286
286
|
cb(node, parents);
|
|
287
287
|
|
|
288
|
-
if (node.items
|
|
288
|
+
if (Array.isArray(node.items) && node.items.length) {
|
|
289
289
|
parents.push(node);
|
|
290
290
|
node.items.forEach((item) => {
|
|
291
291
|
traverseNode(item as T, cb, [...parents]);
|
|
292
292
|
});
|
|
293
293
|
}
|
|
294
294
|
};
|
|
295
|
+
|
|
296
|
+
export const moveItemsInContainer = (sourceIndices: number[], parent: MContainer, targetIndex: number) => {
|
|
297
|
+
sourceIndices.sort((a, b) => a - b);
|
|
298
|
+
for (let i = sourceIndices.length - 1; i >= 0; i--) {
|
|
299
|
+
const sourceIndex = sourceIndices[i];
|
|
300
|
+
if (sourceIndex === targetIndex) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
const [item] = parent.items.splice(sourceIndex, 1);
|
|
304
|
+
parent.items.splice(sourceIndex < targetIndex ? targetIndex - 1 : targetIndex, 0, item);
|
|
305
|
+
|
|
306
|
+
// 更新后续源索引(因为数组已经改变)
|
|
307
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
308
|
+
if (sourceIndices[j] >= targetIndex) {
|
|
309
|
+
sourceIndices[j] += 1;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
@@ -60,5 +60,5 @@ export declare const useClick: (services: Services | undefined, isCtrlKeyDown: R
|
|
|
60
60
|
}> | undefined>;
|
|
61
61
|
nodeClickHandler: (event: MouseEvent, data: TreeNodeData) => void;
|
|
62
62
|
nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData): void;
|
|
63
|
-
highlightHandler:
|
|
63
|
+
highlightHandler: (event: MouseEvent, data: TreeNodeData) => void;
|
|
64
64
|
};
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { Writable } from 'type-fest';
|
|
2
2
|
import { type TargetOptions } from '@tmagic/dep';
|
|
3
|
-
import type { Id, MContainer, MNode } from '@tmagic/schema';
|
|
3
|
+
import type { Id, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
|
|
4
4
|
import BaseService from '../services/BaseService';
|
|
5
5
|
import type { AddMNode, AsyncHookPlugin, EditorNodeInfo, PastePosition, StepValue, StoreState, StoreStateKey } from '../type';
|
|
6
6
|
import { LayerOffset, Layout } from '../type';
|
|
7
|
+
export interface EditorEvents {
|
|
8
|
+
'root-change': [value: StoreState['root'], preValue?: StoreState['root']];
|
|
9
|
+
select: [node: MNode | null];
|
|
10
|
+
add: [nodes: MNode[]];
|
|
11
|
+
remove: [nodes: MNode[]];
|
|
12
|
+
update: [nodes: MNode[]];
|
|
13
|
+
'move-layer': [offset: number | LayerOffset];
|
|
14
|
+
'drag-to': [data: {
|
|
15
|
+
targetIndex: number;
|
|
16
|
+
configs: MNode | MNode[];
|
|
17
|
+
targetParent: MContainer;
|
|
18
|
+
}];
|
|
19
|
+
'history-change': [data: MPage | MPageFragment];
|
|
20
|
+
}
|
|
7
21
|
declare const canUsePluginMethods: {
|
|
8
22
|
async: readonly ["getLayout", "highlight", "select", "multiSelect", "doAdd", "add", "doRemove", "remove", "doUpdate", "update", "sort", "copy", "paste", "doPaste", "doAlignCenter", "alignCenter", "moveLayer", "moveToContainer", "dragTo", "undo", "redo", "move"];
|
|
9
23
|
sync: never[];
|
|
@@ -136,7 +150,7 @@ declare class Editor extends BaseService {
|
|
|
136
150
|
* @param targetId 容器ID
|
|
137
151
|
*/
|
|
138
152
|
moveToContainer(config: MNode, targetId: Id): Promise<MNode | undefined>;
|
|
139
|
-
dragTo(config: MNode, targetParent: MContainer, targetIndex: number): Promise<void>;
|
|
153
|
+
dragTo(config: MNode | MNode[], targetParent: MContainer, targetIndex: number): Promise<void>;
|
|
140
154
|
/**
|
|
141
155
|
* 撤销当前操作
|
|
142
156
|
* @returns 上一次数据
|
|
@@ -152,6 +166,9 @@ declare class Editor extends BaseService {
|
|
|
152
166
|
destroy(): void;
|
|
153
167
|
resetModifiedNodeId(): void;
|
|
154
168
|
usePlugin(options: AsyncHookPlugin<AsyncMethodName, Editor>): void;
|
|
169
|
+
on<Name extends keyof EditorEvents, Param extends EditorEvents[Name]>(eventName: Name, listener: (...args: Param) => void | Promise<void>): this;
|
|
170
|
+
once<Name extends keyof EditorEvents, Param extends EditorEvents[Name]>(eventName: Name, listener: (...args: Param) => void | Promise<void>): this;
|
|
171
|
+
emit<Name extends keyof EditorEvents, Param extends EditorEvents[Name]>(eventName: Name, ...args: Param): boolean;
|
|
155
172
|
private addModifiedNodeId;
|
|
156
173
|
private pushHistoryState;
|
|
157
174
|
private changeHistoryState;
|
|
@@ -2,7 +2,7 @@ import { Writable } from 'type-fest';
|
|
|
2
2
|
import { type TargetOptions } from '@tmagic/dep';
|
|
3
3
|
import type { FormConfig } from '@tmagic/form';
|
|
4
4
|
import type { MNode } from '@tmagic/schema';
|
|
5
|
-
import type { AsyncHookPlugin, SyncHookPlugin } from '../type';
|
|
5
|
+
import type { AsyncHookPlugin, PropsFormConfigFunction, PropsFormValueFunction, SyncHookPlugin } from '../type';
|
|
6
6
|
import BaseService from './BaseService';
|
|
7
7
|
declare const canUsePluginMethods: {
|
|
8
8
|
async: readonly ["setPropsConfig", "getPropsConfig", "setPropsValue", "getPropsValue", "fillConfig", "getDefaultPropsValue"];
|
|
@@ -13,22 +13,22 @@ type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
|
|
|
13
13
|
declare class Props extends BaseService {
|
|
14
14
|
private state;
|
|
15
15
|
constructor();
|
|
16
|
-
setPropsConfigs(configs: Record<string, FormConfig>): void;
|
|
16
|
+
setPropsConfigs(configs: Record<string, FormConfig | PropsFormConfigFunction>): void;
|
|
17
17
|
fillConfig(config: FormConfig, labelWidth?: string): Promise<FormConfig>;
|
|
18
|
-
setPropsConfig(type: string, config: FormConfig): Promise<void>;
|
|
18
|
+
setPropsConfig(type: string, config: FormConfig | PropsFormConfigFunction): Promise<void>;
|
|
19
19
|
/**
|
|
20
20
|
* 获取指点类型的组件属性表单配置
|
|
21
21
|
* @param type 组件类型
|
|
22
22
|
* @returns 组件属性表单配置
|
|
23
23
|
*/
|
|
24
24
|
getPropsConfig(type: string): Promise<FormConfig>;
|
|
25
|
-
setPropsValues(values: Record<string, Partial<MNode
|
|
25
|
+
setPropsValues(values: Record<string, Partial<MNode> | PropsFormValueFunction>): void;
|
|
26
26
|
/**
|
|
27
27
|
* 为指点类型组件设置组件初始值
|
|
28
28
|
* @param type 组件类型
|
|
29
29
|
* @param value 组件初始值
|
|
30
30
|
*/
|
|
31
|
-
setPropsValue(type: string, value: Partial<MNode>): Promise<void>;
|
|
31
|
+
setPropsValue(type: string, value: Partial<MNode> | PropsFormValueFunction): Promise<void>;
|
|
32
32
|
/**
|
|
33
33
|
* 获取指定类型的组件初始值
|
|
34
34
|
* @param type 组件类型
|
package/types/type.d.ts
CHANGED
|
@@ -617,3 +617,9 @@ export interface EventBus extends EventEmitter {
|
|
|
617
617
|
on<Name extends keyof EventBusEvent, Param extends EventBusEvent[Name]>(eventName: Name, listener: (...args: Param) => void): this;
|
|
618
618
|
emit<Name extends keyof EventBusEvent, Param extends EventBusEvent[Name]>(eventName: Name, ...args: Param): boolean;
|
|
619
619
|
}
|
|
620
|
+
export type PropsFormConfigFunction = (data: {
|
|
621
|
+
editorService: EditorService;
|
|
622
|
+
}) => FormConfig;
|
|
623
|
+
export type PropsFormValueFunction = (data: {
|
|
624
|
+
editorService: EditorService;
|
|
625
|
+
}) => Partial<MNode>;
|
package/types/utils/editor.d.ts
CHANGED
|
@@ -56,3 +56,4 @@ export interface NodeItem {
|
|
|
56
56
|
[key: string]: any;
|
|
57
57
|
}
|
|
58
58
|
export declare const traverseNode: <T extends NodeItem = NodeItem>(node: T, cb: (node: T, parents: T[]) => void, parents?: T[]) => void;
|
|
59
|
+
export declare const moveItemsInContainer: (sourceIndices: number[], parent: MContainer, targetIndex: number) => void;
|
package/tsconfig.build.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"baseUrl": ".",
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"declarationDir": "types",
|
|
7
|
-
"forceConsistentCasingInFileNames": true,
|
|
8
|
-
"outDir": "./types",
|
|
9
|
-
"paths": {
|
|
10
|
-
"@editor/*": ["src/*"],
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
"include": [
|
|
14
|
-
"src"
|
|
15
|
-
],
|
|
16
|
-
}
|