@tmagic/editor 1.4.6 → 1.4.7
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/tmagic-editor.js +324 -139
- package/dist/tmagic-editor.umd.cjs +323 -138
- package/package.json +9 -9
- package/src/components/TreeNode.vue +3 -1
- package/src/editorProps.ts +0 -7
- package/src/fields/DataSourceInput.vue +7 -1
- package/src/fields/EventSelect.vue +90 -16
- package/src/initService.ts +24 -28
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +34 -16
- package/src/layouts/sidebar/data-source/DataSourceList.vue +17 -5
- package/src/services/codeBlock.ts +14 -11
- package/src/services/dataSource.ts +14 -7
- package/src/services/dep.ts +77 -5
- package/src/services/editor.ts +23 -14
- package/src/services/props.ts +14 -8
- package/src/utils/data-source/index.ts +20 -13
- package/src/utils/idle-task.ts +72 -0
- package/src/utils/operator.ts +6 -6
- package/types/editorProps.d.ts +0 -7
- package/types/layouts/PropsPanel.vue.d.ts +9 -9
- package/types/services/codeBlock.d.ts +2 -1
- package/types/services/dataSource.d.ts +2 -1
- package/types/services/dep.d.ts +12 -2
- package/types/services/editor.d.ts +3 -2
- package/types/services/props.d.ts +2 -1
- package/types/utils/idle-task.d.ts +14 -0
- package/types/utils/operator.d.ts +2 -2
package/src/services/dep.ts
CHANGED
|
@@ -17,18 +17,35 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { reactive } from 'vue';
|
|
19
19
|
|
|
20
|
-
import { DepTargetType, type Target, Watcher } from '@tmagic/dep';
|
|
20
|
+
import { type DepExtendedData, DepTargetType, type Target, type TargetNode, Watcher } from '@tmagic/dep';
|
|
21
21
|
import type { Id, MNode } from '@tmagic/schema';
|
|
22
|
+
import { isPage } from '@tmagic/utils';
|
|
23
|
+
|
|
24
|
+
import { IdleTask } from '@editor/utils/idle-task';
|
|
22
25
|
|
|
23
26
|
import BaseService from './BaseService';
|
|
24
27
|
|
|
28
|
+
export interface DepEvents {
|
|
29
|
+
'add-target': [target: Target];
|
|
30
|
+
'remove-target': [id: string | number];
|
|
31
|
+
collected: [nodes: MNode[], deep: boolean];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const idleTask = new IdleTask<{ node: TargetNode; deep: boolean; target: Target }>();
|
|
35
|
+
|
|
25
36
|
class Dep extends BaseService {
|
|
26
37
|
private watcher = new Watcher({ initialTargets: reactive({}) });
|
|
27
38
|
|
|
28
39
|
public removeTargets(type: string = DepTargetType.DEFAULT) {
|
|
29
40
|
this.watcher.removeTargets(type);
|
|
30
41
|
|
|
31
|
-
this.
|
|
42
|
+
const targets = this.watcher.getTargets(type);
|
|
43
|
+
|
|
44
|
+
if (!targets) return;
|
|
45
|
+
|
|
46
|
+
for (const target of Object.values(targets)) {
|
|
47
|
+
this.emit('remove-target', target.id);
|
|
48
|
+
}
|
|
32
49
|
}
|
|
33
50
|
|
|
34
51
|
public getTargets(type: string = DepTargetType.DEFAULT) {
|
|
@@ -46,18 +63,55 @@ class Dep extends BaseService {
|
|
|
46
63
|
|
|
47
64
|
public removeTarget(id: Id, type: string = DepTargetType.DEFAULT) {
|
|
48
65
|
this.watcher.removeTarget(id, type);
|
|
49
|
-
this.emit('remove-target');
|
|
66
|
+
this.emit('remove-target', id);
|
|
50
67
|
}
|
|
51
68
|
|
|
52
69
|
public clearTargets() {
|
|
53
70
|
this.watcher.clearTargets();
|
|
54
71
|
}
|
|
55
72
|
|
|
56
|
-
public collect(nodes: MNode[], deep = false, type?: DepTargetType) {
|
|
57
|
-
this.watcher.
|
|
73
|
+
public collect(nodes: MNode[], depExtendedData: DepExtendedData = {}, deep = false, type?: DepTargetType) {
|
|
74
|
+
this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
|
|
75
|
+
this.collectNode(node, target, depExtendedData, deep);
|
|
76
|
+
});
|
|
77
|
+
|
|
58
78
|
this.emit('collected', nodes, deep);
|
|
59
79
|
}
|
|
60
80
|
|
|
81
|
+
public collectIdle(nodes: MNode[], depExtendedData: DepExtendedData = {}, deep = false, type?: DepTargetType) {
|
|
82
|
+
this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
|
|
83
|
+
idleTask.enqueueTask(
|
|
84
|
+
({ node, deep, target }) => {
|
|
85
|
+
this.collectNode(node, target, depExtendedData, deep);
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
node,
|
|
89
|
+
deep,
|
|
90
|
+
target,
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
idleTask.once('finish', () => {
|
|
96
|
+
this.emit('collected', nodes, deep);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
collectNode(node: MNode, target: Target, depExtendedData: DepExtendedData = {}, deep = false) {
|
|
101
|
+
// 先删除原有依赖,重新收集
|
|
102
|
+
if (isPage(node)) {
|
|
103
|
+
Object.entries(target.deps).forEach(([depKey, dep]) => {
|
|
104
|
+
if (dep.data?.pageId && dep.data.pageId === depExtendedData.pageId) {
|
|
105
|
+
delete target.deps[depKey];
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
this.watcher.removeTargetDep(target, node);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
this.watcher.collectItem(node, target, depExtendedData, deep);
|
|
113
|
+
}
|
|
114
|
+
|
|
61
115
|
public clear(nodes?: MNode[]) {
|
|
62
116
|
return this.watcher.clear(nodes);
|
|
63
117
|
}
|
|
@@ -73,6 +127,24 @@ class Dep extends BaseService {
|
|
|
73
127
|
public hasSpecifiedTypeTarget(type: string = DepTargetType.DEFAULT): boolean {
|
|
74
128
|
return this.watcher.hasSpecifiedTypeTarget(type);
|
|
75
129
|
}
|
|
130
|
+
|
|
131
|
+
public on<Name extends keyof DepEvents, Param extends DepEvents[Name]>(
|
|
132
|
+
eventName: Name,
|
|
133
|
+
listener: (...args: Param) => void | Promise<void>,
|
|
134
|
+
) {
|
|
135
|
+
return super.on(eventName, listener as any);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public once<Name extends keyof DepEvents, Param extends DepEvents[Name]>(
|
|
139
|
+
eventName: Name,
|
|
140
|
+
listener: (...args: Param) => void | Promise<void>,
|
|
141
|
+
) {
|
|
142
|
+
return super.once(eventName, listener as any);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public emit<Name extends keyof DepEvents, Param extends DepEvents[Name]>(eventName: Name, ...args: Param) {
|
|
146
|
+
return super.emit(eventName, ...args);
|
|
147
|
+
}
|
|
76
148
|
}
|
|
77
149
|
|
|
78
150
|
export type DepService = Dep;
|
package/src/services/editor.ts
CHANGED
|
@@ -20,14 +20,13 @@ import { reactive, toRaw } from 'vue';
|
|
|
20
20
|
import { cloneDeep, get, isObject, mergeWith, uniq } from 'lodash-es';
|
|
21
21
|
import { Writable } from 'type-fest';
|
|
22
22
|
|
|
23
|
-
import {
|
|
23
|
+
import { Target, type TargetOptions, Watcher } from '@tmagic/dep';
|
|
24
24
|
import type { Id, MApp, MComponent, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
|
|
25
25
|
import { NodeType } from '@tmagic/schema';
|
|
26
26
|
import { calcValueByFontsize, getNodePath, isNumber, isPage, isPageFragment, isPop } from '@tmagic/utils';
|
|
27
27
|
|
|
28
28
|
import BaseService from '@editor/services//BaseService';
|
|
29
29
|
import propsService from '@editor/services//props';
|
|
30
|
-
import depService from '@editor/services/dep';
|
|
31
30
|
import historyService from '@editor/services/history';
|
|
32
31
|
import storageService, { Protocol } from '@editor/services/storage';
|
|
33
32
|
import type {
|
|
@@ -661,16 +660,20 @@ class Editor extends BaseService {
|
|
|
661
660
|
* @param config 组件节点配置
|
|
662
661
|
* @returns
|
|
663
662
|
*/
|
|
664
|
-
public copyWithRelated(config: MNode | MNode[]): void {
|
|
663
|
+
public copyWithRelated(config: MNode | MNode[], collectorOptions?: TargetOptions): void {
|
|
665
664
|
const copyNodes: MNode[] = Array.isArray(config) ? config : [config];
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
665
|
+
|
|
666
|
+
// 初始化复制组件相关的依赖收集器
|
|
667
|
+
if (collectorOptions && typeof collectorOptions.isTarget === 'function') {
|
|
668
|
+
const customTarget = new Target({
|
|
669
|
+
...collectorOptions,
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
const coperWatcher = new Watcher();
|
|
673
|
+
|
|
674
|
+
coperWatcher.addTarget(customTarget);
|
|
675
|
+
|
|
676
|
+
coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
|
|
674
677
|
Object.keys(customTarget.deps).forEach((nodeId: Id) => {
|
|
675
678
|
const node = this.getNodeById(nodeId);
|
|
676
679
|
if (!node) return;
|
|
@@ -686,6 +689,7 @@ class Editor extends BaseService {
|
|
|
686
689
|
});
|
|
687
690
|
});
|
|
688
691
|
}
|
|
692
|
+
|
|
689
693
|
storageService.setItem(COPY_STORAGE_KEY, copyNodes, {
|
|
690
694
|
protocol: Protocol.OBJECT,
|
|
691
695
|
});
|
|
@@ -696,7 +700,7 @@ class Editor extends BaseService {
|
|
|
696
700
|
* @param position 粘贴的坐标
|
|
697
701
|
* @returns 添加后的组件节点配置
|
|
698
702
|
*/
|
|
699
|
-
public async paste(position: PastePosition = {}): Promise<MNode | MNode[] | void> {
|
|
703
|
+
public async paste(position: PastePosition = {}, collectorOptions?: TargetOptions): Promise<MNode | MNode[] | void> {
|
|
700
704
|
const config: MNode[] = storageService.getItem(COPY_STORAGE_KEY);
|
|
701
705
|
if (!Array.isArray(config)) return;
|
|
702
706
|
|
|
@@ -711,13 +715,18 @@ class Editor extends BaseService {
|
|
|
711
715
|
}
|
|
712
716
|
}
|
|
713
717
|
const pasteConfigs = await this.doPaste(config, position);
|
|
714
|
-
|
|
718
|
+
|
|
719
|
+
if (collectorOptions && typeof collectorOptions.isTarget === 'function') {
|
|
720
|
+
propsService.replaceRelateId(config, pasteConfigs, collectorOptions);
|
|
721
|
+
}
|
|
722
|
+
|
|
715
723
|
return this.add(pasteConfigs, parent);
|
|
716
724
|
}
|
|
717
725
|
|
|
718
726
|
public async doPaste(config: MNode[], position: PastePosition = {}): Promise<MNode[]> {
|
|
719
727
|
propsService.clearRelateId();
|
|
720
|
-
const
|
|
728
|
+
const doc = this.get('stage')?.renderer.contentWindow?.document;
|
|
729
|
+
const pasteConfigs = beforePaste(position, cloneDeep(config), doc);
|
|
721
730
|
return pasteConfigs;
|
|
722
731
|
}
|
|
723
732
|
|
package/src/services/props.ts
CHANGED
|
@@ -20,12 +20,11 @@ import { reactive } from 'vue';
|
|
|
20
20
|
import { cloneDeep, mergeWith } from 'lodash-es';
|
|
21
21
|
import { Writable } from 'type-fest';
|
|
22
22
|
|
|
23
|
-
import {
|
|
23
|
+
import { Target, type TargetOptions, Watcher } from '@tmagic/dep';
|
|
24
24
|
import type { FormConfig } from '@tmagic/form';
|
|
25
25
|
import type { Id, MComponent, MNode } from '@tmagic/schema';
|
|
26
26
|
import { getNodePath, getValueByKeyPath, guid, setValueByKeyPath, toLine } from '@tmagic/utils';
|
|
27
27
|
|
|
28
|
-
import depService from '@editor/services/dep';
|
|
29
28
|
import editorService from '@editor/services/editor';
|
|
30
29
|
import type { AsyncHookPlugin, PropsState, SyncHookPlugin } from '@editor/type';
|
|
31
30
|
import { fillConfig } from '@editor/utils/props';
|
|
@@ -196,13 +195,20 @@ class Props extends BaseService {
|
|
|
196
195
|
* @param originConfigs 原组件配置
|
|
197
196
|
* @param targetConfigs 待替换的组件配置
|
|
198
197
|
*/
|
|
199
|
-
public replaceRelateId(originConfigs: MNode[], targetConfigs: MNode[]) {
|
|
198
|
+
public replaceRelateId(originConfigs: MNode[], targetConfigs: MNode[], collectorOptions: TargetOptions) {
|
|
200
199
|
const relateIdMap = this.getRelateIdMap();
|
|
200
|
+
|
|
201
201
|
if (Object.keys(relateIdMap).length === 0) return;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
|
|
203
|
+
const target = new Target({
|
|
204
|
+
...collectorOptions,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const coperWatcher = new Watcher();
|
|
208
|
+
|
|
209
|
+
coperWatcher.addTarget(target);
|
|
210
|
+
coperWatcher.collect(originConfigs, {}, true, collectorOptions.type);
|
|
211
|
+
|
|
206
212
|
originConfigs.forEach((config: MNode) => {
|
|
207
213
|
const newId = relateIdMap[config.id];
|
|
208
214
|
const path = getNodePath(newId, targetConfigs);
|
|
@@ -219,7 +225,7 @@ class Props extends BaseService {
|
|
|
219
225
|
|
|
220
226
|
// 递归items
|
|
221
227
|
if (config.items && Array.isArray(config.items)) {
|
|
222
|
-
this.replaceRelateId(config.items, targetConfigs);
|
|
228
|
+
this.replaceRelateId(config.items, targetConfigs, collectorOptions);
|
|
223
229
|
}
|
|
224
230
|
});
|
|
225
231
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CascaderOption, FormConfig, FormState } from '@tmagic/form';
|
|
2
2
|
import { DataSchema, DataSourceFieldType, DataSourceSchema } from '@tmagic/schema';
|
|
3
|
+
import { isNumber } from '@tmagic/utils';
|
|
3
4
|
|
|
4
5
|
import BaseFormConfig from './formConfigs/base';
|
|
5
6
|
import HttpFormConfig from './formConfigs/http';
|
|
@@ -165,20 +166,26 @@ export const getDisplayField = (dataSources: DataSourceSchema[], key: string) =>
|
|
|
165
166
|
let dsText = '';
|
|
166
167
|
let ds: DataSourceSchema | undefined;
|
|
167
168
|
let fields: DataSchema[] | undefined;
|
|
168
|
-
|
|
169
169
|
// 将模块解析成数据源对应的值
|
|
170
|
-
match[1]
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
170
|
+
match[1]
|
|
171
|
+
.replaceAll(/\[(\d+)\]/g, '.$1')
|
|
172
|
+
.split('.')
|
|
173
|
+
.forEach((item, index) => {
|
|
174
|
+
if (index === 0) {
|
|
175
|
+
ds = dataSources.find((ds) => ds.id === item);
|
|
176
|
+
dsText += ds?.title || item;
|
|
177
|
+
fields = ds?.fields;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (isNumber(item)) {
|
|
182
|
+
dsText += `[${item}]`;
|
|
183
|
+
} else {
|
|
184
|
+
const field = fields?.find((field) => field.name === item);
|
|
185
|
+
fields = field?.fields;
|
|
186
|
+
dsText += `.${field?.title || item}`;
|
|
187
|
+
}
|
|
188
|
+
});
|
|
182
189
|
|
|
183
190
|
displayState.push({
|
|
184
191
|
type: 'var',
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
|
|
3
|
+
export interface IdleTaskEvents {
|
|
4
|
+
finish: [];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
globalThis.requestIdleCallback =
|
|
8
|
+
globalThis.requestIdleCallback ||
|
|
9
|
+
function (cb) {
|
|
10
|
+
const start = Date.now();
|
|
11
|
+
return setTimeout(() => {
|
|
12
|
+
cb({
|
|
13
|
+
didTimeout: false,
|
|
14
|
+
timeRemaining() {
|
|
15
|
+
return Math.max(0, 50 - (Date.now() - start));
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}, 1);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export class IdleTask<T = any> extends EventEmitter {
|
|
22
|
+
private taskList: {
|
|
23
|
+
handler: (data: T) => void;
|
|
24
|
+
data: T;
|
|
25
|
+
}[] = [];
|
|
26
|
+
|
|
27
|
+
private taskHandle: number | null = null;
|
|
28
|
+
|
|
29
|
+
public enqueueTask(taskHandler: (data: T) => void, taskData: T) {
|
|
30
|
+
this.taskList.push({
|
|
31
|
+
handler: taskHandler,
|
|
32
|
+
data: taskData,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (!this.taskHandle) {
|
|
36
|
+
this.taskHandle = globalThis.requestIdleCallback(this.runTaskQueue.bind(this), { timeout: 10000 });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public on<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(
|
|
41
|
+
eventName: Name,
|
|
42
|
+
listener: (...args: Param) => void | Promise<void>,
|
|
43
|
+
) {
|
|
44
|
+
return super.on(eventName, listener as any);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public once<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(
|
|
48
|
+
eventName: Name,
|
|
49
|
+
listener: (...args: Param) => void | Promise<void>,
|
|
50
|
+
) {
|
|
51
|
+
return super.once(eventName, listener as any);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public emit<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(eventName: Name, ...args: Param) {
|
|
55
|
+
return super.emit(eventName, ...args);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private runTaskQueue(deadline: IdleDeadline) {
|
|
59
|
+
while ((deadline.timeRemaining() > 15 || deadline.didTimeout) && this.taskList.length) {
|
|
60
|
+
const task = this.taskList.shift();
|
|
61
|
+
task!.handler(task!.data);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.taskList.length) {
|
|
65
|
+
this.taskHandle = globalThis.requestIdleCallback(this.runTaskQueue.bind(this), { timeout: 10000 });
|
|
66
|
+
} else {
|
|
67
|
+
this.taskHandle = 0;
|
|
68
|
+
|
|
69
|
+
this.emit('finish');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/utils/operator.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { toRaw } from 'vue';
|
|
|
2
2
|
import { isEmpty } from 'lodash-es';
|
|
3
3
|
|
|
4
4
|
import { Id, MContainer, MNode, NodeType } from '@tmagic/schema';
|
|
5
|
-
import { isPage, isPageFragment } from '@tmagic/utils';
|
|
5
|
+
import { calcValueByFontsize, isPage, isPageFragment } from '@tmagic/utils';
|
|
6
6
|
|
|
7
7
|
import editorService from '@editor/services/editor';
|
|
8
8
|
import propsService from '@editor/services/props';
|
|
@@ -15,7 +15,7 @@ import { generatePageNameByApp, getInitPositionStyle } from '@editor/utils/edito
|
|
|
15
15
|
* @param config 待粘贴的元素配置(复制时保存的那份配置)
|
|
16
16
|
* @returns
|
|
17
17
|
*/
|
|
18
|
-
export const beforePaste = (position: PastePosition, config: MNode[]): MNode[] => {
|
|
18
|
+
export const beforePaste = (position: PastePosition, config: MNode[], doc?: Document): MNode[] => {
|
|
19
19
|
if (!config[0]?.style) return config;
|
|
20
20
|
const curNode = editorService.get('node');
|
|
21
21
|
// 将数组中第一个元素的坐标作为参照点
|
|
@@ -29,7 +29,7 @@ export const beforePaste = (position: PastePosition, config: MNode[]): MNode[] =
|
|
|
29
29
|
if (!isEmpty(pastePosition) && curNode?.items) {
|
|
30
30
|
// 如果没有传入粘贴坐标则可能为键盘操作,不再转换
|
|
31
31
|
// 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
|
|
32
|
-
pastePosition = getPositionInContainer(pastePosition, curNode.id);
|
|
32
|
+
pastePosition = getPositionInContainer(pastePosition, curNode.id, doc);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// 将所有待粘贴元素坐标相对于多选第一个元素坐标重新计算,以保证多选粘贴后元素间距不变
|
|
@@ -71,12 +71,12 @@ export const beforePaste = (position: PastePosition, config: MNode[]): MNode[] =
|
|
|
71
71
|
* @param id 元素id
|
|
72
72
|
* @returns PastePosition 转换后的坐标
|
|
73
73
|
*/
|
|
74
|
-
export const getPositionInContainer = (position: PastePosition = {}, id: Id) => {
|
|
74
|
+
export const getPositionInContainer = (position: PastePosition = {}, id: Id, doc?: Document) => {
|
|
75
75
|
let { left = 0, top = 0 } = position;
|
|
76
76
|
const parentEl = editorService.get('stage')?.renderer?.contentWindow?.document.getElementById(`${id}`);
|
|
77
77
|
const parentElRect = parentEl?.getBoundingClientRect();
|
|
78
|
-
left = left - (parentElRect?.left || 0);
|
|
79
|
-
top = top - (parentElRect?.top || 0);
|
|
78
|
+
left = left - calcValueByFontsize(doc, parentElRect?.left || 0);
|
|
79
|
+
top = top - calcValueByFontsize(doc, parentElRect?.top || 0);
|
|
80
80
|
return {
|
|
81
81
|
left,
|
|
82
82
|
top,
|
package/types/editorProps.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { EventOption } from '@tmagic/core';
|
|
2
|
-
import type { CustomTargetOptions } from '@tmagic/dep';
|
|
3
2
|
import type { FormConfig, FormState } from '@tmagic/form';
|
|
4
3
|
import type { DataSourceSchema, Id, MApp, MNode } from '@tmagic/schema';
|
|
5
4
|
import StageCore, { ContainerHighlightType, type CustomizeMoveableOptionsCallbackConfig, type GuidesOptions, type MoveableOptions, RenderType, type UpdateDragEl } from '@tmagic/stage';
|
|
@@ -60,12 +59,6 @@ export interface EditorProps {
|
|
|
60
59
|
};
|
|
61
60
|
/** 禁用鼠标左键按下时就开始拖拽,需要先选中再可以拖拽 */
|
|
62
61
|
disabledDragStart?: boolean;
|
|
63
|
-
/** 自定义依赖收集器,复制组件时会将关联组件一并复制 */
|
|
64
|
-
collectorOptions?: CustomTargetOptions;
|
|
65
|
-
/** 自定义依赖收集器,复制组件时会将关联代码块一并复制 */
|
|
66
|
-
collectorOptionsForCode?: CustomTargetOptions;
|
|
67
|
-
/** 自定义依赖收集器,复制组件时会将关联数据源一并复制 */
|
|
68
|
-
collectorOptionsForDataSource?: CustomTargetOptions;
|
|
69
62
|
/** 标尺配置 */
|
|
70
63
|
guidesOptions?: Partial<GuidesOptions>;
|
|
71
64
|
/** 禁止多选 */
|
|
@@ -5,9 +5,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
5
5
|
extendState?: ((state: FormState) => Record<string, any> | Promise<Record<string, any>>) | undefined;
|
|
6
6
|
}>, {
|
|
7
7
|
configForm: import("vue").Ref<import("vue").CreateComponentPublicInstance<Readonly<import("vue").ExtractPropTypes<{
|
|
8
|
-
size: {
|
|
9
|
-
type: import("vue").PropType<"default" | "small" | "large">;
|
|
10
|
-
};
|
|
11
8
|
popperClass: {
|
|
12
9
|
type: import("vue").PropType<string>;
|
|
13
10
|
};
|
|
@@ -15,6 +12,9 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
15
12
|
type: import("vue").PropType<string>;
|
|
16
13
|
default: string;
|
|
17
14
|
};
|
|
15
|
+
size: {
|
|
16
|
+
type: import("vue").PropType<"default" | "small" | "large">;
|
|
17
|
+
};
|
|
18
18
|
disabled: {
|
|
19
19
|
type: import("vue").PropType<boolean>;
|
|
20
20
|
default: boolean;
|
|
@@ -83,9 +83,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
83
83
|
"field-input": (...args: any[]) => void;
|
|
84
84
|
"field-change": (...args: any[]) => void;
|
|
85
85
|
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<import("vue").ExtractPropTypes<{
|
|
86
|
-
size: {
|
|
87
|
-
type: import("vue").PropType<"default" | "small" | "large">;
|
|
88
|
-
};
|
|
89
86
|
popperClass: {
|
|
90
87
|
type: import("vue").PropType<string>;
|
|
91
88
|
};
|
|
@@ -93,6 +90,9 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
93
90
|
type: import("vue").PropType<string>;
|
|
94
91
|
default: string;
|
|
95
92
|
};
|
|
93
|
+
size: {
|
|
94
|
+
type: import("vue").PropType<"default" | "small" | "large">;
|
|
95
|
+
};
|
|
96
96
|
disabled: {
|
|
97
97
|
type: import("vue").PropType<boolean>;
|
|
98
98
|
default: boolean;
|
|
@@ -168,9 +168,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
168
168
|
M: {};
|
|
169
169
|
Defaults: {};
|
|
170
170
|
}, Readonly<import("vue").ExtractPropTypes<{
|
|
171
|
-
size: {
|
|
172
|
-
type: import("vue").PropType<"default" | "small" | "large">;
|
|
173
|
-
};
|
|
174
171
|
popperClass: {
|
|
175
172
|
type: import("vue").PropType<string>;
|
|
176
173
|
};
|
|
@@ -178,6 +175,9 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
178
175
|
type: import("vue").PropType<string>;
|
|
179
176
|
default: string;
|
|
180
177
|
};
|
|
178
|
+
size: {
|
|
179
|
+
type: import("vue").PropType<"default" | "small" | "large">;
|
|
180
|
+
};
|
|
181
181
|
disabled: {
|
|
182
182
|
type: import("vue").PropType<boolean>;
|
|
183
183
|
default: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Writable } from 'type-fest';
|
|
2
|
+
import { type TargetOptions } from '@tmagic/dep';
|
|
2
3
|
import type { ColumnConfig } from '@tmagic/form';
|
|
3
4
|
import type { CodeBlockContent, CodeBlockDSL, Id, MNode } from '@tmagic/schema';
|
|
4
5
|
import type { AsyncHookPlugin } from '../type';
|
|
@@ -114,7 +115,7 @@ declare class CodeBlock extends BaseService {
|
|
|
114
115
|
* @param config 组件节点配置
|
|
115
116
|
* @returns
|
|
116
117
|
*/
|
|
117
|
-
copyWithRelated(config: MNode | MNode[]): void;
|
|
118
|
+
copyWithRelated(config: MNode | MNode[], collectorOptions?: TargetOptions): void;
|
|
118
119
|
/**
|
|
119
120
|
* 粘贴代码块
|
|
120
121
|
* @returns
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Writable } from 'type-fest';
|
|
2
2
|
import type { EventOption } from '@tmagic/core';
|
|
3
|
+
import { type TargetOptions } from '@tmagic/dep';
|
|
3
4
|
import type { FormConfig } from '@tmagic/form';
|
|
4
5
|
import type { DataSourceSchema, MNode } from '@tmagic/schema';
|
|
5
6
|
import type { DatasourceTypeOption, SyncHookPlugin } from '../type';
|
|
@@ -55,7 +56,7 @@ declare class DataSource extends BaseService {
|
|
|
55
56
|
* @param config 组件节点配置
|
|
56
57
|
* @returns
|
|
57
58
|
*/
|
|
58
|
-
copyWithRelated(config: MNode | MNode[]): void;
|
|
59
|
+
copyWithRelated(config: MNode | MNode[], collectorOptions?: TargetOptions): void;
|
|
59
60
|
/**
|
|
60
61
|
* 粘贴数据源
|
|
61
62
|
* @returns
|
package/types/services/dep.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { DepTargetType, type Target } from '@tmagic/dep';
|
|
1
|
+
import { type DepExtendedData, DepTargetType, type Target } from '@tmagic/dep';
|
|
2
2
|
import type { Id, MNode } from '@tmagic/schema';
|
|
3
3
|
import BaseService from './BaseService';
|
|
4
|
+
export interface DepEvents {
|
|
5
|
+
'add-target': [target: Target];
|
|
6
|
+
'remove-target': [id: string | number];
|
|
7
|
+
collected: [nodes: MNode[], deep: boolean];
|
|
8
|
+
}
|
|
4
9
|
declare class Dep extends BaseService {
|
|
5
10
|
private watcher;
|
|
6
11
|
removeTargets(type?: string): void;
|
|
@@ -12,11 +17,16 @@ declare class Dep extends BaseService {
|
|
|
12
17
|
addTarget(target: Target): void;
|
|
13
18
|
removeTarget(id: Id, type?: string): void;
|
|
14
19
|
clearTargets(): void;
|
|
15
|
-
collect(nodes: MNode[], deep?: boolean, type?: DepTargetType): void;
|
|
20
|
+
collect(nodes: MNode[], depExtendedData?: DepExtendedData, deep?: boolean, type?: DepTargetType): void;
|
|
21
|
+
collectIdle(nodes: MNode[], depExtendedData?: DepExtendedData, deep?: boolean, type?: DepTargetType): void;
|
|
22
|
+
collectNode(node: MNode, target: Target, depExtendedData?: DepExtendedData, deep?: boolean): void;
|
|
16
23
|
clear(nodes?: MNode[]): void;
|
|
17
24
|
clearByType(type: DepTargetType, nodes?: MNode[]): void;
|
|
18
25
|
hasTarget(id: Id, type?: string): boolean;
|
|
19
26
|
hasSpecifiedTypeTarget(type?: string): boolean;
|
|
27
|
+
on<Name extends keyof DepEvents, Param extends DepEvents[Name]>(eventName: Name, listener: (...args: Param) => void | Promise<void>): this;
|
|
28
|
+
once<Name extends keyof DepEvents, Param extends DepEvents[Name]>(eventName: Name, listener: (...args: Param) => void | Promise<void>): this;
|
|
29
|
+
emit<Name extends keyof DepEvents, Param extends DepEvents[Name]>(eventName: Name, ...args: Param): boolean;
|
|
20
30
|
}
|
|
21
31
|
export type DepService = Dep;
|
|
22
32
|
declare const _default: Dep;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Writable } from 'type-fest';
|
|
2
|
+
import { type TargetOptions } from '@tmagic/dep';
|
|
2
3
|
import type { Id, MContainer, MNode } from '@tmagic/schema';
|
|
3
4
|
import BaseService from '../services/BaseService';
|
|
4
5
|
import type { AddMNode, AsyncHookPlugin, EditorNodeInfo, PastePosition, StepValue, StoreState, StoreStateKey } from '../type';
|
|
@@ -109,13 +110,13 @@ declare class Editor extends BaseService {
|
|
|
109
110
|
* @param config 组件节点配置
|
|
110
111
|
* @returns
|
|
111
112
|
*/
|
|
112
|
-
copyWithRelated(config: MNode | MNode[]): void;
|
|
113
|
+
copyWithRelated(config: MNode | MNode[], collectorOptions?: TargetOptions): void;
|
|
113
114
|
/**
|
|
114
115
|
* 从localStorage中获取节点,然后添加到当前容器中
|
|
115
116
|
* @param position 粘贴的坐标
|
|
116
117
|
* @returns 添加后的组件节点配置
|
|
117
118
|
*/
|
|
118
|
-
paste(position?: PastePosition): Promise<MNode | MNode[] | void>;
|
|
119
|
+
paste(position?: PastePosition, collectorOptions?: TargetOptions): Promise<MNode | MNode[] | void>;
|
|
119
120
|
doPaste(config: MNode[], position?: PastePosition): Promise<MNode[]>;
|
|
120
121
|
doAlignCenter(config: MNode): Promise<MNode>;
|
|
121
122
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Writable } from 'type-fest';
|
|
2
|
+
import { type TargetOptions } from '@tmagic/dep';
|
|
2
3
|
import type { FormConfig } from '@tmagic/form';
|
|
3
4
|
import type { MNode } from '@tmagic/schema';
|
|
4
5
|
import type { AsyncHookPlugin, SyncHookPlugin } from '../type';
|
|
@@ -66,7 +67,7 @@ declare class Props extends BaseService {
|
|
|
66
67
|
* @param originConfigs 原组件配置
|
|
67
68
|
* @param targetConfigs 待替换的组件配置
|
|
68
69
|
*/
|
|
69
|
-
replaceRelateId(originConfigs: MNode[], targetConfigs: MNode[]): void;
|
|
70
|
+
replaceRelateId(originConfigs: MNode[], targetConfigs: MNode[], collectorOptions: TargetOptions): void;
|
|
70
71
|
/**
|
|
71
72
|
* 清除setNewItemId前后映射关系
|
|
72
73
|
*/
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
export interface IdleTaskEvents {
|
|
4
|
+
finish: [];
|
|
5
|
+
}
|
|
6
|
+
export declare class IdleTask<T = any> extends EventEmitter {
|
|
7
|
+
private taskList;
|
|
8
|
+
private taskHandle;
|
|
9
|
+
enqueueTask(taskHandler: (data: T) => void, taskData: T): void;
|
|
10
|
+
on<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(eventName: Name, listener: (...args: Param) => void | Promise<void>): this;
|
|
11
|
+
once<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(eventName: Name, listener: (...args: Param) => void | Promise<void>): this;
|
|
12
|
+
emit<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(eventName: Name, ...args: Param): boolean;
|
|
13
|
+
private runTaskQueue;
|
|
14
|
+
}
|
|
@@ -6,14 +6,14 @@ import type { AddMNode, PastePosition } from '../type';
|
|
|
6
6
|
* @param config 待粘贴的元素配置(复制时保存的那份配置)
|
|
7
7
|
* @returns
|
|
8
8
|
*/
|
|
9
|
-
export declare const beforePaste: (position: PastePosition, config: MNode[]) => MNode[];
|
|
9
|
+
export declare const beforePaste: (position: PastePosition, config: MNode[], doc?: Document) => MNode[];
|
|
10
10
|
/**
|
|
11
11
|
* 将元素粘贴到容器内时,将相对于画布坐标转换为相对于容器的坐标
|
|
12
12
|
* @param position PastePosition 粘贴时相对于画布的坐标
|
|
13
13
|
* @param id 元素id
|
|
14
14
|
* @returns PastePosition 转换后的坐标
|
|
15
15
|
*/
|
|
16
|
-
export declare const getPositionInContainer: (position: PastePosition | undefined, id: Id) => {
|
|
16
|
+
export declare const getPositionInContainer: (position: PastePosition | undefined, id: Id, doc?: Document) => {
|
|
17
17
|
left: number;
|
|
18
18
|
top: number;
|
|
19
19
|
};
|