Merge pull request #4158 from xyflow/fix/intersection-helper-positions
Fix/intersection helper positions
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# @xyflow/react
|
# @xyflow/react
|
||||||
|
|
||||||
|
## 12.0.0-next.xx
|
||||||
|
|
||||||
|
## Patch changes
|
||||||
|
|
||||||
|
- use correct positions for intersection helpers
|
||||||
|
|
||||||
## 12.0.0-next.14
|
## 12.0.0-next.14
|
||||||
|
|
||||||
## Patch changes
|
## Patch changes
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
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 useViewportHelper from './useViewportHelper';
|
||||||
import { useStoreApi } from './useStore';
|
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 getNodeRect = useCallback((node: NodeType | { id: string }): Rect | null => {
|
||||||
const internalNode = store.getState().nodeLookup.get(id);
|
const { nodeLookup, nodeOrigin } = store.getState();
|
||||||
return internalNode ? nodeToRect(internalNode) : null;
|
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>>(
|
const getIntersectingNodes = useCallback<Instance.GetIntersectingNodes<NodeType>>(
|
||||||
(nodeOrRect, partially = true, nodes) => {
|
(nodeOrRect, partially = true, nodes) => {
|
||||||
const isRect = isRectObject(nodeOrRect);
|
const isRect = isRectObject(nodeOrRect);
|
||||||
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
||||||
|
const hasNodesOption = nodes !== undefined;
|
||||||
|
|
||||||
if (!nodeRect) {
|
if (!nodeRect) {
|
||||||
return [];
|
return [];
|
||||||
@@ -244,7 +255,7 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currNodeRect = nodeToRect(n);
|
const currNodeRect = nodeToRect(hasNodesOption ? n : internalNode!);
|
||||||
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
||||||
const partiallyVisible = partially && overlappingArea > 0;
|
const partiallyVisible = partially && overlappingArea > 0;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import type {
|
|||||||
SnapGrid,
|
SnapGrid,
|
||||||
Transform,
|
Transform,
|
||||||
InternalNodeBase,
|
InternalNodeBase,
|
||||||
|
NodeLookup,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { type Viewport } from '../types';
|
import { type Viewport } from '../types';
|
||||||
import { getNodePositionWithOrigin } from './graph';
|
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
|
(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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user