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