@flowgram.ai/free-lines-plugin 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/index.js +835 -132
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +135 -8
- package/dist/index.d.ts +135 -8
- package/dist/index.js +845 -143
- package/dist/index.js.map +1 -1
- package/package.json +10 -8
package/dist/esm/index.js
CHANGED
|
@@ -237,13 +237,15 @@ var WorkflowPortRender = (
|
|
|
237
237
|
|
|
238
238
|
// src/constants/lines.ts
|
|
239
239
|
var LINE_OFFSET = 6;
|
|
240
|
+
var LINE_PADDING = 12;
|
|
240
241
|
|
|
241
242
|
// src/create-free-lines-plugin.ts
|
|
243
|
+
import { WorkflowLinesManager as WorkflowLinesManager2 } from "@flowgram.ai/free-layout-core";
|
|
242
244
|
import { definePluginCreator } from "@flowgram.ai/core";
|
|
243
245
|
|
|
244
|
-
// src/layer/lines-layer.tsx
|
|
246
|
+
// src/layer/workflow-lines-layer.tsx
|
|
245
247
|
import ReactDOM2 from "react-dom";
|
|
246
|
-
import
|
|
248
|
+
import React5, { useLayoutEffect, useState as useState2 } from "react";
|
|
247
249
|
import { inject, injectable } from "inversify";
|
|
248
250
|
import { domUtils } from "@flowgram.ai/utils";
|
|
249
251
|
import {
|
|
@@ -251,21 +253,23 @@ import {
|
|
|
251
253
|
WorkflowDocument,
|
|
252
254
|
WorkflowHoverService as WorkflowHoverService2,
|
|
253
255
|
WorkflowLineEntity,
|
|
256
|
+
WorkflowLineRenderData as WorkflowLineRenderData2,
|
|
254
257
|
WorkflowNodeEntity,
|
|
255
258
|
WorkflowPortEntity,
|
|
256
259
|
WorkflowSelectService
|
|
257
260
|
} from "@flowgram.ai/free-layout-core";
|
|
258
261
|
import { Layer, observeEntities, observeEntityDatas, TransformData } from "@flowgram.ai/core";
|
|
259
262
|
|
|
260
|
-
// src/components/
|
|
261
|
-
import
|
|
262
|
-
import { LineType } from "@flowgram.ai/free-layout-core";
|
|
263
|
+
// src/components/workflow-line-render/index.tsx
|
|
264
|
+
import { memo } from "react";
|
|
263
265
|
|
|
264
|
-
// src/components/
|
|
266
|
+
// src/components/workflow-line-render/line-svg.tsx
|
|
265
267
|
import React4 from "react";
|
|
268
|
+
import clsx from "clsx";
|
|
266
269
|
import { POINT_RADIUS } from "@flowgram.ai/free-layout-core";
|
|
270
|
+
import { WorkflowLineRenderData } from "@flowgram.ai/free-layout-core";
|
|
267
271
|
|
|
268
|
-
// src/components/
|
|
272
|
+
// src/components/workflow-line-render/index.style.ts
|
|
269
273
|
import styled2 from "styled-components";
|
|
270
274
|
var LineStyle = styled2.div.attrs({
|
|
271
275
|
className: "gedit-flow-activity-edge"
|
|
@@ -278,13 +282,16 @@ var LineStyle = styled2.div.attrs({
|
|
|
278
282
|
}
|
|
279
283
|
}
|
|
280
284
|
|
|
281
|
-
.
|
|
285
|
+
.dashed-line {
|
|
282
286
|
stroke-dasharray: 8, 5;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.flowing-line {
|
|
283
290
|
animation: flowingDash 0.5s linear infinite;
|
|
284
291
|
}
|
|
285
292
|
`;
|
|
286
293
|
|
|
287
|
-
// src/components/
|
|
294
|
+
// src/components/workflow-line-render/arrow.tsx
|
|
288
295
|
import React3 from "react";
|
|
289
296
|
function ArrowRenderer({
|
|
290
297
|
id,
|
|
@@ -310,116 +317,48 @@ function ArrowRenderer({
|
|
|
310
317
|
);
|
|
311
318
|
}
|
|
312
319
|
|
|
313
|
-
// src/components/
|
|
314
|
-
var FoldLineRender = (props) => {
|
|
315
|
-
const { selected, color, line, children } = props;
|
|
316
|
-
const { to, from } = line.position;
|
|
317
|
-
const strokeWidth = selected ? STROKE_WIDTH_SLECTED : STROKE_WIDTH;
|
|
318
|
-
const arrowToPos = {
|
|
319
|
-
x: to.x - POINT_RADIUS,
|
|
320
|
-
y: to.y
|
|
321
|
-
};
|
|
322
|
-
const arrowFromPos = {
|
|
323
|
-
x: from.x + POINT_RADIUS + LINE_OFFSET,
|
|
324
|
-
y: from.y
|
|
325
|
-
};
|
|
326
|
-
return /* @__PURE__ */ React4.createElement(LineStyle, null, children, /* @__PURE__ */ React4.createElement("svg", { overflow: "visible" }, /* @__PURE__ */ React4.createElement("defs", null, /* @__PURE__ */ React4.createElement(
|
|
327
|
-
"linearGradient",
|
|
328
|
-
{
|
|
329
|
-
x1: "0%",
|
|
330
|
-
y1: "100%",
|
|
331
|
-
x2: "100%",
|
|
332
|
-
y2: "100%",
|
|
333
|
-
id: line.id,
|
|
334
|
-
gradientUnits: "userSpaceOnUse"
|
|
335
|
-
},
|
|
336
|
-
/* @__PURE__ */ React4.createElement("stop", { stopColor: color, offset: "0%" }),
|
|
337
|
-
/* @__PURE__ */ React4.createElement("stop", { stopColor: color, offset: "100%" })
|
|
338
|
-
)), /* @__PURE__ */ React4.createElement("g", null, /* @__PURE__ */ React4.createElement(
|
|
339
|
-
"path",
|
|
340
|
-
{
|
|
341
|
-
d: line.bezier.foldPath,
|
|
342
|
-
fill: "none",
|
|
343
|
-
strokeLinecap: "round",
|
|
344
|
-
stroke: color,
|
|
345
|
-
strokeWidth,
|
|
346
|
-
className: line.flowing || line.processing ? "flowing-line" : ""
|
|
347
|
-
}
|
|
348
|
-
), /* @__PURE__ */ React4.createElement(
|
|
349
|
-
ArrowRenderer,
|
|
350
|
-
{
|
|
351
|
-
id: line.id,
|
|
352
|
-
reverseArrow: line.reverse,
|
|
353
|
-
pos: line.reverse ? arrowFromPos : arrowToPos,
|
|
354
|
-
strokeWidth,
|
|
355
|
-
hide: line.hideArrow
|
|
356
|
-
}
|
|
357
|
-
))));
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
// src/components/lines/bezier-line/index.tsx
|
|
361
|
-
import React5 from "react";
|
|
362
|
-
import { POINT_RADIUS as POINT_RADIUS2 } from "@flowgram.ai/free-layout-core";
|
|
320
|
+
// src/components/workflow-line-render/line-svg.tsx
|
|
363
321
|
var PADDING = 12;
|
|
364
|
-
var
|
|
365
|
-
const { line, color,
|
|
366
|
-
const { bbox } = line.bezier;
|
|
322
|
+
var LineSVG = (props) => {
|
|
323
|
+
const { line, color, selected, children, strokePrefix } = props;
|
|
367
324
|
const { position, reverse, vertical, hideArrow } = line;
|
|
325
|
+
const renderData = line.getData(WorkflowLineRenderData);
|
|
326
|
+
const { bounds, path: bezierPath } = renderData;
|
|
368
327
|
const toRelative = (p) => ({
|
|
369
|
-
x: p.x -
|
|
370
|
-
y: p.y -
|
|
328
|
+
x: p.x - bounds.x + PADDING,
|
|
329
|
+
y: p.y - bounds.y + PADDING
|
|
371
330
|
});
|
|
372
331
|
const fromPos = toRelative(position.from);
|
|
373
332
|
const toPos = toRelative(position.to);
|
|
374
|
-
const arrowToPos = vertical ? { x: toPos.x, y: toPos.y -
|
|
375
|
-
const arrowFromPos = vertical ? { x: fromPos.x, y: fromPos.y +
|
|
376
|
-
const controls = line.bezier.controls.map((c) => toRelative(c));
|
|
377
|
-
const getLinearStartColor = () => {
|
|
378
|
-
if (vertical) {
|
|
379
|
-
return fromPos.y < arrowToPos.y ? fromColor : toColor;
|
|
380
|
-
}
|
|
381
|
-
return fromPos.x < arrowToPos.x ? fromColor : toColor;
|
|
382
|
-
};
|
|
383
|
-
const getLinearEndColor = () => {
|
|
384
|
-
if (vertical) {
|
|
385
|
-
return fromPos.y < arrowToPos.y ? toColor : fromColor;
|
|
386
|
-
}
|
|
387
|
-
return fromPos.x < arrowToPos.x ? toColor : fromColor;
|
|
388
|
-
};
|
|
389
|
-
const linearStartColor = getLinearStartColor();
|
|
390
|
-
const linearEndColor = getLinearEndColor();
|
|
391
|
-
const getPathData = () => {
|
|
392
|
-
const controlPoints = controls.map((s) => `${s.x} ${s.y}`).join(",");
|
|
393
|
-
const curveType = controls.length === 1 ? "S" : "C";
|
|
394
|
-
if (vertical) {
|
|
395
|
-
return `M${fromPos.x} ${fromPos.y + POINT_RADIUS2} ${curveType} ${controlPoints}, ${arrowToPos.x} ${arrowToPos.y}`;
|
|
396
|
-
}
|
|
397
|
-
return `M${fromPos.x + POINT_RADIUS2} ${fromPos.y} ${curveType} ${controlPoints}, ${arrowToPos.x} ${arrowToPos.y}`;
|
|
398
|
-
};
|
|
399
|
-
const pathData = getPathData();
|
|
333
|
+
const arrowToPos = vertical ? { x: toPos.x, y: toPos.y - POINT_RADIUS } : { x: toPos.x - POINT_RADIUS, y: toPos.y };
|
|
334
|
+
const arrowFromPos = vertical ? { x: fromPos.x, y: fromPos.y + POINT_RADIUS + LINE_OFFSET } : { x: fromPos.x + POINT_RADIUS + LINE_OFFSET, y: fromPos.y };
|
|
400
335
|
const strokeWidth = selected ? STROKE_WIDTH_SLECTED : STROKE_WIDTH;
|
|
401
336
|
const strokeID = strokePrefix ? `${strokePrefix}-${line.id}` : line.id;
|
|
402
|
-
const path = /* @__PURE__ */
|
|
337
|
+
const path = /* @__PURE__ */ React4.createElement(
|
|
403
338
|
"path",
|
|
404
339
|
{
|
|
405
|
-
d:
|
|
340
|
+
d: bezierPath,
|
|
406
341
|
fill: "none",
|
|
407
342
|
stroke: `url(#${strokeID})`,
|
|
408
343
|
strokeWidth,
|
|
409
|
-
className:
|
|
344
|
+
className: clsx(
|
|
345
|
+
line.className,
|
|
346
|
+
// 显示流动线条的条件:没有自定义线条class,并且线条处于流动或处理中
|
|
347
|
+
!line.className && (line.processing || line.flowing ? "dashed-line flowing-line" : "")
|
|
348
|
+
)
|
|
410
349
|
}
|
|
411
350
|
);
|
|
412
|
-
return /* @__PURE__ */
|
|
351
|
+
return /* @__PURE__ */ React4.createElement(
|
|
413
352
|
LineStyle,
|
|
414
353
|
{
|
|
415
354
|
style: {
|
|
416
|
-
left:
|
|
417
|
-
top:
|
|
355
|
+
left: bounds.x - PADDING,
|
|
356
|
+
top: bounds.y - PADDING,
|
|
418
357
|
position: "absolute"
|
|
419
358
|
}
|
|
420
359
|
},
|
|
421
360
|
children,
|
|
422
|
-
/* @__PURE__ */
|
|
361
|
+
/* @__PURE__ */ React4.createElement("svg", { width: bounds.width + PADDING * 2, height: bounds.height + PADDING * 2 }, /* @__PURE__ */ React4.createElement("defs", null, /* @__PURE__ */ React4.createElement(
|
|
423
362
|
"linearGradient",
|
|
424
363
|
{
|
|
425
364
|
x1: vertical ? "100%" : "0%",
|
|
@@ -429,9 +368,9 @@ var BezierLineRender = (props) => {
|
|
|
429
368
|
id: strokeID,
|
|
430
369
|
gradientUnits: "userSpaceOnUse"
|
|
431
370
|
},
|
|
432
|
-
/* @__PURE__ */
|
|
433
|
-
/* @__PURE__ */
|
|
434
|
-
)), /* @__PURE__ */
|
|
371
|
+
/* @__PURE__ */ React4.createElement("stop", { stopColor: color, offset: "0%" }),
|
|
372
|
+
/* @__PURE__ */ React4.createElement("stop", { stopColor: color, offset: "100%" })
|
|
373
|
+
)), /* @__PURE__ */ React4.createElement("g", null, path, /* @__PURE__ */ React4.createElement(
|
|
435
374
|
ArrowRenderer,
|
|
436
375
|
{
|
|
437
376
|
id: strokeID,
|
|
@@ -441,24 +380,18 @@ var BezierLineRender = (props) => {
|
|
|
441
380
|
vertical,
|
|
442
381
|
hide: hideArrow
|
|
443
382
|
}
|
|
444
|
-
)
|
|
383
|
+
)))
|
|
445
384
|
);
|
|
446
385
|
};
|
|
447
386
|
|
|
448
|
-
// src/components/
|
|
449
|
-
var
|
|
450
|
-
|
|
451
|
-
return /* @__PURE__ */ React6.createElement(FoldLineRender, { ...props });
|
|
452
|
-
}
|
|
453
|
-
return /* @__PURE__ */ React6.createElement(BezierLineRender, { ...props });
|
|
454
|
-
};
|
|
455
|
-
var LineRender = memo(
|
|
456
|
-
LineTypeRender,
|
|
387
|
+
// src/components/workflow-line-render/index.tsx
|
|
388
|
+
var WorkflowLineRender = memo(
|
|
389
|
+
LineSVG,
|
|
457
390
|
(prevProps, nextProps) => prevProps.version === nextProps.version
|
|
458
391
|
);
|
|
459
392
|
|
|
460
|
-
// src/layer/lines-layer.tsx
|
|
461
|
-
var
|
|
393
|
+
// src/layer/workflow-lines-layer.tsx
|
|
394
|
+
var WorkflowLinesLayer = class extends Layer {
|
|
462
395
|
constructor() {
|
|
463
396
|
super(...arguments);
|
|
464
397
|
this.layerID = nanoid();
|
|
@@ -493,9 +426,10 @@ var LinesLayer = class extends Layer {
|
|
|
493
426
|
const updateLines = () => {
|
|
494
427
|
let needsUpdate = false;
|
|
495
428
|
this.lines.forEach((line) => {
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
429
|
+
const renderData = line.getData(WorkflowLineRenderData2);
|
|
430
|
+
const oldVersion = renderData.renderVersion;
|
|
431
|
+
renderData.update();
|
|
432
|
+
if (renderData.renderVersion !== oldVersion) {
|
|
499
433
|
needsUpdate = true;
|
|
500
434
|
}
|
|
501
435
|
});
|
|
@@ -507,7 +441,7 @@ var LinesLayer = class extends Layer {
|
|
|
507
441
|
return () => cancelAnimationFrame(rafId);
|
|
508
442
|
}, [this.lines]);
|
|
509
443
|
const lines = this.lines.map((line) => this.renderLine(line));
|
|
510
|
-
return /* @__PURE__ */
|
|
444
|
+
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, lines);
|
|
511
445
|
}
|
|
512
446
|
// 用来绕过 memo
|
|
513
447
|
bumpVersion() {
|
|
@@ -517,10 +451,12 @@ var LinesLayer = class extends Layer {
|
|
|
517
451
|
}
|
|
518
452
|
}
|
|
519
453
|
lineProps(line) {
|
|
454
|
+
const renderData = line.getData(WorkflowLineRenderData2);
|
|
455
|
+
const { renderVersion } = renderData;
|
|
520
456
|
const { lineType } = this.workflowDocument.linesManager;
|
|
521
457
|
const selected = this.selectService.isSelected(line.id);
|
|
522
|
-
const { version: lineVersion,
|
|
523
|
-
const version = `${this._version}:${lineVersion}:${
|
|
458
|
+
const { version: lineVersion, color } = line;
|
|
459
|
+
const version = `${this._version}:${lineVersion}:${renderVersion}:${color}:${selected}`;
|
|
524
460
|
return {
|
|
525
461
|
key: line.id,
|
|
526
462
|
color: line.color,
|
|
@@ -532,8 +468,8 @@ var LinesLayer = class extends Layer {
|
|
|
532
468
|
};
|
|
533
469
|
}
|
|
534
470
|
lineComponent(props) {
|
|
535
|
-
const RenderInsideLine = this.options.renderInsideLine ?? (() => /* @__PURE__ */
|
|
536
|
-
return /* @__PURE__ */
|
|
471
|
+
const RenderInsideLine = this.options.renderInsideLine ?? (() => /* @__PURE__ */ React5.createElement(React5.Fragment, null));
|
|
472
|
+
return /* @__PURE__ */ React5.createElement(WorkflowLineRender, { ...props }, /* @__PURE__ */ React5.createElement(RenderInsideLine, { ...props }));
|
|
537
473
|
}
|
|
538
474
|
renderLine(line) {
|
|
539
475
|
const lineProps = this.lineProps(line);
|
|
@@ -566,33 +502,778 @@ var LinesLayer = class extends Layer {
|
|
|
566
502
|
return this.node;
|
|
567
503
|
}
|
|
568
504
|
};
|
|
569
|
-
|
|
505
|
+
WorkflowLinesLayer.type = "WorkflowLinesLayer";
|
|
570
506
|
__decorateClass([
|
|
571
507
|
inject(WorkflowHoverService2)
|
|
572
|
-
],
|
|
508
|
+
], WorkflowLinesLayer.prototype, "hoverService", 2);
|
|
573
509
|
__decorateClass([
|
|
574
510
|
inject(WorkflowSelectService)
|
|
575
|
-
],
|
|
511
|
+
], WorkflowLinesLayer.prototype, "selectService", 2);
|
|
576
512
|
__decorateClass([
|
|
577
513
|
observeEntities(WorkflowLineEntity)
|
|
578
|
-
],
|
|
514
|
+
], WorkflowLinesLayer.prototype, "lines", 2);
|
|
579
515
|
__decorateClass([
|
|
580
516
|
observeEntities(WorkflowPortEntity)
|
|
581
|
-
],
|
|
517
|
+
], WorkflowLinesLayer.prototype, "ports", 2);
|
|
582
518
|
__decorateClass([
|
|
583
519
|
observeEntityDatas(WorkflowNodeEntity, TransformData)
|
|
584
|
-
],
|
|
520
|
+
], WorkflowLinesLayer.prototype, "trans", 2);
|
|
585
521
|
__decorateClass([
|
|
586
522
|
inject(WorkflowDocument)
|
|
587
|
-
],
|
|
588
|
-
|
|
523
|
+
], WorkflowLinesLayer.prototype, "workflowDocument", 2);
|
|
524
|
+
WorkflowLinesLayer = __decorateClass([
|
|
589
525
|
injectable()
|
|
590
|
-
],
|
|
526
|
+
], WorkflowLinesLayer);
|
|
527
|
+
|
|
528
|
+
// src/contributions/bezier/bezier-controls.ts
|
|
529
|
+
import { Rectangle } from "@flowgram.ai/utils";
|
|
530
|
+
var BezierControlType = /* @__PURE__ */ ((BezierControlType2) => {
|
|
531
|
+
BezierControlType2[BezierControlType2["RIGHT_TOP"] = 0] = "RIGHT_TOP";
|
|
532
|
+
BezierControlType2[BezierControlType2["RIGHT_BOTTOM"] = 1] = "RIGHT_BOTTOM";
|
|
533
|
+
BezierControlType2[BezierControlType2["LEFT_TOP"] = 2] = "LEFT_TOP";
|
|
534
|
+
BezierControlType2[BezierControlType2["LEFT_BOTTOM"] = 3] = "LEFT_BOTTOM";
|
|
535
|
+
return BezierControlType2;
|
|
536
|
+
})(BezierControlType || {});
|
|
537
|
+
var CONTROL_MAX = 300;
|
|
538
|
+
function getBezierHorizontalControlPoints(fromPos, toPos) {
|
|
539
|
+
const rect = Rectangle.createRectangleWithTwoPoints(fromPos, toPos);
|
|
540
|
+
let type;
|
|
541
|
+
if (fromPos.x <= toPos.x) {
|
|
542
|
+
type = fromPos.y <= toPos.y ? 1 /* RIGHT_BOTTOM */ : 0 /* RIGHT_TOP */;
|
|
543
|
+
} else {
|
|
544
|
+
type = fromPos.y <= toPos.y ? 3 /* LEFT_BOTTOM */ : 2 /* LEFT_TOP */;
|
|
545
|
+
}
|
|
546
|
+
let controls;
|
|
547
|
+
switch (type) {
|
|
548
|
+
case 0 /* RIGHT_TOP */:
|
|
549
|
+
controls = [
|
|
550
|
+
{
|
|
551
|
+
x: rect.rightBottom.x - rect.width / 2,
|
|
552
|
+
y: rect.rightBottom.y
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
x: rect.leftTop.x + rect.width / 2,
|
|
556
|
+
y: rect.leftTop.y
|
|
557
|
+
}
|
|
558
|
+
];
|
|
559
|
+
break;
|
|
560
|
+
case 1 /* RIGHT_BOTTOM */:
|
|
561
|
+
controls = [
|
|
562
|
+
{
|
|
563
|
+
x: rect.rightTop.x - rect.width / 2,
|
|
564
|
+
y: rect.rightTop.y
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
x: rect.leftBottom.x + rect.width / 2,
|
|
568
|
+
y: rect.leftBottom.y
|
|
569
|
+
}
|
|
570
|
+
];
|
|
571
|
+
break;
|
|
572
|
+
case 2 /* LEFT_TOP */:
|
|
573
|
+
controls = [
|
|
574
|
+
{
|
|
575
|
+
x: rect.rightBottom.x + Math.min(rect.width, CONTROL_MAX),
|
|
576
|
+
y: rect.rightBottom.y
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
x: rect.leftTop.x - Math.min(rect.width, CONTROL_MAX),
|
|
580
|
+
y: rect.leftTop.y
|
|
581
|
+
}
|
|
582
|
+
];
|
|
583
|
+
break;
|
|
584
|
+
case 3 /* LEFT_BOTTOM */:
|
|
585
|
+
controls = [
|
|
586
|
+
{
|
|
587
|
+
x: rect.rightTop.x + Math.min(rect.width, CONTROL_MAX),
|
|
588
|
+
y: rect.rightTop.y
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
x: rect.leftBottom.x - Math.min(rect.width, CONTROL_MAX),
|
|
592
|
+
y: rect.leftBottom.y
|
|
593
|
+
}
|
|
594
|
+
];
|
|
595
|
+
}
|
|
596
|
+
return controls;
|
|
597
|
+
}
|
|
598
|
+
function getBezierVerticalControlPoints(fromPos, toPos) {
|
|
599
|
+
const rect = Rectangle.createRectangleWithTwoPoints(fromPos, toPos);
|
|
600
|
+
let type;
|
|
601
|
+
if (fromPos.y <= toPos.y) {
|
|
602
|
+
type = fromPos.x <= toPos.x ? 1 /* RIGHT_BOTTOM */ : 3 /* LEFT_BOTTOM */;
|
|
603
|
+
} else {
|
|
604
|
+
type = fromPos.x <= toPos.x ? 0 /* RIGHT_TOP */ : 2 /* LEFT_TOP */;
|
|
605
|
+
}
|
|
606
|
+
let controls;
|
|
607
|
+
switch (type) {
|
|
608
|
+
case 1 /* RIGHT_BOTTOM */:
|
|
609
|
+
controls = [
|
|
610
|
+
{
|
|
611
|
+
x: rect.leftTop.x,
|
|
612
|
+
y: rect.leftTop.y + rect.height / 2
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
x: rect.rightBottom.x,
|
|
616
|
+
y: rect.rightBottom.y - rect.height / 2
|
|
617
|
+
}
|
|
618
|
+
];
|
|
619
|
+
break;
|
|
620
|
+
case 3 /* LEFT_BOTTOM */:
|
|
621
|
+
controls = [
|
|
622
|
+
{
|
|
623
|
+
x: rect.rightTop.x,
|
|
624
|
+
y: rect.rightTop.y + rect.height / 2
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
x: rect.leftBottom.x,
|
|
628
|
+
y: rect.leftBottom.y - rect.height / 2
|
|
629
|
+
}
|
|
630
|
+
];
|
|
631
|
+
break;
|
|
632
|
+
case 0 /* RIGHT_TOP */:
|
|
633
|
+
controls = [
|
|
634
|
+
{
|
|
635
|
+
x: rect.leftBottom.x,
|
|
636
|
+
y: rect.leftBottom.y + Math.min(rect.height, CONTROL_MAX)
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
x: rect.rightTop.x,
|
|
640
|
+
y: rect.rightTop.y - Math.min(rect.height, CONTROL_MAX)
|
|
641
|
+
}
|
|
642
|
+
];
|
|
643
|
+
break;
|
|
644
|
+
case 2 /* LEFT_TOP */:
|
|
645
|
+
controls = [
|
|
646
|
+
{
|
|
647
|
+
x: rect.rightBottom.x,
|
|
648
|
+
y: rect.rightBottom.y + Math.min(rect.height, CONTROL_MAX)
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
x: rect.leftTop.x,
|
|
652
|
+
y: rect.leftTop.y - Math.min(rect.height, CONTROL_MAX)
|
|
653
|
+
}
|
|
654
|
+
];
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
return controls;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// src/contributions/bezier/index.ts
|
|
661
|
+
import { Bezier } from "bezier-js";
|
|
662
|
+
import { Point, Rectangle as Rectangle2 } from "@flowgram.ai/utils";
|
|
663
|
+
import {
|
|
664
|
+
POINT_RADIUS as POINT_RADIUS2
|
|
665
|
+
} from "@flowgram.ai/free-layout-core";
|
|
666
|
+
import { LineType } from "@flowgram.ai/free-layout-core";
|
|
667
|
+
var WorkflowBezierLineContribution = class {
|
|
668
|
+
constructor(entity) {
|
|
669
|
+
this.entity = entity;
|
|
670
|
+
}
|
|
671
|
+
get path() {
|
|
672
|
+
return this.data?.path ?? "";
|
|
673
|
+
}
|
|
674
|
+
calcDistance(pos) {
|
|
675
|
+
if (!this.data) {
|
|
676
|
+
return Number.MAX_SAFE_INTEGER;
|
|
677
|
+
}
|
|
678
|
+
return Point.getDistance(pos, this.data.bezier.project(pos));
|
|
679
|
+
}
|
|
680
|
+
get bounds() {
|
|
681
|
+
if (!this.data) {
|
|
682
|
+
return new Rectangle2();
|
|
683
|
+
}
|
|
684
|
+
return this.data.bbox;
|
|
685
|
+
}
|
|
686
|
+
update(params) {
|
|
687
|
+
this.data = this.calcBezier(params.fromPos, params.toPos);
|
|
688
|
+
}
|
|
689
|
+
calcBezier(fromPos, toPos) {
|
|
690
|
+
const controls = this.entity.vertical ? getBezierVerticalControlPoints(fromPos, toPos) : getBezierHorizontalControlPoints(fromPos, toPos);
|
|
691
|
+
const bezier = new Bezier([fromPos, ...controls, toPos]);
|
|
692
|
+
const bbox = bezier.bbox();
|
|
693
|
+
const bboxBounds = new Rectangle2(
|
|
694
|
+
bbox.x.min,
|
|
695
|
+
bbox.y.min,
|
|
696
|
+
bbox.x.max - bbox.x.min,
|
|
697
|
+
bbox.y.max - bbox.y.min
|
|
698
|
+
);
|
|
699
|
+
const path = this.getPath({ bbox: bboxBounds, fromPos, toPos, controls });
|
|
700
|
+
this.data = {
|
|
701
|
+
fromPos,
|
|
702
|
+
toPos,
|
|
703
|
+
bezier,
|
|
704
|
+
bbox: bboxBounds,
|
|
705
|
+
controls,
|
|
706
|
+
path
|
|
707
|
+
};
|
|
708
|
+
return this.data;
|
|
709
|
+
}
|
|
710
|
+
getPath(params) {
|
|
711
|
+
const { bbox } = params;
|
|
712
|
+
const toRelative = (p) => ({
|
|
713
|
+
x: p.x - bbox.x + LINE_PADDING,
|
|
714
|
+
y: p.y - bbox.y + LINE_PADDING
|
|
715
|
+
});
|
|
716
|
+
const fromPos = toRelative(params.fromPos);
|
|
717
|
+
const toPos = toRelative(params.toPos);
|
|
718
|
+
const controls = params.controls.map((c) => toRelative(c));
|
|
719
|
+
const renderToPos = this.entity.vertical ? { x: toPos.x, y: toPos.y - POINT_RADIUS2 } : { x: toPos.x - POINT_RADIUS2, y: toPos.y };
|
|
720
|
+
const getPathData = () => {
|
|
721
|
+
const controlPoints = controls.map((s) => `${s.x} ${s.y}`).join(",");
|
|
722
|
+
const curveType = controls.length === 1 ? "S" : "C";
|
|
723
|
+
if (this.entity.vertical) {
|
|
724
|
+
return `M${fromPos.x} ${fromPos.y + POINT_RADIUS2} ${curveType} ${controlPoints}, ${renderToPos.x} ${renderToPos.y}`;
|
|
725
|
+
}
|
|
726
|
+
return `M${fromPos.x + POINT_RADIUS2} ${fromPos.y} ${curveType} ${controlPoints}, ${renderToPos.x} ${renderToPos.y}`;
|
|
727
|
+
};
|
|
728
|
+
const path = getPathData();
|
|
729
|
+
return path;
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
WorkflowBezierLineContribution.type = LineType.BEZIER;
|
|
733
|
+
|
|
734
|
+
// src/contributions/fold/index.ts
|
|
735
|
+
import { Rectangle as Rectangle4 } from "@flowgram.ai/utils";
|
|
736
|
+
import {
|
|
737
|
+
POINT_RADIUS as POINT_RADIUS3
|
|
738
|
+
} from "@flowgram.ai/free-layout-core";
|
|
739
|
+
import { LineType as LineType2 } from "@flowgram.ai/free-layout-core";
|
|
740
|
+
|
|
741
|
+
// src/contributions/fold/fold-line.ts
|
|
742
|
+
import { Point as Point2, Rectangle as Rectangle3 } from "@flowgram.ai/utils";
|
|
743
|
+
function pointLineDistance(p1, p2, p3) {
|
|
744
|
+
let len;
|
|
745
|
+
if (p1.x - p2.x === 0) {
|
|
746
|
+
len = Math.abs(p3.x - p1.x);
|
|
747
|
+
} else {
|
|
748
|
+
const A = (p1.y - p2.y) / (p1.x - p2.x);
|
|
749
|
+
const B = p1.y - A * p1.x;
|
|
750
|
+
len = Math.abs((A * p3.x + B - p3.y) / Math.sqrt(A * A + 1));
|
|
751
|
+
}
|
|
752
|
+
return len;
|
|
753
|
+
}
|
|
754
|
+
var FoldLine;
|
|
755
|
+
((FoldLine2) => {
|
|
756
|
+
const EDGE_RADIUS = 5;
|
|
757
|
+
const OFFSET = 20;
|
|
758
|
+
function getEdgeCenter({ source, target }) {
|
|
759
|
+
const xOffset = Math.abs(target.x - source.x) / 2;
|
|
760
|
+
const centerX = target.x < source.x ? target.x + xOffset : target.x - xOffset;
|
|
761
|
+
const yOffset = Math.abs(target.y - source.y) / 2;
|
|
762
|
+
const centerY = target.y < source.y ? target.y + yOffset : target.y - yOffset;
|
|
763
|
+
return [centerX, centerY];
|
|
764
|
+
}
|
|
765
|
+
const getDirection = ({ source, target }) => source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };
|
|
766
|
+
function getPoints({
|
|
767
|
+
source,
|
|
768
|
+
target,
|
|
769
|
+
vertical = false
|
|
770
|
+
}) {
|
|
771
|
+
const sourceDir = vertical ? { x: 0, y: 1 } : { x: 1, y: 0 };
|
|
772
|
+
const targetDir = vertical ? { x: 0, y: -1 } : { x: -1, y: 0 };
|
|
773
|
+
const sourceGapped = {
|
|
774
|
+
x: source.x + sourceDir.x * OFFSET,
|
|
775
|
+
y: source.y + sourceDir.y * OFFSET
|
|
776
|
+
};
|
|
777
|
+
const targetGapped = {
|
|
778
|
+
x: target.x + targetDir.x * OFFSET,
|
|
779
|
+
y: target.y + targetDir.y * OFFSET
|
|
780
|
+
};
|
|
781
|
+
const dir = vertical ? { x: 0, y: sourceGapped.y < targetGapped.y ? 1 : -1 } : getDirection({ source: sourceGapped, target: targetGapped });
|
|
782
|
+
const dirAccessor = dir.x !== 0 ? "x" : "y";
|
|
783
|
+
const currDir = dir[dirAccessor];
|
|
784
|
+
let points = [];
|
|
785
|
+
let centerX, centerY;
|
|
786
|
+
const [defaultCenterX, defaultCenterY] = getEdgeCenter({
|
|
787
|
+
source,
|
|
788
|
+
target
|
|
789
|
+
});
|
|
790
|
+
if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
|
|
791
|
+
centerX = defaultCenterX;
|
|
792
|
+
centerY = defaultCenterY;
|
|
793
|
+
const verticalSplit = [
|
|
794
|
+
{ x: centerX, y: sourceGapped.y },
|
|
795
|
+
{ x: centerX, y: targetGapped.y }
|
|
796
|
+
];
|
|
797
|
+
const horizontalSplit = [
|
|
798
|
+
{ x: sourceGapped.x, y: centerY },
|
|
799
|
+
{ x: targetGapped.x, y: centerY }
|
|
800
|
+
];
|
|
801
|
+
if (sourceDir[dirAccessor] === currDir) {
|
|
802
|
+
points = dirAccessor === "x" ? verticalSplit : horizontalSplit;
|
|
803
|
+
} else {
|
|
804
|
+
points = dirAccessor === "x" ? horizontalSplit : verticalSplit;
|
|
805
|
+
}
|
|
806
|
+
} else {
|
|
807
|
+
const sourceTarget = [{ x: sourceGapped.x, y: targetGapped.y }];
|
|
808
|
+
const targetSource = [{ x: targetGapped.x, y: sourceGapped.y }];
|
|
809
|
+
if (dirAccessor === "x") {
|
|
810
|
+
points = sourceDir.x === currDir ? targetSource : sourceTarget;
|
|
811
|
+
} else {
|
|
812
|
+
points = sourceDir.y === currDir ? sourceTarget : targetSource;
|
|
813
|
+
}
|
|
814
|
+
const dirAccessorOpposite = dirAccessor === "x" ? "y" : "x";
|
|
815
|
+
const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite];
|
|
816
|
+
const sourceGtTargetOppo = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];
|
|
817
|
+
const sourceLtTargetOppo = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];
|
|
818
|
+
const flipSourceTarget = sourceDir[dirAccessor] === 1 && (!isSameDir && sourceGtTargetOppo || isSameDir && sourceLtTargetOppo) || sourceDir[dirAccessor] !== 1 && (!isSameDir && sourceLtTargetOppo || isSameDir && sourceGtTargetOppo);
|
|
819
|
+
if (flipSourceTarget) {
|
|
820
|
+
points = dirAccessor === "x" ? sourceTarget : targetSource;
|
|
821
|
+
}
|
|
822
|
+
const sourceGapPoint = { x: sourceGapped.x, y: sourceGapped.y };
|
|
823
|
+
const targetGapPoint = { x: targetGapped.x, y: targetGapped.y };
|
|
824
|
+
const maxXDistance = Math.max(
|
|
825
|
+
Math.abs(sourceGapPoint.x - points[0].x),
|
|
826
|
+
Math.abs(targetGapPoint.x - points[0].x)
|
|
827
|
+
);
|
|
828
|
+
const maxYDistance = Math.max(
|
|
829
|
+
Math.abs(sourceGapPoint.y - points[0].y),
|
|
830
|
+
Math.abs(targetGapPoint.y - points[0].y)
|
|
831
|
+
);
|
|
832
|
+
if (maxXDistance >= maxYDistance) {
|
|
833
|
+
centerX = (sourceGapPoint.x + targetGapPoint.x) / 2;
|
|
834
|
+
centerY = points[0].y;
|
|
835
|
+
} else {
|
|
836
|
+
centerX = points[0].x;
|
|
837
|
+
centerY = (sourceGapPoint.y + targetGapPoint.y) / 2;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
const pathPoints = [
|
|
841
|
+
source,
|
|
842
|
+
{ x: sourceGapped.x, y: sourceGapped.y },
|
|
843
|
+
...points,
|
|
844
|
+
{ x: targetGapped.x, y: targetGapped.y },
|
|
845
|
+
target
|
|
846
|
+
];
|
|
847
|
+
return pathPoints;
|
|
848
|
+
}
|
|
849
|
+
FoldLine2.getPoints = getPoints;
|
|
850
|
+
function getBend(a, b, c) {
|
|
851
|
+
const bendSize = Math.min(
|
|
852
|
+
Point2.getDistance(a, b) / 2,
|
|
853
|
+
Point2.getDistance(b, c) / 2,
|
|
854
|
+
EDGE_RADIUS
|
|
855
|
+
);
|
|
856
|
+
const { x, y } = b;
|
|
857
|
+
if (a.x === x && x === c.x || a.y === y && y === c.y) {
|
|
858
|
+
return `L${x} ${y}`;
|
|
859
|
+
}
|
|
860
|
+
if (a.y === y) {
|
|
861
|
+
const xDir2 = a.x < c.x ? -1 : 1;
|
|
862
|
+
const yDir2 = a.y < c.y ? 1 : -1;
|
|
863
|
+
return `L ${x + bendSize * xDir2},${y}Q ${x},${y} ${x},${y + bendSize * yDir2}`;
|
|
864
|
+
}
|
|
865
|
+
const xDir = a.x < c.x ? 1 : -1;
|
|
866
|
+
const yDir = a.y < c.y ? -1 : 1;
|
|
867
|
+
return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
|
|
868
|
+
}
|
|
869
|
+
function getSmoothStepPath(points) {
|
|
870
|
+
const path = points.reduce((res, p, i) => {
|
|
871
|
+
let segment = "";
|
|
872
|
+
if (i > 0 && i < points.length - 1) {
|
|
873
|
+
segment = getBend(points[i - 1], p, points[i + 1]);
|
|
874
|
+
} else {
|
|
875
|
+
segment = `${i === 0 ? "M" : "L"}${p.x} ${p.y}`;
|
|
876
|
+
}
|
|
877
|
+
res += segment;
|
|
878
|
+
return res;
|
|
879
|
+
}, "");
|
|
880
|
+
return path;
|
|
881
|
+
}
|
|
882
|
+
FoldLine2.getSmoothStepPath = getSmoothStepPath;
|
|
883
|
+
function getBounds(points) {
|
|
884
|
+
const xList = points.map((p) => p.x);
|
|
885
|
+
const yList = points.map((p) => p.y);
|
|
886
|
+
const left = Math.min(...xList);
|
|
887
|
+
const right = Math.max(...xList);
|
|
888
|
+
const top = Math.min(...yList);
|
|
889
|
+
const bottom = Math.max(...yList);
|
|
890
|
+
return Rectangle3.createRectangleWithTwoPoints(
|
|
891
|
+
{
|
|
892
|
+
x: left,
|
|
893
|
+
y: top
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
x: right,
|
|
897
|
+
y: bottom
|
|
898
|
+
}
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
FoldLine2.getBounds = getBounds;
|
|
902
|
+
function getFoldLineToPointDistance(points, pos) {
|
|
903
|
+
const bounds = getBounds(points);
|
|
904
|
+
if (bounds.contains(pos.x, pos.y)) {
|
|
905
|
+
const lines = points.reduce((res, point, index) => {
|
|
906
|
+
if (index === 0) {
|
|
907
|
+
return res;
|
|
908
|
+
}
|
|
909
|
+
res.push([points[index - 1], point]);
|
|
910
|
+
return res;
|
|
911
|
+
}, []);
|
|
912
|
+
return Math.min(...lines.map((l) => pointLineDistance(...l, pos)));
|
|
913
|
+
}
|
|
914
|
+
return Math.min(...points.map((p) => Point2.getDistance(p, pos)));
|
|
915
|
+
}
|
|
916
|
+
FoldLine2.getFoldLineToPointDistance = getFoldLineToPointDistance;
|
|
917
|
+
})(FoldLine || (FoldLine = {}));
|
|
918
|
+
|
|
919
|
+
// src/contributions/fold/index.ts
|
|
920
|
+
var WorkflowFoldLineContribution = class {
|
|
921
|
+
constructor(entity) {
|
|
922
|
+
this.entity = entity;
|
|
923
|
+
}
|
|
924
|
+
get path() {
|
|
925
|
+
return this.data?.path ?? "";
|
|
926
|
+
}
|
|
927
|
+
calcDistance(pos) {
|
|
928
|
+
if (!this.data) {
|
|
929
|
+
return Number.MAX_SAFE_INTEGER;
|
|
930
|
+
}
|
|
931
|
+
return FoldLine.getFoldLineToPointDistance(this.data.points, pos);
|
|
932
|
+
}
|
|
933
|
+
get bounds() {
|
|
934
|
+
if (!this.data) {
|
|
935
|
+
return new Rectangle4();
|
|
936
|
+
}
|
|
937
|
+
return this.data.bbox;
|
|
938
|
+
}
|
|
939
|
+
update(params) {
|
|
940
|
+
const { fromPos, toPos } = params;
|
|
941
|
+
const { vertical } = this.entity;
|
|
942
|
+
const sourceOffset = {
|
|
943
|
+
x: vertical ? 0 : POINT_RADIUS3,
|
|
944
|
+
y: vertical ? POINT_RADIUS3 : 0
|
|
945
|
+
};
|
|
946
|
+
const targetOffset = {
|
|
947
|
+
x: vertical ? 0 : -POINT_RADIUS3,
|
|
948
|
+
y: vertical ? -POINT_RADIUS3 : 0
|
|
949
|
+
};
|
|
950
|
+
const points = FoldLine.getPoints({
|
|
951
|
+
source: {
|
|
952
|
+
x: fromPos.x + sourceOffset.x,
|
|
953
|
+
y: fromPos.y + sourceOffset.y
|
|
954
|
+
},
|
|
955
|
+
target: {
|
|
956
|
+
x: toPos.x + targetOffset.x,
|
|
957
|
+
y: toPos.y + targetOffset.y
|
|
958
|
+
},
|
|
959
|
+
vertical
|
|
960
|
+
});
|
|
961
|
+
const bbox = FoldLine.getBounds(points);
|
|
962
|
+
const adjustedPoints = points.map((p) => ({
|
|
963
|
+
x: p.x - bbox.x + LINE_PADDING,
|
|
964
|
+
y: p.y - bbox.y + LINE_PADDING
|
|
965
|
+
}));
|
|
966
|
+
const path = FoldLine.getSmoothStepPath(adjustedPoints);
|
|
967
|
+
this.data = {
|
|
968
|
+
points,
|
|
969
|
+
path,
|
|
970
|
+
bbox
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
};
|
|
974
|
+
WorkflowFoldLineContribution.type = LineType2.LINE_CHART;
|
|
975
|
+
|
|
976
|
+
// src/contributions/straight/index.ts
|
|
977
|
+
import { Point as Point3, Rectangle as Rectangle5 } from "@flowgram.ai/utils";
|
|
978
|
+
import {
|
|
979
|
+
POINT_RADIUS as POINT_RADIUS4
|
|
980
|
+
} from "@flowgram.ai/free-layout-core";
|
|
981
|
+
|
|
982
|
+
// src/contributions/straight/point-on-line.ts
|
|
983
|
+
function projectPointOnLine(point, lineStart, lineEnd) {
|
|
984
|
+
const dx = lineEnd.x - lineStart.x;
|
|
985
|
+
const dy = lineEnd.y - lineStart.y;
|
|
986
|
+
if (dx === 0) {
|
|
987
|
+
return { x: lineStart.x, y: point.y };
|
|
988
|
+
}
|
|
989
|
+
if (dy === 0) {
|
|
990
|
+
return { x: point.x, y: lineStart.y };
|
|
991
|
+
}
|
|
992
|
+
const t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / (dx * dx + dy * dy);
|
|
993
|
+
const clampedT = Math.max(0, Math.min(1, t));
|
|
994
|
+
return {
|
|
995
|
+
x: lineStart.x + clampedT * dx,
|
|
996
|
+
y: lineStart.y + clampedT * dy
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
// src/contributions/straight/index.ts
|
|
1001
|
+
var WorkflowStraightLineContribution = class {
|
|
1002
|
+
constructor(entity) {
|
|
1003
|
+
this.entity = entity;
|
|
1004
|
+
}
|
|
1005
|
+
get path() {
|
|
1006
|
+
return this.data?.path ?? "";
|
|
1007
|
+
}
|
|
1008
|
+
calcDistance(pos) {
|
|
1009
|
+
if (!this.data) {
|
|
1010
|
+
return Number.MAX_SAFE_INTEGER;
|
|
1011
|
+
}
|
|
1012
|
+
const [start, end] = this.data.points;
|
|
1013
|
+
return Point3.getDistance(pos, projectPointOnLine(pos, start, end));
|
|
1014
|
+
}
|
|
1015
|
+
get bounds() {
|
|
1016
|
+
if (!this.data) {
|
|
1017
|
+
return new Rectangle5();
|
|
1018
|
+
}
|
|
1019
|
+
return this.data.bbox;
|
|
1020
|
+
}
|
|
1021
|
+
update(params) {
|
|
1022
|
+
const { fromPos, toPos } = params;
|
|
1023
|
+
const { vertical } = this.entity;
|
|
1024
|
+
const sourceOffset = {
|
|
1025
|
+
x: vertical ? 0 : POINT_RADIUS4,
|
|
1026
|
+
y: vertical ? POINT_RADIUS4 : 0
|
|
1027
|
+
};
|
|
1028
|
+
const targetOffset = {
|
|
1029
|
+
x: vertical ? 0 : -POINT_RADIUS4,
|
|
1030
|
+
y: vertical ? -POINT_RADIUS4 : 0
|
|
1031
|
+
};
|
|
1032
|
+
const points = [
|
|
1033
|
+
{
|
|
1034
|
+
x: fromPos.x + sourceOffset.x,
|
|
1035
|
+
y: fromPos.y + sourceOffset.y
|
|
1036
|
+
},
|
|
1037
|
+
{
|
|
1038
|
+
x: toPos.x + targetOffset.x,
|
|
1039
|
+
y: toPos.y + targetOffset.y
|
|
1040
|
+
}
|
|
1041
|
+
];
|
|
1042
|
+
const bbox = Rectangle5.createRectangleWithTwoPoints(points[0], points[1]);
|
|
1043
|
+
const adjustedPoints = points.map((p) => ({
|
|
1044
|
+
x: p.x - bbox.x + LINE_PADDING,
|
|
1045
|
+
y: p.y - bbox.y + LINE_PADDING
|
|
1046
|
+
}));
|
|
1047
|
+
const path = `M ${adjustedPoints[0].x} ${adjustedPoints[0].y} L ${adjustedPoints[1].x} ${adjustedPoints[1].y}`;
|
|
1048
|
+
this.data = {
|
|
1049
|
+
points,
|
|
1050
|
+
path,
|
|
1051
|
+
bbox
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
WorkflowStraightLineContribution.type = "WorkflowStraightLineContribution";
|
|
1056
|
+
|
|
1057
|
+
// src/contributions/arc/index.ts
|
|
1058
|
+
import { Point as Point4, Rectangle as Rectangle6 } from "@flowgram.ai/utils";
|
|
1059
|
+
import {
|
|
1060
|
+
POINT_RADIUS as POINT_RADIUS5
|
|
1061
|
+
} from "@flowgram.ai/free-layout-core";
|
|
1062
|
+
var WorkflowArkLineContribution = class {
|
|
1063
|
+
constructor(entity) {
|
|
1064
|
+
this.entity = entity;
|
|
1065
|
+
}
|
|
1066
|
+
get path() {
|
|
1067
|
+
return this.data?.path ?? "";
|
|
1068
|
+
}
|
|
1069
|
+
calcDistance(pos) {
|
|
1070
|
+
if (!this.data) {
|
|
1071
|
+
return Number.MAX_SAFE_INTEGER;
|
|
1072
|
+
}
|
|
1073
|
+
const { fromPos, toPos, bbox } = this.data;
|
|
1074
|
+
if (!bbox.contains(pos.x, pos.y)) {
|
|
1075
|
+
const dx = Math.max(bbox.x - pos.x, 0, pos.x - (bbox.x + bbox.width));
|
|
1076
|
+
const dy = Math.max(bbox.y - pos.y, 0, pos.y - (bbox.y + bbox.height));
|
|
1077
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
1078
|
+
}
|
|
1079
|
+
const center = {
|
|
1080
|
+
x: (fromPos.x + toPos.x) / 2,
|
|
1081
|
+
y: (fromPos.y + toPos.y) / 2
|
|
1082
|
+
};
|
|
1083
|
+
const radius = Point4.getDistance(fromPos, center);
|
|
1084
|
+
const distanceToCenter = Point4.getDistance(pos, center);
|
|
1085
|
+
return Math.abs(distanceToCenter - radius);
|
|
1086
|
+
}
|
|
1087
|
+
get bounds() {
|
|
1088
|
+
if (!this.data) {
|
|
1089
|
+
return new Rectangle6();
|
|
1090
|
+
}
|
|
1091
|
+
return this.data.bbox;
|
|
1092
|
+
}
|
|
1093
|
+
update(params) {
|
|
1094
|
+
const { fromPos, toPos } = params;
|
|
1095
|
+
const { vertical } = this.entity;
|
|
1096
|
+
const sourceOffset = {
|
|
1097
|
+
x: vertical ? 0 : POINT_RADIUS5,
|
|
1098
|
+
y: vertical ? POINT_RADIUS5 : 0
|
|
1099
|
+
};
|
|
1100
|
+
const targetOffset = {
|
|
1101
|
+
x: vertical ? 0 : -POINT_RADIUS5,
|
|
1102
|
+
y: vertical ? -POINT_RADIUS5 : 0
|
|
1103
|
+
};
|
|
1104
|
+
const start = {
|
|
1105
|
+
x: fromPos.x + sourceOffset.x,
|
|
1106
|
+
y: fromPos.y + sourceOffset.y
|
|
1107
|
+
};
|
|
1108
|
+
const end = {
|
|
1109
|
+
x: toPos.x + targetOffset.x,
|
|
1110
|
+
y: toPos.y + targetOffset.y
|
|
1111
|
+
};
|
|
1112
|
+
const bbox = this.calculateArcBBox(start, end);
|
|
1113
|
+
const path = this.getArcPath(start, end, bbox);
|
|
1114
|
+
this.data = {
|
|
1115
|
+
fromPos: start,
|
|
1116
|
+
toPos: end,
|
|
1117
|
+
path,
|
|
1118
|
+
bbox
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
calculateArcBBox(start, end) {
|
|
1122
|
+
const dx = end.x - start.x;
|
|
1123
|
+
const dy = end.y - start.y;
|
|
1124
|
+
const radius = Math.sqrt(dx * dx + dy * dy) / 2;
|
|
1125
|
+
const centerX = (start.x + end.x) / 2;
|
|
1126
|
+
const centerY = (start.y + end.y) / 2;
|
|
1127
|
+
return new Rectangle6(centerX - radius, centerY - radius, radius * 2, radius * 2);
|
|
1128
|
+
}
|
|
1129
|
+
getArcPath(start, end, bbox) {
|
|
1130
|
+
const dx = end.x - start.x;
|
|
1131
|
+
const dy = end.y - start.y;
|
|
1132
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
1133
|
+
const startRel = {
|
|
1134
|
+
x: start.x - bbox.x + LINE_PADDING,
|
|
1135
|
+
y: start.y - bbox.y + LINE_PADDING
|
|
1136
|
+
};
|
|
1137
|
+
const endRel = {
|
|
1138
|
+
x: end.x - bbox.x + LINE_PADDING,
|
|
1139
|
+
y: end.y - bbox.y + LINE_PADDING
|
|
1140
|
+
};
|
|
1141
|
+
return `M ${startRel.x} ${startRel.y} A ${distance / 2} ${distance / 2} 0 0 1 ${endRel.x} ${endRel.y}`;
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1144
|
+
WorkflowArkLineContribution.type = "WorkflowArkLineContribution";
|
|
1145
|
+
|
|
1146
|
+
// src/contributions/manhattan/index.ts
|
|
1147
|
+
import { Point as Point5, Rectangle as Rectangle7 } from "@flowgram.ai/utils";
|
|
1148
|
+
import {
|
|
1149
|
+
POINT_RADIUS as POINT_RADIUS6
|
|
1150
|
+
} from "@flowgram.ai/free-layout-core";
|
|
1151
|
+
var WorkflowManhattanLineContribution = class {
|
|
1152
|
+
constructor(entity) {
|
|
1153
|
+
this.entity = entity;
|
|
1154
|
+
}
|
|
1155
|
+
get path() {
|
|
1156
|
+
return this.data?.path ?? "";
|
|
1157
|
+
}
|
|
1158
|
+
calcDistance(pos) {
|
|
1159
|
+
if (!this.data) {
|
|
1160
|
+
return Number.MAX_SAFE_INTEGER;
|
|
1161
|
+
}
|
|
1162
|
+
return Math.min(
|
|
1163
|
+
...this.data.points.slice(1).map((point, index) => {
|
|
1164
|
+
const prevPoint = this.data.points[index];
|
|
1165
|
+
return this.getDistanceToLineSegment(pos, prevPoint, point);
|
|
1166
|
+
})
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
getDistanceToLineSegment(point, start, end) {
|
|
1170
|
+
const dx = end.x - start.x;
|
|
1171
|
+
const dy = end.y - start.y;
|
|
1172
|
+
if (dx === 0 && dy === 0) {
|
|
1173
|
+
return Point5.getDistance(point, start);
|
|
1174
|
+
}
|
|
1175
|
+
const t = ((point.x - start.x) * dx + (point.y - start.y) * dy) / (dx * dx + dy * dy);
|
|
1176
|
+
if (t < 0) return Point5.getDistance(point, start);
|
|
1177
|
+
if (t > 1) return Point5.getDistance(point, end);
|
|
1178
|
+
const projectionPoint = {
|
|
1179
|
+
x: start.x + t * dx,
|
|
1180
|
+
y: start.y + t * dy
|
|
1181
|
+
};
|
|
1182
|
+
return Point5.getDistance(point, projectionPoint);
|
|
1183
|
+
}
|
|
1184
|
+
get bounds() {
|
|
1185
|
+
if (!this.data) {
|
|
1186
|
+
return new Rectangle7();
|
|
1187
|
+
}
|
|
1188
|
+
return this.data.bbox;
|
|
1189
|
+
}
|
|
1190
|
+
update(params) {
|
|
1191
|
+
const { fromPos, toPos } = params;
|
|
1192
|
+
const { vertical } = this.entity;
|
|
1193
|
+
const sourceOffset = {
|
|
1194
|
+
x: vertical ? 0 : POINT_RADIUS6,
|
|
1195
|
+
y: vertical ? POINT_RADIUS6 : 0
|
|
1196
|
+
};
|
|
1197
|
+
const targetOffset = {
|
|
1198
|
+
x: vertical ? 0 : -POINT_RADIUS6,
|
|
1199
|
+
y: vertical ? -POINT_RADIUS6 : 0
|
|
1200
|
+
};
|
|
1201
|
+
const points = this.getManhattanPoints({
|
|
1202
|
+
source: {
|
|
1203
|
+
x: fromPos.x + sourceOffset.x,
|
|
1204
|
+
y: fromPos.y + sourceOffset.y
|
|
1205
|
+
},
|
|
1206
|
+
target: {
|
|
1207
|
+
x: toPos.x + targetOffset.x,
|
|
1208
|
+
y: toPos.y + targetOffset.y
|
|
1209
|
+
},
|
|
1210
|
+
vertical
|
|
1211
|
+
});
|
|
1212
|
+
const bbox = Rectangle7.createRectangleWithTwoPoints(
|
|
1213
|
+
points.reduce(
|
|
1214
|
+
(min, p) => ({
|
|
1215
|
+
x: Math.min(min.x, p.x),
|
|
1216
|
+
y: Math.min(min.y, p.y)
|
|
1217
|
+
}),
|
|
1218
|
+
points[0]
|
|
1219
|
+
),
|
|
1220
|
+
points.reduce(
|
|
1221
|
+
(max, p) => ({
|
|
1222
|
+
x: Math.max(max.x, p.x),
|
|
1223
|
+
y: Math.max(max.y, p.y)
|
|
1224
|
+
}),
|
|
1225
|
+
points[0]
|
|
1226
|
+
)
|
|
1227
|
+
);
|
|
1228
|
+
const adjustedPoints = points.map((p) => ({
|
|
1229
|
+
x: p.x - bbox.x + LINE_PADDING,
|
|
1230
|
+
y: p.y - bbox.y + LINE_PADDING
|
|
1231
|
+
}));
|
|
1232
|
+
const path = this.getPathFromPoints(adjustedPoints);
|
|
1233
|
+
this.data = {
|
|
1234
|
+
points,
|
|
1235
|
+
path,
|
|
1236
|
+
bbox
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
getManhattanPoints(params) {
|
|
1240
|
+
const { source, target, vertical } = params;
|
|
1241
|
+
const points = [source];
|
|
1242
|
+
if (vertical) {
|
|
1243
|
+
if (source.y !== target.y) {
|
|
1244
|
+
points.push({ x: source.x, y: target.y });
|
|
1245
|
+
}
|
|
1246
|
+
if (source.x !== target.x) {
|
|
1247
|
+
points.push({ x: target.x, y: target.y });
|
|
1248
|
+
}
|
|
1249
|
+
} else {
|
|
1250
|
+
if (source.x !== target.x) {
|
|
1251
|
+
points.push({ x: target.x, y: source.y });
|
|
1252
|
+
}
|
|
1253
|
+
if (source.y !== target.y) {
|
|
1254
|
+
points.push({ x: target.x, y: target.y });
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
if (points[points.length - 1] !== target) {
|
|
1258
|
+
points.push(target);
|
|
1259
|
+
}
|
|
1260
|
+
return points;
|
|
1261
|
+
}
|
|
1262
|
+
getPathFromPoints(points) {
|
|
1263
|
+
return points.reduce((path, point, index) => {
|
|
1264
|
+
if (index === 0) {
|
|
1265
|
+
return `M ${point.x} ${point.y}`;
|
|
1266
|
+
}
|
|
1267
|
+
return `${path} L ${point.x} ${point.y}`;
|
|
1268
|
+
}, "");
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
WorkflowManhattanLineContribution.type = "WorkflowManhattanLineContribution";
|
|
591
1272
|
|
|
592
1273
|
// src/create-free-lines-plugin.ts
|
|
593
1274
|
var createFreeLinesPlugin = definePluginCreator({
|
|
594
1275
|
onInit: (ctx, opts) => {
|
|
595
|
-
ctx.playground.registerLayer(
|
|
1276
|
+
ctx.playground.registerLayer(WorkflowLinesLayer, {
|
|
596
1277
|
...opts,
|
|
597
1278
|
renderElement: () => {
|
|
598
1279
|
if (typeof opts.renderElement === "function") {
|
|
@@ -602,12 +1283,34 @@ var createFreeLinesPlugin = definePluginCreator({
|
|
|
602
1283
|
}
|
|
603
1284
|
}
|
|
604
1285
|
});
|
|
1286
|
+
},
|
|
1287
|
+
onReady: (ctx, opts) => {
|
|
1288
|
+
const linesManager = ctx.container.get(WorkflowLinesManager2);
|
|
1289
|
+
linesManager.registerContribution(WorkflowBezierLineContribution).registerContribution(WorkflowFoldLineContribution);
|
|
1290
|
+
if (opts.contributions) {
|
|
1291
|
+
opts.contributions.forEach((contribution) => {
|
|
1292
|
+
linesManager.registerContribution(contribution);
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
if (opts.defaultLineType) {
|
|
1296
|
+
linesManager.switchLineType(opts.defaultLineType);
|
|
1297
|
+
}
|
|
605
1298
|
}
|
|
606
1299
|
});
|
|
607
1300
|
export {
|
|
1301
|
+
BezierControlType,
|
|
608
1302
|
LINE_OFFSET,
|
|
609
|
-
|
|
1303
|
+
LINE_PADDING,
|
|
1304
|
+
WorkflowLinesLayer as LinesLayer,
|
|
1305
|
+
WorkflowArkLineContribution,
|
|
1306
|
+
WorkflowBezierLineContribution,
|
|
1307
|
+
WorkflowFoldLineContribution,
|
|
1308
|
+
WorkflowLinesLayer,
|
|
1309
|
+
WorkflowManhattanLineContribution,
|
|
610
1310
|
WorkflowPortRender,
|
|
611
|
-
|
|
1311
|
+
WorkflowStraightLineContribution,
|
|
1312
|
+
createFreeLinesPlugin,
|
|
1313
|
+
getBezierHorizontalControlPoints,
|
|
1314
|
+
getBezierVerticalControlPoints
|
|
612
1315
|
};
|
|
613
1316
|
//# sourceMappingURL=index.js.map
|