@flowgram.ai/free-layout-core 0.1.0-alpha.34 → 0.1.0-alpha.36

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/index.d.mts CHANGED
@@ -2,8 +2,8 @@ import { PlaygroundConfigEntity, CommandService, PlaygroundDragEvent, EntityData
2
2
  export { bindConfigEntity, useConfigEntity, useEntities, useEntityDataFromContext, useEntityFromContext, useListenEvents, usePlayground, usePlaygroundContainer, usePlaygroundContext, useRefresh, useService } from '@flowgram.ai/core';
3
3
  import { NodeFormProps } from '@flowgram.ai/node';
4
4
  import { FlowNodeType, FlowOperationBaseServiceImpl, FlowNodeEntityOrId, FlowNodeEntity } from '@flowgram.ai/document';
5
- import { W as WorkflowJSON, L as LineCenterPoint, a as WorkflowDocument, b as WorkflowNodeEntity, c as WorkflowHoverService, d as WorkflowLinesManager, e as WorkflowSelectService, f as WorkflowDocumentOptions, g as LineEventProps, N as NodesDragEvent, h as WorkflowNodeJSON, i as WorkflowPortEntity, j as WorkflowLineEntity, O as OnDragLineEnd, k as LineRenderType, l as WorkflowLineRenderContribution, m as LinePosition } from './workflow-node-entity-C6bFzfXc.mjs';
6
- export { Y as HoverPosition, G as LINE_HOVER_DISTANCE, y as LineColor, z as LineColors, x as LinePoint, w as LinePointLocation, v as LineType, D as NodesDragEndEvent, C as NodesDragStartEvent, E as NodesDraggingEvent, P as POINT_RADIUS, M as PORT_SIZE, q as WORKFLOW_LINE_ENTITY, Z as WorkfloEntityHoverable, t as WorkflowContentChangeEvent, s as WorkflowContentChangeType, $ as WorkflowDocumentOptionsDefault, _ as WorkflowDocumentProvider, X as WorkflowEntityHoverable, I as WorkflowLineEntityOpts, J as WorkflowLineInfo, H as WorkflowLinePortInfo, A as WorkflowLineRenderContributionFactory, K as WorkflowLineUIState, U as WorkflowNodeLines, V as WorkflowNodeLinesData, u as WorkflowNodeMeta, T as WorkflowNodePortsData, Q as WorkflowPort, S as WorkflowPortEntityOpts, n as WorkflowPortType, R as WorkflowPorts, B as WorkflowSubCanvas, r as domReactToBounds, p as getPortEntityId, o as getPortEntityIdByNodeId, F as onDragLineEndParams } from './workflow-node-entity-C6bFzfXc.mjs';
5
+ import { W as WorkflowJSON, L as LineCenterPoint, a as WorkflowDocument, b as WorkflowNodeEntity, c as WorkflowHoverService, d as WorkflowLinesManager, e as WorkflowSelectService, f as WorkflowDocumentOptions, g as LineEventProps, N as NodesDragEvent, h as WorkflowNodeJSON, i as WorkflowPortEntity, j as WorkflowLineEntity, O as OnDragLineEnd, k as LineRenderType, l as WorkflowLineRenderContribution, m as LinePosition } from './workflow-node-entity-DcXjib68.mjs';
6
+ export { Y as HoverPosition, G as LINE_HOVER_DISTANCE, y as LineColor, z as LineColors, x as LinePoint, w as LinePointLocation, v as LineType, D as NodesDragEndEvent, C as NodesDragStartEvent, E as NodesDraggingEvent, P as POINT_RADIUS, M as PORT_SIZE, q as WORKFLOW_LINE_ENTITY, Z as WorkfloEntityHoverable, t as WorkflowContentChangeEvent, s as WorkflowContentChangeType, $ as WorkflowDocumentOptionsDefault, _ as WorkflowDocumentProvider, X as WorkflowEntityHoverable, I as WorkflowLineEntityOpts, J as WorkflowLineInfo, H as WorkflowLinePortInfo, A as WorkflowLineRenderContributionFactory, K as WorkflowLineUIState, U as WorkflowNodeLines, V as WorkflowNodeLinesData, u as WorkflowNodeMeta, T as WorkflowNodePortsData, Q as WorkflowPort, S as WorkflowPortEntityOpts, n as WorkflowPortType, R as WorkflowPorts, B as WorkflowSubCanvas, r as domReactToBounds, p as getPortEntityId, o as getPortEntityIdByNodeId, F as onDragLineEndParams } from './workflow-node-entity-DcXjib68.mjs';
7
7
  import * as _flowgram_ai_utils from '@flowgram.ai/utils';
8
8
  import { IPoint, Rectangle, DisposableCollection, Disposable } from '@flowgram.ai/utils';
9
9
  export { compose, composeAsync, delay } from '@flowgram.ai/utils';
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import { PlaygroundConfigEntity, CommandService, PlaygroundDragEvent, EntityData
2
2
  export { bindConfigEntity, useConfigEntity, useEntities, useEntityDataFromContext, useEntityFromContext, useListenEvents, usePlayground, usePlaygroundContainer, usePlaygroundContext, useRefresh, useService } from '@flowgram.ai/core';
3
3
  import { NodeFormProps } from '@flowgram.ai/node';
4
4
  import { FlowNodeType, FlowOperationBaseServiceImpl, FlowNodeEntityOrId, FlowNodeEntity } from '@flowgram.ai/document';
5
- import { W as WorkflowJSON, L as LineCenterPoint, a as WorkflowDocument, b as WorkflowNodeEntity, c as WorkflowHoverService, d as WorkflowLinesManager, e as WorkflowSelectService, f as WorkflowDocumentOptions, g as LineEventProps, N as NodesDragEvent, h as WorkflowNodeJSON, i as WorkflowPortEntity, j as WorkflowLineEntity, O as OnDragLineEnd, k as LineRenderType, l as WorkflowLineRenderContribution, m as LinePosition } from './workflow-node-entity-03Q7Fvv6.js';
6
- export { Y as HoverPosition, G as LINE_HOVER_DISTANCE, y as LineColor, z as LineColors, x as LinePoint, w as LinePointLocation, v as LineType, D as NodesDragEndEvent, C as NodesDragStartEvent, E as NodesDraggingEvent, P as POINT_RADIUS, M as PORT_SIZE, q as WORKFLOW_LINE_ENTITY, Z as WorkfloEntityHoverable, t as WorkflowContentChangeEvent, s as WorkflowContentChangeType, $ as WorkflowDocumentOptionsDefault, _ as WorkflowDocumentProvider, X as WorkflowEntityHoverable, I as WorkflowLineEntityOpts, J as WorkflowLineInfo, H as WorkflowLinePortInfo, A as WorkflowLineRenderContributionFactory, K as WorkflowLineUIState, U as WorkflowNodeLines, V as WorkflowNodeLinesData, u as WorkflowNodeMeta, T as WorkflowNodePortsData, Q as WorkflowPort, S as WorkflowPortEntityOpts, n as WorkflowPortType, R as WorkflowPorts, B as WorkflowSubCanvas, r as domReactToBounds, p as getPortEntityId, o as getPortEntityIdByNodeId, F as onDragLineEndParams } from './workflow-node-entity-03Q7Fvv6.js';
5
+ import { W as WorkflowJSON, L as LineCenterPoint, a as WorkflowDocument, b as WorkflowNodeEntity, c as WorkflowHoverService, d as WorkflowLinesManager, e as WorkflowSelectService, f as WorkflowDocumentOptions, g as LineEventProps, N as NodesDragEvent, h as WorkflowNodeJSON, i as WorkflowPortEntity, j as WorkflowLineEntity, O as OnDragLineEnd, k as LineRenderType, l as WorkflowLineRenderContribution, m as LinePosition } from './workflow-node-entity-_7O7-wJE.js';
6
+ export { Y as HoverPosition, G as LINE_HOVER_DISTANCE, y as LineColor, z as LineColors, x as LinePoint, w as LinePointLocation, v as LineType, D as NodesDragEndEvent, C as NodesDragStartEvent, E as NodesDraggingEvent, P as POINT_RADIUS, M as PORT_SIZE, q as WORKFLOW_LINE_ENTITY, Z as WorkfloEntityHoverable, t as WorkflowContentChangeEvent, s as WorkflowContentChangeType, $ as WorkflowDocumentOptionsDefault, _ as WorkflowDocumentProvider, X as WorkflowEntityHoverable, I as WorkflowLineEntityOpts, J as WorkflowLineInfo, H as WorkflowLinePortInfo, A as WorkflowLineRenderContributionFactory, K as WorkflowLineUIState, U as WorkflowNodeLines, V as WorkflowNodeLinesData, u as WorkflowNodeMeta, T as WorkflowNodePortsData, Q as WorkflowPort, S as WorkflowPortEntityOpts, n as WorkflowPortType, R as WorkflowPorts, B as WorkflowSubCanvas, r as domReactToBounds, p as getPortEntityId, o as getPortEntityIdByNodeId, F as onDragLineEndParams } from './workflow-node-entity-_7O7-wJE.js';
7
7
  import * as _flowgram_ai_utils from '@flowgram.ai/utils';
8
8
  import { IPoint, Rectangle, DisposableCollection, Disposable } from '@flowgram.ai/utils';
9
9
  export { compose, composeAsync, delay } from '@flowgram.ai/utils';
package/dist/index.js CHANGED
@@ -365,7 +365,14 @@ var WorkflowPortEntity = class extends import_core4.Entity {
365
365
  );
366
366
  }
367
367
  isHovered(x, y) {
368
- return this.bounds.contains(x, y);
368
+ const { point } = this;
369
+ const size = this._size || { width: PORT_SIZE, height: PORT_SIZE };
370
+ const halfWidth = size.width / 2;
371
+ const halfHeight = size.height / 2;
372
+ if (size.width <= 0 || size.height <= 0) {
373
+ return false;
374
+ }
375
+ return x >= point.x - halfWidth && x <= point.x + halfWidth && y >= point.y - halfHeight && y <= point.y + halfHeight;
369
376
  }
370
377
  /**
371
378
  * 相对节点左上角的位置
@@ -466,6 +473,7 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
466
473
  this._staticPorts = [];
467
474
  /** 存储 port 实体的 id,用于判断 port 是否存在 */
468
475
  this._portIDSet = /* @__PURE__ */ new Set();
476
+ this._portDisposeIDSet = /* @__PURE__ */ new Set();
469
477
  this.entity = entity;
470
478
  const meta = entity.getNodeMeta();
471
479
  const defaultPorts = meta.useDynamicPort ? [] : [{ type: "input" }, { type: "output" }];
@@ -552,6 +560,7 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
552
560
  });
