@flowgram.ai/free-layout-core 0.1.0-alpha.37 → 0.1.0-alpha.39

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
@@ -318,14 +318,7 @@ var WorkflowPortEntity = class extends Entity {
318
318
  );
319
319
  }
320
320
  isHovered(x, y) {
321
- const { point } = this;
322
- const size = this._size || { width: PORT_SIZE, height: PORT_SIZE };
323
- const halfWidth = size.width / 2;
324
- const halfHeight = size.height / 2;
325
- if (size.width <= 0 || size.height <= 0) {
326
- return false;
327
- }
328
- return x >= point.x - halfWidth && x <= point.x + halfWidth && y >= point.y - halfHeight && y <= point.y + halfHeight;
321
+ return this.bounds.contains(x, y);
329
322
  }
330
323
  /**
331
324
  * 相对节点左上角的位置
@@ -426,7 +419,6 @@ var WorkflowNodePortsData = class extends EntityData {
426
419
  this._staticPorts = [];
427
420
  /** 存储 port 实体的 id,用于判断 port 是否存在 */
428
421
  this._portIDSet = /* @__PURE__ */ new Set();
429
- this._portDisposeIDSet = /* @__PURE__ */ new Set();
430
422
  this.entity = entity;
431
423
  const meta = entity.getNodeMeta();
432
424
  const defaultPorts = meta.useDynamicPort ? [] : [{ type: "input" }, { type: "output" }];
@@ -513,7 +505,6 @@ var WorkflowNodePortsData = class extends EntityData {
513
505
  });
514
506
  ports.forEach((port) => this.updatePortEntity(port));
515
507
  this._prePorts = ports;
516
- this.clearPortsCache();
517
508
  this.fireChange();
518
509
  }
519
510
  this.allPorts.forEach((port) => {
@@ -526,28 +517,19 @@ var WorkflowNodePortsData = class extends EntityData {
526
517
  * 获取所有 port entities
527
518
  */
528
519
  get allPorts() {
529
- if (!this._allPortsCache) {
530
- this._allPortsCache = Array.from(this._portIDSet).map((portId) => this.getPortEntity(portId)).filter(Boolean);
531
- }
532
- return this._allPortsCache;
520
+ return Array.from(this._portIDSet).map((portId) => this.getPortEntity(portId)).filter(Boolean);
533
521
  }
534
522
  /**
535
523
  * 获取输入点位
536
524
  */
537
525
  get inputPorts() {
538
- if (!this._inputPortsCache) {
539
- this._inputPortsCache = this.allPorts.filter((port) => port.portType === "input");
540
- }
541
- return this._inputPortsCache;
526
+ return this.allPorts.filter((port) => port.portType === "input");
542
527
  }
543
528
  /**
544
529
  * 获取输出点位
545
530
  */
546
531
  get outputPorts() {
547
- if (!this._outputPortsCache) {
548
- this._outputPortsCache = this.allPorts.filter((port) => port.portType === "output");
549
- }
550
- return this._outputPortsCache;
532
+ return this.allPorts.filter((port) => port.portType === "output");
551
533
  }
552
534
  /**
553
535
  * 获取输入点位置
@@ -559,7 +541,7 @@ var WorkflowNodePortsData = class extends EntityData {
559
541
  * 获取输出点位置
560
542
  */
561
543
  get outputPoints() {
562
- return this.outputPorts.map((port) => port.point);
544
+ return this.inputPorts.map((port) => port.point);
563
545
  }
564
546
  /**
565
547
  * 根据 key 获取 输入点位置
@@ -588,11 +570,6 @@ var WorkflowNodePortsData = class extends EntityData {
588
570
  getPortId(portType, portKey = "") {
589
571
  return getPortEntityId(this.entity, portType, portKey);
590
572
  }
591
- clearPortsCache() {
592
- this._allPortsCache = void 0;
593
- this._inputPortsCache = void 0;
594
- this._outputPortsCache = void 0;
595
- }
596
573
  /**
597
574
  * 创建 port 实体
598
575
  */
@@ -606,18 +583,10 @@ var WorkflowNodePortsData = class extends EntityData {
606
583
  ...portInfo
607
584
  });
608
585
  }
609
- if (!this._portDisposeIDSet.has(id)) {
610
- this._portDisposeIDSet.add(id);
611
- portEntity.onDispose(() => {
612
- this._portIDSet.delete(id);
613
- this._portDisposeIDSet.delete(id);
614
- this.clearPortsCache();
615
- });
616
- }
617
- if (!this._portIDSet.has(id)) {
618
- this._portIDSet.add(id);
619
- this.clearPortsCache();
620
- }
586
+ portEntity.onDispose(() => {
587
+ this._portIDSet.delete(id);
588
+ });
589
+ this._portIDSet.add(id);
621
590
  return portEntity;
622
591
  }
