@flowgram.ai/free-layout-core 0.4.18 → 0.5.0

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 CHANGED
@@ -776,16 +776,8 @@ var WorkflowLineRenderData = class extends EntityData3 {
776
776
  * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排
777
777
  */
778
778
  updatePosition() {
779
- this.data.position.from = this.entity.from.ports.getOutputPoint(this.entity.info.fromPort);
780
- if (this.entity.info.drawingTo) {
781
- this.data.position.to = this.entity.info.drawingTo;
782
- } else {
783
- this.data.position.to = this.entity.to?.ports?.getInputPoint(this.entity.info.toPort) ?? {
784
- x: this.data.position.from.x,
785
- y: this.data.position.from.y,
786
- location: this.data.position.from.location === "right" ? "left" : "top"
787
- };
788
- }
779
+ this.data.position.from = this.entity.drawingFrom || this.entity.fromPort.point;
780
+ this.data.position.to = this.entity.drawingTo || this.entity.toPort.point;
789
781
  this.data.version = [
790
782
  this.lineType,
791
783
  this.data.position.from.x,
@@ -850,10 +842,11 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
850
842
  to: opts.to,
851
843
  drawingTo: opts.drawingTo,
852
844
  fromPort: opts.fromPort,
845
+ drawingFrom: opts.drawingFrom,
853
846
  toPort: opts.toPort,
854
847
  data: opts.data
855
848
  });
856
- if (opts.drawingTo) {
849
+ if (opts.drawingTo || opts.drawingFrom) {
857
850
  this.isDrawing = true;
858
851
  }
859
852
  this.onEntityChange(() => {
@@ -988,6 +981,30 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
988
981
  }
989
982
  this.fireChange();
990
983
  }
984
+ setFromPort(fromPort) {
985
+ if (!this.isDrawing) {
986
+ throw new Error("[setFromPort] only support drawing line.");
987
+ }
988
+ if (this.fromPort === fromPort) {
989
+ return;
990
+ }
991
+ const prePort = this.fromPort;
992
+ if (fromPort && fromPort.portType === "output" && this.linesManager.canAddLine(fromPort, this.toPort, true)) {
993
+ const { node, portID } = fromPort;
994
+ this._from = node;
995
+ this.info.drawingFrom = void 0;
996
+ this.info.from = node.id;
997
+ this.info.fromPort = portID;
998
+ } else {
999
+ this._from = void 0;
1000
+ this.info.from = void 0;
1001
+ this.info.fromPort = "";
1002
+ }
1003
+ if (prePort) {
1004
+ prePort.validate();
1005
+ }
1006
+ this.fireChange();
1007
+ }
991
1008
  /**
992
1009
  * 设置线条画线时的目标位置
993
1010
  */
@@ -1004,6 +1021,22 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
1004
1021
  this.fireChange();
1005
1022
  }
1006
1023
  }
1024
+ set drawingFrom(pos) {
1025
+ const oldDrawingFrom = this.info.drawingFrom;
1026
+ if (!pos) {
1027
+ this.info.drawingFrom = void 0;
1028
+ this.fireChange();
1029
+ return;
1030
+ }
1031
+ if (!oldDrawingFrom || pos.x !== oldDrawingFrom.x || pos.y !== oldDrawingFrom.y) {
1032
+ this.info.from = void 0;
1033
+ this.info.drawingFrom = pos;
1034
+ this.fireChange();
1035
+ }
1036
+ }
1037
+ get drawingFrom() {
1038
+ return this.info.drawingFrom;
1039
+ }
1007
1040
  /**
1008
1041
  * 获取线条正在画线的位置
1009
1042
  */
@@ -1042,6 +1075,9 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
1042
1075
  return this.getData(WorkflowLineRenderData).calcDistance(pos);
1043
1076
  }
1044
1077
  get fromPort() {
1078
+ if (!this.from) {
1079
+ return void 0;
1080
+ }
1045
1081
  return this.from.ports.getPortEntityByKey("output", this.info.fromPort);
1046
1082
  }