553
561
  ports.forEach((port) => this.updatePortEntity(port));
554
562
  this._prePorts = ports;
563
+ this.clearPortsCache();
555
564
  this.fireChange();
556
565
  }
557
566
  this.allPorts.forEach((port) => {
@@ -564,19 +573,28 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
564
573
  * 获取所有 port entities
565
574
  */
566
575
  get allPorts() {
567
- return Array.from(this._portIDSet).map((portId) => this.getPortEntity(portId)).filter(Boolean);
576
+ if (!this._allPortsCache) {
577
+ this._allPortsCache = Array.from(this._portIDSet).map((portId) => this.getPortEntity(portId)).filter(Boolean);
578
+ }
579
+ return this._allPortsCache;
568
580
  }
569
581
  /**
570
582
  * 获取输入点位
571
583
  */
572
584
  get inputPorts() {
573
- return this.allPorts.filter((port) => port.portType === "input");
585
+ if (!this._inputPortsCache) {
586
+ this._inputPortsCache = this.allPorts.filter((port) => port.portType === "input");
587
+ }
588
+ return this._inputPortsCache;
574
589
  }
575
590
  /**
576
591
  * 获取输出点位
577
592
  */
578
593
  get outputPorts() {
579
- return this.allPorts.filter((port) => port.portType === "output");
594
+ if (!this._outputPortsCache) {
595
+ this._outputPortsCache = this.allPorts.filter((port) => port.portType === "output");
596
+ }
597
+ return this._outputPortsCache;
580
598
  }
581
599
  /**
582
600
  * 获取输入点位置
@@ -617,6 +635,11 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
617
635
  getPortId(portType, portKey = "") {
618
636
  return getPortEntityId(this.entity, portType, portKey);
619
637
  }
638
+ clearPortsCache() {
639
+ this._allPortsCache = void 0;
640
+ this._inputPortsCache = void 0;
641
+ this._outputPortsCache = void 0;
642
+ }
620
643
  /**
621
644
  * 创建 port 实体
622
645
  */
@@ -630,10 +653,18 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
630
653
  ...portInfo
631
654
  });
