fix(getNodesBounds): use absolute position by default, add options param
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
- fix `OnNodeDrag` type
|
- fix `OnNodeDrag` type
|
||||||
- do not use fallback handle if a specific id is being used
|
- do not use fallback handle if a specific id is being used
|
||||||
- fix `defaultEdgeOptions` markers not being applied
|
- fix `defaultEdgeOptions` markers not being applied
|
||||||
|
- fix `getNodesBounds` and add second param for passing options
|
||||||
|
|
||||||
## 12.0.0-next.7
|
## 12.0.0-next.7
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ const selector = (s: ReactFlowState) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
viewBB,
|
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,
|
rfId: s.rfId,
|
||||||
nodeOrigin: s.nodeOrigin,
|
nodeOrigin: s.nodeOrigin,
|
||||||
panZoom: s.panZoom,
|
panZoom: s.panZoom,
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export function NodeToolbar({
|
|||||||
return null;
|
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 zIndex: number = Math.max(...nodes.map((node) => (node[internalsSymbol]?.z || 1) + 1));
|
||||||
|
|
||||||
const wrapperStyle: CSSProperties = {
|
const wrapperStyle: CSSProperties = {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export type NodesSelectionProps = {
|
|||||||
|
|
||||||
const selector = (s: ReactFlowState) => {
|
const selector = (s: ReactFlowState) => {
|
||||||
const selectedNodes = s.nodes.filter((n) => n.selected);
|
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 {
|
return {
|
||||||
width,
|
width,
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ const getInitialState = ({
|
|||||||
|
|
||||||
if (fitView && width && height) {
|
if (fitView && width && height) {
|
||||||
const nodesWithDimensions = nextNodes.filter((node) => node.width && node.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);
|
const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
||||||
transform = [x, y, zoom];
|
transform = [x, y, zoom];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
- Edge label has a default background and is clickable
|
- Edge label has a default background and is clickable
|
||||||
- do not use fallback handle if a specific id is being used
|
- do not use fallback handle if a specific id is being used
|
||||||
- use correct id for `<Handle />` data-id attribute
|
- use correct id for `<Handle />` data-id attribute
|
||||||
|
- fix `getNodesBounds` and add second param for passing options
|
||||||
|
|
||||||
## 0.0.34
|
## 0.0.34
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
height: toolbarNode.computed?.height ?? toolbarNode.height ?? 0
|
height: toolbarNode.computed?.height ?? toolbarNode.height ?? 0
|
||||||
};
|
};
|
||||||
} else if (toolbarNodes.length > 1) {
|
} else if (toolbarNodes.length > 1) {
|
||||||
nodeRect = getNodesBounds(toolbarNodes, $nodeOrigin);
|
nodeRect = getNodesBounds(toolbarNodes, { nodeOrigin: $nodeOrigin });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeRect) {
|
if (nodeRect) {
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ export const getInitialStore = ({
|
|||||||
|
|
||||||
if (fitView && width && height) {
|
if (fitView && width && height) {
|
||||||
const nodesWithDimensions = nextNodes.filter((node) => node.width && node.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);
|
viewport = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,11 +102,13 @@ export const getIncomers = <NodeType extends NodeBase = NodeBase, EdgeType exten
|
|||||||
export const getNodePositionWithOrigin = (
|
export const getNodePositionWithOrigin = (
|
||||||
node: NodeBase | undefined,
|
node: NodeBase | undefined,
|
||||||
nodeOrigin: NodeOrigin = [0, 0]
|
nodeOrigin: NodeOrigin = [0, 0]
|
||||||
): XYPosition & { positionAbsolute: XYPosition } => {
|
): { position: XYPosition; positionAbsolute: XYPosition } => {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return {
|
return {
|
||||||
x: 0,
|
position: {
|
||||||
y: 0,
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
positionAbsolute: {
|
positionAbsolute: {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
@@ -123,7 +125,7 @@ export const getNodePositionWithOrigin = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...position,
|
position,
|
||||||
positionAbsolute: node.computed?.positionAbsolute
|
positionAbsolute: node.computed?.positionAbsolute
|
||||||
? {
|
? {
|
||||||
x: node.computed.positionAbsolute.x - offsetX,
|
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
|
* Determines a bounding box that contains all given nodes in an array
|
||||||
* @public
|
* @public
|
||||||
* @remarks Useful when combined with {@link getViewportForBounds} to calculate the correct transform to fit the given nodes in a viewport.
|
* @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 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
|
* @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) {
|
if (nodes.length === 0) {
|
||||||
return { x: 0, y: 0, width: 0, height: 0 };
|
return { x: 0, y: 0, width: 0, height: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const box = nodes.reduce(
|
const box = nodes.reduce(
|
||||||
(currBox, node) => {
|
(currBox, node) => {
|
||||||
const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
|
const nodePos = getNodePositionWithOrigin(node, node.origin || params.nodeOrigin);
|
||||||
return getBoundsOfBoxes(
|
return getBoundsOfBoxes(
|
||||||
currBox,
|
currBox,
|
||||||
rectToBox({
|
rectToBox({
|
||||||
x,
|
...nodePos[params.useRelativePosition ? 'position' : 'positionAbsolute'],
|
||||||
y,
|
|
||||||
width: node.computed?.width ?? node.width ?? 0,
|
width: node.computed?.width ?? node.width ?? 0,
|
||||||
height: node.computed?.height ?? node.height ?? 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) {
|
if (filteredNodes.length > 0) {
|
||||||
const bounds = getNodesBounds(filteredNodes, nodeOrigin);
|
const bounds = getNodesBounds(filteredNodes, { nodeOrigin });
|
||||||
|
|
||||||
const viewport = getViewportForBounds(
|
const viewport = getViewportForBounds(
|
||||||
bounds,
|
bounds,
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ function calculateXYZPosition<NodeType extends NodeBase>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parentNode = nodeLookup.get(node.parentNode)!;
|
const parentNode = nodeLookup.get(node.parentNode)!;
|
||||||
const parentNodePosition = getNodePositionWithOrigin(parentNode, parentNode?.origin || nodeOrigin);
|
const { position: parentNodePosition } = getNodePositionWithOrigin(parentNode, parentNode?.origin || nodeOrigin);
|
||||||
|
|
||||||
return calculateXYZPosition(
|
return calculateXYZPosition(
|
||||||
parentNode,
|
parentNode,
|
||||||
|
|||||||
@@ -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 };
|
let nodesBox: Box = { x: 0, y: 0, x2: 0, y2: 0 };
|
||||||
|
|
||||||
if (dragItems.length > 1 && nodeExtent) {
|
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);
|
nodesBox = rectToBox(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user