@flowgram.ai/free-layout-core 0.1.0-alpha.12 → 0.1.0-alpha.13

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.
Files changed (35) hide show
  1. package/dist/esm/{chunk-CTGO4RKX.js → chunk-E7ZUQ7LV.js} +1 -1
  2. package/dist/esm/chunk-E7ZUQ7LV.js.map +1 -0
  3. package/dist/esm/{chunk-242F2JCI.js → chunk-U2XMPOSL.js} +2 -1
  4. package/dist/esm/{chunk-242F2JCI.js.map → chunk-U2XMPOSL.js.map} +1 -1
  5. package/dist/esm/index.js +221 -78
  6. package/dist/esm/index.js.map +1 -1
  7. package/dist/esm/typings/index.js +2 -2
  8. package/dist/esm/typings/workflow-json.js +1 -1
  9. package/dist/esm/typings/workflow-line.js +1 -1
  10. package/dist/index.d.mts +14 -9
  11. package/dist/index.d.ts +14 -9
  12. package/dist/index.js +201 -57
  13. package/dist/index.js.map +1 -1
  14. package/dist/typings/index.d.mts +1 -1
  15. package/dist/typings/index.d.ts +1 -1
  16. package/dist/typings/index.js +1 -0
  17. package/dist/typings/index.js.map +1 -1
  18. package/dist/typings/workflow-drag.d.mts +1 -1
  19. package/dist/typings/workflow-drag.d.ts +1 -1
  20. package/dist/typings/workflow-json.d.mts +1 -1
  21. package/dist/typings/workflow-json.d.ts +1 -1
  22. package/dist/typings/workflow-json.js +1 -0
  23. package/dist/typings/workflow-json.js.map +1 -1
  24. package/dist/typings/workflow-line.d.mts +1 -1
  25. package/dist/typings/workflow-line.d.ts +1 -1
  26. package/dist/typings/workflow-line.js.map +1 -1
  27. package/dist/typings/workflow-node.d.mts +1 -1
  28. package/dist/typings/workflow-node.d.ts +1 -1
  29. package/dist/typings/workflow-registry.d.mts +2 -1
  30. package/dist/typings/workflow-registry.d.ts +2 -1
  31. package/dist/typings/workflow-registry.js.map +1 -1
  32. package/dist/{workflow-line-entity-Iq1OHmuK.d.mts → workflow-line-entity-DSC3qPV1.d.mts} +123 -38
  33. package/dist/{workflow-line-entity-LhmV98jq.d.ts → workflow-line-entity-I_VrhJ_t.d.ts} +123 -38
  34. package/package.json +9 -9
  35. package/dist/esm/chunk-CTGO4RKX.js.map +0 -1