632
655
  }
633
- portEntity.onDispose(() => {
634
- this._portIDSet.delete(id);
635
- });
636
- this._portIDSet.add(id);
656
+ if (!this._portDisposeIDSet.has(id)) {
657
+ this._portDisposeIDSet.add(id);
658
+ portEntity.onDispose(() => {
659
+ this._portIDSet.delete(id);
660
+ this._portDisposeIDSet.delete(id);
661
+ this.clearPortsCache();
662
+ });
663
+ }
664
+ if (!this._portIDSet.has(id)) {
665
+ this._portIDSet.add(id);
666
+ this.clearPortsCache();
667
+ }
637
668
  return portEntity;
638
669
  }
639
670
  /**
@@ -1491,7 +1522,6 @@ var import_document10 = require("@flowgram.ai/document");
1491
1522
  var import_core15 = require("@flowgram.ai/core");
1492
1523
 
1493
1524
  // src/workflow-lines-manager.ts
1494
- var import_lodash_es3 = require("lodash-es");
1495
1525
  var import_inversify3 = require("inversify");
1496
1526
  var import_utils12 = require("@flowgram.ai/utils");
1497
1527
  var import_document6 = require("@flowgram.ai/document");
@@ -1640,6 +1670,10 @@ var WorkflowLinesManager = class {
1640
1670
  forceUpdate() {
1641
1671
  this.onForceUpdateEmitter.fire();
1642
1672
  }
1673
+ invalidateSortedNodesCache() {
1674
+ this.sortedNodesCache = void 0;
1675
+ this.sortedNodesCacheVersion = void 0;
1676
+ }
1643
1677
  get lineType() {
1644
1678
  return this._lineType;
1645
1679
  }
@@ -1826,13 +1860,18 @@ var WorkflowLinesManager = class {
1826
1860
  */
