@flowgram.ai/free-layout-core 0.1.6 → 0.1.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/esm/{chunk-KAL7YCC2.js → chunk-PT4ZVDZZ.js} +1 -1
- package/dist/esm/chunk-PT4ZVDZZ.js.map +1 -0
- package/dist/esm/index.js +346 -549
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/typings/index.js +1 -1
- package/dist/esm/typings/workflow-line.js +1 -1
- package/dist/index.d.mts +54 -42
- package/dist/index.d.ts +54 -42
- package/dist/index.js +460 -665
- package/dist/index.js.map +1 -1
- package/dist/typings/index.d.mts +1 -3
- package/dist/typings/index.d.ts +1 -3
- package/dist/typings/index.js.map +1 -1
- package/dist/typings/workflow-json.d.mts +1 -3
- package/dist/typings/workflow-json.d.ts +1 -3
- package/dist/typings/workflow-line.d.mts +7 -27
- package/dist/typings/workflow-line.d.ts +7 -27
- package/dist/typings/workflow-line.js.map +1 -1
- package/dist/typings/workflow-node.d.mts +1 -3
- package/dist/typings/workflow-node.d.ts +1 -3
- package/dist/typings/workflow-registry.d.mts +1 -3
- package/dist/typings/workflow-registry.d.ts +1 -3
- package/dist/{workflow-line-entity-CG_8mknJ.d.ts → workflow-line-entity-BcXJ4GjA.d.ts} +57 -49
- package/dist/{workflow-line-entity-1qT4aXVU.d.mts → workflow-line-entity-DZGrnBuq.d.mts} +57 -49
- package/package.json +9 -10
- package/dist/esm/chunk-KAL7YCC2.js.map +0 -1
package/dist/esm/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
LineColors,
|
|
10
10
|
LineType
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PT4ZVDZZ.js";
|
|
12
12
|
import {
|
|
13
13
|
__decorateClass
|
|
14
14
|
} from "./chunk-EUXUH3YW.js";
|
|
@@ -57,321 +57,12 @@ import {
|
|
|
57
57
|
SelectionService,
|
|
58
58
|
TransformData as TransformData4
|
|
59
59
|
} from "@flowgram.ai/core";
|
|
60
|
-
import { Rectangle as
|
|
60
|
+
import { Rectangle as Rectangle6, SizeSchema } from "@flowgram.ai/utils";
|
|
61
61
|
|
|
62
62
|
// src/utils/index.ts
|
|
63
63
|
import { bindConfigEntity } from "@flowgram.ai/core";
|
|
64
64
|
import { delay } from "@flowgram.ai/utils";
|
|
65
65
|
|
|
66
|
-
// src/utils/fold-line.ts
|
|
67
|
-
import { Point, Rectangle } from "@flowgram.ai/utils";
|
|
68
|
-
function pointLineDistance(p1, p2, p3) {
|
|
69
|
-
let len;
|
|
70
|
-
if (p1.x - p2.x === 0) {
|
|
71
|
-
len = Math.abs(p3.x - p1.x);
|
|
72
|
-
} else {
|
|
73
|
-
const A = (p1.y - p2.y) / (p1.x - p2.x);
|
|
74
|
-
const B = p1.y - A * p1.x;
|
|
75
|
-
len = Math.abs((A * p3.x + B - p3.y) / Math.sqrt(A * A + 1));
|
|
76
|
-
}
|
|
77
|
-
return len;
|
|
78
|
-
}
|
|
79
|
-
var FoldLine;
|
|
80
|
-
((FoldLine2) => {
|
|
81
|
-
const EDGE_RADIUS = 5;
|
|
82
|
-
const OFFSET = 20;
|
|
83
|
-
function getEdgeCenter({ source, target }) {
|
|
84
|
-
const xOffset = Math.abs(target.x - source.x) / 2;
|
|
85
|
-
const centerX = target.x < source.x ? target.x + xOffset : target.x - xOffset;
|
|
86
|
-
const yOffset = Math.abs(target.y - source.y) / 2;
|
|
87
|
-
const centerY = target.y < source.y ? target.y + yOffset : target.y - yOffset;
|
|
88
|
-
return [centerX, centerY];
|
|
89
|
-
}
|
|
90
|
-
const getDirection = ({ source, target }) => source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };
|
|
91
|
-
function getPoints({ source, target }) {
|
|
92
|
-
const sourceDir = { x: 1, y: 0 };
|
|
93
|
-
const targetDir = { x: -1, y: 0 };
|
|
94
|
-
const sourceGapped = {
|
|
95
|
-
x: source.x + sourceDir.x * OFFSET,
|
|
96
|
-
y: source.y + sourceDir.y * OFFSET
|
|
97
|
-
};
|
|
98
|
-
const targetGapped = {
|
|
99
|
-
x: target.x + targetDir.x * OFFSET,
|
|
100
|
-
y: target.y + targetDir.y * OFFSET
|
|
101
|
-
};
|
|
102
|
-
const dir = getDirection({
|
|
103
|
-
source: sourceGapped,
|
|
104
|
-
target: targetGapped
|
|
105
|
-
});
|
|
106
|
-
const dirAccessor = dir.x !== 0 ? "x" : "y";
|
|
107
|
-
const currDir = dir[dirAccessor];
|
|
108
|
-
let points = [];
|
|
109
|
-
let centerX, centerY;
|
|
110
|
-
const [defaultCenterX, defaultCenterY] = getEdgeCenter({
|
|
111
|
-
source,
|
|
112
|
-
target
|
|
113
|
-
});
|
|
114
|
-
if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
|
|
115
|
-
centerX = defaultCenterX;
|
|
116
|
-
centerY = defaultCenterY;
|
|
117
|
-
const verticalSplit = [
|
|
118
|
-
{ x: centerX, y: sourceGapped.y },
|
|
119
|
-
{ x: centerX, y: targetGapped.y }
|
|
120
|
-
];
|
|
121
|
-
const horizontalSplit = [
|
|
122
|
-
{ x: sourceGapped.x, y: centerY },
|
|
123
|
-
{ x: targetGapped.x, y: centerY }
|
|
124
|
-
];
|
|
125
|
-
if (sourceDir[dirAccessor] === currDir) {
|
|
126
|
-
points = dirAccessor === "x" ? verticalSplit : horizontalSplit;
|
|
127
|
-
} else {
|
|
128
|
-
points = dirAccessor === "x" ? horizontalSplit : verticalSplit;
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
const sourceTarget = [{ x: sourceGapped.x, y: targetGapped.y }];
|
|
132
|
-
const targetSource = [{ x: targetGapped.x, y: sourceGapped.y }];
|
|
133
|
-
if (dirAccessor === "x") {
|
|
134
|
-
points = sourceDir.x === currDir ? targetSource : sourceTarget;
|
|
135
|
-
} else {
|
|
136
|
-
points = sourceDir.y === currDir ? sourceTarget : targetSource;
|
|
137
|
-
}
|
|
138
|
-
const dirAccessorOpposite = dirAccessor === "x" ? "y" : "x";
|
|
139
|
-
const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite];
|
|
140
|
-
const sourceGtTargetOppo = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];
|
|
141
|
-
const sourceLtTargetOppo = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];
|
|
142
|
-
const flipSourceTarget = sourceDir[dirAccessor] === 1 && (!isSameDir && sourceGtTargetOppo || isSameDir && sourceLtTargetOppo) || sourceDir[dirAccessor] !== 1 && (!isSameDir && sourceLtTargetOppo || isSameDir && sourceGtTargetOppo);
|
|
143
|
-
if (flipSourceTarget) {
|
|
144
|
-
points = dirAccessor === "x" ? sourceTarget : targetSource;
|
|
145
|
-
}
|
|
146
|
-
const sourceGapPoint = { x: sourceGapped.x, y: sourceGapped.y };
|
|
147
|
-
const targetGapPoint = { x: targetGapped.x, y: targetGapped.y };
|
|
148
|
-
const maxXDistance = Math.max(
|
|
149
|
-
Math.abs(sourceGapPoint.x - points[0].x),
|
|
150
|
-
Math.abs(targetGapPoint.x - points[0].x)
|
|
151
|
-
);
|
|
152
|
-
const maxYDistance = Math.max(
|
|
153
|
-
Math.abs(sourceGapPoint.y - points[0].y),
|
|
154
|
-
Math.abs(targetGapPoint.y - points[0].y)
|
|
155
|
-
);
|
|
156
|
-
if (maxXDistance >= maxYDistance) {
|
|
157
|
-
centerX = (sourceGapPoint.x + targetGapPoint.x) / 2;
|
|
158
|
-
centerY = points[0].y;
|
|
159
|
-
} else {
|
|
160
|
-
centerX = points[0].x;
|
|
161
|
-
centerY = (sourceGapPoint.y + targetGapPoint.y) / 2;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
const pathPoints = [
|
|
165
|
-
source,
|
|
166
|
-
{ x: sourceGapped.x, y: sourceGapped.y },
|
|
167
|
-
...points,
|
|
168
|
-
{ x: targetGapped.x, y: targetGapped.y },
|
|
169
|
-
target
|
|
170
|
-
];
|
|
171
|
-
return pathPoints;
|
|
172
|
-
}
|
|
173
|
-
FoldLine2.getPoints = getPoints;
|
|
174
|
-
function getBend(a, b, c) {
|
|
175
|
-
const bendSize = Math.min(
|
|
176
|
-
Point.getDistance(a, b) / 2,
|
|
177
|
-
Point.getDistance(b, c) / 2,
|
|
178
|
-
EDGE_RADIUS
|
|
179
|
-
);
|
|
180
|
-
const { x, y } = b;
|
|
181
|
-
if (a.x === x && x === c.x || a.y === y && y === c.y) {
|
|
182
|
-
return `L${x} ${y}`;
|
|
183
|
-
}
|
|
184
|
-
if (a.y === y) {
|
|
185
|
-
const xDir2 = a.x < c.x ? -1 : 1;
|
|
186
|
-
const yDir2 = a.y < c.y ? 1 : -1;
|
|
187
|
-
return `L ${x + bendSize * xDir2},${y}Q ${x},${y} ${x},${y + bendSize * yDir2}`;
|
|
188
|
-
}
|
|
189
|
-
const xDir = a.x < c.x ? 1 : -1;
|
|
190
|
-
const yDir = a.y < c.y ? -1 : 1;
|
|
191
|
-
return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
|
|
192
|
-
}
|
|
193
|
-
function getSmoothStepPath(points) {
|
|
194
|
-
const path = points.reduce((res, p, i) => {
|
|
195
|
-
let segment = "";
|
|
196
|
-
if (i > 0 && i < points.length - 1) {
|
|
197
|
-
segment = getBend(points[i - 1], p, points[i + 1]);
|
|
198
|
-
} else {
|
|
199
|
-
segment = `${i === 0 ? "M" : "L"}${p.x} ${p.y}`;
|
|
200
|
-
}
|
|
201
|
-
res += segment;
|
|
202
|
-
return res;
|
|
203
|
-
}, "");
|
|
204
|
-
return path;
|
|
205
|
-
}
|
|
206
|
-
FoldLine2.getSmoothStepPath = getSmoothStepPath;
|
|
207
|
-
function getBounds(points) {
|
|
208
|
-
const xList = points.map((p) => p.x);
|
|
209
|
-
const yList = points.map((p) => p.y);
|
|
210
|
-
const left = Math.min(...xList);
|
|
211
|
-
const right = Math.max(...xList);
|
|
212
|
-
const top = Math.min(...yList);
|
|
213
|
-
const bottom = Math.max(...yList);
|
|
214
|
-
return Rectangle.createRectangleWithTwoPoints(
|
|
215
|
-
{
|
|
216
|
-
x: left,
|
|
217
|
-
y: top
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
x: right,
|
|
221
|
-
y: bottom
|
|
222
|
-
}
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
FoldLine2.getBounds = getBounds;
|
|
226
|
-
function getFoldLineToPointDistance(points, pos) {
|
|
227
|
-
const bounds = getBounds(points);
|
|
228
|
-
if (bounds.contains(pos.x, pos.y)) {
|
|
229
|
-
const lines = points.reduce((res, point, index) => {
|
|
230
|
-
if (index === 0) {
|
|
231
|
-
return res;
|
|
232
|
-
}
|
|
233
|
-
res.push([points[index - 1], point]);
|
|
234
|
-
return res;
|
|
235
|
-
}, []);
|
|
236
|
-
return Math.min(...lines.map((l) => pointLineDistance(...l, pos)));
|
|
237
|
-
}
|
|
238
|
-
return Math.min(...points.map((p) => Point.getDistance(p, pos)));
|
|
239
|
-
}
|
|
240
|
-
FoldLine2.getFoldLineToPointDistance = getFoldLineToPointDistance;
|
|
241
|
-
})(FoldLine || (FoldLine = {}));
|
|
242
|
-
|
|
243
|
-
// src/utils/bezier.ts
|
|
244
|
-
import { Rectangle as Rectangle2 } from "@flowgram.ai/utils";
|
|
245
|
-
var BezierControlType = /* @__PURE__ */ ((BezierControlType2) => {
|
|
246
|
-
BezierControlType2[BezierControlType2["RIGHT_TOP"] = 0] = "RIGHT_TOP";
|
|
247
|
-
BezierControlType2[BezierControlType2["RIGHT_BOTTOM"] = 1] = "RIGHT_BOTTOM";
|
|
248
|
-
BezierControlType2[BezierControlType2["LEFT_TOP"] = 2] = "LEFT_TOP";
|
|
249
|
-
BezierControlType2[BezierControlType2["LEFT_BOTTOM"] = 3] = "LEFT_BOTTOM";
|
|
250
|
-
return BezierControlType2;
|
|
251
|
-
})(BezierControlType || {});
|
|
252
|
-
var CONTROL_MAX = 300;
|
|
253
|
-
function getBezierHorizontalControlPoints(fromPos, toPos) {
|
|
254
|
-
const rect = Rectangle2.createRectangleWithTwoPoints(fromPos, toPos);
|
|
255
|
-
let type;
|
|
256
|
-
if (fromPos.x <= toPos.x) {
|
|
257
|
-
type = fromPos.y <= toPos.y ? 1 /* RIGHT_BOTTOM */ : 0 /* RIGHT_TOP */;
|
|
258
|
-
} else {
|
|
259
|
-
type = fromPos.y <= toPos.y ? 3 /* LEFT_BOTTOM */ : 2 /* LEFT_TOP */;
|
|
260
|
-
}
|
|
261
|
-
let controls;
|
|
262
|
-
switch (type) {
|
|
263
|
-
case 0 /* RIGHT_TOP */:
|
|
264
|
-
controls = [
|
|
265
|
-
{
|
|
266
|
-
x: rect.rightBottom.x - rect.width / 2,
|
|
267
|
-
y: rect.rightBottom.y
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
x: rect.leftTop.x + rect.width / 2,
|
|
271
|
-
y: rect.leftTop.y
|
|
272
|
-
}
|
|
273
|
-
];
|
|
274
|
-
break;
|
|
275
|
-
case 1 /* RIGHT_BOTTOM */:
|
|
276
|
-
controls = [
|
|
277
|
-
{
|
|
278
|
-
x: rect.rightTop.x - rect.width / 2,
|
|
279
|
-
y: rect.rightTop.y
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
x: rect.leftBottom.x + rect.width / 2,
|
|
283
|
-
y: rect.leftBottom.y
|
|
284
|
-
}
|
|
285
|
-
];
|
|
286
|
-
break;
|
|
287
|
-
case 2 /* LEFT_TOP */:
|
|
288
|
-
controls = [
|
|
289
|
-
{
|
|
290
|
-
x: rect.rightBottom.x + Math.min(rect.width, CONTROL_MAX),
|
|
291
|
-
y: rect.rightBottom.y
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
x: rect.leftTop.x - Math.min(rect.width, CONTROL_MAX),
|
|
295
|
-
y: rect.leftTop.y
|
|
296
|
-
}
|
|
297
|
-
];
|
|
298
|
-
break;
|
|
299
|
-
case 3 /* LEFT_BOTTOM */:
|
|
300
|
-
controls = [
|
|
301
|
-
{
|
|
302
|
-
x: rect.rightTop.x + Math.min(rect.width, CONTROL_MAX),
|
|
303
|
-
y: rect.rightTop.y
|
|
304
|
-
},
|
|
305
|
-
{
|
|
306
|
-
x: rect.leftBottom.x - Math.min(rect.width, CONTROL_MAX),
|
|
307
|
-
y: rect.leftBottom.y
|
|
308
|
-
}
|
|
309
|
-
];
|
|
310
|
-
}
|
|
311
|
-
return controls;
|
|
312
|
-
}
|
|
313
|
-
function getBezierVerticalControlPoints(fromPos, toPos) {
|
|
314
|
-
const rect = Rectangle2.createRectangleWithTwoPoints(fromPos, toPos);
|
|
315
|
-
let type;
|
|
316
|
-
if (fromPos.y <= toPos.y) {
|
|
317
|
-
type = fromPos.x <= toPos.x ? 1 /* RIGHT_BOTTOM */ : 3 /* LEFT_BOTTOM */;
|
|
318
|
-
} else {
|
|
319
|
-
type = fromPos.x <= toPos.x ? 0 /* RIGHT_TOP */ : 2 /* LEFT_TOP */;
|
|
320
|
-
}
|
|
321
|
-
let controls;
|
|
322
|
-
switch (type) {
|
|
323
|
-
case 1 /* RIGHT_BOTTOM */:
|
|
324
|
-
controls = [
|
|
325
|
-
{
|
|
326
|
-
x: rect.leftTop.x,
|
|
327
|
-
y: rect.leftTop.y + rect.height / 2
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
x: rect.rightBottom.x,
|
|
331
|
-
y: rect.rightBottom.y - rect.height / 2
|
|
332
|
-
}
|
|
333
|
-
];
|
|
334
|
-
break;
|
|
335
|
-
case 3 /* LEFT_BOTTOM */:
|
|
336
|
-
controls = [
|
|
337
|
-
{
|
|
338
|
-
x: rect.rightTop.x,
|
|
339
|
-
y: rect.rightTop.y + rect.height / 2
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
x: rect.leftBottom.x,
|
|
343
|
-
y: rect.leftBottom.y - rect.height / 2
|
|
344
|
-
}
|
|
345
|
-
];
|
|
346
|
-
break;
|
|
347
|
-
case 0 /* RIGHT_TOP */:
|
|
348
|
-
controls = [
|
|
349
|
-
{
|
|
350
|
-
x: rect.leftBottom.x,
|
|
351
|
-
y: rect.leftBottom.y + Math.min(rect.height, CONTROL_MAX)
|
|
352
|
-
},
|
|
353
|
-
{
|
|
354
|
-
x: rect.rightTop.x,
|
|
355
|
-
y: rect.rightTop.y - Math.min(rect.height, CONTROL_MAX)
|
|
356
|
-
}
|
|
357
|
-
];
|
|
358
|
-
break;
|
|
359
|
-
case 2 /* LEFT_TOP */:
|
|
360
|
-
controls = [
|
|
361
|
-
{
|
|
362
|
-
x: rect.rightBottom.x,
|
|
363
|
-
y: rect.rightBottom.y + Math.min(rect.height, CONTROL_MAX)
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
x: rect.leftTop.x,
|
|
367
|
-
y: rect.leftTop.y - Math.min(rect.height, CONTROL_MAX)
|
|
368
|
-
}
|
|
369
|
-
];
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
return controls;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
66
|
// src/utils/nanoid.ts
|
|
376
67
|
import { nanoid as nanoidOrigin } from "nanoid";
|
|
377
68
|
function nanoid(n) {
|
|
@@ -383,9 +74,9 @@ import { compose, composeAsync } from "@flowgram.ai/utils";
|
|
|
383
74
|
|
|
384
75
|
// src/utils/fit-view.ts
|
|
385
76
|
import { TransformData } from "@flowgram.ai/core";
|
|
386
|
-
import { Rectangle
|
|
77
|
+
import { Rectangle } from "@flowgram.ai/utils";
|
|
387
78
|
var fitView = (doc, playgroundConfig, easing = true) => {
|
|
388
|
-
const bounds =
|
|
79
|
+
const bounds = Rectangle.enlarge(
|
|
389
80
|
doc.getAllNodes().map((node) => node.getData(TransformData).bounds)
|
|
390
81
|
);
|
|
391
82
|
return playgroundConfig.fitView(bounds, easing, 30);
|
|
@@ -417,11 +108,11 @@ function getAntiOverlapPosition(doc, position, containerNode) {
|
|
|
417
108
|
}
|
|
418
109
|
|
|
419
110
|
// src/utils/statics.ts
|
|
420
|
-
import { Rectangle as
|
|
111
|
+
import { Rectangle as Rectangle2 } from "@flowgram.ai/utils";
|
|
421
112
|
var getPortEntityId = (node, portType, portID = "") => `port_${portType}_${node.id}_${portID}`;
|
|
422
113
|
var WORKFLOW_LINE_ENTITY = "WorkflowLineEntity";
|
|
423
114
|
function domReactToBounds(react) {
|
|
424
|
-
return new
|
|
115
|
+
return new Rectangle2(react.x, react.y, react.width, react.height);
|
|
425
116
|
}
|
|
426
117
|
|
|
427
118
|
// src/entities/workflow-node-entity.ts
|
|
@@ -430,8 +121,7 @@ var WorkflowNodeEntity = FlowNodeEntity;
|
|
|
430
121
|
|
|
431
122
|
// src/entities/workflow-line-entity.ts
|
|
432
123
|
import { isEqual as isEqual2 } from "lodash-es";
|
|
433
|
-
import {
|
|
434
|
-
import { domUtils, Point as Point2, Rectangle as Rectangle6 } from "@flowgram.ai/utils";
|
|
124
|
+
import { domUtils } from "@flowgram.ai/utils";
|
|
435
125
|
import { Entity as Entity2 } from "@flowgram.ai/core";
|
|
436
126
|
|
|
437
127
|
// src/entity-datas/workflow-node-ports-data.ts
|
|
@@ -440,7 +130,7 @@ import { FlowNodeRenderData } from "@flowgram.ai/document";
|
|
|
440
130
|
import { EntityData, SizeData } from "@flowgram.ai/core";
|
|
441
131
|
|
|
442
132
|
// src/entities/workflow-port-entity.ts
|
|
443
|
-
import { Rectangle as
|
|
133
|
+
import { Rectangle as Rectangle3, Emitter } from "@flowgram.ai/utils";
|
|
444
134
|
import {
|
|
445
135
|
Entity,
|
|
446
136
|
PlaygroundConfigEntity,
|
|
@@ -511,7 +201,7 @@ var WorkflowPortEntity = class extends Entity {
|
|
|
511
201
|
get bounds() {
|
|
512
202
|
const { point } = this;
|
|
513
203
|
const halfSize = PORT_SIZE / 2;
|
|
514
|
-
return new
|
|
204
|
+
return new Rectangle3(point.x - halfSize, point.y - halfSize, PORT_SIZE, PORT_SIZE);
|
|
515
205
|
}
|
|
516
206
|
isHovered(x, y) {
|
|
517
207
|
return this.bounds.contains(x, y);
|
|
@@ -767,6 +457,218 @@ var WorkflowNodePortsData = class extends EntityData {
|
|
|
767
457
|
};
|
|
768
458
|
WorkflowNodePortsData.type = "WorkflowNodePortsData";
|
|
769
459
|
|
|
460
|
+
// src/entity-datas/workflow-node-lines-data.ts
|
|
461
|
+
import { Disposable } from "@flowgram.ai/utils";
|
|
462
|
+
import { EntityData as EntityData2 } from "@flowgram.ai/core";
|
|
463
|
+
var _WorkflowNodeLinesData = class _WorkflowNodeLinesData extends EntityData2 {
|
|
464
|
+
getDefaultData() {
|
|
465
|
+
return {
|
|
466
|
+
inputLines: [],
|
|
467
|
+
outputLines: []
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
constructor(entity) {
|
|
471
|
+
super(entity);
|
|
472
|
+
this.entity = entity;
|
|
473
|
+
this.toDispose.push(
|
|
474
|
+
Disposable.create(() => {
|
|
475
|
+
this.inputLines.slice().forEach((line) => line.dispose());
|
|
476
|
+
this.outputLines.slice().forEach((line) => line.dispose());
|
|
477
|
+
})
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* 输入线条
|
|
482
|
+
*/
|
|
483
|
+
get inputLines() {
|
|
484
|
+
return this.data.inputLines;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* 输出线条
|
|
488
|
+
*/
|
|
489
|
+
get outputLines() {
|
|
490
|
+
return this.data.outputLines;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* 输入节点
|
|
494
|
+
*/
|
|
495
|
+
get inputNodes() {
|
|
496
|
+
return this.inputLines.map((l) => l.from).filter(Boolean);
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* 所有输入节点
|
|
500
|
+
*/
|
|
501
|
+
get allInputNodes() {
|
|
502
|
+
const nodeSet = /* @__PURE__ */ new Set();
|
|
503
|
+
const handleNode = (node) => {
|
|
504
|
+
if (nodeSet.has(node)) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
nodeSet.add(node);
|
|
508
|
+
const { inputNodes } = node.getData(_WorkflowNodeLinesData);
|
|
509
|
+
if (!inputNodes || !inputNodes.length) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
inputNodes.forEach((inputNode) => {
|
|
513
|
+
if (inputNode?.parent === node || node?.parent === inputNode) {
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
handleNode(inputNode);
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
handleNode(this.entity);
|
|
520
|
+
nodeSet.delete(this.entity);
|
|
521
|
+
return Array.from(nodeSet);
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* 输出节点
|
|
525
|
+
*/
|
|
526
|
+
get outputNodes() {
|
|
527
|
+
return this.outputLines.map((l) => l.to).filter(Boolean);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* 输入输出节点
|
|
531
|
+
*/
|
|
532
|
+
get allOutputNodes() {
|
|
533
|
+
const nodeSet = /* @__PURE__ */ new Set();
|
|
534
|
+
const handleNode = (node) => {
|
|
535
|
+
if (nodeSet.has(node)) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
nodeSet.add(node);
|
|
539
|
+
const { outputNodes } = node.getData(_WorkflowNodeLinesData);
|
|
540
|
+
if (!outputNodes || !outputNodes.length) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
outputNodes.forEach((outputNode) => {
|
|
544
|
+
if (outputNode?.parent === node || node?.parent === outputNode) {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
handleNode(outputNode);
|
|
548
|
+
});
|
|
549
|
+
};
|
|
550
|
+
handleNode(this.entity);
|
|
551
|
+
nodeSet.delete(this.entity);
|
|
552
|
+
return Array.from(nodeSet);
|
|
553
|
+
}
|
|
554
|
+
addLine(line) {
|
|
555
|
+
if (line.from === this.entity) {
|
|
556
|
+
this.outputLines.push(line);
|
|
557
|
+
} else {
|
|
558
|
+
this.inputLines.push(line);
|
|
559
|
+
}
|
|
560
|
+
this.fireChange();
|
|
561
|
+
}
|
|
562
|
+
removeLine(line) {
|
|
563
|
+
const { inputLines, outputLines } = this;
|
|
564
|
+
const inputIndex = inputLines.indexOf(line);
|
|
565
|
+
const outputIndex = outputLines.indexOf(line);
|
|
566
|
+
if (inputIndex !== -1) {
|
|
567
|
+
inputLines.splice(inputIndex, 1);
|
|
568
|
+
this.fireChange();
|
|
569
|
+
}
|
|
570
|
+
if (outputIndex !== -1) {
|
|
571
|
+
outputLines.splice(outputIndex, 1);
|
|
572
|
+
this.fireChange();
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
_WorkflowNodeLinesData.type = "WorkflowNodeLinesData";
|
|
577
|
+
var WorkflowNodeLinesData = _WorkflowNodeLinesData;
|
|
578
|
+
|
|
579
|
+
// src/entity-datas/workflow-line-render-data.ts
|
|
580
|
+
import { Rectangle as Rectangle4 } from "@flowgram.ai/utils";
|
|
581
|
+
import { EntityData as EntityData3 } from "@flowgram.ai/core";
|
|
582
|
+
var WorkflowLineRenderData = class extends EntityData3 {
|
|
583
|
+
constructor(entity) {
|
|
584
|
+
super(entity);
|
|
585
|
+
this.syncContributions();
|
|
586
|
+
}
|
|
587
|
+
getDefaultData() {
|
|
588
|
+
return {
|
|
589
|
+
version: "",
|
|
590
|
+
contributions: /* @__PURE__ */ new Map(),
|
|
591
|
+
position: {
|
|
592
|
+
from: { x: 0, y: 0 },
|
|
593
|
+
to: { x: 0, y: 0 }
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
get renderVersion() {
|
|
598
|
+
return this.data.version;
|
|
599
|
+
}
|
|
600
|
+
get position() {
|
|
601
|
+
return this.data.position;
|
|
602
|
+
}
|
|
603
|
+
get path() {
|
|
604
|
+
return this.currentLine?.path ?? "";
|
|
605
|
+
}
|
|
606
|
+
calcDistance(pos) {
|
|
607
|
+
return this.currentLine?.calcDistance(pos) ?? Number.MAX_SAFE_INTEGER;
|
|
608
|
+
}
|
|
609
|
+
get bounds() {
|
|
610
|
+
return this.currentLine?.bounds ?? new Rectangle4();
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* 更新数据
|
|
614
|
+
* WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排
|
|
615
|
+
*/
|
|
616
|
+
update() {
|
|
617
|
+
this.syncContributions();
|
|
618
|
+
const oldVersion = this.data.version;
|
|
619
|
+
this.updatePosition();
|
|
620
|
+
const newVersion = this.data.version;
|
|
621
|
+
if (oldVersion === newVersion) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
this.data.version = newVersion;
|
|
625
|
+
this.currentLine?.update({
|
|
626
|
+
fromPos: this.data.position.from,
|
|
627
|
+
toPos: this.data.position.to
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
get lineType() {
|
|
631
|
+
return this.entity.renderType ?? this.entity.linesManager.lineType;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* 更新版本
|
|
635
|
+
* WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排
|
|
636
|
+
*/
|
|
637
|
+
updatePosition() {
|
|
638
|
+
this.data.position.from = this.entity.from.getData(WorkflowNodePortsData).getOutputPoint(this.entity.info.fromPort);
|
|
639
|
+
this.data.position.to = this.entity.info.drawingTo ?? this.entity.to?.getData(WorkflowNodePortsData)?.getInputPoint(this.entity.info.toPort) ?? {
|
|
640
|
+
x: this.data.position.from.x,
|
|
641
|
+
y: this.data.position.from.y
|
|
642
|
+
};
|
|
643
|
+
this.data.version = [
|
|
644
|
+
this.lineType,
|
|
645
|
+
this.data.position.from.x,
|
|
646
|
+
this.data.position.from.y,
|
|
647
|
+
this.data.position.to.x,
|
|
648
|
+
this.data.position.to.y
|
|
649
|
+
].join("-");
|
|
650
|
+
}
|
|
651
|
+
get currentLine() {
|
|
652
|
+
return this.data.contributions.get(this.lineType);
|
|
653
|
+
}
|
|
654
|
+
syncContributions() {
|
|
655
|
+
if (this.entity.linesManager.contributionFactories.length === this.data.contributions.size) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
this.entity.linesManager.contributionFactories.forEach((factory) => {
|
|
659
|
+
this.registerContribution(factory);
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
registerContribution(contributionFactory) {
|
|
663
|
+
if (this.data.contributions.has(contributionFactory.type)) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
const contribution = new contributionFactory(this.entity);
|
|
667
|
+
this.data.contributions.set(contributionFactory.type, contribution);
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
WorkflowLineRenderData.type = "WorkflowLineRenderData";
|
|
671
|
+
|
|
770
672
|
// src/entities/workflow-line-entity.ts
|
|
771
673
|
var LINE_HOVER_DISTANCE = 8;
|
|
772
674
|
var POINT_RADIUS = 10;
|
|
@@ -781,10 +683,6 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
|
|
|
781
683
|
this.info = {
|
|
782
684
|
from: ""
|
|
783
685
|
};
|
|
784
|
-
/**
|
|
785
|
-
* 贝塞尔线条版本
|
|
786
|
-
*/
|
|
787
|
-
this._bezierVersion = "";
|
|
788
686
|
this.document = opts.document;
|
|
789
687
|
this.linesManager = opts.linesManager;
|
|
790
688
|
this.initInfo({
|
|
@@ -910,59 +808,17 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
|
|
|
910
808
|
this.fireChange();
|
|
911
809
|
}
|
|
912
810
|
}
|
|
913
|
-
/**
|
|
914
|
-
* 创建贝塞尔线条
|
|
915
|
-
* @param fromPos 前置节点位置
|
|
916
|
-
* @param toPos 后置节点位置
|
|
917
|
-
* @returns 贝塞尔线条数据
|
|
918
|
-
*/
|
|
919
|
-
createBezier(fromPos, toPos) {
|
|
920
|
-
const controls = this.vertical ? getBezierVerticalControlPoints(fromPos, toPos) : getBezierHorizontalControlPoints(fromPos, toPos);
|
|
921
|
-
const bezier = new Bezier([fromPos, ...controls, toPos]);
|
|
922
|
-
const bbox = bezier.bbox();
|
|
923
|
-
const bboxBounds = new Rectangle6(
|
|
924
|
-
bbox.x.min,
|
|
925
|
-
bbox.y.min,
|
|
926
|
-
bbox.x.max - bbox.x.min,
|
|
927
|
-
bbox.y.max - bbox.y.min
|
|
928
|
-
);
|
|
929
|
-
const foldPoints = FoldLine.getPoints({
|
|
930
|
-
source: {
|
|
931
|
-
x: fromPos.x + POINT_RADIUS,
|
|
932
|
-
y: fromPos.y
|
|
933
|
-
},
|
|
934
|
-
target: {
|
|
935
|
-
x: toPos.x - POINT_RADIUS,
|
|
936
|
-
y: toPos.y
|
|
937
|
-
}
|
|
938
|
-
});
|
|
939
|
-
const foldPath = FoldLine.getSmoothStepPath(foldPoints);
|
|
940
|
-
this._bezier = {
|
|
941
|
-
fromPos,
|
|
942
|
-
toPos,
|
|
943
|
-
bezier,
|
|
944
|
-
bbox: bboxBounds,
|
|
945
|
-
controls,
|
|
946
|
-
foldPath,
|
|
947
|
-
foldPoints,
|
|
948
|
-
foldBounds: FoldLine.getBounds(foldPoints)
|
|
949
|
-
};
|
|
950
|
-
return this._bezier;
|
|
951
|
-
}
|
|
952
811
|
/**
|
|
953
812
|
* 获取线条的边框位置大小
|
|
954
813
|
*/
|
|
955
814
|
get bounds() {
|
|
956
|
-
return this.
|
|
815
|
+
return this.getData(WorkflowLineRenderData).bounds;
|
|
957
816
|
}
|
|
958
817
|
/**
|
|
959
818
|
* 获取点和线最接近的距离
|
|
960
819
|
*/
|
|
961
|
-
getHoverDist(pos
|
|
962
|
-
|
|
963
|
-
return Point2.getDistance(pos, this.bezier.bezier.project(pos));
|
|
964
|
-
}
|
|
965
|
-
return FoldLine.getFoldLineToPointDistance(this.bezier.foldPoints, pos);
|
|
820
|
+
getHoverDist(pos) {
|
|
821
|
+
return this.getData(WorkflowLineRenderData).calcDistance(pos);
|
|
966
822
|
}
|
|
967
823
|
get fromPort() {
|
|
968
824
|
return this.from.getData(WorkflowNodePortsData).getPortEntityByKey("output", this.info.fromPort);
|
|
@@ -977,37 +833,7 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
|
|
|
977
833
|
* 获取线条真实的输入输出节点坐标
|
|
978
834
|
*/
|
|
979
835
|
get position() {
|
|
980
|
-
|
|
981
|
-
return {
|
|
982
|
-
from: bezier.fromPos,
|
|
983
|
-
to: bezier.toPos
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
/**
|
|
987
|
-
* 获取贝塞尔数据
|
|
988
|
-
* 根据两边节点的位置信息创建贝塞尔曲线
|
|
989
|
-
*/
|
|
990
|
-
get bezier() {
|
|
991
|
-
if (!this._bezier) {
|
|
992
|
-
this.refreshBezier();
|
|
993
|
-
}
|
|
994
|
-
return this._bezier;
|
|
995
|
-
}
|
|
996
|
-
refreshBezier() {
|
|
997
|
-
const fromPos = this.from.getData(WorkflowNodePortsData).getOutputPoint(this.info.fromPort);
|
|
998
|
-
const toPos = this.info.drawingTo || this.to.getData(WorkflowNodePortsData).getInputPoint(this.info.toPort);
|
|
999
|
-
const bezierVersion = [fromPos.x, fromPos.y, toPos.x, toPos.y].join("-");
|
|
1000
|
-
if (this._bezier && this._bezierVersion === bezierVersion) {
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
this._bezierVersion = bezierVersion;
|
|
1004
|
-
this._bezier = this.createBezier(fromPos, toPos);
|
|
1005
|
-
}
|
|
1006
|
-
/**
|
|
1007
|
-
* 可以用于判断线条点位信息是否变化
|
|
1008
|
-
*/
|
|
1009
|
-
get bezierDataVersion() {
|
|
1010
|
-
return this._bezierVersion;
|
|
836
|
+
return this.getData(WorkflowLineRenderData).position;
|
|
1011
837
|
}
|
|
1012
838
|
/** 是否反转箭头 */
|
|
1013
839
|
get reverse() {
|
|
@@ -1029,17 +855,17 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
|
|
|
1029
855
|
get vertical() {
|
|
1030
856
|
return this.linesManager.isVerticalLine(this);
|
|
1031
857
|
}
|
|
858
|
+
/** 获取线条渲染器类型 */
|
|
859
|
+
get renderType() {
|
|
860
|
+
return this.linesManager.setLineRenderType(this);
|
|
861
|
+
}
|
|
862
|
+
/** 获取线条样式 */
|
|
863
|
+
get className() {
|
|
864
|
+
return this.linesManager.setLineClassName(this) ?? "";
|
|
865
|
+
}
|
|
1032
866
|
get color() {
|
|
1033
867
|
return this.linesManager.getLineColor(this);
|
|
1034
868
|
}
|
|
1035
|
-
// get defaultToPos(): IPoint {
|
|
1036
|
-
// const fromPos = this.from.getData(TransformComponent)!.toBounds.center;
|
|
1037
|
-
//
|
|
1038
|
-
// return {
|
|
1039
|
-
// x: fromPos.x + DEFAULT_LINE_LENGTH,
|
|
1040
|
-
// y: fromPos.y,
|
|
1041
|
-
// };
|
|
1042
|
-
// }
|
|
1043
869
|
/**
|
|
1044
870
|
* 初始化线条
|
|
1045
871
|
* @param info 线条信息
|
|
@@ -1071,15 +897,6 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
|
|
|
1071
897
|
}
|
|
1072
898
|
return _WorkflowLineEntity.portInfoToLineId(line) === this.id;
|
|
1073
899
|
}
|
|
1074
|
-
/**
|
|
1075
|
-
* 框选 贝塞尔曲线
|
|
1076
|
-
* TODO 这个方法可能有性能问题,后续看看有没有更好的方式
|
|
1077
|
-
* @param rect
|
|
1078
|
-
*/
|
|
1079
|
-
intersectsRectangle(rect) {
|
|
1080
|
-
const dots = this.bezier.bezier.getLUT(50);
|
|
1081
|
-
return dots.some((dot) => rect.contains(dot.x, dot.y));
|
|
1082
|
-
}
|
|
1083
900
|
canRemove(newLineInfo) {
|
|
1084
901
|
return this.linesManager.canRemove(this, newLineInfo);
|
|
1085
902
|
}
|
|
@@ -1185,7 +1002,7 @@ var WorkflowSelectService = class {
|
|
|
1185
1002
|
entities: [node]
|
|
1186
1003
|
};
|
|
1187
1004
|
if (fitView2) {
|
|
1188
|
-
const bounds =
|
|
1005
|
+
const bounds = Rectangle6.enlarge([node.getData(TransformData4).bounds]).pad(
|
|
1189
1006
|
30,
|
|
1190
1007
|
30
|
|
1191
1008
|
);
|
|
@@ -1278,7 +1095,7 @@ import {
|
|
|
1278
1095
|
PromiseDeferred,
|
|
1279
1096
|
Emitter as Emitter5,
|
|
1280
1097
|
DisposableCollection as DisposableCollection2,
|
|
1281
|
-
Rectangle as
|
|
1098
|
+
Rectangle as Rectangle8,
|
|
1282
1099
|
delay as delay2
|
|
1283
1100
|
} from "@flowgram.ai/utils";
|
|
1284
1101
|
import {
|
|
@@ -1351,125 +1168,6 @@ var WorkflowDocumentOptionsDefault = {
|
|
|
1351
1168
|
}
|
|
1352
1169
|
};
|
|
1353
1170
|
|
|
1354
|
-
// src/entity-datas/workflow-node-lines-data.ts
|
|
1355
|
-
import { Disposable } from "@flowgram.ai/utils";
|
|
1356
|
-
import { EntityData as EntityData2 } from "@flowgram.ai/core";
|
|
1357
|
-
var _WorkflowNodeLinesData = class _WorkflowNodeLinesData extends EntityData2 {
|
|
1358
|
-
getDefaultData() {
|
|
1359
|
-
return {
|
|
1360
|
-
inputLines: [],
|
|
1361
|
-
outputLines: []
|
|
1362
|
-
};
|
|
1363
|
-
}
|
|
1364
|
-
constructor(entity) {
|
|
1365
|
-
super(entity);
|
|
1366
|
-
this.entity = entity;
|
|
1367
|
-
this.toDispose.push(
|
|
1368
|
-
Disposable.create(() => {
|
|
1369
|
-
this.inputLines.slice().forEach((line) => line.dispose());
|
|
1370
|
-
this.outputLines.slice().forEach((line) => line.dispose());
|
|
1371
|
-
})
|
|
1372
|
-
);
|
|
1373
|
-
}
|
|
1374
|
-
/**
|
|
1375
|
-
* 输入线条
|
|
1376
|
-
*/
|
|
1377
|
-
get inputLines() {
|
|
1378
|
-
return this.data.inputLines;
|
|
1379
|
-
}
|
|
1380
|
-
/**
|
|
1381
|
-
* 输出线条
|
|
1382
|
-
*/
|
|
1383
|
-
get outputLines() {
|
|
1384
|
-
return this.data.outputLines;
|
|
1385
|
-
}
|
|
1386
|
-
/**
|
|
1387
|
-
* 输入节点
|
|
1388
|
-
*/
|
|
1389
|
-
get inputNodes() {
|
|
1390
|
-
return this.inputLines.map((l) => l.from).filter(Boolean);
|
|
1391
|
-
}
|
|
1392
|
-
/**
|
|
1393
|
-
* 所有输入节点
|
|
1394
|
-
*/
|
|
1395
|
-
get allInputNodes() {
|
|
1396
|
-
const nodeSet = /* @__PURE__ */ new Set();
|
|
1397
|
-
const handleNode = (node) => {
|
|
1398
|
-
if (nodeSet.has(node)) {
|
|
1399
|
-
return;
|
|
1400
|
-
}
|
|
1401
|
-
nodeSet.add(node);
|
|
1402
|
-
const { inputNodes } = node.getData(_WorkflowNodeLinesData);
|
|
1403
|
-
if (!inputNodes || !inputNodes.length) {
|
|
1404
|
-
return;
|
|
1405
|
-
}
|
|
1406
|
-
inputNodes.forEach((inputNode) => {
|
|
1407
|
-
if (inputNode?.parent === node || node?.parent === inputNode) {
|
|
1408
|
-
return;
|
|
1409
|
-
}
|
|
1410
|
-
handleNode(inputNode);
|
|
1411
|
-
});
|
|
1412
|
-
};
|
|
1413
|
-
handleNode(this.entity);
|
|
1414
|
-
nodeSet.delete(this.entity);
|
|
1415
|
-
return Array.from(nodeSet);
|
|
1416
|
-
}
|
|
1417
|
-
/**
|
|
1418
|
-
* 输出节点
|
|
1419
|
-
*/
|
|
1420
|
-
get outputNodes() {
|
|
1421
|
-
return this.outputLines.map((l) => l.to).filter(Boolean);
|
|
1422
|
-
}
|
|
1423
|
-
/**
|
|
1424
|
-
* 输入输出节点
|
|
1425
|
-
*/
|
|
1426
|
-
get allOutputNodes() {
|
|
1427
|
-
const nodeSet = /* @__PURE__ */ new Set();
|
|
1428
|
-
const handleNode = (node) => {
|
|
1429
|
-
if (nodeSet.has(node)) {
|
|
1430
|
-
return;
|
|
1431
|
-
}
|
|
1432
|
-
nodeSet.add(node);
|
|
1433
|
-
const { outputNodes } = node.getData(_WorkflowNodeLinesData);
|
|
1434
|
-
if (!outputNodes || !outputNodes.length) {
|
|
1435
|
-
return;
|
|
1436
|
-
}
|
|
1437
|
-
outputNodes.forEach((outputNode) => {
|
|
1438
|
-
if (outputNode?.parent === node || node?.parent === outputNode) {
|
|
1439
|
-
return;
|
|
1440
|
-
}
|
|
1441
|
-
handleNode(outputNode);
|
|
1442
|
-
});
|
|
1443
|
-
};
|
|
1444
|
-
handleNode(this.entity);
|
|
1445
|
-
nodeSet.delete(this.entity);
|
|
1446
|
-
return Array.from(nodeSet);
|
|
1447
|
-
}
|
|
1448
|
-
addLine(line) {
|
|
1449
|
-
if (line.from === this.entity) {
|
|
1450
|
-
this.outputLines.push(line);
|
|
1451
|
-
} else {
|
|
1452
|
-
this.inputLines.push(line);
|
|
1453
|
-
}
|
|
1454
|
-
this.fireChange();
|
|
1455
|
-
}
|
|
1456
|
-
removeLine(line) {
|
|
1457
|
-
const { inputLines, outputLines } = this;
|
|
1458
|
-
const inputIndex = inputLines.indexOf(line);
|
|
1459
|
-
const outputIndex = outputLines.indexOf(line);
|
|
1460
|
-
if (inputIndex !== -1) {
|
|
1461
|
-
inputLines.splice(inputIndex, 1);
|
|
1462
|
-
this.fireChange();
|
|
1463
|
-
}
|
|
1464
|
-
if (outputIndex !== -1) {
|
|
1465
|
-
outputLines.splice(outputIndex, 1);
|
|
1466
|
-
this.fireChange();
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
};
|
|
1470
|
-
_WorkflowNodeLinesData.type = "WorkflowNodeLinesData";
|
|
1471
|
-
var WorkflowNodeLinesData = _WorkflowNodeLinesData;
|
|
1472
|
-
|
|
1473
1171
|
// src/workflow-lines-manager.ts
|
|
1474
1172
|
var WorkflowLinesManager = class {
|
|
1475
1173
|
constructor() {
|
|
@@ -1486,6 +1184,7 @@ var WorkflowLinesManager = class {
|
|
|
1486
1184
|
* 强制渲染 lines
|
|
1487
1185
|
*/
|
|
1488
1186
|
this.onForceUpdate = this.onForceUpdateEmitter.event;
|
|
1187
|
+
this.contributionFactories = [];
|
|
1489
1188
|
/**
|
|
1490
1189
|
* 是否在调整线条
|
|
1491
1190
|
*/
|
|
@@ -1524,7 +1223,12 @@ var WorkflowLinesManager = class {
|
|
|
1524
1223
|
}
|
|
1525
1224
|
if (newType !== this._lineType) {
|
|
1526
1225
|
this._lineType = newType;
|
|
1527
|
-
this.
|
|
1226
|
+
this.getAllLines().forEach((line) => {
|
|
1227
|
+
line.getData(WorkflowLineRenderData).update();
|
|
1228
|
+
});
|
|
1229
|
+
window.requestAnimationFrame(() => {
|
|
1230
|
+
this.entityManager.fireEntityChanged(WorkflowLineEntity.type);
|
|
1231
|
+
});
|
|
1528
1232
|
}
|
|
1529
1233
|
return this._lineType;
|
|
1530
1234
|
}
|
|
@@ -1574,6 +1278,7 @@ var WorkflowLinesManager = class {
|
|
|
1574
1278
|
to,
|
|
1575
1279
|
drawingTo
|
|
1576
1280
|
});
|
|
1281
|
+
this.registerData(line);
|
|
1577
1282
|
fromNode.addLine(line);
|
|
1578
1283
|
toNode?.addLine(line);
|
|
1579
1284
|
line.onDispose(() => {
|
|
@@ -1614,7 +1319,7 @@ var WorkflowLinesManager = class {
|
|
|
1614
1319
|
getCloseInLineFromMousePos(mousePos, minDistance = LINE_HOVER_DISTANCE) {
|
|
1615
1320
|
let targetLine, targetLineDist;
|
|
1616
1321
|
this.getAllLines().forEach((line) => {
|
|
1617
|
-
const dist = line.getHoverDist(mousePos
|
|
1322
|
+
const dist = line.getHoverDist(mousePos);
|
|
1618
1323
|
if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {
|
|
1619
1324
|
targetLineDist = dist;
|
|
1620
1325
|
targetLine = line;
|
|
@@ -1664,6 +1369,18 @@ var WorkflowLinesManager = class {
|
|
|
1664
1369
|
}
|
|
1665
1370
|
return false;
|
|
1666
1371
|
}
|
|
1372
|
+
setLineRenderType(line) {
|
|
1373
|
+
if (this.options.setLineRenderType) {
|
|
1374
|
+
return this.options.setLineRenderType(line);
|
|
1375
|
+
}
|
|
1376
|
+
return void 0;
|
|
1377
|
+
}
|
|
1378
|
+
setLineClassName(line) {
|
|
1379
|
+
if (this.options.setLineClassName) {
|
|
1380
|
+
return this.options.setLineClassName(line);
|
|
1381
|
+
}
|
|
1382
|
+
return void 0;
|
|
1383
|
+
}
|
|
1667
1384
|
getLineColor(line) {
|
|
1668
1385
|
if (line.isHidden) {
|
|
1669
1386
|
return this.lineColor.hidden;
|
|
@@ -1752,6 +1469,13 @@ var WorkflowLinesManager = class {
|
|
|
1752
1469
|
}
|
|
1753
1470
|
return last(containNodes);
|
|
1754
1471
|
}
|
|
1472
|
+
registerContribution(factory) {
|
|
1473
|
+
this.contributionFactories.push(factory);
|
|
1474
|
+
return this;
|
|
1475
|
+
}
|
|
1476
|
+
registerData(line) {
|
|
1477
|
+
line.addData(WorkflowLineRenderData);
|
|
1478
|
+
}
|
|
1755
1479
|
};
|
|
1756
1480
|
__decorateClass([
|
|
1757
1481
|
inject3(WorkflowHoverService)
|
|
@@ -1791,7 +1515,7 @@ import {
|
|
|
1791
1515
|
import { PlaygroundConfigEntity as PlaygroundConfigEntity3, TransformData as TransformData7 } from "@flowgram.ai/core";
|
|
1792
1516
|
import {
|
|
1793
1517
|
PaddingSchema,
|
|
1794
|
-
Rectangle as
|
|
1518
|
+
Rectangle as Rectangle7,
|
|
1795
1519
|
SizeSchema as SizeSchema2
|
|
1796
1520
|
} from "@flowgram.ai/utils";
|
|
1797
1521
|
var FREE_LAYOUT_KEY = "free-layout";
|
|
@@ -1845,7 +1569,7 @@ var FreeLayout = class {
|
|
|
1845
1569
|
* @param contentSize
|
|
1846
1570
|
*/
|
|
1847
1571
|
getInitScroll(contentSize) {
|
|
1848
|
-
const bounds =
|
|
1572
|
+
const bounds = Rectangle7.enlarge(
|
|
1849
1573
|
this.document.getAllNodes().map((node) => node.getData(TransformData7).bounds)
|
|
1850
1574
|
).pad(30, 30);
|
|
1851
1575
|
const viewport = this.playgroundConfig.getViewport(false);
|
|
@@ -2656,17 +2380,17 @@ var WorkflowDragService = class {
|
|
|
2656
2380
|
domNode.style.left = `${left}px`;
|
|
2657
2381
|
domNode.style.top = `${right}px`;
|
|
2658
2382
|
const { x, y } = this.playgroundConfig.getPosFromMouseEvent(e);
|
|
2659
|
-
const draggingRect = new
|
|
2383
|
+
const draggingRect = new Rectangle8(x, y, 170, 90);
|
|
2660
2384
|
const collisionTransform = this._droppableTransforms.find((transform) => {
|
|
2661
2385
|
const { bounds, entity } = transform;
|
|
2662
2386
|
const padding = this.document.layout.getPadding(entity);
|
|
2663
|
-
const transformRect = new
|
|
2387
|
+
const transformRect = new Rectangle8(
|
|
2664
2388
|
bounds.x + padding.left + padding.right,
|
|
2665
2389
|
bounds.y,
|
|
2666
2390
|
bounds.width,
|
|
2667
2391
|
bounds.height
|
|
2668
2392
|
);
|
|
2669
|
-
return
|
|
2393
|
+
return Rectangle8.intersects(draggingRect, transformRect);
|
|
2670
2394
|
});
|
|
2671
2395
|
this.updateDropNode(collisionTransform?.entity);
|
|
2672
2396
|
},
|
|
@@ -2770,7 +2494,7 @@ var WorkflowDragService = class {
|
|
|
2770
2494
|
* 获取节点整体位置
|
|
2771
2495
|
*/
|
|
2772
2496
|
getNodesPosition(nodes) {
|
|
2773
|
-
const selectedBounds =
|
|
2497
|
+
const selectedBounds = Rectangle8.enlarge(
|
|
2774
2498
|
nodes.map((n) => n.getData(FlowNodeTransformData5).bounds)
|
|
2775
2499
|
);
|
|
2776
2500
|
const position = {
|
|
@@ -3372,10 +3096,83 @@ var WorkflowDocumentContainerModule = new ContainerModule(
|
|
|
3372
3096
|
bind(WorkflowDocumentProvider).toDynamicValue((ctx) => () => ctx.container.get(WorkflowDocument)).inSingletonScope();
|
|
3373
3097
|
}
|
|
3374
3098
|
);
|
|
3099
|
+
|
|
3100
|
+
// src/utils/simple-line.ts
|
|
3101
|
+
import { Point, Rectangle as Rectangle9 } from "@flowgram.ai/utils";
|
|
3102
|
+
var LINE_PADDING = 12;
|
|
3103
|
+
var WorkflowSimpleLineContribution = class {
|
|
3104
|
+
constructor(entity) {
|
|
3105
|
+
this.entity = entity;
|
|
3106
|
+
}
|
|
3107
|
+
get path() {
|
|
3108
|
+
return this.data?.path ?? "";
|
|
3109
|
+
}
|
|
3110
|
+
calcDistance(pos) {
|
|
3111
|
+
if (!this.data) {
|
|
3112
|
+
return Number.MAX_SAFE_INTEGER;
|
|
3113
|
+
}
|
|
3114
|
+
const [start, end] = this.data.points;
|
|
3115
|
+
return Point.getDistance(pos, this.projectPointOnLine(pos, start, end));
|
|
3116
|
+
}
|
|
3117
|
+
get bounds() {
|
|
3118
|
+
if (!this.data) {
|
|
3119
|
+
return new Rectangle9();
|
|
3120
|
+
}
|
|
3121
|
+
return this.data.bbox;
|
|
3122
|
+
}
|
|
3123
|
+
update(params) {
|
|
3124
|
+
const { fromPos, toPos } = params;
|
|
3125
|
+
const { vertical } = this.entity;
|
|
3126
|
+
const sourceOffset = {
|
|
3127
|
+
x: vertical ? 0 : POINT_RADIUS,
|
|
3128
|
+
y: vertical ? POINT_RADIUS : 0
|
|
3129
|
+
};
|
|
3130
|
+
const targetOffset = {
|
|
3131
|
+
x: vertical ? 0 : -POINT_RADIUS,
|
|
3132
|
+
y: vertical ? -POINT_RADIUS : 0
|
|
3133
|
+
};
|
|
3134
|
+
const points = [
|
|
3135
|
+
{
|
|
3136
|
+
x: fromPos.x + sourceOffset.x,
|
|
3137
|
+
y: fromPos.y + sourceOffset.y
|
|
3138
|
+
},
|
|
3139
|
+
{
|
|
3140
|
+
x: toPos.x + targetOffset.x,
|
|
3141
|
+
y: toPos.y + targetOffset.y
|
|
3142
|
+
}
|
|
3143
|
+
];
|
|
3144
|
+
const bbox = Rectangle9.createRectangleWithTwoPoints(points[0], points[1]);
|
|
3145
|
+
const adjustedPoints = points.map((p) => ({
|
|
3146
|
+
x: p.x - bbox.x + LINE_PADDING,
|
|
3147
|
+
y: p.y - bbox.y + LINE_PADDING
|
|
3148
|
+
}));
|
|
3149
|
+
const path = `M ${adjustedPoints[0].x} ${adjustedPoints[0].y} L ${adjustedPoints[1].x} ${adjustedPoints[1].y}`;
|
|
3150
|
+
this.data = {
|
|
3151
|
+
points,
|
|
3152
|
+
path,
|
|
3153
|
+
bbox
|
|
3154
|
+
};
|
|
3155
|
+
}
|
|
3156
|
+
projectPointOnLine(point, lineStart, lineEnd) {
|
|
3157
|
+
const dx = lineEnd.x - lineStart.x;
|
|
3158
|
+
const dy = lineEnd.y - lineStart.y;
|
|
3159
|
+
if (dx === 0) {
|
|
3160
|
+
return { x: lineStart.x, y: point.y };
|
|
3161
|
+
}
|
|
3162
|
+
if (dy === 0) {
|
|
3163
|
+
return { x: point.x, y: lineStart.y };
|
|
3164
|
+
}
|
|
3165
|
+
const t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / (dx * dx + dy * dy);
|
|
3166
|
+
const clampedT = Math.max(0, Math.min(1, t));
|
|
3167
|
+
return {
|
|
3168
|
+
x: lineStart.x + clampedT * dx,
|
|
3169
|
+
y: lineStart.y + clampedT * dy
|
|
3170
|
+
};
|
|
3171
|
+
}
|
|
3172
|
+
};
|
|
3173
|
+
WorkflowSimpleLineContribution.type = "WorkflowSimpleLineContribution";
|
|
3375
3174
|
export {
|
|
3376
|
-
BezierControlType,
|
|
3377
3175
|
EditorCursorState,
|
|
3378
|
-
FoldLine,
|
|
3379
3176
|
InteractiveType,
|
|
3380
3177
|
LINE_HOVER_DISTANCE,
|
|
3381
3178
|
LineColors,
|
|
@@ -3394,6 +3191,7 @@ export {
|
|
|
3394
3191
|
WorkflowDragService,
|
|
3395
3192
|
WorkflowHoverService,
|
|
3396
3193
|
WorkflowLineEntity,
|
|
3194
|
+
WorkflowLineRenderData,
|
|
3397
3195
|
WorkflowLinesManager,
|
|
3398
3196
|
WorkflowNodeEntity,
|
|
3399
3197
|
WorkflowNodeLinesData,
|
|
@@ -3401,6 +3199,7 @@ export {
|
|
|
3401
3199
|
WorkflowPortEntity,
|
|
3402
3200
|
WorkflowResetLayoutService,
|
|
3403
3201
|
WorkflowSelectService,
|
|
3202
|
+
WorkflowSimpleLineContribution,
|
|
3404
3203
|
bindConfigEntity,
|
|
3405
3204
|
compose,
|
|
3406
3205
|
composeAsync,
|
|
@@ -3408,8 +3207,6 @@ export {
|
|
|
3408
3207
|
domReactToBounds,
|
|
3409
3208
|
fitView,
|
|
3410
3209
|
getAntiOverlapPosition,
|
|
3411
|
-
getBezierHorizontalControlPoints,
|
|
3412
|
-
getBezierVerticalControlPoints,
|
|
3413
3210
|
getPortEntityId,
|
|
3414
3211
|
nanoid,
|
|
3415
3212
|
useConfigEntity,
|