1047
1083
  get toPort() {
@@ -1082,7 +1118,7 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
1082
1118
  * @deprecated
1083
1119
  */
1084
1120
  get vertical() {
1085
- const fromLocation = this.fromPort.location;
1121
+ const fromLocation = this.fromPort?.location;
1086
1122
  const toLocation = this.toPort?.location;
1087
1123
  if (toLocation) {
1088
1124
  return toLocation === "top";
@@ -1108,7 +1144,7 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
1108
1144
  initInfo(info) {
1109
1145
  if (!isEqual2(info, this.info)) {
1110
1146
  this.info = info;
1111
- this._from = this.document.getNode(info.from);
1147
+ this._from = info.from ? this.document.getNode(info.from) : void 0;
1112
1148
  this._to = info.to ? this.document.getNode(info.to) : void 0;
1113
1149
  this._lineData = info.data;
1114
1150
  this.fireChange();
@@ -1142,7 +1178,7 @@ var _WorkflowLineEntity = class _WorkflowLineEntity extends Entity2 {
1142
1178
  this._node = domUtils.createDivWithClass("gedit-flow-activity-line");
1143
1179
  this._node.dataset.testid = "sdk.workflow.canvas.line";
1144
1180
  this._node.dataset.lineId = this.id;
1145
- this._node.dataset.fromNodeId = this.from.id;
1181
+ this._node.dataset.fromNodeId = this.from?.id ?? "";
1146
1182
  this._node.dataset.fromPortId = this.fromPort?.id ?? "";
1147
1183
  this._node.dataset.toNodeId = this.to?.id ?? "";
1148
1184
  this._node.dataset.toPortId = this.toPort?.id ?? "";
@@ -1324,10 +1360,17 @@ var WorkflowHoverService = class {
1324
1360
  }
1325
1361
  /**
1326
1362
  * 获取被 hover 的节点或线条
1363
+ * @deprecated use 'someHovered' instead
1327
1364
  */
1328
1365
  get hoveredNode() {
1329
1366
  return this.entityManager.getEntityById(this.hoveredKey);
1330
1367
  }
1368
+ /**
1369
+ * 获取被 hover 的节点或线条
1370
+ */
1371
+ get someHovered() {
1372
+ return this.entityManager.getEntityById(this.hoveredKey);
1373
+ }
1331
1374
  };
1332
1375
  __decorateClass([
1333
1376
  inject2(EntityManager)
@@ -1345,7 +1388,8 @@ import {
1345
1388
  Emitter as Emitter6,
1346
1389
  DisposableCollection as DisposableCollection2,
1347
1390
  Rectangle as Rectangle8,
1348
- delay as delay2
1391
+ delay as delay2,
1392
+ Point
1349
1393
  } from "@flowgram.ai/utils";
1350
1394
  import {
1351
1395
  FlowNodeTransformData as FlowNodeTransformData6,
@@ -1509,6 +1553,9 @@ var WorkflowLinesManager = class {
1509
1553
  getAllLines() {
1510
1554
  return this.entityManager.getEntities(WorkflowLineEntity);
1511
1555
  }
1556
+ getAllAvailableLines() {
1557
+ return this.getAllLines().filter((l) => !l.isDrawing && !l.isHidden);
1558
+ }
1512
1559
  hasLine(portInfo) {
1513
1560
  return !!this.entityManager.getEntityById(
1514
1561
  WorkflowLineEntity.portInfoToLineId(portInfo)
@@ -1530,7 +1577,7 @@ var WorkflowLinesManager = class {
1530
1577
  return this.createLine(newPortInfo);
1531
1578
  }
1532
1579
  createLine(options) {
1533
- const { from, to, drawingTo, fromPort, toPort, data } = options;
1580
+ const { from, to, drawingTo, fromPort, drawingFrom, toPort, data } = options;
1534
1581
  const available = Boolean(from && to);
1535
1582
  const key = options.key || WorkflowLineEntity.portInfoToLineId(options);
1536
1583
  let line = this.entityManager.getEntityById(key);
@@ -1539,12 +1586,12 @@ var WorkflowLinesManager = class {
1539
1586
  line.validate();
1540
1587
  return line;
1541
1588
  }
1542
- const fromNode = this.entityManager.getEntityById(from)?.getData(WorkflowNodeLinesData);
1589
+ const fromNode = from ? this.entityManager.getEntityById(from).getData(WorkflowNodeLinesData) : void 0;
1543
1590
  const toNode = to ? this.entityManager.getEntityById(to).getData(WorkflowNodeLinesData) : void 0;
1544
- if (!fromNode) {
1591
+ if (!fromNode && !toNode) {
1545
1592
  return;
1546
1593
  }
1547
- this.isDrawing = Boolean(drawingTo);
1594
+ this.isDrawing = Boolean(drawingTo || drawingFrom);
1548
1595
  line = this.entityManager.createEntity(WorkflowLineEntity, {
1549
1596
  id: key,
1550
1597
  document: this.document,
@@ -1554,16 +1601,15 @@ var WorkflowLinesManager = class {
1554
1601
  toPort,
1555
1602
  to,
1556
1603
  drawingTo,
1604
+ drawingFrom,
1557
1605
  data
1558
1606
  });
1559
1607
  this.registerData(line);
1560
- fromNode.addLine(line);
1608
+ fromNode?.addLine(line);
1561
1609
  toNode?.addLine(line);
1562
1610
  line.onDispose(() => {
1563
- if (drawingTo) {
1564
- this.isDrawing = false;
1565
- }
1566
- fromNode.removeLine(line);
1611
+ this.isDrawing = false;
1612
+ fromNode?.removeLine(line);
1567
1613
  toNode?.removeLine(line);
1568
1614
  });
1569
1615
  line.onDispose(() => {
@@ -1686,7 +1732,7 @@ var WorkflowLinesManager = class {
1686
1732
  return this.lineColor.default;
1687
1733
  }
1688
1734
  canAddLine(fromPort, toPort, silent) {
1689
- if (fromPort === toPort || fromPort.node === toPort.node || fromPort.portType !== "output" || toPort.portType !== "input" || toPort.disabled) {
1735
+ if (fromPort === toPort || fromPort.node === toPort.node || fromPort.portType !== "output" || toPort.portType !== "input" || fromPort.disabled || toPort.disabled) {
1690
1736
  return false;
1691
1737
  }
1692
1738
  const fromCanAdd = fromPort.node.getNodeRegistry().canAddLine;
@@ -1714,8 +1760,8 @@ var WorkflowLinesManager = class {
1714
1760
  }
1715
1761
  return true;
1716
1762
  }
1717
- canReset(fromPort, oldToPort, newToPort) {
1718
- if (this.options && this.options.canResetLine && !this.options.canResetLine(fromPort, oldToPort, newToPort, this)) {
1763
+ canReset(oldLine, newLineInfo) {
1764
+ if (this.options && this.options.canResetLine && !this.options.canResetLine(oldLine, newLineInfo, this)) {
1719
1765
  return false;
1720
1766
  }
1721
1767
  return true;
@@ -1724,9 +1770,14 @@ var WorkflowLinesManager = class {
1724
1770
  * 根据鼠标位置找到 port
1725
1771
  * @param pos
1726
1772
  */
1727
- getPortFromMousePos(pos) {
1773
+ getPortFromMousePos(pos, portType) {
1728
1774
  const allNodes = this.getSortedNodes().reverse();
1729
- const allPorts = allNodes.map((node) => node.ports.allPorts).flat();
1775
+ const allPorts = allNodes.map((node) => {
1776
+ if (!portType) {
1777
+ return node.ports.allPorts;
1778
+ }
1779
+ return portType === "input" ? node.ports.inputPorts : node.ports.outputPorts;
1780
+ }).flat();
1730
1781
  const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));
1731
1782
  if (targetPort) {
1732
1783
  const containNodes = this.getContainNodesFromMousePos(pos);
@@ -2946,18 +2997,30 @@ var WorkflowDragService = class {
2946
2997
  line.highlightColor = color;
2947
2998
  this.hoverService.clearHovered();
2948
2999
  }
2949
- handleDragOnNode(toNode, fromPort, line, toPort, originLine) {
2950
- if (toPort && (originLine?.toPort === toPort || toPort.portType === "input" && this.linesManager.canAddLine(fromPort, toPort, true))) {
2951
- this.hoverService.updateHoveredKey(toPort.id);
2952
- line.setToPort(toPort);
3000
+ checkDraggingPort(isDrawingTo, line, draggingNode, draggingPort, originLine) {
3001
+ let successDrawing = false;
3002
+ if (isDrawingTo) {
3003
+ successDrawing = !!(draggingPort && // 同一条线条则不用在判断 canAddLine
3004
+ (originLine?.toPort === draggingPort || draggingPort.portType === "input" && this.linesManager.canAddLine(line.fromPort, draggingPort, true)));
3005
+ } else {
3006
+ successDrawing = !!(draggingPort && // 同一条线条则不用在判断 canAddLine
3007
+ (originLine?.fromPort === draggingPort || draggingPort.portType === "output" && this.linesManager.canAddLine(draggingPort, line.toPort, true)));
3008
+ }
3009
+ if (successDrawing) {
3010
+ this.hoverService.updateHoveredKey(draggingPort.id);
3011
+ if (isDrawingTo) {
3012
+ line.setToPort(draggingPort);
3013
+ } else {
3014
+ line.setFromPort(draggingPort);
3015
+ }
2953
3016
  this._onDragLineEventEmitter.fire({
2954
3017
  type: "onDrag",
2955
- onDragNodeId: toNode.id
3018
+ onDragNodeId: draggingNode.id
2956
3019
  });
2957
3020
  return {
2958
3021
  hasError: false
2959
3022
  };
2960
- } else if (this.isContainer(toNode)) {
3023
+ } else if (this.isContainer(draggingNode)) {
2961
3024
  return {
2962
3025
  hasError: false
2963
3026
  };
@@ -3009,7 +3072,7 @@ var WorkflowDragService = class {
3009
3072
  return;
3010
3073
  }
3011
3074
  const sourceContainer = nodes[0]?.parent;
3012
- if (!sourceContainer) {
3075
+ if (!sourceContainer || sourceContainer.flowNodeType === FlowNodeBaseType3.ROOT) {
3013
3076
  return;
3014
3077
  }
3015
3078
  const valid = nodes.every((node) => node?.parent === sourceContainer);
@@ -3023,16 +3086,18 @@ var WorkflowDragService = class {
3023
3086
  * @param opts
3024
3087
  * @param event
3025
3088
  */
3026
- async startDrawingLine(fromPort, event, originLine) {
3027
- const isFromInActivePort = !originLine && fromPort.isErrorPort() && fromPort.disabled;
3028
- if (originLine?.disabled || isFromInActivePort || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
3089
+ async startDrawingLine(port, event, originLine) {
3090
+ const isDrawingTo = port.portType === "output";
3091
+ const isInActivePort = !originLine && port.isErrorPort() && port.disabled;
3092
+ if (originLine?.disabled || isInActivePort || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
3029
3093
  return { dragSuccess: false, newLine: void 0 };
3030
3094
  }
3031
3095
  this.selectService.clear();
3032
3096
  const config = this.playgroundConfig;
3033
3097
  const deferred = new PromiseDeferred();
3034
3098
  const preCursor = config.cursor;
3035
- let line, toPort, toNode, lineErrorReset = false;
3099
+ let line;
3100
+ let newLineInfo;
3036
3101
  const startTime = Date.now();
3037
3102
  let dragSuccess = false;
3038
3103
  const dragger = new PlaygroundDrag({
@@ -3043,16 +3108,29 @@ var WorkflowDragService = class {
3043
3108
  }
3044
3109
  dragSuccess = true;
3045
3110
  const pos = config.getPosFromMouseEvent(event);
3046
- line = this.linesManager.createLine({
3047
- from: fromPort.node.id,
3048
- fromPort: fromPort.portID,
3049
- data: originLine?.lineData,
3050
- drawingTo: {
3051
- x: pos.x,
3052
- y: pos.y,
3053
- location: fromPort.location === "right" ? "left" : "top"
3054
- }
3055
- });
3111
+ if (isDrawingTo) {
3112
+ line = this.linesManager.createLine({
3113
+ from: port.node.id,
3114
+ fromPort: port.portID,
3115
+ data: originLine?.lineData,
3116
+ drawingTo: {
3117
+ x: pos.x,
3118
+ y: pos.y,
3119
+ location: port.location === "right" ? "left" : "top"
3120
+ }
3121
+ });
3122
+ } else {
3123
+ line = this.linesManager.createLine({
3124
+ to: port.node.id,
3125
+ toPort: port.portID,
3126
+ data: originLine?.lineData,
3127
+ drawingFrom: {
3128
+ x: pos.x,
3129
+ y: pos.y,
3130
+ location: port.location === "left" ? "right" : "bottom"
3131
+ }
3132
+ });
3133
+ }
3056
3134
  if (!line) {
3057
3135
  return;
3058
3136
  }
@@ -3063,49 +3141,15 @@ var WorkflowDragService = class {
3063
3141
  if (!line) {
3064
3142
  return;
3065
3143
  }
3066
- lineErrorReset = false;
3067
3144
  const dragPos = config.getPosFromMouseEvent(e);
3068
- toNode = this.linesManager.getNodeFromMousePos(dragPos);
3069
- toPort = this.linesManager.getPortFromMousePos(dragPos);
3070
- if (!toPort) {
3071
- line.setToPort(void 0);
3072
- } else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {
3073
- line.highlightColor = this.linesManager.lineColor.error;
3074
- lineErrorReset = true;
3075
- line.setToPort(void 0);
3076
- } else {
3077
- line.setToPort(toPort);
3078
- }
3079
- this._onDragLineEventEmitter.fire({
3080
- type: "onDrag"
3081
- });
3082
- this.setLineColor(line, originLine?.lockedColor || this.linesManager.lineColor.drawing);
3083
- if (toNode && this.canBuildContainerLine(toNode, dragPos)) {
3084
- toPort = this.getNearestPort(toNode, dragPos);
3085
- const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);
3086
- lineErrorReset = hasError;
3087
- }
3088
- if (line.toPort) {
3089
- line.drawingTo = {
3090
- x: line.toPort.point.x,
3091
- y: line.toPort.point.y,
3092
- location: line.toPort.location
3093
- };
3094
- } else {
3095
- line.drawingTo = {
3096
- x: dragPos.x,
3097
- y: dragPos.y,
3098
- location: reverseLocation(line.fromPort.location)
3099
- };
3100
- }
3101
- originLine?.validate();
3102
- line.validate();
3145
+ newLineInfo = this.updateDrawingLine(isDrawingTo, line, dragPos, originLine);
3103
3146
  },
3104
3147
  // eslint-disable-next-line complexity
3105
3148
  onDragEnd: async (e) => {
3106
3149
  const dragPos = config.getPosFromMouseEvent(e);
3107
3150
  const onDragLineEndCallbacks = Array.from(this._onDragLineEndCallbacks.values());
3108
3151
  config.updateCursor(preCursor);
3152
+ const { fromPort, toPort, hasError } = newLineInfo || {};
3109
3153
  await Promise.all(
3110
3154
  onDragLineEndCallbacks.map(
3111
3155
  (callback) => callback({
@@ -3130,36 +3174,32 @@ var WorkflowDragService = class {
3130
3174
  deferred.resolve({ dragSuccess });
3131
3175
  };
3132
3176
  if (dragSuccess) {
3133
- if (originLine && originLine.toPort === toPort) {
3177
+ if (originLine && originLine.toPort === toPort && originLine.fromPort === fromPort) {
3134
3178
  return end();
3135
3179
  }
3136
- if (toPort && toPort.portType !== "input") {
3180
+ if (toPort && toPort.portType !== "input" || fromPort && fromPort.portType !== "output") {
3137
3181
  return end();
3138
3182
  }
3139
- const newLineInfo = toPort ? {
3183
+ const newLinePortInfo = toPort && fromPort ? {
3140
3184
  from: fromPort.node.id,
3141
3185
  fromPort: fromPort.portID,
3142
3186
  to: toPort.node.id,
3143
3187
  toPort: toPort.portID,
3144
3188
  data: originLine?.lineData
3145
3189
  } : void 0;
3146
- const isReset = originLine && toPort;
3147
- if (isReset && !this.linesManager.canReset(
3148
- originLine.fromPort,
3149
- originLine.toPort,
3150
- toPort
3151
- )) {
3190
+ const isReset = originLine && newLinePortInfo;
3191
+ if (isReset && !this.linesManager.canReset(originLine, newLinePortInfo)) {
3152
3192
  return end();
3153
3193
  }
3154
- if (originLine && (!this.linesManager.canRemove(originLine, newLineInfo, false) || lineErrorReset)) {
3194
+ if (originLine && (!this.linesManager.canRemove(originLine, newLinePortInfo, false) || hasError)) {
3155
3195
  return end();
3156
3196
  } else {
3157
3197
  originLine?.dispose();
3158
3198
  }
3159
- if (!toPort || !this.linesManager.canAddLine(fromPort, toPort, false)) {
3199
+ if (!newLinePortInfo || !this.linesManager.canAddLine(fromPort, toPort, false)) {
3160
3200
  return end();
3161
3201
  }
3162
- const newLine = this.linesManager.createLine(newLineInfo);
3202
+ const newLine = this.linesManager.createLine(newLinePortInfo);
3163
3203
  if (!newLine) {
3164
3204
  end();
3165
3205
  }
@@ -3176,14 +3216,109 @@ var WorkflowDragService = class {
3176
3216
  await dragger.start(clientX, clientY, config);
3177
3217
  return deferred.promise;
3178
3218
  }
3219
+ updateDrawingLine(isDrawingTo, line, dragPos, originLine) {
3220
+ let hasError = false;
3221
+ const mouseNode = this.linesManager.getNodeFromMousePos(dragPos);
3222
+ let toNode;
3223
+ let toPort;
3224
+ let fromPort;
3225
+ let fromNode;
3226
+ if (isDrawingTo) {
3227
+ fromPort = line.fromPort;
3228
+ toNode = mouseNode;
3229
+ toPort = this.linesManager.getPortFromMousePos(dragPos, "input");
3230
+ if (toNode && this.canBuildContainerLine(toNode, dragPos)) {
3231
+ toPort = this.getNearestPort(toNode, dragPos, "input");
3232
+ hasError = this.checkDraggingPort(isDrawingTo, line, toNode, toPort, originLine).hasError;
3233
+ }
3234
+ if (!toPort) {
3235
+ line.setToPort(void 0);
3236
+ } else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {
3237
+ hasError = true;
3238
+ line.setToPort(void 0);
3239
+ } else {
3240
+ line.setToPort(toPort);
3241
+ }
3242
+ if (line.toPort) {
3243
+ line.drawingTo = {
3244
+ x: line.toPort.point.x,
3245
+ y: line.toPort.point.y,
3246
+ location: line.toPort.location
3247
+ };
3248
+ } else {
3249
+ line.drawingTo = {
3250
+ x: dragPos.x,
3251
+ y: dragPos.y,
3252
+ location: reverseLocation(line.fromPort.location)
3253
+ };
3254
+ }
3255
+ } else {
3256
+ toPort = line.toPort;
3257
+ fromNode = mouseNode;
3258
+ fromPort = this.linesManager.getPortFromMousePos(dragPos, "output");
3259
+ if (fromNode && this.canBuildContainerLine(fromNode, dragPos)) {
3260
+ fromPort = this.getNearestPort(fromNode, dragPos, "output");
3261
+ hasError = this.checkDraggingPort(
3262
+ isDrawingTo,
3263
+ line,
3264
+ fromNode,
3265
+ fromPort,
3266
+ originLine
3267
+ ).hasError;
3268
+ }
3269
+ if (!fromPort) {
3270
+ line.setFromPort(void 0);
3271
+ } else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {
3272
+ hasError = true;
3273
+ line.setFromPort(void 0);
3274
+ } else {
3275
+ line.setFromPort(fromPort);
3276
+ }
3277
+ if (line.fromPort) {
3278
+ line.drawingFrom = {
3279
+ x: line.fromPort.point.x,
3280
+ y: line.fromPort.point.y,
3281
+ location: line.fromPort.location
3282
+ };
3283
+ } else {
3284
+ line.drawingFrom = {
3285
+ x: dragPos.x,
3286
+ y: dragPos.y,
3287
+ location: reverseLocation(line.toPort.location)
3288
+ };
3289
+ }
3290
+ }
3291
+ this._onDragLineEventEmitter.fire({
3292
+ type: "onDrag"
3293
+ });
3294
+ if (hasError) {
3295
+ this.setLineColor(line, this.linesManager.lineColor.error);
3296
+ } else {
3297
+ this.setLineColor(line, originLine?.lockedColor || this.linesManager.lineColor.drawing);
3298
+ }
3299
+ originLine?.validate();
3300
+ line.validate();
3301
+ return {
3302
+ fromPort,
3303
+ toPort,
3304
+ hasError
3305
+ };
3306
+ }
3179
3307
  /**
3180
3308
  * 重新连接线条
3181
3309
  * @param line
3182
3310
  * @param e
3183
3311
  */
3184
3312
  async resetLine(line, e) {
3185
- const { fromPort } = line;
3186
- const { dragSuccess } = await this.startDrawingLine(fromPort, e, line);
3313
+ const { fromPort, toPort } = line;
3314
+ const mousePos = this.playgroundConfig.getPosFromMouseEvent(e);
3315
+ const distanceFrom = Point.getDistance(fromPort.point, mousePos);
3316
+ const distanceTo = Point.getDistance(toPort.point, mousePos);
3317
+ const { dragSuccess } = await this.startDrawingLine(
3318
+ distanceTo <= distanceFrom || !this.document.options.twoWayConnection ? fromPort : toPort,
3319
+ e,
3320
+ line
3321
+ );
3187
3322
  if (!dragSuccess) {
3188
3323
  this.selectService.select(line);
3189
3324
  }
@@ -3205,17 +3340,27 @@ var WorkflowDragService = class {
3205
3340
  return true;
3206
3341
  }
3207
3342
  const { padding, bounds } = node.transform;
3208
- const contentRect = new Rectangle8(bounds.x, bounds.y, padding.left * 2 / 3, bounds.height);
3209
- return contentRect.contains(mousePos.x, mousePos.y);
3343
+ const DEFAULT_DELTA = 10;
3344
+ const leftDelta = padding.left * 2 / 3 || DEFAULT_DELTA;
3345
+ const rightDelta = padding.right * 2 / 3 || DEFAULT_DELTA;
3346
+ const bottomDelta = padding.bottom * 2 / 3 || DEFAULT_DELTA;
3347
+ const topDelta = padding.top * 2 / 3 || DEFAULT_DELTA;
3348
+ const rectangles = [
3349
+ new Rectangle8(bounds.x, bounds.y, leftDelta, bounds.height),
3350
+ // left
3351
+ new Rectangle8(bounds.x, bounds.y, bounds.width, topDelta),
3352
+ // top
3353
+ new Rectangle8(bounds.x, bounds.y + bounds.height - bottomDelta, bounds.width, bottomDelta),
3354
+ // bottom
3355
+ new Rectangle8(bounds.x + bounds.width - rightDelta, bounds.y, rightDelta, bounds.height)
3356
+ // right
3357
+ ];
3358
+ return rectangles.some((rect) => rect.contains(mousePos.x, mousePos.y));
3210
3359
  }
3211
3360
  /** 获取最近的 port */
3212
- getNearestPort(node, mousePos) {
3361
+ getNearestPort(node, mousePos, portType = "input") {
3213
3362
  const portsData = node.ports;
3214
- const distanceSortedPorts = portsData.inputPorts.sort((a, b) => {
3215
- const aDistance = Math.abs(mousePos.y - a.point.y);
3216
- const bDistance = Math.abs(mousePos.y - b.point.y);
3217
- return aDistance - bDistance;
3218
- });
3363
+ const distanceSortedPorts = (portType === "input" ? portsData.inputPorts : portsData.outputPorts).sort((a, b) => Point.getDistance(mousePos, a.point) - Point.getDistance(mousePos, b.point));
3219
3364
  return distanceSortedPorts[0];
3220
3365
  }
3221
3366
  };