1827
1861
  getCloseInLineFromMousePos(mousePos, minDistance = LINE_HOVER_DISTANCE) {
1828
1862
  let targetLine, targetLineDist;
1829
- this.getAllLines().forEach((line) => {
1863
+ const lines = this.getAllLines();
1864
+ for (let i = 0; i < lines.length; i++) {
1865
+ const line = lines[i];
1866
+ if (!this.isPointInBounds(mousePos, line.bounds, minDistance)) {
1867
+ continue;
1868
+ }
1830
1869
  const dist = line.getHoverDist(mousePos);
1831
- if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {
1870
+ if (dist <= minDistance && (targetLineDist === void 0 || targetLineDist >= dist)) {
1832
1871
  targetLineDist = dist;
1833
1872
  targetLine = line;
1834
1873
  }
1835
- });
1874
+ }
1836
1875
  return targetLine;
1837
1876
  }
1838
1877
  dispose() {
@@ -1951,39 +1990,44 @@ var WorkflowLinesManager = class {
1951
1990
  * @param pos
1952
1991
  */
1953
1992
  getPortFromMousePos(pos, portType) {
1954
- const allNodes = this.getSortedNodes().reverse();
1955
- const allPorts = allNodes.map((node) => {
1956
- if (!portType) {
1957
- return node.ports.allPorts;
1958
- }
1959
- return portType === "input" ? node.ports.inputPorts : node.ports.outputPorts;
1960
- }).flat();
1961
- const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));
1962
- if (targetPort) {
1963
- const containNodes = this.getContainNodesFromMousePos(pos);
1964
- const targetNode = (0, import_lodash_es3.last)(containNodes);
1965
- if (targetNode && targetNode !== targetPort.node) {
1966
- return;
1993
+ return this.getHoveredPortFromSortedNodes(pos, this.getSortedNodes(), portType);
1994
+ }
1995
+ getPortsFromMousePos(pos) {
1996
+ return this.getHoveredPortsFromSortedNodes(pos, this.getSortedNodes(), void 0, {
1997
+ collectBoth: true
1998
+ });
1999
+ }
2000
+ getNodeAndPortFromMousePos(pos, portType) {
2001
+ const sortedNodes = this.getSortedNodes();
2002
+ const nodeHitInfo = this.getNodeHitInfoFromSortedNodes(
2003
+ pos,
2004
+ sortedNodes,
2005
+ this.selectService.selection
2006
+ );
2007
+ const ports = this.getHoveredPortsFromSortedNodes(pos, sortedNodes, portType, {
2008
+ topCoverNode: nodeHitInfo.topCoverNode
2009
+ });
2010
+ return {
2011
+ node: nodeHitInfo.topNode,
2012
+ port: ports.port
2013
+ };
2014
+ }
2015
+ getHoverNodeFromMousePos(pos) {
2016
+ const nodes = this.getHoverNodes();
2017
+ for (let i = 0; i < nodes.length; i++) {
2018
+ const node = nodes[i];
2019
+ const { bounds } = node.getData(import_document6.FlowNodeTransformData);
2020
+ if (this.isPointInBounds(pos, bounds)) {
2021
+ return node;
1967
2022
  }
1968
2023
  }
1969
- return targetPort;
1970
2024
  }
1971
2025
  /**
1972
2026
  * 根据鼠标位置找到 node
1973
2027
  * @param pos - 鼠标位置
1974
2028
  */
1975
2029
  getNodeFromMousePos(pos) {
1976
- const { selection } = this.selectService;
1977
- const containNodes = this.getContainNodesFromMousePos(pos);
1978
- if (selection?.length) {
1979
- const filteredNodes = containNodes.filter(
1980
- (node) => selection.some((_node) => node.id === _node.id)
1981
- );
1982
- if (filteredNodes?.length) {
1983
- return (0, import_lodash_es3.last)(filteredNodes);
1984
- }
1985
- }
1986
- return (0, import_lodash_es3.last)(containNodes);
2030
+ return this.getTopNodeFromSortedNodes(pos, this.getSortedNodes(), this.selectService.selection);
1987
2031
  }
1988
2032
  registerContribution(factory) {
1989
2033
  this.contributionFactories.push(factory);
@@ -1993,19 +2037,125 @@ var WorkflowLinesManager = class {
1993
2037
  line.addData(WorkflowLineRenderData);
1994
2038
  }
1995
2039
  getSortedNodes() {
1996
- return this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
2040
+ const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
2041
+ if (this.sortedNodesCache && this.sortedNodesCacheVersion === nodeVersion) {
2042
+ return this.sortedNodesCache;
2043
+ }
2044
+ this.sortedNodesCache = [...this.document.getAllNodes()].sort(
2045
+ (a, b) => this.getNodeIndex(a) - this.getNodeIndex(b)
2046
+ );
2047
+ this.sortedNodesCacheVersion = nodeVersion;
2048
+ return this.sortedNodesCache;
2049
+ }
2050
+ getHoveredPortFromSortedNodes(pos, sortedNodes, portType) {
2051
+ return this.getHoveredPortsFromSortedNodes(pos, sortedNodes, portType).port;
2052
+ }
2053
+ getHoveredPortsFromSortedNodes(pos, sortedNodes, portType, options = {}) {
2054
+ let inputPort;
2055
+ let outputPort;
2056
+ let anyPort;
2057
+ const { collectBoth = false } = options;
2058
+ for (let i = sortedNodes.length - 1; i >= 0; i--) {
2059
+ const node = sortedNodes[i];
2060
+ if (!portType && !anyPort) {
2061
+ anyPort = this.findHoveredPort(node.ports.allPorts, pos);
2062
+ }
2063
+ if ((!portType || portType === "output") && !outputPort) {
2064
+ outputPort = this.findHoveredPort(node.ports.outputPorts, pos);
2065
+ }
2066
+ if ((!portType || portType === "input") && !inputPort) {
2067
+ inputPort = this.findHoveredPort(node.ports.inputPorts, pos);
2068
+ }
2069
+ if (portType === "input" && inputPort || portType === "output" && outputPort || !portType && (collectBoth ? inputPort && outputPort : anyPort)) {
2070
+ break;
2071
+ }
2072
+ }
2073
+ const needCoverCheck = inputPort || outputPort || anyPort;
2074
+ const topCoverNode = needCoverCheck ? options.topCoverNode || this.getNodeHitInfoFromSortedNodes(pos, sortedNodes).topCoverNode : void 0;
2075
+ inputPort = this.filterCoveredPort(inputPort, topCoverNode);
2076
+ outputPort = this.filterCoveredPort(outputPort, topCoverNode);
2077
+ anyPort = this.filterCoveredPort(anyPort, topCoverNode);
2078
+ return {
2079
+ input: inputPort,
2080
+ output: outputPort,
2081
+ port: portType === "input" ? inputPort : portType === "output" ? outputPort : anyPort
2082
+ };
1997
2083
  }
1998
- /** 获取鼠标坐标位置的所有节点(stackIndex 从小到大排序) */
1999
- getContainNodesFromMousePos(pos) {
2000
- const allNodes = this.getSortedNodes();
2084
+ findHoveredPort(ports, pos) {
2085
+ for (let i = 0; i < ports.length; i++) {
2086
+ const port = ports[i];
2087
+ if (port.isHovered(pos.x, pos.y)) {
2088
+ return port;
2089
+ }
2090
+ }
2091
+ }
2092
+ filterCoveredPort(port, topCoverNode) {
2093
+ if (port && topCoverNode && topCoverNode !== port.node) {
2094
+ return void 0;
2095
+ }
2096
+ return port;
2097
+ }
2098
+ getTopNodeFromSortedNodes(pos, sortedNodes, selection) {
2099
+ return this.getNodeHitInfoFromSortedNodes(pos, sortedNodes, selection).topNode;
2100
+ }
2101
+ getNodeHitInfoFromSortedNodes(pos, sortedNodes, selection) {
2001
2102
  const zoom = this.entityManager.getEntity(import_core12.PlaygroundConfigEntity)?.config?.zoom || 1;
2002
- const containNodes = allNodes.map((node) => {
2103
+ const padding = 4 / zoom;
2104
+ const selectedIDs = selection?.length ? new Set(selection.map((node) => node.id)) : void 0;
2105
+ let topCoverNode;
2106
+ for (let i = sortedNodes.length - 1; i >= 0; i--) {
2107
+ const node = sortedNodes[i];
2003
2108
  const { bounds } = node.getData(import_document6.FlowNodeTransformData);
2004
- if (bounds.clone().pad(4 / zoom).contains(pos.x, pos.y)) {
2005
- return node;
2109
+ if (!this.isPointInBounds(pos, bounds, padding)) {
2110
+ continue;
2006
2111
  }
2007
- }).filter(Boolean);
2008
- return containNodes;
2112
+ if (!topCoverNode) {
2113
+ topCoverNode = node;
2114
+ }
2115
+ if (!selectedIDs) {
2116
+ return {
2117
+ topCoverNode,
2118
+ topNode: node
2119
+ };
2120
+ }
2121
+ if (selectedIDs.has(node.id)) {
2122
+ return {
2123
+ topCoverNode,
2124
+ topNode: node
2125
+ };
2126
+ }
2127
+ }
2128
+ return {
2129
+ topCoverNode,
2130
+ topNode: topCoverNode
2131
+ };
2132
+ }
2133
+ getHoverNodes() {
2134
+ const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
2135
+ const activatedID = this.selectService.activatedNode?.id;
2136
+ if (this.hoverNodesCache && this.hoverNodesCacheVersion === nodeVersion && this.hoverNodesCacheActivatedID === activatedID) {
2137
+ return this.hoverNodesCache;
2138
+ }
2139
+ const nodes = this.document.getAllNodes().filter(
2140
+ (node) => node.id !== "root" && node.flowNodeType !== import_document6.FlowNodeBaseType.ROOT && node.flowNodeType !== import_document6.FlowNodeBaseType.GROUP
2141
+ ).reverse();
2142
+ if (activatedID) {
2143
+ const activatedIndex = nodes.findIndex((node) => node.id === activatedID);
2144
+ if (activatedIndex > 0) {
2145
+ const [activatedNode] = nodes.splice(activatedIndex, 1);
2146
+ nodes.unshift(activatedNode);
2147
+ }
2148
+ }
2149
+ this.hoverNodesCache = nodes;
2150
+ this.hoverNodesCacheVersion = nodeVersion;
2151
+ this.hoverNodesCacheActivatedID = activatedID;
2152
+ return this.hoverNodesCache;
2153
+ }
2154
+ isPointInBounds(pos, bounds, padding = 0) {
2155
+ if (bounds.width + padding * 2 <= 0 || bounds.height + padding * 2 <= 0) {
2156
+ return false;
2157
+ }
2158
+ return pos.x >= bounds.x - padding && pos.x <= bounds.right + padding && pos.y >= bounds.y - padding && pos.y <= bounds.bottom + padding;
2009
2159
  }
2010
2160
  getNodeIndex(node) {
2011
2161
  const nodeRenderData = node.getData(import_document6.FlowNodeRenderData);
@@ -3407,15 +3557,15 @@ var WorkflowDragService = class {
3407
3557
  }
3408
3558
  updateDrawingLine(isDrawingTo, line, dragPos, originLine) {
3409
3559
  let hasError = false;
3410
- const mouseNode = this.linesManager.getNodeFromMousePos(dragPos);
3411
3560
  let toNode;
3412
3561
  let toPort;
3413
3562
  let fromPort;
3414
3563
  let fromNode;
3415
3564
  if (isDrawingTo) {
3565
+ const mouseHitInfo = this.linesManager.getNodeAndPortFromMousePos(dragPos, "input");
3416
3566
  fromPort = line.fromPort;
3417
- toNode = mouseNode;
3418
- toPort = this.linesManager.getPortFromMousePos(dragPos, "input");
3567
+ toNode = mouseHitInfo.node;
3568
+ toPort = mouseHitInfo.port;
3419
3569
  if (toNode && this.canBuildContainerLine(toNode, dragPos)) {
3420
3570
  toPort = this.getNearestPort(toNode, dragPos, "input");
3421
3571
  hasError = this.checkDraggingPort(isDrawingTo, line, toNode, toPort, originLine).hasError;
@@ -3442,9 +3592,10 @@ var WorkflowDragService = class {
3442
3592
  };
3443
3593
  }
3444
3594
  } else {
3595
+ const mouseHitInfo = this.linesManager.getNodeAndPortFromMousePos(dragPos, "output");
3445
3596
  toPort = line.toPort;
3446
- fromNode = mouseNode;
3447
- fromPort = this.linesManager.getPortFromMousePos(dragPos, "output");
3597
+ fromNode = mouseHitInfo.node;
3598
+ fromPort = mouseHitInfo.port;
3448
3599
  if (fromNode && this.canBuildContainerLine(fromNode, dragPos)) {
3449
3600
  fromPort = this.getNearestPort(fromNode, dragPos, "output");
3450
3601
  hasError = this.checkDraggingPort(