623
592
  /**
@@ -1479,7 +1448,7 @@ import {
1479
1448
  Point
1480
1449
  } from "@flowgram.ai/utils";
1481
1450
  import { FlowNodeTransformData as FlowNodeTransformData6 } from "@flowgram.ai/document";
1482
- import { FlowNodeBaseType as FlowNodeBaseType4 } from "@flowgram.ai/document";
1451
+ import { FlowNodeBaseType as FlowNodeBaseType3 } from "@flowgram.ai/document";
1483
1452
  import {
1484
1453
  CommandService,
1485
1454
  MouseTouchEvent,
@@ -1489,9 +1458,10 @@ import {
1489
1458
  } from "@flowgram.ai/core";
1490
1459
 
1491
1460
  // src/workflow-lines-manager.ts
1461
+ import { last } from "lodash-es";
1492
1462
  import { inject as inject3, injectable as injectable3 } from "inversify";
1493
1463
  import { DisposableCollection, Emitter as Emitter4 } from "@flowgram.ai/utils";
1494
- import { FlowNodeBaseType as FlowNodeBaseType2, FlowNodeRenderData as FlowNodeRenderData2, FlowNodeTransformData as FlowNodeTransformData3 } from "@flowgram.ai/document";
1464
+ import { FlowNodeRenderData as FlowNodeRenderData2, FlowNodeTransformData as FlowNodeTransformData3 } from "@flowgram.ai/document";
1495
1465
  import { EntityManager as EntityManager2, PlaygroundConfigEntity as PlaygroundConfigEntity2 } from "@flowgram.ai/core";
1496
1466
 
1497
1467
  // src/workflow-document-option.ts
@@ -1570,12 +1540,6 @@ var WorkflowDocumentOptionsDefault = {
1570
1540
  };
1571
1541
 
1572
1542
  // src/workflow-lines-manager.ts
1573
- var NODE_HIT_CELL_SIZE = 512;
1574
- var LINE_HIT_CELL_SIZE = 512;
1575
- var PORT_NODE_BOUNDS_PADDING = 96;
1576
- var NODE_INDEX_MIN_SIZE = 128;
1577
- var LINE_INDEX_MIN_SIZE = 128;
1578
- var MAX_SPATIAL_CELLS_PER_ITEM = 64;
1579
1543
  var WorkflowLinesManager = class {
1580
1544
  constructor() {
1581
1545
  this.toDispose = new DisposableCollection();
@@ -1599,35 +1563,11 @@ var WorkflowLinesManager = class {
1599
1563
  this.isDrawing = false;
1600
1564
  }
1601
1565
  init(doc) {
1602
- if (this.document === doc) {
1603
- return;
1604
- }
1605
1566
  this.document = doc;
1606
- this.toDispose.pushAll([
1607
- this.entityManager.onEntityChange((entityType) => {
1608
- if (entityType === WorkflowNodeEntity.type) {
1609
- this.invalidateNodeHitCaches();
1610
- }
1611
- if (entityType === WorkflowLineEntity.type || entityType === WorkflowPortEntity.type) {
1612
- this.invalidateLineHitCache();
1613
- this.outsidePortNodesCache = void 0;
1614
- }
1615
- }),
1616
- this.entityManager.onEntityDataChange(({ entityDataType }) => {
1617
- if (entityDataType === FlowNodeTransformData3.type) {
1618
- this.invalidateSpatialHitCaches();
1619
- }
1620
- })
1621
- ]);
1622
1567
  }
1623
1568
  forceUpdate() {
1624
1569
  this.onForceUpdateEmitter.fire();
1625
1570
  }
1626
- invalidateSortedNodesCache() {
1627
- this.sortedNodesCache = void 0;
1628
- this.sortedNodesCacheVersion = void 0;
1629
- this.invalidateNodeHitCaches();
1630
- }
1631
1571
  get lineType() {
1632
1572
  return this._lineType;
1633
1573
  }
@@ -1656,7 +1596,6 @@ var WorkflowLinesManager = class {
1656
1596
  }
1657
1597
  if (newType !== this._lineType) {
1658
1598
  this._lineType = newType;
1659
- this.lineSpatialCache = void 0;
1660
1599
  this.getAllLines().forEach((line) => {
1661
1600
  line.getData(WorkflowLineRenderData).update();
1662
1601
  });
@@ -1815,26 +1754,17 @@ var WorkflowLinesManager = class {
1815
1754
  */