package/dist/index.js CHANGED
@@ -156,8 +156,8 @@ function nanoid(n) {
156
156
  var import_utils = require("@flowgram.ai/utils");
157
157
 
158
158
  // src/utils/fit-view.ts
159
- var import_core = require("@flowgram.ai/core");
160
159
  var import_utils2 = require("@flowgram.ai/utils");
160
+ var import_core = require("@flowgram.ai/core");
161
161
  var fitView = (doc, playgroundConfig, easing = true) => {
162
162
  const bounds = import_utils2.Rectangle.enlarge(
163
163
  doc.getAllNodes().map((node) => node.getData(import_core.TransformData).bounds)
@@ -218,17 +218,18 @@ var import_document3 = require("@flowgram.ai/document");
218
218
  var import_core4 = require("@flowgram.ai/core");
219
219
  var PORT_SIZE = 24;
220
220
  var WorkflowPortEntity = class extends import_core4.Entity {
221
- // relativePosition
222
221
  constructor(opts) {
223
222
  super(opts);
224
223
  this.portID = "";
225
- this._disabled = false;
226
224
  this._hasError = false;
227
225
  this._onErrorChangedEmitter = new import_utils5.Emitter();
228
226
  this.onErrorChanged = this._onErrorChangedEmitter.event;
229
227
  this.portID = opts.portID || "";
230
228
  this.portType = opts.type;
231
- this._disabled = opts.disabled ?? false;
229
+ this._disabled = opts.disabled;
230
+ this._offset = opts.offset;
231
+ this._location = opts.location;
232
+ this._size = opts.size;
232
233
  this.node = opts.node;
233
234
  this.updateTargetElement(opts.targetElement);
234
235
  this.toDispose.push(this.node.getData(import_core4.TransformData).onDataChange(() => this.fireChange()));
@@ -237,6 +238,9 @@ var WorkflowPortEntity = class extends import_core4.Entity {
237
238
  static getPortEntityId(node, portType, portID = "") {
238
239
  return getPortEntityId(node, portType, portID);
239
240
  }
241
+ get position() {
242
+ return this._location;
243
+ }
240
244
  // 获取连线是否为错误态
241
245
  get hasError() {
242
246
  return this._hasError;
@@ -261,28 +265,65 @@ var WorkflowPortEntity = class extends import_core4.Entity {
261
265
  isErrorPort() {
262
266
  return this.node.document.isErrorPort(this, this.hasError);
263
267
  }
268
+ get location() {
269
+ if (this._location) {
270
+ return this._location;
271
+ }
272
+ if (this.portType === "input") {
273
+ return "left";
274
+ }
275
+ return "right";
276
+ }
264
277
  get point() {
265
278
  const { targetElement } = this;
266
279
  const { bounds } = this.node.getData(import_document3.FlowNodeTransformData);
280
+ const location2 = this.location;
267
281
  if (targetElement) {
268
282
  const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;
269
- return this.entityManager.getEntity(import_core4.PlaygroundConfigEntity).getPosFromMouseEvent({
283
+ const point2 = this.entityManager.getEntity(import_core4.PlaygroundConfigEntity).getPosFromMouseEvent({
270
284
  clientX: pos.x,
271
285
  clientY: pos.y
272
286
  });
287
+ return {
288
+ x: point2.x,
289
+ y: point2.y,
290
+ location: location2
291
+ };
273
292
  }
274
- if (this.portType === "input") {
275
- return bounds.leftCenter;
293
+ let point = { x: 0, y: 0 };
294
+ const offset = this._offset || { x: 0, y: 0 };
295
+ switch (location2) {
296
+ case "left":
297
+ point = bounds.leftCenter;
298
+ break;
299
+ case "top":
300
+ point = bounds.topCenter;
301
+ break;
302
+ case "right":
303
+ point = bounds.rightCenter;
304
+ break;
305
+ case "bottom":
306
+ point = bounds.bottomCenter;
307
+ break;
276
308
  }
277
- return bounds.rightCenter;
309
+ return {
310
+ x: point.x + offset.x,
311
+ y: point.y + offset.y,
312
+ location: location2
313
+ };
278
314
  }
279
315
  /**
280
- * 点的区域
316
+ * 端口热区
281
317
  */
282
318
  get bounds() {
283
319
  const { point } = this;
284
- const halfSize = PORT_SIZE / 2;
285
- return new import_utils5.Rectangle(point.x - halfSize, point.y - halfSize, PORT_SIZE, PORT_SIZE);
320
+ const size = this._size || { width: PORT_SIZE, height: PORT_SIZE };
321
+ return new import_utils5.Rectangle(
322
+ point.x - size.width / 2,
323
+ point.y - size.height / 2,
324
+ size.width,
325
+ size.height
326
+ );
286
327
  }
287
328
  isHovered(x, y) {
288
329
  return this.bounds.contains(x, y);
@@ -349,6 +390,32 @@ var WorkflowPortEntity = class extends import_core4.Entity {
349
390
  });
350
391
  return lines;
351
392
  }
393
+ update(data) {
394
+ let changed = false;
395
+ if (data.targetElement !== this.targetElement) {
396
+ this.targetElement = data.targetElement;
397
+ changed = true;
398
+ }
399
+ if (data.location !== this._location) {
400
+ this._location = data.location;
401
+ changed = true;
402
+ }
403
+ if (import_utils5.Compare.isChanged(data.offset, this._offset)) {
404
+ this._offset = data.offset;
405
+ changed = true;
406
+ }
407
+ if (import_utils5.Compare.isChanged(data.size, this._size)) {
408
+ this._size = data.size;
409
+ changed = true;
410
+ }
411
+ if (data.disabled !== this._disabled) {
412
+ this._disabled = data.disabled;
413
+ changed = true;
414
+ }
415
+ if (changed) {
416
+ this.fireChange();
417
+ }
418
+ }
352
419
  dispose() {
353
420
  this.lines.forEach((l) => l.dispose());
354
421
  super.dispose();
@@ -387,17 +454,26 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
387
454
  return {};
388
455
  }
389
456
  /**
390
- * 更新静态的 ports 数据
457
+ * Update all ports data, includes static ports and dynamic ports
458
+ * @param ports
391
459
  */
392
- updateStaticPorts(ports) {
460
+ updateAllPorts(ports) {
393
461
  const meta = this.entity.getNodeMeta();
394
- this._staticPorts = ports;
462
+ if (ports) {
463
+ this._staticPorts = ports;
464
+ }
395
465
  if (meta.useDynamicPort) {
396
466
  this.updateDynamicPorts();
397
467
  } else {
398
468
  this.updatePorts(this._staticPorts);
399
469
  }
400
470
  }
471
+ /**
472
+ * @deprecated use `updateAllPorts` instead
473
+ */
474
+ updateStaticPorts(ports) {
475
+ this.updateAllPorts(ports);
476
+ }
401
477
  /**
402
478
  * 动态计算点位,通过 dom 的 data-port-key
403
479
  */
@@ -536,9 +612,7 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
536
612
  */
537
613
  updatePortEntity(portInfo) {
538
614
  const portEntity = this.getOrCreatePortEntity(portInfo);
539
- if (portInfo.targetElement) {
540
- portEntity.updateTargetElement(portInfo.targetElement);
541
- }
615
+ portEntity.update(portInfo);
542
616
  return portEntity;
543
617
  }
544
618
  };
@@ -679,8 +753,8 @@ var WorkflowLineRenderData = class extends import_core7.EntityData {
679
753
  version: "",
680
754
  contributions: /* @__PURE__ */ new Map(),
681
755
  position: {
682
- from: { x: 0, y: 0 },
683
- to: { x: 0, y: 0 }
756
+ from: { x: 0, y: 0, location: "right" },
757
+ to: { x: 0, y: 0, location: "left" }
684
758
  }
685
759
  };
686
760
  }
@@ -726,16 +800,23 @@ var WorkflowLineRenderData = class extends import_core7.EntityData {
726
800
  */
727
801
  updatePosition() {
728
802
  this.data.position.from = this.entity.from.getData(WorkflowNodePortsData).getOutputPoint(this.entity.info.fromPort);
729
- this.data.position.to = this.entity.info.drawingTo ?? this.entity.to?.getData(WorkflowNodePortsData)?.getInputPoint(this.entity.info.toPort) ?? {
730
- x: this.data.position.from.x,
731
- y: this.data.position.from.y
732
- };
803
+ if (this.entity.info.drawingTo) {
804
+ this.data.position.to = this.entity.info.drawingTo;
805
+ } else {
806
+ this.data.position.to = this.entity.to?.getData(WorkflowNodePortsData)?.getInputPoint(this.entity.info.toPort) ?? {
807
+ x: this.data.position.from.x,
808
+ y: this.data.position.from.y,
809
+ location: this.data.position.from.location === "right" ? "left" : "top"
810
+ };
811
+ }
733
812
  this.data.version = [
734
813
  this.lineType,
735
814
  this.data.position.from.x,
736
815
  this.data.position.from.y,
816
+ this.data.position.from.location,
737
817
  this.data.position.to.x,
738
- this.data.position.to.y
818
+ this.data.position.to.y,
819
+ this.data.position.to.location
739
820
  ].join("-");
740
821
  }
741
822
  get currentLine() {
@@ -765,13 +846,16 @@ var POINT_RADIUS = 10;
765
846
  var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity {
766
847
  constructor(opts) {
767
848
  super(opts);
849
+ this._onLineDataChangeEmitter = new import_utils8.Emitter();
850
+ this.onLineDataChange = this._onLineDataChangeEmitter.event;
768
851
  this._uiState = {
769
852
  hasError: false,
770
853
  flowing: false,
771
854
  disabled: false,
772
- vertical: false,
773
855
  hideArrow: false,
774
856
  reverse: false,
857
+ shrink: 10,
858
+ curvature: 0.25,
775
859
  highlightColor: "",
776
860
  lockedColor: ""
777
861
  };
@@ -789,7 +873,8 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
789
873
  to: opts.to,
790
874
  drawingTo: opts.drawingTo,
791
875
  fromPort: opts.fromPort,
792
- toPort: opts.toPort
876
+ toPort: opts.toPort,
877
+ data: opts.data
793
878
  });
794
879
  if (opts.drawingTo) {
795
880
  this.isDrawing = true;
@@ -802,6 +887,7 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
802
887
  this.fromPort?.validate();
803
888
  this.toPort?.validate();
804
889
  });
890
+ this.toDispose.push(this._onLineDataChangeEmitter);
805
891
  }
806
892
  /**
807
893
  * 转成线条 id
@@ -844,9 +930,13 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
844
930
  * 更新线条扩展数据
845
931
  * @param data
846
932
  */
847
- set lineData(data) {
848
- this._lineData = data;
849
- this.fireChange();
933
+ set lineData(newValue) {
934
+ const oldValue = this._lineData;
935
+ if (!(0, import_lodash_es2.isEqual)(oldValue, newValue)) {
936
+ this._lineData = newValue;
937
+ this._onLineDataChangeEmitter.fire({ oldValue, newValue });
938
+ this.fireChange();
939
+ }
850
940
  }
851
941
  /**
852
942
  * 获取线条的前置节点
@@ -869,20 +959,17 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
869
959
  }
870
960
  /**
871
961
  * 获取是否 testrun processing
872
- * @deprecated use `uiState.flowing` instead
962
+ * @deprecated use `flowing` instead
873
963
  */
874
964
  get processing() {
875
965
  return this._uiState.flowing;
876
966
  }
877
967
  /**
878
968
  * 设置 testrun processing 状态
879
- * @deprecated use `uiState.flowing` instead
969
+ * @deprecated use `flowing` instead
880
970
  */
881
971
  set processing(status) {
882
- if (this._uiState.flowing !== status) {
883
- this._uiState.flowing = status;
884
- this.fireChange();
885
- }
972
+ this.flowing = status;
886
973
  }
887
974
  // 获取连线是否为错误态
888
975
  get hasError() {
@@ -912,7 +999,6 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
912
999
  const { node, portID } = toPort;
913
1000
  this._to = node;
914
1001
  this.info.drawingTo = void 0;
915
- this.info.isDefaultLine = false;
916
1002
  this.info.to = node.id;
917
1003
  this.info.toPort = portID;
918
1004
  } else {
@@ -937,7 +1023,6 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
937
1023
  }
938
1024
  if (!oldDrawingTo || pos.x !== oldDrawingTo.x || pos.y !== oldDrawingTo.y) {
939
1025
  this.info.to = void 0;
940
- this.info.isDefaultLine = false;
941
1026
  this.info.drawingTo = pos;
942
1027
  this.fireChange();
943
1028
  }
@@ -1003,13 +1088,25 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
1003
1088
  get flowing() {
1004
1089
  return this.linesManager.isFlowingLine(this, this.uiState.flowing);
1005
1090
  }
1091
+ set flowing(flowing) {
1092
+ if (this._uiState.flowing !== flowing) {
1093
+ this._uiState.flowing = flowing;
1094
+ this.fireChange();
1095
+ }
1096
+ }
1006
1097
  /** 是否禁用 */
1007
1098
  get disabled() {
1008
1099
  return this.linesManager.isDisabledLine(this, this.uiState.disabled);
1009
1100
  }
1010
1101
  /** 是否竖向 */
1011
1102
  get vertical() {
1012
- return this.linesManager.isVerticalLine(this, this.uiState.vertical);
1103
+ const fromLocation = this.fromPort.location;
1104
+ const toLocation = this.toPort?.location;
1105
+ if (toLocation) {
1106
+ return toLocation === "top";
1107
+ } else {
1108
+ return fromLocation === "bottom";
1109
+ }
1013
1110
  }
1014
1111
  /** 获取线条渲染器类型 */
1015
1112
  get renderType() {
@@ -1017,7 +1114,7 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
1017
1114
  }
1018
1115
  /** 获取线条样式 */
1019
1116
  get className() {
1020
- return this.linesManager.setLineClassName(this) ?? "";
1117
+ return [this.linesManager.setLineClassName(this), this._uiState.className].filter((s) => !!s).join(" ");
1021
1118
  }
1022
1119
  get color() {
1023
1120
  return this.linesManager.getLineColor(this);
@@ -1031,6 +1128,7 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity
1031
1128
  this.info = info;
1032
1129
  this._from = this.document.getNode(info.from);
1033
1130
  this._to = info.to ? this.document.getNode(info.to) : void 0;
1131
+ this._lineData = info.data;
1034
1132
  this.fireChange();
1035
1133
  }
1036
1134
  }
@@ -1287,6 +1385,7 @@ var WorkflowContentChangeType = /* @__PURE__ */ ((WorkflowContentChangeType2) =>
1287
1385
  WorkflowContentChangeType2["NODE_DATA_CHANGE"] = "NODE_DATA_CHANGE";
1288
1386
  WorkflowContentChangeType2["ADD_LINE"] = "ADD_LINE";
1289
1387
  WorkflowContentChangeType2["DELETE_LINE"] = "DELETE_LINE";
1388
+ WorkflowContentChangeType2["LINE_DATA_CHANGE"] = "LINE_DATA_CHANGE";
1290
1389
  WorkflowContentChangeType2["META_CHANGE"] = "META_CHANGE";
1291
1390
  return WorkflowContentChangeType2;
1292
1391
  })(WorkflowContentChangeType || {});
@@ -1460,6 +1559,9 @@ var WorkflowLinesManager = class {
1460
1559
  WorkflowLineEntity.portInfoToLineId(portInfo)
1461
1560
  );
1462
1561
  }
1562
+ getLineById(id) {
1563
+ return this.entityManager.getEntityById(id);
1564
+ }
1463
1565
  replaceLine(oldPortInfo, newPortInfo) {
1464
1566
  const oldLine = this.getLine(oldPortInfo);
1465
1567
  if (oldLine) {
@@ -1468,7 +1570,7 @@ var WorkflowLinesManager = class {
1468
1570
  return this.createLine(newPortInfo);
1469
1571
  }
1470
1572
  createLine(options) {
1471
- const { from, to, drawingTo, fromPort, toPort } = options;
1573
+ const { from, to, drawingTo, fromPort, toPort, data } = options;
1472
1574
  const available = Boolean(from && to);
1473
1575
  const key = options.key || WorkflowLineEntity.portInfoToLineId(options);
1474
1576
  let line = this.entityManager.getEntityById(key);
@@ -1491,7 +1593,8 @@ var WorkflowLinesManager = class {
1491
1593
  fromPort,
1492
1594
  toPort,
1493
1595
  to,
1494
- drawingTo
1596
+ drawingTo,
1597
+ data
1495
1598
  });
1496
1599
  this.registerData(line);
1497
1600
  fromNode.addLine(line);
@@ -1512,6 +1615,14 @@ var WorkflowLinesManager = class {
1512
1615
  });
1513
1616
  }
1514
1617
  });
1618
+ line.onLineDataChange(({ oldValue }) => {
1619
+ this.onAvailableLinesChangeEmitter.fire({
1620
+ type: "LINE_DATA_CHANGE" /* LINE_DATA_CHANGE */,
1621
+ toJSON: () => line.toJSON(),
1622
+ oldValue,
1623
+ entity: line
1624
+ });
1625
+ });
1515
1626
  if (available) {
1516
1627
  this.onAvailableLinesChangeEmitter.fire({
1517
1628
  type: "ADD_LINE" /* ADD_LINE */,
@@ -1575,12 +1686,6 @@ var WorkflowLinesManager = class {
1575
1686
  }
1576
1687
  return defaultValue;
1577
1688
  }
1578
- isVerticalLine(line, defaultValue = false) {
1579
- if (this.options.isVerticalLine) {
1580
- return this.options.isVerticalLine(line);
1581
- }
1582
- return defaultValue;
1583
- }
1584
1689
  setLineRenderType(line) {
1585
1690
  if (this.options.setLineRenderType) {
1586
1691
  return this.options.setLineRenderType(line);
@@ -1624,6 +1729,14 @@ var WorkflowLinesManager = class {
1624
1729
  if (fromPort === toPort || fromPort.node === toPort.node || fromPort.portType !== "output" || toPort.portType !== "input" || toPort.disabled) {
1625
1730
  return false;
1626
1731
  }
1732
+ const fromCanAdd = fromPort.node.getNodeRegistry().canAddLine;
1733
+ const toCanAdd = toPort.node.getNodeRegistry().canAddLine;
1734
+ if (fromCanAdd && !fromCanAdd(fromPort, toPort, this, silent)) {
1735
+ return false;
1736
+ }
1737
+ if (toCanAdd && !toCanAdd(fromPort, toPort, this, silent)) {
1738
+ return false;
1739
+ }
1627
1740
  if (this.options.canAddLine) {
1628
1741
  return this.options.canAddLine(fromPort, toPort, this, silent);
1629
1742
  }
@@ -1887,6 +2000,11 @@ var WorkflowDocument = class extends import_document8.FlowDocument {
1887
2000
  get loading() {
1888
2001
  return this._loading;
1889
2002
  }
2003
+ /**
2004
+ * use `ctx.tools.fitView()` instead
2005
+ * @deprecated
2006
+ * @param easing
2007
+ */
1890
2008
  async fitView(easing) {
1891
2009
  return fitView(this, this.playgroundConfig, easing).then(() => {
1892
2010
  this.linesManager.forceUpdate();
@@ -2194,10 +2312,13 @@ var WorkflowDocument = class extends import_document8.FlowDocument {
2194
2312
  from: line.from.id,
2195
2313
  to: line.to.id
2196
2314
  }));
2197
- const startNodeId = allNode.find((node) => node.isStart).id;
2198
- const endNodeId = allNode.find((node) => node.isNodeEnd).id;
2315
+ const startNodeId = allNode.find((node) => node.isStart)?.id;
2316
+ const endNodeId = allNode.find((node) => node.isNodeEnd)?.id;
2199
2317
  const nodeInContainer = allNode.filter((node) => node.parent?.getNodeMeta().isContainer).map((node) => node.id);
2200
- const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInContainer]);
2318
+ const associatedCache = new Set(nodeInContainer);
2319
+ if (endNodeId) {
2320
+ associatedCache.add(endNodeId);
2321
+ }
2201
2322
  const bfs = (nodeId) => {
2202
2323
  if (associatedCache.has(nodeId)) {
2203
2324
  return;
@@ -2211,7 +2332,9 @@ var WorkflowDocument = class extends import_document8.FlowDocument {
2211
2332
  }, []);
2212
2333
  nextNodes.forEach(bfs);
2213
2334
  };
2214
- bfs(startNodeId);
2335
+ if (startNodeId) {
2336
+ bfs(startNodeId);
2337
+ }
2215
2338
  const associatedNodes = allNode.filter((node) => associatedCache.has(node.id));
2216
2339
  return associatedNodes;
2217
2340
  }
@@ -2333,6 +2456,11 @@ var WorkflowDocument = class extends import_document8.FlowDocument {
2333
2456
  * 导出数据
2334
2457
  */
2335
2458
  toJSON() {
2459
+ if (this.disposed) {
2460
+ throw new Error(
2461
+ "The WorkflowDocument has been disposed and it is no longer possible to call toJSON."
2462
+ );
2463
+ }
2336
2464
  const rootJSON = this.toNodeJSON(this.root);
2337
2465
  const json = {
2338
2466
  nodes: rootJSON.blocks ?? [],
@@ -2413,7 +2541,8 @@ var WorkflowDocument = class extends import_document8.FlowDocument {
2413
2541
  from: json.sourceNodeID,
2414
2542
  fromPort: json.sourcePortID,
2415
2543
  to: json.targetNodeID,
2416
- toPort: json.targetPortID
2544
+ toPort: json.targetPortID,
2545
+ data: json.data
2417
2546
  };
2418
2547
  if (!parentId) {
2419
2548
  return this.linesManager.createLine(lineInfo);
@@ -2880,10 +3009,16 @@ var WorkflowDragService = class {
2880
3009
  originLine.highlightColor = this.linesManager.lineColor.hidden;
2881
3010
  }
2882
3011
  dragSuccess = true;
3012
+ const pos = config.getPosFromMouseEvent(event);
2883
3013
  line = this.linesManager.createLine({
2884
3014
  from: fromPort.node.id,
2885
3015
  fromPort: fromPort.portID,
2886
- drawingTo: config.getPosFromMouseEvent(event)
3016
+ data: originLine?.lineData,
3017
+ drawingTo: {
3018
+ x: pos.x,
3019
+ y: pos.y,
3020
+ location: fromPort.location === "right" ? "left" : "top"
3021
+ }
2887
3022
  });
2888
3023
  if (!line) {
2889
3024
  return;
@@ -2918,9 +3053,17 @@ var WorkflowDragService = class {
2918
3053
  lineErrorReset = hasError;
2919
3054
  }
2920
3055
  if (line.toPort) {
2921
- line.drawingTo = { x: line.toPort.point.x, y: line.toPort.point.y };
3056
+ line.drawingTo = {
3057
+ x: line.toPort.point.x,
3058
+ y: line.toPort.point.y,
3059
+ location: line.toPort.location
3060
+ };
2922
3061
  } else {
2923
- line.drawingTo = { x: dragPos.x, y: dragPos.y };
3062
+ line.drawingTo = {
3063
+ x: dragPos.x,
3064
+ y: dragPos.y,
3065
+ location: line.fromPort.location === "right" ? "left" : "top"
3066
+ };
2924
3067
  }
2925
3068
  originLine?.validate();
2926
3069
  line.validate();
@@ -2964,7 +3107,8 @@ var WorkflowDragService = class {
2964
3107
  from: fromPort.node.id,
2965
3108
  fromPort: fromPort.portID,
2966
3109
  to: toPort.node.id,
2967
- toPort: toPort.portID
3110
+ toPort: toPort.portID,
3111
+ data: originLine?.lineData
2968
3112
  } : void 0;
2969
3113
  const isReset = originLine && toPort;
2970
3114
  if (isReset && !this.linesManager.canReset(
@@ -3234,6 +3378,7 @@ function usePlaygroundReadonlyState(listenChange) {
3234
3378
  function checkTargetDraggable(el) {
3235
3379
  return el && el.tagName !== "INPUT" && el.tagName !== "TEXTAREA" && !el.closest(".flow-canvas-not-draggable");
3236
3380
  }
3381
+ var isFirefox = navigator?.userAgent?.includes?.("Firefox");
3237
3382
  function useNodeRender(nodeFromProps) {
3238
3383
  const node = nodeFromProps || (0, import_react2.useContext)(import_core21.PlaygroundEntityContext);
3239
3384
  const renderData = node.getData(import_document13.FlowNodeRenderData);
@@ -3297,7 +3442,6 @@ function useNodeRender(nodeFromProps) {
3297
3442
  );
3298
3443
  const deleteNode = (0, import_react2.useCallback)(() => node.dispose(), [node]);
3299
3444
  (0, import_core21.useListenEvents)(portsData.onDataChange);
3300
- const isFirefox = navigator?.userAgent?.includes?.("Firefox");
3301
3445
  const onFocus = (0, import_react2.useCallback)(() => {
3302
3446
  if (isFirefox) {
3303
3447
  nodeRef.current?.setAttribute("draggable", "false");