fix(getNodesBounds): use absolute position by default, add options param

This commit is contained in:
moklick
2024-01-25 17:46:46 +01:00
parent e352f3cdc4
commit 19bcfe28a2
11 changed files with 33 additions and 18 deletions

View File

@@ -8,6 +8,7 @@
- fix `OnNodeDrag` type
- do not use fallback handle if a specific id is being used
- fix `defaultEdgeOptions` markers not being applied
- fix `getNodesBounds` and add second param for passing options
## 12.0.0-next.7

View File

@@ -25,7 +25,8 @@ const selector = (s: ReactFlowState) => {
return {
viewBB,
boundingRect: s.nodes.length > 0 ? getBoundsOfRects(getNodesBounds(s.nodes, s.nodeOrigin), viewBB) : viewBB,
boundingRect:
s.nodes.length > 0 ? getBoundsOfRects(getNodesBounds(s.nodes, { nodeOrigin: s.nodeOrigin }), viewBB) : viewBB,
rfId: s.rfId,
nodeOrigin: s.nodeOrigin,
panZoom: s.panZoom,

View File

@@ -73,7 +73,7 @@ export function NodeToolbar({
return null;
}
const nodeRect: Rect = getNodesBounds(nodes, nodeOrigin);
const nodeRect: Rect = getNodesBounds(nodes, { nodeOrigin });
const zIndex: number = Math.max(...nodes.map((node) => (node[internalsSymbol]?.z || 1) + 1));
const wrapperStyle: CSSProperties = {

View File

@@ -22,7 +22,7 @@ export type NodesSelectionProps = {
const selector = (s: ReactFlowState) => {
const selectedNodes = s.nodes.filter((n) => n.selected);
const { width, height, x, y } = getNodesBounds(selectedNodes, s.nodeOrigin);
const { width, height, x, y } = getNodesBounds(selectedNodes, { nodeOrigin: s.nodeOrigin });
return {
width,

View File

@@ -38,7 +38,8 @@ const getInitialState = ({
if (fitView && width && height) {
const nodesWithDimensions = nextNodes.filter((node) => node.width && node.height);
const bounds = getNodesBounds(nodesWithDimensions, [0, 0]);
// @todo users nodeOrigin should be used here
const bounds = getNodesBounds(nodesWithDimensions, { nodeOrigin: [0, 0] });
const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
transform = [x, y, zoom];
}

View File

@@ -13,6 +13,7 @@
- Edge label has a default background and is clickable
- do not use fallback handle if a specific id is being used
- use correct id for `<Handle />` data-id attribute
- fix `getNodesBounds` and add second param for passing options
## 0.0.34

View File

@@ -58,7 +58,7 @@
height: toolbarNode.computed?.height ?? toolbarNode.height ?? 0
};
} else if (toolbarNodes.length > 1) {
nodeRect = getNodesBounds(toolbarNodes, $nodeOrigin);
nodeRect = getNodesBounds(toolbarNodes, { nodeOrigin: $nodeOrigin });
}
if (nodeRect) {

View File

@@ -92,7 +92,8 @@ export const getInitialStore = ({
if (fitView && width && height) {
const nodesWithDimensions = nextNodes.filter((node) => node.width && node.height);
const bounds = getNodesBounds(nodesWithDimensions, [0, 0]);
// @todo users nodeOrigin should be used here
const bounds = getNodesBounds(nodesWithDimensions, { nodeOrigin: [0, 0] });
viewport = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
}

View File

@@ -102,11 +102,13 @@ export const getIncomers = <NodeType extends NodeBase = NodeBase, EdgeType exten
export const getNodePositionWithOrigin = (
node: NodeBase | undefined,
nodeOrigin: NodeOrigin = [0, 0]
): XYPosition & { positionAbsolute: XYPosition } => {
): { position: XYPosition; positionAbsolute: XYPosition } => {
if (!node) {
return {
x: 0,
y: 0,
position: {
x: 0,
y: 0,
},
positionAbsolute: {
x: 0,
y: 0,
@@ -123,7 +125,7 @@ export const getNodePositionWithOrigin = (
};
return {
...position,
position,
positionAbsolute: node.computed?.positionAbsolute
? {
x: node.computed.positionAbsolute.x - offsetX,
@@ -133,27 +135,35 @@ export const getNodePositionWithOrigin = (
};
};
export type GetNodesBoundsParams = {
nodeOrigin?: NodeOrigin;
useRelativePosition?: boolean;
};
/**
* Determines a bounding box that contains all given nodes in an array
* @public
* @remarks Useful when combined with {@link getViewportForBounds} to calculate the correct transform to fit the given nodes in a viewport.
* @param nodes - Nodes to calculate the bounds for
* @param nodeOrigin - Origin of the nodes: [0, 0] - top left, [0.5, 0.5] - center
* @param params.nodeOrigin - Origin of the nodes: [0, 0] - top left, [0.5, 0.5] - center
* @param params.useRelativePosition - Whether to use the relative or absolute node positions
* @returns Bounding box enclosing all nodes
*/
export const getNodesBounds = (nodes: NodeBase[], nodeOrigin: NodeOrigin = [0, 0]): Rect => {
export const getNodesBounds = (
nodes: NodeBase[],
params: GetNodesBoundsParams = { nodeOrigin: [0, 0], useRelativePosition: false }
): Rect => {
if (nodes.length === 0) {
return { x: 0, y: 0, width: 0, height: 0 };
}
const box = nodes.reduce(
(currBox, node) => {
const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
const nodePos = getNodePositionWithOrigin(node, node.origin || params.nodeOrigin);
return getBoundsOfBoxes(
currBox,
rectToBox({
x,
y,
...nodePos[params.useRelativePosition ? 'position' : 'positionAbsolute'],
width: node.computed?.width ?? node.width ?? 0,
height: node.computed?.height ?? node.height ?? 0,
})
@@ -239,7 +249,7 @@ export function fitView<Params extends FitViewParamsBase<NodeBase>, Options exte
});
if (filteredNodes.length > 0) {
const bounds = getNodesBounds(filteredNodes, nodeOrigin);
const bounds = getNodesBounds(filteredNodes, { nodeOrigin });
const viewport = getViewportForBounds(
bounds,

View File

@@ -136,7 +136,7 @@ function calculateXYZPosition<NodeType extends NodeBase>(
}
const parentNode = nodeLookup.get(node.parentNode)!;
const parentNodePosition = getNodePositionWithOrigin(parentNode, parentNode?.origin || nodeOrigin);
const { position: parentNodePosition } = getNodePositionWithOrigin(parentNode, parentNode?.origin || nodeOrigin);
return calculateXYZPosition(
parentNode,

View File

@@ -120,7 +120,7 @@ export function XYDrag<OnNodeDrag extends (e: any, nodes: any, node: any) => voi
let nodesBox: Box = { x: 0, y: 0, x2: 0, y2: 0 };
if (dragItems.length > 1 && nodeExtent) {
const rect = getNodesBounds(dragItems as unknown as NodeBase[], nodeOrigin);
const rect = getNodesBounds(dragItems as unknown as NodeBase[], { nodeOrigin });
nodesBox = rectToBox(rect);
}