1816
1755
  getCloseInLineFromMousePos(mousePos, minDistance = LINE_HOVER_DISTANCE) {
1817
1756
  let targetLine, targetLineDist;
1818
- const lines = this.getLineHitCandidates(mousePos, minDistance);
1819
- for (let i = 0; i < lines.length; i++) {
1820
- const line = lines[i];
1821
- if (!this.isPointInBounds(mousePos, line.bounds, minDistance)) {
1822
- continue;
1823
- }
1757
+ this.getAllLines().forEach((line) => {
1824
1758
  const dist = line.getHoverDist(mousePos);
1825
- if (dist <= minDistance && (targetLineDist === void 0 || targetLineDist >= dist)) {
1759
+ if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {
1826
1760
  targetLineDist = dist;
1827
1761
  targetLine = line;
1828
1762
  }
1829
- }
1763
+ });
1830
1764
  return targetLine;
1831
1765
  }
1832
1766
  dispose() {
1833
1767
  this.portLineMap.clear();
1834
- this.sortedNodeSpatialCache = void 0;
1835
- this.hoverNodeSpatialCache = void 0;
1836
- this.lineSpatialCache = void 0;
1837
- this.outsidePortNodesCache = void 0;
1838
1768
  this.toDispose.dispose();
1839
1769
  }
1840
1770
  get disposed() {
@@ -1949,45 +1879,39 @@ var WorkflowLinesManager = class {
1949
1879
  * @param pos
1950
1880
  */
1951
1881
  getPortFromMousePos(pos, portType) {
1952
- return this.getHoveredPortFromSortedNodes(pos, this.getSortedNodes(), portType);
1953
- }
1954
- getPortsFromMousePos(pos) {
1955
- return this.getHoveredPortsFromSortedNodes(pos, this.getSortedNodes(), void 0, {
1956
- collectBoth: true
1957
- });
1958
- }
1959
- getNodeAndPortFromMousePos(pos, portType) {
1960
- const sortedNodes = this.getSortedNodes();
1961
- const nodeHitInfo = this.getNodeHitInfoFromSortedNodes(
1962
- pos,
1963
- sortedNodes,
1964
- this.selectService.selection
1965
- );
1966
- const ports = this.getHoveredPortsFromSortedNodes(pos, sortedNodes, portType, {
1967
- topCoverNode: nodeHitInfo.topCoverNode
1968
- });
1969
- return {
1970
- node: nodeHitInfo.topNode,
1971
- port: ports.port
1972
- };
1973
- }
1974
- getHoverNodeFromMousePos(pos) {
1975
- const nodes = this.getHoverNodes();
1976
- const candidates = this.getHoverNodeHitCandidates(pos, nodes);
1977
- for (let i = 0; i < candidates.length; i++) {
1978
- const node = candidates[i];
1979
- const { bounds } = node.getData(FlowNodeTransformData3);
1980
- if (this.isPointInBounds(pos, bounds)) {
1981
- return node;
1882
+ const allNodes = this.getSortedNodes().reverse();
1883
+ const allPorts = allNodes.map((node) => {
1884
+ if (!portType) {
1885
+ return node.ports.allPorts;
1886
+ }
1887
+ return portType === "input" ? node.ports.inputPorts : node.ports.outputPorts;
1888
+ }).flat();
1889
+ const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));
1890
+ if (targetPort) {
1891
+ const containNodes = this.getContainNodesFromMousePos(pos);
1892
+ const targetNode = last(containNodes);
1893
+ if (targetNode && targetNode !== targetPort.node) {
1894
+ return;
1982
1895
  }
1983
1896
  }
1897
+ return targetPort;
1984
1898
  }
1985
1899
  /**
1986
1900
  * 根据鼠标位置找到 node
1987
1901
  * @param pos - 鼠标位置
1988
1902
  */
1989
1903
  getNodeFromMousePos(pos) {
1990
- return this.getTopNodeFromSortedNodes(pos, this.getSortedNodes(), this.selectService.selection);
1904
+ const { selection } = this.selectService;
1905
+ const containNodes = this.getContainNodesFromMousePos(pos);
1906
+ if (selection?.length) {
1907
+ const filteredNodes = containNodes.filter(
1908
+ (node) => selection.some((_node) => node.id === _node.id)
1909
+ );
1910
+ if (filteredNodes?.length) {
1911
+ return last(filteredNodes);
1912
+ }
1913
+ }
1914
+ return last(containNodes);
1991
1915
  }
1992
1916
  registerContribution(factory) {
1993
1917
  this.contributionFactories.push(factory);
@@ -1997,352 +1921,19 @@ var WorkflowLinesManager = class {
1997
1921
  line.addData(WorkflowLineRenderData);
1998
1922
  }
1999
1923
  getSortedNodes() {
2000
- const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
2001
- if (this.sortedNodesCache && this.sortedNodesCacheVersion === nodeVersion) {
2002
- return this.sortedNodesCache;
2003
- }
2004
- this.sortedNodesCache = [...this.document.getAllNodes()].sort(
2005
- (a, b) => this.getNodeIndex(a) - this.getNodeIndex(b)
2006
- );
2007
- this.sortedNodesCacheVersion = nodeVersion;
2008
- this.sortedNodeSpatialCache = void 0;
2009
- this.outsidePortNodesCache = void 0;
2010
- return this.sortedNodesCache;
2011
- }
2012
- invalidateNodeHitCaches() {
2013
- this.sortedNodeSpatialCache = void 0;
2014
- this.hoverNodeSpatialCache = void 0;
2015
- this.outsidePortNodesCache = void 0;
2016
- }
2017
- invalidateLineHitCache() {
2018
- this.lineSpatialCache = void 0;
2019
- }
2020
- invalidateSpatialHitCaches() {
2021
- this.invalidateNodeHitCaches();
2022
- this.invalidateLineHitCache();
2023
- }
2024
- getHoveredPortFromSortedNodes(pos, sortedNodes, portType) {
2025
- return this.getHoveredPortsFromSortedNodes(pos, sortedNodes, portType).port;
2026
- }
2027
- getHoveredPortsFromSortedNodes(pos, sortedNodes, portType, options = {}) {
2028
- let inputPort;
2029
- let outputPort;
2030
- let anyPort;
2031
- const { collectBoth = false } = options;
2032
- const needInput = !portType || portType === "input";
2033
- const needOutput = !portType || portType === "output";
2034
- const needAny = !portType && !collectBoth;
2035
- const candidates = this.getSortedNodeHitCandidates(pos, sortedNodes, PORT_NODE_BOUNDS_PADDING);
2036
- const checkedNodes = candidates.length === sortedNodes.length ? void 0 : new Set(candidates);
2037
- for (let i = candidates.length - 1; i >= 0; i--) {
2038
- const node = candidates[i];
2039
- if (!this.isPointNearNodePorts(pos, node)) {
2040
- continue;
2041
- }
2042
- const result = this.collectHoveredPorts(node.ports.allPorts, pos, {
2043
- needInput,
2044
- needOutput,
2045
- needAny,
2046
- inputPort,
2047
- outputPort,
2048
- anyPort
2049
- });
2050
- inputPort = result.inputPort;
2051
- outputPort = result.outputPort;
2052
- anyPort = result.anyPort;
2053
- if (portType === "input" && inputPort || portType === "output" && outputPort || !portType && (collectBoth ? inputPort && outputPort : anyPort)) {
2054
- break;
2055
- }
2056
- }
2057
- if (checkedNodes && !(portType === "input" && inputPort || portType === "output" && outputPort || !portType && (collectBoth ? inputPort && outputPort : anyPort))) {
2058
- const outsidePortNodes = this.getOutsidePortNodes(sortedNodes);
2059
- for (let i = outsidePortNodes.length - 1; i >= 0; i--) {
2060
- const node = outsidePortNodes[i];
2061
- if (checkedNodes.has(node)) {
2062
- continue;
2063
- }
2064
- const result = this.collectHoveredPorts(node.ports.allPorts, pos, {
2065
- needInput,
2066
- needOutput,
2067
- needAny,
2068
- inputPort,
2069
- outputPort,
2070
- anyPort
2071
- });
2072
- inputPort = result.inputPort;
2073
- outputPort = result.outputPort;
2074
- anyPort = result.anyPort;
2075
- if (portType === "input" && inputPort || portType === "output" && outputPort || !portType && (collectBoth ? inputPort && outputPort : anyPort)) {
2076
- break;
2077
- }
2078
- }
2079
- }
2080
- const needCoverCheck = inputPort || outputPort || anyPort;
2081
- const topCoverNode = needCoverCheck ? options.topCoverNode || this.getNodeHitInfoFromSortedNodes(pos, sortedNodes).topCoverNode : void 0;
2082
- inputPort = this.filterCoveredPort(inputPort, topCoverNode);
2083
- outputPort = this.filterCoveredPort(outputPort, topCoverNode);
2084
- anyPort = this.filterCoveredPort(anyPort, topCoverNode);
2085
- return {
2086
- input: inputPort,
2087
- output: outputPort,
2088
- port: portType === "input" ? inputPort : portType === "output" ? outputPort : anyPort
2089
- };
1924
+ return this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
2090
1925
  }
2091
- collectHoveredPorts(ports, pos, options) {
2092
- let { inputPort, outputPort, anyPort } = options;
2093
- for (let i = 0; i < ports.length; i++) {
2094
- const port = ports[i];
2095
- if ((!options.needAny || anyPort) && (!options.needInput || inputPort) && (!options.needOutput || outputPort)) {
2096
- break;
2097
- }
2098
- if (port.isHovered(pos.x, pos.y)) {
2099
- if (!anyPort && options.needAny) {
2100
- anyPort = port;
2101
- }
2102
- if (!inputPort && options.needInput && port.portType === "input") {
2103
- inputPort = port;
2104
- }
2105
- if (!outputPort && options.needOutput && port.portType === "output") {
2106
- outputPort = port;
2107
- }
2108
- }
2109
- }
2110
- return {
2111
- inputPort,
2112
- outputPort,
2113
- anyPort
2114
- };
2115
- }
2116
- filterCoveredPort(port, topCoverNode) {
2117
- if (port && topCoverNode && topCoverNode !== port.node) {
2118
- return void 0;
2119
- }
2120
- return port;
2121
- }
2122
- getTopNodeFromSortedNodes(pos, sortedNodes, selection) {
2123
- return this.getNodeHitInfoFromSortedNodes(pos, sortedNodes, selection).topNode;
2124
- }
2125
- getNodeHitInfoFromSortedNodes(pos, sortedNodes, selection) {
1926
+ /** 获取鼠标坐标位置的所有节点(stackIndex 从小到大排序) */
1927
+ getContainNodesFromMousePos(pos) {
1928
+ const allNodes = this.getSortedNodes();
2126
1929
  const zoom = this.entityManager.getEntity(PlaygroundConfigEntity2)?.config?.zoom || 1;
2127
- const padding = 4 / zoom;
2128
- const selectedIDs = selection?.length ? new Set(selection.map((node) => node.id)) : void 0;
2129
- const candidates = this.getSortedNodeHitCandidates(pos, sortedNodes, padding);
2130
- let topCoverNode;
2131
- for (let i = candidates.length - 1; i >= 0; i--) {
2132
- const node = candidates[i];
1930
+ const containNodes = allNodes.map((node) => {
2133
1931
  const { bounds } = node.getData(FlowNodeTransformData3);
2134
- if (!this.isPointInBounds(pos, bounds, padding)) {
2135
- continue;
2136
- }
2137
- if (!topCoverNode) {
2138
- topCoverNode = node;
2139
- }
2140
- if (!selectedIDs) {
2141
- return {
2142
- topCoverNode,
2143
- topNode: node
2144
- };
2145
- }
2146
- if (selectedIDs.has(node.id)) {
2147
- return {
2148
- topCoverNode,
2149
- topNode: node
2150
- };
2151
- }
2152
- }
2153
- return {
2154
- topCoverNode,
2155
- topNode: topCoverNode
2156
- };
2157
- }
2158
- getHoverNodeHitCandidates(pos, nodes) {
2159
- if (nodes.length < NODE_INDEX_MIN_SIZE) {
2160
- return nodes;
2161
- }
2162
- const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
2163
- const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
2164
- const activatedID = this.selectService.activatedNode?.id;
2165
- if (!this.hoverNodeSpatialCache || this.hoverNodeSpatialCache.nodeVersion !== nodeVersion || this.hoverNodeSpatialCache.transformVersion !== transformVersion || this.hoverNodeSpatialCache.activatedID !== activatedID || this.hoverNodeSpatialCache.nodes !== nodes) {
2166
- this.hoverNodeSpatialCache = {
2167
- nodeVersion,
2168
- transformVersion,
2169
- activatedID,
2170
- nodes,
2171
- index: this.createSpatialIndex(
2172
- nodes,
2173
- (node) => node.getData(FlowNodeTransformData3).bounds,
2174
- NODE_HIT_CELL_SIZE
2175
- )
2176
- };
2177
- }
2178
- return this.querySpatialIndex(this.hoverNodeSpatialCache.index, pos);
2179
- }
2180
- getSortedNodeHitCandidates(pos, sortedNodes, padding = 0) {
2181
- if (sortedNodes.length < NODE_INDEX_MIN_SIZE) {
2182
- return sortedNodes;
2183
- }
2184
- const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
2185
- const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
2186
- if (!this.sortedNodeSpatialCache || this.sortedNodeSpatialCache.nodeVersion !== nodeVersion || this.sortedNodeSpatialCache.transformVersion !== transformVersion || this.sortedNodeSpatialCache.nodes !== sortedNodes) {
2187
- this.sortedNodeSpatialCache = {
2188
- nodeVersion,
2189
- transformVersion,
2190
- nodes: sortedNodes,
2191
- index: this.createSpatialIndex(
2192
- sortedNodes,
2193
- (node) => node.getData(FlowNodeTransformData3).bounds,
2194
- NODE_HIT_CELL_SIZE
2195
- )
2196
- };
2197
- }
2198
- return this.querySpatialIndex(this.sortedNodeSpatialCache.index, pos, padding);
2199
- }
2200
- getLineHitCandidates(pos, padding) {
2201
- const lines = this.getAllLines();
2202
- if (lines.length < LINE_INDEX_MIN_SIZE) {
2203
- return lines;
2204
- }
2205
- const lineVersion = this.entityManager.getEntityVersion(WorkflowLineEntity);
2206
- const portVersion = this.entityManager.getEntityVersion(WorkflowPortEntity);
2207
- const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
2208
- if (!this.lineSpatialCache || this.lineSpatialCache.lineVersion !== lineVersion || this.lineSpatialCache.portVersion !== portVersion || this.lineSpatialCache.transformVersion !== transformVersion) {
2209
- this.lineSpatialCache = {
2210
- lineVersion,
2211
- portVersion,
2212
- transformVersion,
2213
- index: this.createSpatialIndex(lines, (line) => line.bounds, LINE_HIT_CELL_SIZE)
2214
- };
2215
- }
2216
- return this.querySpatialIndex(this.lineSpatialCache.index, pos, padding);
2217
- }
2218
- createSpatialIndex(items, getBounds, cellSize) {
2219
- const index = {
2220
- cellSize,
2221
- cells: /* @__PURE__ */ new Map(),
2222
- overflowItems: [],
2223
- order: /* @__PURE__ */ new Map()
2224
- };
2225
- items.forEach((item, itemIndex) => {
2226
- index.order.set(item, itemIndex);
2227
- const bounds = getBounds(item);
2228
- if (!this.canIndexBounds(bounds)) {
2229
- index.overflowItems.push(item);
2230
- return;
2231
- }
2232
- const minCellX = this.getSpatialCell(bounds.x, cellSize);
2233
- const maxCellX = this.getSpatialCell(bounds.right, cellSize);
2234
- const minCellY = this.getSpatialCell(bounds.y, cellSize);
2235
- const maxCellY = this.getSpatialCell(bounds.bottom, cellSize);
2236
- const cellCount = (maxCellX - minCellX + 1) * (maxCellY - minCellY + 1);
2237
- if (cellCount > MAX_SPATIAL_CELLS_PER_ITEM) {
2238
- index.overflowItems.push(item);
2239
- return;
2240
- }
2241
- for (let x = minCellX; x <= maxCellX; x++) {
2242
- for (let y = minCellY; y <= maxCellY; y++) {
2243
- const key = this.getSpatialCellKey(x, y);
2244
- let cellItems = index.cells.get(key);
2245
- if (!cellItems) {
2246
- cellItems = [];
2247
- index.cells.set(key, cellItems);
2248
- }
2249
- cellItems.push(item);
2250
- }
2251
- }
2252
- });
2253
- return index;
2254
- }
2255
- querySpatialIndex(index, pos, padding = 0) {
2256
- const minCellX = this.getSpatialCell(pos.x - padding, index.cellSize);
2257
- const maxCellX = this.getSpatialCell(pos.x + padding, index.cellSize);
2258
- const minCellY = this.getSpatialCell(pos.y - padding, index.cellSize);
2259
- const maxCellY = this.getSpatialCell(pos.y + padding, index.cellSize);
2260
- const candidates = [];
2261
- const candidateSet = /* @__PURE__ */ new Set();
2262
- const pushCandidate = (item) => {
2263
- if (candidateSet.has(item)) {
2264
- return;
2265
- }
2266
- candidateSet.add(item);
2267
- candidates.push(item);
2268
- };
2269
- for (let x = minCellX; x <= maxCellX; x++) {
2270
- for (let y = minCellY; y <= maxCellY; y++) {
2271
- const cellItems = index.cells.get(this.getSpatialCellKey(x, y));
2272
- if (cellItems) {
2273
- cellItems.forEach(pushCandidate);
2274
- }
2275
- }
2276
- }
2277
- index.overflowItems.forEach(pushCandidate);
2278
- return candidates.sort((a, b) => (index.order.get(a) ?? 0) - (index.order.get(b) ?? 0));
2279
- }
2280
- getSpatialCell(value, cellSize) {
2281
- return Math.floor(value / cellSize);
2282
- }
2283
- getSpatialCellKey(x, y) {
2284
- return `${x}:${y}`;
2285
- }
2286
- canIndexBounds(bounds) {
2287
- return Number.isFinite(bounds.x) && Number.isFinite(bounds.y) && Number.isFinite(bounds.width) && Number.isFinite(bounds.height) && bounds.width > 0 && bounds.height > 0;
2288
- }
2289
- isPointNearNodePorts(pos, node) {
2290
- const { bounds } = node.getData(FlowNodeTransformData3);
2291
- return this.isPointInBounds(pos, bounds, PORT_NODE_BOUNDS_PADDING);
2292
- }
2293
- hasPortOutsideNodeBounds(node) {
2294
- const { bounds } = node.getData(FlowNodeTransformData3);
2295
- return node.ports.allPorts.some((port) => {
2296
- if (port.targetElement) {
2297
- return true;
2298
- }
2299
- return !this.isPointInBounds(port.point, bounds, PORT_NODE_BOUNDS_PADDING);
2300
- });
2301
- }
2302
- getOutsidePortNodes(sortedNodes) {
2303
- const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
2304
- const portVersion = this.entityManager.getEntityVersion(WorkflowPortEntity);
2305
- const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
2306
- if (this.outsidePortNodesCache && this.outsidePortNodesCache.nodeVersion === nodeVersion && this.outsidePortNodesCache.portVersion === portVersion && this.outsidePortNodesCache.transformVersion === transformVersion && this.outsidePortNodesCache.sortedNodes === sortedNodes) {
2307
- return this.outsidePortNodesCache.outsideNodes;
2308
- }
2309
- const outsideNodes = sortedNodes.filter((node) => this.hasPortOutsideNodeBounds(node));
2310
- this.outsidePortNodesCache = {
2311
- nodeVersion,
2312
- portVersion,
2313
- transformVersion,
2314
- sortedNodes,
2315
- outsideNodes
2316
- };
2317
- return outsideNodes;
2318
- }
2319
- getHoverNodes() {
2320
- const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
2321
- const activatedID = this.selectService.activatedNode?.id;
2322
- if (this.hoverNodesCache && this.hoverNodesCacheVersion === nodeVersion && this.hoverNodesCacheActivatedID === activatedID) {
2323
- return this.hoverNodesCache;
2324
- }
2325
- const nodes = this.document.getAllNodes().filter(
2326
- (node) => node.id !== "root" && node.flowNodeType !== FlowNodeBaseType2.ROOT && node.flowNodeType !== FlowNodeBaseType2.GROUP
2327
- ).reverse();
2328
- if (activatedID) {
2329
- const activatedIndex = nodes.findIndex((node) => node.id === activatedID);
2330
- if (activatedIndex > 0) {
2331
- const [activatedNode] = nodes.splice(activatedIndex, 1);
2332
- nodes.unshift(activatedNode);
1932
+ if (bounds.clone().pad(4 / zoom).contains(pos.x, pos.y)) {
1933
+ return node;
2333
1934
  }
2334
- }
2335
- this.hoverNodesCache = nodes;
2336
- this.hoverNodesCacheVersion = nodeVersion;
2337
- this.hoverNodesCacheActivatedID = activatedID;
2338
- this.hoverNodeSpatialCache = void 0;
2339
- return this.hoverNodesCache;
2340
- }
2341
- isPointInBounds(pos, bounds, padding = 0) {
2342
- if (bounds.width + padding * 2 <= 0 || bounds.height + padding * 2 <= 0) {
2343
- return false;
2344
- }
2345
- return pos.x >= bounds.x - padding && pos.x <= bounds.right + padding && pos.y >= bounds.y - padding && pos.y <= bounds.bottom + padding;
1935
+ }).filter(Boolean);
1936
+ return containNodes;
2346
1937
  }
2347
1938
  getNodeIndex(node) {
2348
1939
  const nodeRenderData = node.getData(FlowNodeRenderData2);
@@ -2372,7 +1963,7 @@ import { Emitter as Emitter5 } from "@flowgram.ai/utils";
2372
1963
  import { NodeEngineContext } from "@flowgram.ai/form-core";
2373
1964
  import {
2374
1965
  FlowDocument,
2375
- FlowNodeBaseType as FlowNodeBaseType3,
1966
+ FlowNodeBaseType as FlowNodeBaseType2,
2376
1967
  FlowNodeTransformData as FlowNodeTransformData5
2377
1968
  } from "@flowgram.ai/document";
2378
1969
  import {
@@ -2686,7 +2277,7 @@ var WorkflowDocument = class extends FlowDocument {
2686
2277
  toJSON: () => this.toNodeJSON(node)
2687
2278
  });
2688
2279
  node.onDispose(() => {
2689
- if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType3.ROOT) {
2280
+ if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType2.ROOT) {
2690
2281
  return;
2691
2282
  }
2692
2283
  const parentTransform = node.parent.getData(FlowNodeTransformData5);
@@ -2857,13 +2448,13 @@ var WorkflowDocument = class extends FlowDocument {
2857
2448
  );
2858
2449
  }
2859
2450
  getAllNodes() {
2860
- return this.entityManager.getEntities(WorkflowNodeEntity).filter((n) => n.id !== FlowNodeBaseType3.ROOT);
2451
+ return this.entityManager.getEntities(WorkflowNodeEntity).filter((n) => n.id !== FlowNodeBaseType2.ROOT);
2861
2452
  }
2862
2453
  getAllEdges() {
2863
2454
  return this.entityManager.getEntities(WorkflowLineEntity);
2864
2455
  }
2865
2456
  getAllPorts() {
2866
- return this.entityManager.getEntities(WorkflowPortEntity).filter((p) => p.node.id !== FlowNodeBaseType3.ROOT);
2457
+ return this.entityManager.getEntities(WorkflowPortEntity).filter((p) => p.node.id !== FlowNodeBaseType2.ROOT);
2867
2458
  }
2868
2459
  /**
2869
2460
  * 获取画布中的非游离节点
@@ -3075,7 +2666,7 @@ var WorkflowDocument = class extends FlowDocument {
3075
2666
  return subCanvas;
3076
2667
  }
3077
2668
  getNodeChildren(node) {
3078
- if (!node || node.flowNodeType === FlowNodeBaseType3.GROUP) return [];
2669
+ if (!node || node.flowNodeType === FlowNodeBaseType2.GROUP) return [];
3079
2670
  const subCanvas = this.getNodeSubCanvas(node);
3080
2671
  const realChildren = subCanvas ? subCanvas.canvasNode.blocks : node.blocks;
3081
2672
  const childrenWithoutSubCanvas = realChildren.filter((child) => {
@@ -3083,7 +2674,7 @@ var WorkflowDocument = class extends FlowDocument {
3083
2674
  return !childMeta.subCanvas?.(node)?.isCanvas;
3084
2675
  }).filter(Boolean);
3085
2676
  const children = childrenWithoutSubCanvas.map((child) => {
3086
- if (child.flowNodeType === FlowNodeBaseType3.GROUP) {
2677
+ if (child.flowNodeType === FlowNodeBaseType2.GROUP) {
3087
2678
  return [child, ...child.blocks];
3088
2679
  }
3089
2680
  return child;
@@ -3402,7 +2993,7 @@ var WorkflowDragService = class {
3402
2993
  if (!mousePos) {
3403
2994
  return { x: 0, y: 0 };
3404
2995
  }
3405
- if (!subNodeType || !containerNode || containerNode.flowNodeType === FlowNodeBaseType4.ROOT) {
2996
+ if (!subNodeType || !containerNode || containerNode.flowNodeType === FlowNodeBaseType3.ROOT) {
3406
2997
  return mousePos;
3407
2998
  }
3408
2999
  const isParentEmpty = !containerNode.children || containerNode.children.length === 0;
@@ -3615,7 +3206,7 @@ var WorkflowDragService = class {
3615
3206
  return;
3616
3207
  }
3617
3208
  const sourceContainer = nodes[0]?.parent;
3618
- if (!sourceContainer || sourceContainer.flowNodeType === FlowNodeBaseType4.ROOT) {
3209
+ if (!sourceContainer || sourceContainer.flowNodeType === FlowNodeBaseType3.ROOT) {
3619
3210
  return;
3620
3211
  }
3621
3212
  const valid = nodes.every((node) => node?.parent === sourceContainer);
@@ -3760,15 +3351,15 @@ var WorkflowDragService = class {
3760
3351
  }
3761
3352
  updateDrawingLine(isDrawingTo, line, dragPos, originLine) {
3762
3353
  let hasError = false;
3354
+ const mouseNode = this.linesManager.getNodeFromMousePos(dragPos);
3763
3355
  let toNode;
3764
3356
  let toPort;
3765
3357
  let fromPort;
3766
3358
  let fromNode;
3767
3359
  if (isDrawingTo) {
3768
- const mouseHitInfo = this.linesManager.getNodeAndPortFromMousePos(dragPos, "input");
3769
3360
  fromPort = line.fromPort;
3770
- toNode = mouseHitInfo.node;
3771
- toPort = mouseHitInfo.port;
3361
+ toNode = mouseNode;
3362
+ toPort = this.linesManager.getPortFromMousePos(dragPos, "input");
3772
3363
  if (toNode && this.canBuildContainerLine(toNode, dragPos)) {
3773
3364
  toPort = this.getNearestPort(toNode, dragPos, "input");
3774
3365
  hasError = this.checkDraggingPort(isDrawingTo, line, toNode, toPort, originLine).hasError;
@@ -3795,10 +3386,9 @@ var WorkflowDragService = class {
3795
3386
  };
3796
3387
  }
3797
3388
  } else {
3798
- const mouseHitInfo = this.linesManager.getNodeAndPortFromMousePos(dragPos, "output");
3799
3389
  toPort = line.toPort;
3800
- fromNode = mouseHitInfo.node;
3801
- fromPort = mouseHitInfo.port;
3390
+ fromNode = mouseNode;
3391
+ fromPort = this.linesManager.getPortFromMousePos(dragPos, "output");
3802
3392
  if (fromNode && this.canBuildContainerLine(fromNode, dragPos)) {
3803
3393
  fromPort = this.getNearestPort(fromNode, dragPos, "output");
3804
3394
  hasError = this.checkDraggingPort(