@flowgram.ai/free-node-panel-plugin 0.1.0-alpha.4 → 0.1.0-alpha.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/esm/index.js +365 -263
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +92 -21
- package/dist/index.d.ts +92 -21
- package/dist/index.js +369 -265
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
package/dist/esm/index.js
CHANGED
|
@@ -10,27 +10,135 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/create-plugin.ts
|
|
13
|
-
import {
|
|
14
|
-
definePluginCreator
|
|
15
|
-
} from "@flowgram.ai/core";
|
|
13
|
+
import { definePluginCreator } from "@flowgram.ai/core";
|
|
16
14
|
|
|
17
15
|
// src/service.ts
|
|
18
16
|
import { inject, injectable } from "inversify";
|
|
19
|
-
import {
|
|
17
|
+
import { DisposableCollection } from "@flowgram.ai/utils";
|
|
20
18
|
import {
|
|
21
19
|
WorkflowDocument,
|
|
22
20
|
WorkflowDragService,
|
|
23
|
-
WorkflowLinesManager
|
|
24
|
-
WorkflowNodePortsData
|
|
21
|
+
WorkflowLinesManager as WorkflowLinesManager2
|
|
25
22
|
} from "@flowgram.ai/free-layout-core";
|
|
26
23
|
import { WorkflowSelectService } from "@flowgram.ai/free-layout-core";
|
|
27
|
-
import {
|
|
28
|
-
import { FlowNodeTransformData } from "@flowgram.ai/document";
|
|
29
|
-
import { FlowNodeBaseType } from "@flowgram.ai/document";
|
|
24
|
+
import { HistoryService as HistoryService2 } from "@flowgram.ai/free-history-plugin";
|
|
30
25
|
import { PlaygroundConfigEntity } from "@flowgram.ai/core";
|
|
26
|
+
|
|
27
|
+
// src/utils/wait-node-render.ts
|
|
28
|
+
import { delay } from "@flowgram.ai/free-layout-core";
|
|
29
|
+
var waitNodeRender = async () => {
|
|
30
|
+
await delay(20);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/utils/update-sub-nodes-position.ts
|
|
34
|
+
import { FreeOperationType } from "@flowgram.ai/free-history-plugin";
|
|
31
35
|
import { TransformData } from "@flowgram.ai/core";
|
|
32
36
|
|
|
33
|
-
// src/utils.ts
|
|
37
|
+
// src/utils/get-port-box.ts
|
|
38
|
+
import { Rectangle } from "@flowgram.ai/utils";
|
|
39
|
+
import { FlowNodeTransformData } from "@flowgram.ai/document";
|
|
40
|
+
|
|
41
|
+
// src/utils/is-container.ts
|
|
42
|
+
var isContainer = (node) => node?.getNodeMeta().isContainer ?? false;
|
|
43
|
+
|
|
44
|
+
// src/utils/get-port-box.ts
|
|
45
|
+
var getPortBox = (port, offset = { x: 0, y: 0 }) => {
|
|
46
|
+
const node = port.node;
|
|
47
|
+
if (isContainer(node)) {
|
|
48
|
+
const { point } = port;
|
|
49
|
+
if (port.portType === "input") {
|
|
50
|
+
return new Rectangle(point.x + offset.x, point.y - 50 + offset.y, 300, 100);
|
|
51
|
+
}
|
|
52
|
+
return new Rectangle(point.x - 300, point.y - 50, 300, 100);
|
|
53
|
+
}
|
|
54
|
+
const box = node.getData(FlowNodeTransformData).bounds;
|
|
55
|
+
return box;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/utils/update-sub-nodes-position.ts
|
|
59
|
+
var updateSubSequentNodesPosition = (params) => {
|
|
60
|
+
const {
|
|
61
|
+
node,
|
|
62
|
+
subsequentNodes,
|
|
63
|
+
fromPort,
|
|
64
|
+
toPort,
|
|
65
|
+
containerNode,
|
|
66
|
+
offset,
|
|
67
|
+
historyService,
|
|
68
|
+
dragService
|
|
69
|
+
} = params;
|
|
70
|
+
if (!offset || !toPort) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const subsequentNodesPositions = subsequentNodes.map((node2) => {
|
|
74
|
+
const nodeTrans2 = node2.getData(TransformData);
|
|
75
|
+
return {
|
|
76
|
+
x: nodeTrans2.position.x,
|
|
77
|
+
y: nodeTrans2.position.y
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
historyService.pushOperation({
|
|
81
|
+
type: FreeOperationType.dragNodes,
|
|
82
|
+
value: {
|
|
83
|
+
ids: subsequentNodes.map((node2) => node2.id),
|
|
84
|
+
value: subsequentNodesPositions.map((position) => ({
|
|
85
|
+
x: position.x + offset.x,
|
|
86
|
+
y: position.y + offset.y
|
|
87
|
+
})),
|
|
88
|
+
oldValue: subsequentNodesPositions
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const fromBox = getPortBox(fromPort);
|
|
92
|
+
const toBox = getPortBox(toPort, offset);
|
|
93
|
+
const nodeTrans = node.getData(TransformData);
|
|
94
|
+
let nodePos = {
|
|
95
|
+
x: (fromBox.center.x + toBox.center.x) / 2,
|
|
96
|
+
y: (fromBox.y + toBox.y) / 2
|
|
97
|
+
};
|
|
98
|
+
if (containerNode) {
|
|
99
|
+
nodePos = dragService.adjustSubNodePosition(
|
|
100
|
+
node.flowNodeType,
|
|
101
|
+
containerNode,
|
|
102
|
+
nodePos
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
historyService.pushOperation({
|
|
106
|
+
type: FreeOperationType.dragNodes,
|
|
107
|
+
value: {
|
|
108
|
+
ids: [node.id],
|
|
109
|
+
value: [nodePos],
|
|
110
|
+
oldValue: [
|
|
111
|
+
{
|
|
112
|
+
x: nodeTrans.position.x,
|
|
113
|
+
y: nodeTrans.position.y
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// src/utils/sub-position-offset.ts
|
|
121
|
+
import { Rectangle as Rectangle3 } from "@flowgram.ai/utils";
|
|
122
|
+
import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
|
|
123
|
+
|
|
124
|
+
// src/utils/rect-distance.ts
|
|
125
|
+
import { Rectangle as Rectangle2 } from "@flowgram.ai/utils";
|
|
126
|
+
var rectDistance = (rectA, rectB) => {
|
|
127
|
+
const distanceX = Math.abs(Math.min(rectA.right, rectB.right) - Math.max(rectA.left, rectB.left));
|
|
128
|
+
const distanceY = Math.abs(Math.min(rectA.bottom, rectB.bottom) - Math.max(rectA.top, rectB.top));
|
|
129
|
+
if (Rectangle2.intersects(rectA, rectB)) {
|
|
130
|
+
return {
|
|
131
|
+
x: -distanceX,
|
|
132
|
+
y: -distanceY
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
x: distanceX,
|
|
137
|
+
y: distanceY
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/utils/greater-or-less.ts
|
|
34
142
|
var isGreaterThan = (a, b) => {
|
|
35
143
|
if (a === void 0 || b === void 0) {
|
|
36
144
|
return false;
|
|
@@ -46,6 +154,213 @@ var isLessThan = (a, b) => {
|
|
|
46
154
|
return b - a > EPSILON;
|
|
47
155
|
};
|
|
48
156
|
|
|
157
|
+
// src/utils/sub-position-offset.ts
|
|
158
|
+
var subPositionOffset = (params) => {
|
|
159
|
+
const { node, fromPort, toPort, padding } = params;
|
|
160
|
+
const fromBox = getPortBox(fromPort);
|
|
161
|
+
const toBox = getPortBox(toPort);
|
|
162
|
+
const nodeTrans = node.getData(FlowNodeTransformData2);
|
|
163
|
+
const nodeSize = node.getNodeMeta()?.size ?? {
|
|
164
|
+
width: nodeTrans.bounds.width,
|
|
165
|
+
height: nodeTrans.bounds.height
|
|
166
|
+
};
|
|
167
|
+
const minDistance = {
|
|
168
|
+
x: nodeSize.width + padding.x,
|
|
169
|
+
y: nodeSize.height + padding.y
|
|
170
|
+
};
|
|
171
|
+
const boxDistance = rectDistance(fromBox, toBox);
|
|
172
|
+
const neededOffset = {
|
|
173
|
+
x: isGreaterThan(boxDistance.x, minDistance.x) ? 0 : minDistance.x - boxDistance.x,
|
|
174
|
+
y: isGreaterThan(boxDistance.y, minDistance.y) ? 0 : minDistance.y - boxDistance.y
|
|
175
|
+
};
|
|
176
|
+
if (neededOffset.x === 0 || neededOffset.y === 0) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const intersection = {
|
|
180
|
+
// 这里没有写反,Rectangle内置的算法是反的
|
|
181
|
+
vertical: Rectangle3.intersects(fromBox, toBox, "horizontal"),
|
|
182
|
+
horizontal: Rectangle3.intersects(fromBox, toBox, "vertical")
|
|
183
|
+
};
|
|
184
|
+
let offsetX = 0;
|
|
185
|
+
let offsetY = 0;
|
|
186
|
+
if (!intersection.horizontal) {
|
|
187
|
+
if (isGreaterThan(toBox.center.y, fromBox.center.y)) {
|
|
188
|
+
offsetY = neededOffset.y;
|
|
189
|
+
} else if (isLessThan(toBox.center.y, fromBox.center.y)) {
|
|
190
|
+
offsetY = -neededOffset.y;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (!intersection.vertical) {
|
|
194
|
+
if (isGreaterThan(toBox.center.x, fromBox.center.x)) {
|
|
195
|
+
offsetX = neededOffset.x;
|
|
196
|
+
} else if (isLessThan(toBox.center.x, fromBox.center.x)) {
|
|
197
|
+
offsetX = -neededOffset.x;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
x: offsetX,
|
|
202
|
+
y: offsetY
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// src/utils/get-sub-nodes.ts
|
|
207
|
+
var getSubsequentNodes = (params) => {
|
|
208
|
+
const { node, linesManager } = params;
|
|
209
|
+
if (isContainer(node)) {
|
|
210
|
+
return [];
|
|
211
|
+
}
|
|
212
|
+
const brothers = node.parent?.blocks ?? [];
|
|
213
|
+
const linkedBrothers = /* @__PURE__ */ new Set();
|
|
214
|
+
const linesMap = /* @__PURE__ */ new Map();
|
|
215
|
+
linesManager.getAllLines().forEach((line) => {
|
|
216
|
+
if (!linesMap.has(line.from.id)) {
|
|
217
|
+
linesMap.set(line.from.id, []);
|
|
218
|
+
}
|
|
219
|
+
if (!line.to?.id || isContainer(line.to)) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
linesMap.get(line.from.id)?.push(line.to.id);
|
|
223
|
+
});
|
|
224
|
+
const bfs = (nodeId) => {
|
|
225
|
+
if (linkedBrothers.has(nodeId)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
linkedBrothers.add(nodeId);
|
|
229
|
+
const nextNodes = linesMap.get(nodeId) ?? [];
|
|
230
|
+
nextNodes.forEach(bfs);
|
|
231
|
+
};
|
|
232
|
+
bfs(node.id);
|
|
233
|
+
const subsequentNodes = brothers.filter((node2) => linkedBrothers.has(node2.id));
|
|
234
|
+
return subsequentNodes;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// src/utils/sub-nodes-auto-offset.ts
|
|
238
|
+
var subNodesAutoOffset = (params) => {
|
|
239
|
+
const {
|
|
240
|
+
node,
|
|
241
|
+
fromPort,
|
|
242
|
+
toPort,
|
|
243
|
+
linesManager,
|
|
244
|
+
historyService,
|
|
245
|
+
dragService,
|
|
246
|
+
containerNode,
|
|
247
|
+
padding = {
|
|
248
|
+
x: 100,
|
|
249
|
+
y: 100
|
|
250
|
+
}
|
|
251
|
+
} = params;
|
|
252
|
+
const subOffset = subPositionOffset({
|
|
253
|
+
node,
|
|
254
|
+
fromPort,
|
|
255
|
+
toPort,
|
|
256
|
+
padding
|
|
257
|
+
});
|
|
258
|
+
const subsequentNodes = getSubsequentNodes({
|
|
259
|
+
node: toPort.node,
|
|
260
|
+
linesManager
|
|
261
|
+
});
|
|
262
|
+
updateSubSequentNodesPosition({
|
|
263
|
+
node,
|
|
264
|
+
subsequentNodes,
|
|
265
|
+
fromPort,
|
|
266
|
+
toPort,
|
|
267
|
+
containerNode,
|
|
268
|
+
offset: subOffset,
|
|
269
|
+
historyService,
|
|
270
|
+
dragService
|
|
271
|
+
});
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// src/utils/get-container-node.ts
|
|
275
|
+
var getContainerNode = (params) => {
|
|
276
|
+
const { fromPort, containerNode } = params;
|
|
277
|
+
if (containerNode) {
|
|
278
|
+
return containerNode;
|
|
279
|
+
}
|
|
280
|
+
const fromNode = fromPort?.node;
|
|
281
|
+
const fromContainer = fromNode?.parent;
|
|
282
|
+
if (isContainer(fromNode)) {
|
|
283
|
+
return fromNode;
|
|
284
|
+
}
|
|
285
|
+
return fromContainer;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// src/utils/build-line.ts
|
|
289
|
+
import {
|
|
290
|
+
WorkflowNodePortsData
|
|
291
|
+
} from "@flowgram.ai/free-layout-core";
|
|
292
|
+
var buildLine = (params) => {
|
|
293
|
+
const { fromPort, node, toPort, linesManager } = params;
|
|
294
|
+
const portsData = node.getData(WorkflowNodePortsData);
|
|
295
|
+
if (!portsData) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const shouldBuildFromLine = portsData.inputPorts?.length > 0;
|
|
299
|
+
if (fromPort && shouldBuildFromLine) {
|
|
300
|
+
const toTargetPort = portsData.inputPorts[0];
|
|
301
|
+
const isSingleInput = portsData.inputPorts.length === 1;
|
|
302
|
+
linesManager.createLine({
|
|
303
|
+
from: fromPort.node.id,
|
|
304
|
+
fromPort: fromPort.portID,
|
|
305
|
+
to: node.id,
|
|
306
|
+
toPort: isSingleInput ? void 0 : toTargetPort.id
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
const shouldBuildToLine = portsData.outputPorts?.length > 0;
|
|
310
|
+
if (toPort && shouldBuildToLine) {
|
|
311
|
+
const fromTargetPort = portsData.outputPorts[0];
|
|
312
|
+
linesManager.createLine({
|
|
313
|
+
from: node.id,
|
|
314
|
+
fromPort: fromTargetPort.portID,
|
|
315
|
+
to: toPort.node.id,
|
|
316
|
+
toPort: toPort.portID
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// src/utils/adjust-node-position.ts
|
|
322
|
+
var adjustNodePosition = (params) => {
|
|
323
|
+
const { nodeType, position, fromPort, toPort, containerNode, document, dragService } = params;
|
|
324
|
+
const register = document.getNodeRegistry(nodeType);
|
|
325
|
+
const size = register?.meta?.size;
|
|
326
|
+
let adjustedPosition = position;
|
|
327
|
+
if (!size) {
|
|
328
|
+
adjustedPosition = position;
|
|
329
|
+
} else if (fromPort && toPort) {
|
|
330
|
+
adjustedPosition = {
|
|
331
|
+
x: position.x,
|
|
332
|
+
y: position.y - size.height / 2
|
|
333
|
+
};
|
|
334
|
+
} else if (fromPort && !toPort) {
|
|
335
|
+
adjustedPosition = {
|
|
336
|
+
x: position.x + size.width / 2,
|
|
337
|
+
y: position.y - size.height / 2
|
|
338
|
+
};
|
|
339
|
+
} else if (!fromPort && toPort) {
|
|
340
|
+
adjustedPosition = {
|
|
341
|
+
x: position.x - size.width / 2,
|
|
342
|
+
y: position.y - size.height / 2
|
|
343
|
+
};
|
|
344
|
+
} else {
|
|
345
|
+
adjustedPosition = position;
|
|
346
|
+
}
|
|
347
|
+
return dragService.adjustSubNodePosition(nodeType, containerNode, adjustedPosition);
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
// src/utils/index.ts
|
|
351
|
+
var WorkflowNodePanelUtils = {
|
|
352
|
+
adjustNodePosition,
|
|
353
|
+
buildLine,
|
|
354
|
+
getPortBox,
|
|
355
|
+
getSubsequentNodes,
|
|
356
|
+
getContainerNode,
|
|
357
|
+
rectDistance,
|
|
358
|
+
subNodesAutoOffset,
|
|
359
|
+
subPositionOffset,
|
|
360
|
+
updateSubSequentNodesPosition,
|
|
361
|
+
waitNodeRender
|
|
362
|
+
};
|
|
363
|
+
|
|
49
364
|
// src/service.ts
|
|
50
365
|
var WorkflowNodePanelService = class {
|
|
51
366
|
constructor() {
|
|
@@ -78,7 +393,7 @@ var WorkflowNodePanelService = class {
|
|
|
78
393
|
position: panelPosition,
|
|
79
394
|
enableMultiAdd,
|
|
80
395
|
panelProps,
|
|
81
|
-
containerNode:
|
|
396
|
+
containerNode: WorkflowNodePanelUtils.getContainerNode({
|
|
82
397
|
fromPort,
|
|
83
398
|
containerNode
|
|
84
399
|
}),
|
|
@@ -97,6 +412,23 @@ var WorkflowNodePanelService = class {
|
|
|
97
412
|
});
|
|
98
413
|
});
|
|
99
414
|
}
|
|
415
|
+
/**
|
|
416
|
+
* 唤起单选面板
|
|
417
|
+
*/
|
|
418
|
+
async singleSelectNodePanel(params) {
|
|
419
|
+
return new Promise((resolve) => {
|
|
420
|
+
this.callNodePanel({
|
|
421
|
+
...params,
|
|
422
|
+
enableMultiAdd: false,
|
|
423
|
+
onSelect: async (panelParams) => {
|
|
424
|
+
resolve(panelParams);
|
|
425
|
+
},
|
|
426
|
+
onClose: () => {
|
|
427
|
+
resolve(void 0);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
}
|
|
100
432
|
/** 添加节点 */
|
|
101
433
|
async addNode(callParams, panelParams) {
|
|
102
434
|
const {
|
|
@@ -117,7 +449,7 @@ var WorkflowNodePanelService = class {
|
|
|
117
449
|
return;
|
|
118
450
|
}
|
|
119
451
|
const { nodeType, selectEvent, nodeJSON } = panelParams;
|
|
120
|
-
const containerNode =
|
|
452
|
+
const containerNode = WorkflowNodePanelUtils.getContainerNode({
|
|
121
453
|
fromPort,
|
|
122
454
|
containerNode: callParams.containerNode
|
|
123
455
|
});
|
|
@@ -128,14 +460,16 @@ var WorkflowNodePanelService = class {
|
|
|
128
460
|
}
|
|
129
461
|
}
|
|
130
462
|
const selectPosition = this.playgroundConfig.getPosFromMouseEvent(selectEvent);
|
|
131
|
-
const nodePosition = callParams.customPosition ? callParams.customPosition({ nodeType, selectPosition }) :
|
|
463
|
+
const nodePosition = callParams.customPosition ? callParams.customPosition({ nodeType, selectPosition }) : WorkflowNodePanelUtils.adjustNodePosition({
|
|
132
464
|
nodeType,
|
|
133
465
|
position: enableSelectPosition ? selectPosition : panelPosition,
|
|
134
466
|
fromPort,
|
|
135
467
|
toPort,
|
|
136
|
-
containerNode
|
|
468
|
+
containerNode,
|
|
469
|
+
document: this.document,
|
|
470
|
+
dragService: this.dragService
|
|
137
471
|
});
|
|
138
|
-
const node =
|
|
472
|
+
const node = this.document.createWorkflowNodeByType(
|
|
139
473
|
nodeType,
|
|
140
474
|
nodePosition,
|
|
141
475
|
nodeJSON ?? {},
|
|
@@ -145,31 +479,27 @@ var WorkflowNodePanelService = class {
|
|
|
145
479
|
return;
|
|
146
480
|
}
|
|
147
481
|
if (enableAutoOffset && fromPort && toPort) {
|
|
148
|
-
|
|
482
|
+
WorkflowNodePanelUtils.subNodesAutoOffset({
|
|
149
483
|
node,
|
|
150
484
|
fromPort,
|
|
151
485
|
toPort,
|
|
152
|
-
padding: autoOffsetPadding
|
|
153
|
-
});
|
|
154
|
-
const subsequentNodes = this.getSubsequentNodes(toPort.node);
|
|
155
|
-
this.updateSubSequentNodesPosition({
|
|
156
|
-
node,
|
|
157
|
-
subsequentNodes,
|
|
158
|
-
fromPort,
|
|
159
|
-
toPort,
|
|
486
|
+
padding: autoOffsetPadding,
|
|
160
487
|
containerNode,
|
|
161
|
-
|
|
488
|
+
historyService: this.historyService,
|
|
489
|
+
dragService: this.dragService,
|
|
490
|
+
linesManager: this.linesManager
|
|
162
491
|
});
|
|
163
492
|
}
|
|
164
493
|
if (!enableBuildLine && !enableDragNode) {
|
|
165
494
|
return node;
|
|
166
495
|
}
|
|
167
|
-
await
|
|
496
|
+
await WorkflowNodePanelUtils.waitNodeRender();
|
|
168
497
|
if (enableBuildLine) {
|
|
169
|
-
|
|
498
|
+
WorkflowNodePanelUtils.buildLine({
|
|
170
499
|
fromPort,
|
|
171
500
|
node,
|
|
172
|
-
toPort
|
|
501
|
+
toPort,
|
|
502
|
+
linesManager: this.linesManager
|
|
173
503
|
});
|
|
174
504
|
}
|
|
175
505
|
if (enableDragNode) {
|
|
@@ -178,236 +508,6 @@ var WorkflowNodePanelService = class {
|
|
|
178
508
|
}
|
|
179
509
|
return node;
|
|
180
510
|
}
|
|
181
|
-
/** 建立连线 */
|
|
182
|
-
buildLine(params) {
|
|
183
|
-
const { fromPort, node, toPort } = params;
|
|
184
|
-
const portsData = node.getData(WorkflowNodePortsData);
|
|
185
|
-
if (!portsData) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
const shouldBuildFromLine = portsData.inputPorts?.length > 0;
|
|
189
|
-
if (fromPort && shouldBuildFromLine) {
|
|
190
|
-
const toTargetPort = portsData.inputPorts[0];
|
|
191
|
-
const isSingleInput = portsData.inputPorts.length === 1;
|
|
192
|
-
this.linesManager.createLine({
|
|
193
|
-
from: fromPort.node.id,
|
|
194
|
-
fromPort: fromPort.portID,
|
|
195
|
-
to: node.id,
|
|
196
|
-
toPort: isSingleInput ? void 0 : toTargetPort.id
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
const shouldBuildToLine = portsData.outputPorts?.length > 0;
|
|
200
|
-
if (toPort && shouldBuildToLine) {
|
|
201
|
-
const fromTargetPort = portsData.outputPorts[0];
|
|
202
|
-
this.linesManager.createLine({
|
|
203
|
-
from: node.id,
|
|
204
|
-
fromPort: fromTargetPort.portID,
|
|
205
|
-
to: toPort.node.id,
|
|
206
|
-
toPort: toPort.portID
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/** 调整节点坐标 */
|
|
211
|
-
adjustNodePosition(params) {
|
|
212
|
-
const { nodeType, position, fromPort, toPort, containerNode } = params;
|
|
213
|
-
const register = this.document.getNodeRegistry(nodeType);
|
|
214
|
-
const size = register?.meta?.size;
|
|
215
|
-
let adjustedPosition = position;
|
|
216
|
-
if (!size) {
|
|
217
|
-
adjustedPosition = position;
|
|
218
|
-
} else if (fromPort && toPort) {
|
|
219
|
-
adjustedPosition = {
|
|
220
|
-
x: position.x,
|
|
221
|
-
y: position.y - size.height / 2
|
|
222
|
-
};
|
|
223
|
-
} else if (fromPort && !toPort) {
|
|
224
|
-
adjustedPosition = {
|
|
225
|
-
x: position.x + size.width / 2,
|
|
226
|
-
y: position.y - size.height / 2
|
|
227
|
-
};
|
|
228
|
-
} else if (!fromPort && toPort) {
|
|
229
|
-
adjustedPosition = {
|
|
230
|
-
x: position.x - size.width / 2,
|
|
231
|
-
y: position.y - size.height / 2
|
|
232
|
-
};
|
|
233
|
-
} else {
|
|
234
|
-
adjustedPosition = position;
|
|
235
|
-
}
|
|
236
|
-
return this.dragService.adjustSubNodePosition(nodeType, containerNode, adjustedPosition);
|
|
237
|
-
}
|
|
238
|
-
getContainerNode(params) {
|
|
239
|
-
const { fromPort, containerNode } = params;
|
|
240
|
-
if (containerNode) {
|
|
241
|
-
return containerNode;
|
|
242
|
-
}
|
|
243
|
-
const fromNode = fromPort?.node;
|
|
244
|
-
const fromContainer = fromNode?.parent;
|
|
245
|
-
if (fromNode?.flowNodeType === FlowNodeBaseType.SUB_CANVAS) {
|
|
246
|
-
return fromNode;
|
|
247
|
-
}
|
|
248
|
-
return fromContainer;
|
|
249
|
-
}
|
|
250
|
-
/** 获取端口矩形 */
|
|
251
|
-
getPortBox(port, offset = { x: 0, y: 0 }) {
|
|
252
|
-
const node = port.node;
|
|
253
|
-
if (node.flowNodeType === FlowNodeBaseType.SUB_CANVAS) {
|
|
254
|
-
const { point } = port;
|
|
255
|
-
if (port.portType === "input") {
|
|
256
|
-
return new Rectangle(point.x + offset.x, point.y - 50 + offset.y, 300, 100);
|
|
257
|
-
}
|
|
258
|
-
return new Rectangle(point.x - 300, point.y - 50, 300, 100);
|
|
259
|
-
}
|
|
260
|
-
const box = node.getData(FlowNodeTransformData).bounds;
|
|
261
|
-
return box;
|
|
262
|
-
}
|
|
263
|
-
/** 后续节点位置偏移 */
|
|
264
|
-
subPositionOffset(params) {
|
|
265
|
-
const { node, fromPort, toPort, padding } = params;
|
|
266
|
-
const fromBox = this.getPortBox(fromPort);
|
|
267
|
-
const toBox = this.getPortBox(toPort);
|
|
268
|
-
const nodeTrans = node.getData(FlowNodeTransformData);
|
|
269
|
-
const nodeSize = node.getNodeMeta()?.size ?? {
|
|
270
|
-
width: nodeTrans.bounds.width,
|
|
271
|
-
height: nodeTrans.bounds.height
|
|
272
|
-
};
|
|
273
|
-
const minDistance = {
|
|
274
|
-
x: nodeSize.width + padding.x,
|
|
275
|
-
y: nodeSize.height + padding.y
|
|
276
|
-
};
|
|
277
|
-
const boxDistance = this.rectDistance(fromBox, toBox);
|
|
278
|
-
const neededOffset = {
|
|
279
|
-
x: isGreaterThan(boxDistance.x, minDistance.x) ? 0 : minDistance.x - boxDistance.x,
|
|
280
|
-
y: isGreaterThan(boxDistance.y, minDistance.y) ? 0 : minDistance.y - boxDistance.y
|
|
281
|
-
};
|
|
282
|
-
if (neededOffset.x === 0 || neededOffset.y === 0) {
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
const intersection = {
|
|
286
|
-
// 这里没有写反,Rectangle内置的算法是反的
|
|
287
|
-
vertical: Rectangle.intersects(fromBox, toBox, "horizontal"),
|
|
288
|
-
horizontal: Rectangle.intersects(fromBox, toBox, "vertical")
|
|
289
|
-
};
|
|
290
|
-
let offsetX = 0;
|
|
291
|
-
let offsetY = 0;
|
|
292
|
-
if (!intersection.horizontal) {
|
|
293
|
-
if (isGreaterThan(toBox.center.y, fromBox.center.y)) {
|
|
294
|
-
offsetY = neededOffset.y;
|
|
295
|
-
} else if (isLessThan(toBox.center.y, fromBox.center.y)) {
|
|
296
|
-
offsetY = -neededOffset.y;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
if (!intersection.vertical) {
|
|
300
|
-
if (isGreaterThan(toBox.center.x, fromBox.center.x)) {
|
|
301
|
-
offsetX = neededOffset.x;
|
|
302
|
-
} else if (isLessThan(toBox.center.x, fromBox.center.x)) {
|
|
303
|
-
offsetX = -neededOffset.x;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
return {
|
|
307
|
-
x: offsetX,
|
|
308
|
-
y: offsetY
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
/** 矩形间距 */
|
|
312
|
-
rectDistance(rectA, rectB) {
|
|
313
|
-
const distanceX = Math.abs(
|
|
314
|
-
Math.min(rectA.right, rectB.right) - Math.max(rectA.left, rectB.left)
|
|
315
|
-
);
|
|
316
|
-
const distanceY = Math.abs(
|
|
317
|
-
Math.min(rectA.bottom, rectB.bottom) - Math.max(rectA.top, rectB.top)
|
|
318
|
-
);
|
|
319
|
-
if (Rectangle.intersects(rectA, rectB)) {
|
|
320
|
-
return {
|
|
321
|
-
x: -distanceX,
|
|
322
|
-
y: -distanceY
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
return {
|
|
326
|
-
x: distanceX,
|
|
327
|
-
y: distanceY
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
/** 获取后续节点 */
|
|
331
|
-
getSubsequentNodes(node) {
|
|
332
|
-
if (node.flowNodeType === FlowNodeBaseType.SUB_CANVAS) {
|
|
333
|
-
return [];
|
|
334
|
-
}
|
|
335
|
-
const brothers = node.parent?.collapsedChildren ?? [];
|
|
336
|
-
const linkedBrothers = /* @__PURE__ */ new Set();
|
|
337
|
-
const linesMap = /* @__PURE__ */ new Map();
|
|
338
|
-
this.linesManager.getAllLines().forEach((line) => {
|
|
339
|
-
if (!linesMap.has(line.from.id)) {
|
|
340
|
-
linesMap.set(line.from.id, []);
|
|
341
|
-
}
|
|
342
|
-
if (!line.to?.id || line.to.flowNodeType === FlowNodeBaseType.SUB_CANVAS) {
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
linesMap.get(line.from.id)?.push(line.to.id);
|
|
346
|
-
});
|
|
347
|
-
const bfs = (nodeId) => {
|
|
348
|
-
if (linkedBrothers.has(nodeId)) {
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
linkedBrothers.add(nodeId);
|
|
352
|
-
const nextNodes = linesMap.get(nodeId) ?? [];
|
|
353
|
-
nextNodes.forEach(bfs);
|
|
354
|
-
};
|
|
355
|
-
bfs(node.id);
|
|
356
|
-
const subsequentNodes = brothers.filter((node2) => linkedBrothers.has(node2.id));
|
|
357
|
-
return subsequentNodes;
|
|
358
|
-
}
|
|
359
|
-
/** 更新后续节点位置 */
|
|
360
|
-
updateSubSequentNodesPosition(params) {
|
|
361
|
-
const { node, subsequentNodes, fromPort, toPort, containerNode, offset } = params;
|
|
362
|
-
if (!offset || !toPort) {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
const subsequentNodesPositions = subsequentNodes.map((node2) => {
|
|
366
|
-
const nodeTrans2 = node2.getData(TransformData);
|
|
367
|
-
return {
|
|
368
|
-
x: nodeTrans2.position.x,
|
|
369
|
-
y: nodeTrans2.position.y
|
|
370
|
-
};
|
|
371
|
-
});
|
|
372
|
-
this.historyService.pushOperation({
|
|
373
|
-
type: FreeOperationType.dragNodes,
|
|
374
|
-
value: {
|
|
375
|
-
ids: subsequentNodes.map((node2) => node2.id),
|
|
376
|
-
value: subsequentNodesPositions.map((position) => ({
|
|
377
|
-
x: position.x + offset.x,
|
|
378
|
-
y: position.y + offset.y
|
|
379
|
-
})),
|
|
380
|
-
oldValue: subsequentNodesPositions
|
|
381
|
-
}
|
|
382
|
-
});
|
|
383
|
-
const fromBox = this.getPortBox(fromPort);
|
|
384
|
-
const toBox = this.getPortBox(toPort, offset);
|
|
385
|
-
const nodeTrans = node.getData(TransformData);
|
|
386
|
-
let nodePos = {
|
|
387
|
-
x: (fromBox.center.x + toBox.center.x) / 2,
|
|
388
|
-
y: (fromBox.y + toBox.y) / 2
|
|
389
|
-
};
|
|
390
|
-
if (containerNode) {
|
|
391
|
-
nodePos = this.dragService.adjustSubNodePosition(
|
|
392
|
-
node.flowNodeType,
|
|
393
|
-
containerNode,
|
|
394
|
-
nodePos
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
this.historyService.pushOperation({
|
|
398
|
-
type: FreeOperationType.dragNodes,
|
|
399
|
-
value: {
|
|
400
|
-
ids: [node.id],
|
|
401
|
-
value: [nodePos],
|
|
402
|
-
oldValue: [
|
|
403
|
-
{
|
|
404
|
-
x: nodeTrans.position.x,
|
|
405
|
-
y: nodeTrans.position.y
|
|
406
|
-
}
|
|
407
|
-
]
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
511
|
};
|
|
412
512
|
__decorateClass([
|
|
413
513
|
inject(WorkflowDocument)
|
|
@@ -419,13 +519,13 @@ __decorateClass([
|
|
|
419
519
|
inject(WorkflowSelectService)
|
|
420
520
|
], WorkflowNodePanelService.prototype, "selectService", 2);
|
|
421
521
|
__decorateClass([
|
|
422
|
-
inject(
|
|
522
|
+
inject(WorkflowLinesManager2)
|
|
423
523
|
], WorkflowNodePanelService.prototype, "linesManager", 2);
|
|
424
524
|
__decorateClass([
|
|
425
525
|
inject(PlaygroundConfigEntity)
|
|
426
526
|
], WorkflowNodePanelService.prototype, "playgroundConfig", 2);
|
|
427
527
|
__decorateClass([
|
|
428
|
-
inject(
|
|
528
|
+
inject(HistoryService2)
|
|
429
529
|
], WorkflowNodePanelService.prototype, "historyService", 2);
|
|
430
530
|
WorkflowNodePanelService = __decorateClass([
|
|
431
531
|
injectable()
|
|
@@ -434,9 +534,9 @@ WorkflowNodePanelService = __decorateClass([
|
|
|
434
534
|
// src/layer.tsx
|
|
435
535
|
import React from "react";
|
|
436
536
|
import { inject as inject2 } from "inversify";
|
|
437
|
-
import { Layer } from "@flowgram.ai/core";
|
|
438
|
-
import { nanoid } from "@flowgram.ai/free-layout-core";
|
|
439
537
|
import { domUtils } from "@flowgram.ai/utils";
|
|
538
|
+
import { nanoid } from "@flowgram.ai/free-layout-core";
|
|
539
|
+
import { Layer } from "@flowgram.ai/core";
|
|
440
540
|
var WorkflowNodePanelLayer = class extends Layer {
|
|
441
541
|
constructor() {
|
|
442
542
|
super();
|
|
@@ -459,7 +559,7 @@ var WorkflowNodePanelLayer = class extends Layer {
|
|
|
459
559
|
}
|
|
460
560
|
async call(params) {
|
|
461
561
|
const taskId = nanoid();
|
|
462
|
-
const {
|
|
562
|
+
const { onSelect, onClose, enableMultiAdd = false, panelProps = {} } = params;
|
|
463
563
|
return new Promise((resolve) => {
|
|
464
564
|
const unmount = () => {
|
|
465
565
|
this.renderList.delete(taskId);
|
|
@@ -478,6 +578,7 @@ var WorkflowNodePanelLayer = class extends Layer {
|
|
|
478
578
|
};
|
|
479
579
|
const renderProps = {
|
|
480
580
|
...params,
|
|
581
|
+
panelProps,
|
|
481
582
|
onSelect: handleSelect,
|
|
482
583
|
onClose: handleClose
|
|
483
584
|
};
|
|
@@ -508,6 +609,7 @@ var createFreeNodePanelPlugin = definePluginCreator({
|
|
|
508
609
|
});
|
|
509
610
|
export {
|
|
510
611
|
WorkflowNodePanelService,
|
|
612
|
+
WorkflowNodePanelUtils,
|
|
511
613
|
createFreeNodePanelPlugin
|
|
512
614
|
};
|
|
513
615
|
//# sourceMappingURL=index.js.map
|