Skip to content

Commit 56cf3b0

Browse files
committed
fix(system): include hidden intrinsic-sized nodes in fitView when includeHiddenNodes is set
getFitViewNodes gated every node on measured dimensions (n.measured.width && n.measured.height). Hidden nodes are never rendered so they have no measured size, which meant a hidden node that declares an intrinsic size (width/height or initialWidth/initialHeight) was dropped from the fit even when includeHiddenNodes: true was passed. When includeHiddenNodes is set, fall back to the node's declared dimensions via getNodeDimensions (the same measured -> width -> initialWidth fallback nodeToBox already uses to compute bounds), so such nodes contribute to the fit. Truly size-less nodes are still skipped, and the default path (without includeHiddenNodes) keeps its exact previous behavior. Fixes #5841
1 parent f55ed9e commit 56cf3b0

2 files changed

Lines changed: 19 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@xyflow/system": patch
3+
---
4+
5+
Fix `fitView` with `includeHiddenNodes` ignoring hidden nodes that declare an intrinsic size (`width`/`height`/`initialWidth`/`initialHeight`) but were never measured

packages/system/src/utils/graph.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,20 @@ function getFitViewNodes<
339339
const optionNodeIds = options?.nodes ? new Set(options.nodes.map((node) => node.id)) : null;
340340

341341
nodeLookup.forEach((n) => {
342-
const isVisible = n.measured.width && n.measured.height && (options?.includeHiddenNodes || !n.hidden);
342+
let isVisible: boolean;
343+
344+
if (options?.includeHiddenNodes) {
345+
/*
346+
* when hidden nodes are included they were never rendered, so they have no
347+
* measured size. Fall back to the declared dimensions (same fallback as
348+
* nodeToBox) so a hidden node with an intrinsic size still contributes to
349+
* the fit bounds instead of being dropped by a measured-only check. (#5841)
350+
*/
351+
const { width, height } = getNodeDimensions(n);
352+
isVisible = width > 0 && height > 0;
353+
} else {
354+
isVisible = Boolean(n.measured.width && n.measured.height && !n.hidden);
355+
}
343356

344357
if (isVisible && (!optionNodeIds || optionNodeIds.has(n.id))) {
345358
fitViewNodes.set(n.id, n);

0 commit comments

Comments
 (0)