Merge pull request #4158 from xyflow/fix/intersection-helper-positions

Fix/intersection helper positions
This commit is contained in:
Moritz Klack
2024-04-15 13:20:47 +02:00
committed by GitHub
3 changed files with 68 additions and 5 deletions
+6
View File
@@ -1,5 +1,11 @@
# @xyflow/react
## 12.0.0-next.xx
## Patch changes
- use correct positions for intersection helpers
## 12.0.0-next.14
## Patch changes
+16 -5
View File
@@ -1,5 +1,12 @@
import { useCallback, useMemo, useRef, useState } from 'react';
import { getElementsToRemove, getOverlappingArea, isRectObject, nodeToRect, type Rect } from '@xyflow/system';
import {
evaluateNodePosition,
getElementsToRemove,
getOverlappingArea,
isRectObject,
nodeToRect,
type Rect,
} from '@xyflow/system';
import useViewportHelper from './useViewportHelper';
import { useStoreApi } from './useStore';
@@ -223,15 +230,19 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
[]
);
const getNodeRect = useCallback(({ id }: { id: string }): Rect | null => {
const internalNode = store.getState().nodeLookup.get(id);
return internalNode ? nodeToRect(internalNode) : null;
const getNodeRect = useCallback((node: NodeType | { id: string }): Rect | null => {
const { nodeLookup, nodeOrigin } = store.getState();
const nodeToUse = isNode(node) ? node : nodeLookup.get(node.id)!;
const nodeWithPos = evaluateNodePosition(nodeToUse, nodeLookup, nodeOrigin);
return nodeWithPos ? nodeToRect(nodeWithPos) : null;
}, []);
const getIntersectingNodes = useCallback<Instance.GetIntersectingNodes<NodeType>>(
(nodeOrRect, partially = true, nodes) => {
const isRect = isRectObject(nodeOrRect);
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
const hasNodesOption = nodes !== undefined;
if (!nodeRect) {
return [];
@@ -244,7 +255,7 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
return false;
}
const currNodeRect = nodeToRect(n);
const currNodeRect = nodeToRect(hasNodesOption ? n : internalNode!);
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
const partiallyVisible = partially && overlappingArea > 0;
+46
View File
@@ -9,6 +9,7 @@ import type {
SnapGrid,
Transform,
InternalNodeBase,
NodeLookup,
} from '../types';
import { type Viewport } from '../types';
import { getNodePositionWithOrigin } from './graph';
@@ -219,3 +220,48 @@ export function nodeHasDimensions<NodeType extends NodeBase = NodeBase>(node: No
(node.measured?.height ?? node.height ?? node.initialHeight) !== undefined
);
}
/**
* Helper to calculate the absolute position of a node
*
* @internal
* @param node
* @param nodeLookup
* @param nodeOrigin
* @returns an internal node with an absolute position
*/
export function evaluateNodePosition(
node: NodeBase | InternalNodeBase,
nodeLookup: NodeLookup,
nodeOrigin: NodeOrigin = [0, 0]
): InternalNodeBase | null {
const internalNode = nodeLookup.get(node.id);
if (!internalNode) {
return null;
}
let parentId = internalNode.parentId;
const positionAbsolute = { ...node.position };
while (parentId) {
const parent = nodeLookup.get(parentId);
parentId = parent?.parentId;
if (parent) {
const origin = parent.origin || nodeOrigin;
const xOffset = (parent.measured.width ?? 0) * origin[0];
const yOffset = (parent.measured.height ?? 0) * origin[1];
positionAbsolute.x += parent.position.x - xOffset;
positionAbsolute.y += parent.position.y - yOffset;
}
}
return {
...internalNode,
internals: {
...internalNode.internals,
positionAbsolute,
},
};
}