@flowgram.ai/free-node-panel-plugin 0.1.0-alpha.2 → 0.1.0-alpha.21
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 +372 -263
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +156 -21
- package/dist/index.d.ts +156 -21
- package/dist/index.js +379 -268
- package/dist/index.js.map +1 -1
- package/package.json +14 -19
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,220 @@ 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.getAllAvailableLines().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 isVertical = fromPort.location === "bottom";
|
|
301
|
+
const toTargetPort = portsData.inputPorts.find((port) => isVertical ? port.location === "top" : true) || portsData.inputPorts[0];
|
|
302
|
+
linesManager.createLine({
|
|
303
|
+
from: fromPort.node.id,
|
|
304
|
+
fromPort: fromPort.portID,
|
|
305
|
+
to: node.id,
|
|
306
|
+
toPort: toTargetPort.portID
|
|
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
|
+
if (fromPort.location === "bottom") {
|
|
336
|
+
adjustedPosition = {
|
|
337
|
+
x: position.x,
|
|
338
|
+
y: position.y
|
|
339
|
+
};
|
|
340
|
+
} else {
|
|
341
|
+
adjustedPosition = {
|
|
342
|
+
x: position.x + size.width / 2,
|
|
343
|
+
y: position.y - size.height / 2
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
} else if (!fromPort && toPort) {
|
|
347
|
+
adjustedPosition = {
|
|
348
|
+
x: position.x - size.width / 2,
|
|
349
|
+
y: position.y - size.height / 2
|
|
350
|
+
};
|
|
351
|
+
} else {
|
|
352
|
+
adjustedPosition = position;
|
|
353
|
+
}
|
|
354
|
+
return dragService.adjustSubNodePosition(nodeType, containerNode, adjustedPosition);
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
// src/utils/index.ts
|
|
358
|
+
var WorkflowNodePanelUtils = {
|
|
359
|
+
adjustNodePosition,
|
|
360
|
+
buildLine,
|
|
361
|
+
getPortBox,
|
|
362
|
+
getSubsequentNodes,
|
|
363
|
+
getContainerNode,
|
|
364
|
+
rectDistance,
|
|
365
|
+
subNodesAutoOffset,
|
|
366
|
+
subPositionOffset,
|
|
367
|
+
updateSubSequentNodesPosition,
|
|
368
|
+
waitNodeRender
|
|
369
|
+
};
|
|
370
|
+
|
|
49
371
|
// src/service.ts
|
|
50
372
|
var WorkflowNodePanelService = class {
|
|
51
373
|
constructor() {
|
|
@@ -78,7 +400,7 @@ var WorkflowNodePanelService = class {
|
|
|
78
400
|
position: panelPosition,
|
|
79
401
|
enableMultiAdd,
|
|
80
402
|
panelProps,
|
|
81
|
-
containerNode:
|
|
403
|
+
containerNode: WorkflowNodePanelUtils.getContainerNode({
|
|
82
404
|
fromPort,
|
|
83
405
|
containerNode
|
|
84
406
|
}),
|
|
@@ -97,6 +419,23 @@ var WorkflowNodePanelService = class {
|
|
|
97
419
|
});
|
|
98
420
|
});
|
|
99
421
|
}
|
|
422
|
+
/**
|
|
423
|
+
* 唤起单选面板
|
|
424
|
+
*/
|
|
425
|
+
async singleSelectNodePanel(params) {
|
|
426
|
+
return new Promise((resolve) => {
|
|
427
|
+
this.callNodePanel({
|
|
428
|
+
...params,
|
|
429
|
+
enableMultiAdd: false,
|
|
430
|
+
onSelect: async (panelParams) => {
|
|
431
|
+
resolve(panelParams);
|
|
432
|
+
},
|
|
433
|
+
onClose: () => {
|
|
434
|
+
resolve(void 0);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
}
|
|
100
439
|
/** 添加节点 */
|
|
101
440
|
async addNode(callParams, panelParams) {
|
|
102
441
|
const {
|
|
@@ -117,7 +456,7 @@ var WorkflowNodePanelService = class {
|
|
|
117
456
|
return;
|
|
118
457
|
}
|
|
119
458
|
const { nodeType, selectEvent, nodeJSON } = panelParams;
|
|
120
|
-
const containerNode =
|
|
459
|
+
const containerNode = WorkflowNodePanelUtils.getContainerNode({
|
|
121
460
|
fromPort,
|
|
122
461
|
containerNode: callParams.containerNode
|
|
123
462
|
});
|
|
@@ -128,14 +467,16 @@ var WorkflowNodePanelService = class {
|
|
|
128
467
|
}
|
|
129
468
|
}
|
|
130
469
|
const selectPosition = this.playgroundConfig.getPosFromMouseEvent(selectEvent);
|
|
131
|
-
const nodePosition = callParams.customPosition ? callParams.customPosition({ nodeType, selectPosition }) :
|
|
470
|
+
const nodePosition = callParams.customPosition ? callParams.customPosition({ nodeType, selectPosition }) : WorkflowNodePanelUtils.adjustNodePosition({
|
|
132
471
|
nodeType,
|
|
133
472
|
position: enableSelectPosition ? selectPosition : panelPosition,
|
|
134
473
|
fromPort,
|
|
135
474
|
toPort,
|
|
136
|
-
containerNode
|
|
475
|
+
containerNode,
|
|
476
|
+
document: this.document,
|
|
477
|
+
dragService: this.dragService
|
|
137
478
|
});
|
|
138
|
-
const node =
|
|
479
|
+
const node = this.document.createWorkflowNodeByType(
|
|
139
480
|
nodeType,
|
|
140
481
|
nodePosition,
|
|
141
482
|
nodeJSON ?? {},
|
|
@@ -145,31 +486,27 @@ var WorkflowNodePanelService = class {
|
|
|
145
486
|
return;
|
|
146
487
|
}
|
|
147
488
|
if (enableAutoOffset && fromPort && toPort) {
|
|
148
|
-
|
|
489
|
+
WorkflowNodePanelUtils.subNodesAutoOffset({
|
|
149
490
|
node,
|
|
150
491
|
fromPort,
|
|
151
492
|
toPort,
|
|
152
|
-
padding: autoOffsetPadding
|
|
153
|
-
});
|
|
154
|
-
const subsequentNodes = this.getSubsequentNodes(toPort.node);
|
|
155
|
-
this.updateSubSequentNodesPosition({
|
|
156
|
-
node,
|
|
157
|
-
subsequentNodes,
|
|
158
|
-
fromPort,
|
|
159
|
-
toPort,
|
|
493
|
+
padding: autoOffsetPadding,
|
|
160
494
|
containerNode,
|
|
161
|
-
|
|
495
|
+
historyService: this.historyService,
|
|
496
|
+
dragService: this.dragService,
|
|
497
|
+
linesManager: this.linesManager
|
|
162
498
|
});
|
|
163
499
|
}
|
|
164
500
|
if (!enableBuildLine && !enableDragNode) {
|
|
165
501
|
return node;
|
|
166
502
|
}
|
|
167
|
-
await
|
|
503
|
+
await WorkflowNodePanelUtils.waitNodeRender();
|
|
168
504
|
if (enableBuildLine) {
|
|
169
|
-
|
|
505
|
+
WorkflowNodePanelUtils.buildLine({
|
|
170
506
|
fromPort,
|
|
171
507
|
node,
|
|
172
|
-
toPort
|
|
508
|
+
toPort,
|
|
509
|
+
linesManager: this.linesManager
|
|
173
510
|
});
|
|
174
511
|
}
|
|
175
512
|
if (enableDragNode) {
|
|
@@ -178,236 +515,6 @@ var WorkflowNodePanelService = class {
|
|
|
178
515
|
}
|
|
179
516
|
return node;
|
|
180
517
|
}
|
|
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
518
|
};
|
|
412
519
|
__decorateClass([
|
|
413
520
|
inject(WorkflowDocument)
|
|
@@ -419,13 +526,13 @@ __decorateClass([
|
|
|
419
526
|
inject(WorkflowSelectService)
|
|
420
527
|
], WorkflowNodePanelService.prototype, "selectService", 2);
|
|
421
528
|
__decorateClass([
|
|
422
|
-
inject(
|
|
529
|
+
inject(WorkflowLinesManager2)
|
|
423
530
|
], WorkflowNodePanelService.prototype, "linesManager", 2);
|
|
424
531
|
__decorateClass([
|
|
425
532
|
inject(PlaygroundConfigEntity)
|
|
426
533
|
], WorkflowNodePanelService.prototype, "playgroundConfig", 2);
|
|
427
534
|
__decorateClass([
|
|
428
|
-
inject(
|
|
535
|
+
inject(HistoryService2)
|
|
429
536
|
], WorkflowNodePanelService.prototype, "historyService", 2);
|
|
430
537
|
WorkflowNodePanelService = __decorateClass([
|
|
431
538
|
injectable()
|
|
@@ -434,9 +541,9 @@ WorkflowNodePanelService = __decorateClass([
|
|
|
434
541
|
// src/layer.tsx
|
|
435
542
|
import React from "react";
|
|
436
543
|
import { inject as inject2 } from "inversify";
|
|
437
|
-
import { Layer } from "@flowgram.ai/core";
|
|
438
|
-
import { nanoid } from "@flowgram.ai/free-layout-core";
|
|
439
544
|
import { domUtils } from "@flowgram.ai/utils";
|
|
545
|
+
import { nanoid } from "@flowgram.ai/free-layout-core";
|
|
546
|
+
import { Layer } from "@flowgram.ai/core";
|
|
440
547
|
var WorkflowNodePanelLayer = class extends Layer {
|
|
441
548
|
constructor() {
|
|
442
549
|
super();
|
|
@@ -459,7 +566,7 @@ var WorkflowNodePanelLayer = class extends Layer {
|
|
|
459
566
|
}
|
|
460
567
|
async call(params) {
|
|
461
568
|
const taskId = nanoid();
|
|
462
|
-
const {
|
|
569
|
+
const { onSelect, onClose, enableMultiAdd = false, panelProps = {} } = params;
|
|
463
570
|
return new Promise((resolve) => {
|
|
464
571
|
const unmount = () => {
|
|
465
572
|
this.renderList.delete(taskId);
|
|
@@ -478,6 +585,7 @@ var WorkflowNodePanelLayer = class extends Layer {
|
|
|
478
585
|
};
|
|
479
586
|
const renderProps = {
|
|
480
587
|
...params,
|
|
588
|
+
panelProps,
|
|
481
589
|
onSelect: handleSelect,
|
|
482
590
|
onClose: handleClose
|
|
483
591
|
};
|
|
@@ -508,6 +616,7 @@ var createFreeNodePanelPlugin = definePluginCreator({
|
|
|
508
616
|
});
|
|
509
617
|
export {
|
|
510
618
|
WorkflowNodePanelService,
|
|
619
|
+
WorkflowNodePanelUtils,
|
|
511
620
|
createFreeNodePanelPlugin
|
|
512
621
|
};
|
|
513
622
|
//# sourceMappingURL=index.js.map
|