fix(embedded): block layout should not be dependent on viewport (#3621)

* fix(embedded): block layout should not be dependent on viewport

* address comments
This commit is contained in:
Vikhyath Mondreti
2026-03-16 23:16:33 -07:00
committed by GitHub
parent 2a7b07e3b4
commit e804ea356c
@@ -208,7 +208,8 @@ const reactFlowStyles = [
'[&_.react-flow__node-subflowNode.selected]:!shadow-none',
].join(' ')
const reactFlowFitViewOptions = { padding: 0.6, maxZoom: 1.0 } as const
const embeddedFitViewOptions = { padding: 0.15, maxZoom: 0.85, minZoom: 0.35 } as const
const embeddedFitViewOptions = { padding: 0.15, maxZoom: 0.85, minZoom: 0.1 } as const
const embeddedResizeFitViewOptions = { ...embeddedFitViewOptions, duration: 0 } as const
const reactFlowProOptions = { hideAttribution: true } as const
/**
@@ -244,7 +245,10 @@ const WorkflowContent = React.memo(
const [potentialParentId, setPotentialParentId] = useState<string | null>(null)
const [selectedEdges, setSelectedEdges] = useState<SelectedEdgesMap>(new Map())
const [isErrorConnectionDrag, setIsErrorConnectionDrag] = useState(false)
const canvasContainerRef = useRef<HTMLDivElement>(null)
const selectedIdsRef = useRef<string[] | null>(null)
const embeddedFitFrameRef = useRef<number | null>(null)
const hasCompletedInitialEmbeddedFitRef = useRef(false)
const canvasMode = useCanvasModeStore((state) => state.mode)
const isHandMode = embedded ? true : canvasMode === 'hand'
const { handleCanvasMouseDown, selectionProps } = useShiftSelectionLock({ isHandMode })
@@ -373,6 +377,34 @@ const WorkflowContent = React.memo(
]
)
const scheduleEmbeddedFit = useCallback(() => {
if (!embedded || !isWorkflowReady) return
if (embeddedFitFrameRef.current !== null) {
cancelAnimationFrame(embeddedFitFrameRef.current)
}
embeddedFitFrameRef.current = requestAnimationFrame(() => {
embeddedFitFrameRef.current = null
const container = canvasContainerRef.current
if (!container) return
const rect = container.getBoundingClientRect()
if (rect.width <= 0 || rect.height <= 0) return
const nodes = reactFlowInstance.getNodes()
if (nodes.length > 0) {
void reactFlowInstance.fitView(embeddedResizeFitViewOptions)
}
if (!hasCompletedInitialEmbeddedFitRef.current) {
hasCompletedInitialEmbeddedFitRef.current = true
setIsCanvasReady(true)
}
})
}, [embedded, isWorkflowReady, reactFlowInstance])
const {
getNodeDepth,
getNodeAbsolutePosition,
@@ -3750,10 +3782,46 @@ const WorkflowContent = React.memo(
activeWorkflowId,
])
useEffect(() => {
if (!embedded || !isWorkflowReady) {
return
}
const container = canvasContainerRef.current
if (!container) {
return
}
scheduleEmbeddedFit()
const resizeObserver = new ResizeObserver(() => {
scheduleEmbeddedFit()
})
resizeObserver.observe(container)
return () => {
resizeObserver.disconnect()
if (embeddedFitFrameRef.current !== null) {
cancelAnimationFrame(embeddedFitFrameRef.current)
embeddedFitFrameRef.current = null
}
}
}, [embedded, isWorkflowReady, scheduleEmbeddedFit])
useEffect(() => {
if (!embedded || !isWorkflowReady) {
return
}
scheduleEmbeddedFit()
}, [blocksStructureHash, embedded, isWorkflowReady, scheduleEmbeddedFit])
return (
<div className='flex h-full w-full overflow-hidden'>
<div className='flex min-w-0 flex-1 flex-col'>
<div className='relative flex-1 overflow-hidden'>
<div ref={canvasContainerRef} className='relative flex-1 overflow-hidden'>
{!isWorkflowReady && (
<div className='absolute inset-0 z-[5] flex items-center justify-center bg-[var(--bg)]'>
<div
@@ -3791,8 +3859,12 @@ const WorkflowContent = React.memo(
onDrop={effectivePermissions.canEdit ? onDrop : undefined}
onDragOver={effectivePermissions.canEdit ? onDragOver : undefined}
onInit={(instance) => {
if (embedded) {
return
}
requestAnimationFrame(() => {
instance.fitView(embedded ? embeddedFitViewOptions : reactFlowFitViewOptions)
instance.fitView(reactFlowFitViewOptions)
setIsCanvasReady(true)
})
}}