Skip to content

Commit 201228c

Browse files
committed
fix(embedded): autolayout viewport calculation for resource view
1 parent b3d9e54 commit 201228c

File tree

3 files changed

+45
-16
lines changed

3 files changed

+45
-16
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-auto-layout.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useReactFlow } from 'reactflow'
44
import type { AutoLayoutOptions } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils/auto-layout-utils'
55
import { applyAutoLayoutAndUpdateStore as applyAutoLayoutStandalone } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils/auto-layout-utils'
66
import { useSnapToGridSize } from '@/hooks/queries/general-settings'
7+
import type { CanvasViewportOptions } from '@/hooks/use-canvas-viewport'
78
import { useCanvasViewport } from '@/hooks/use-canvas-viewport'
89

910
export type { AutoLayoutOptions }
@@ -18,9 +19,9 @@ const logger = createLogger('useAutoLayout')
1819
*
1920
* Note: This hook requires a ReactFlowProvider ancestor.
2021
*/
21-
export function useAutoLayout(workflowId: string | null) {
22+
export function useAutoLayout(workflowId: string | null, options?: CanvasViewportOptions) {
2223
const reactFlowInstance = useReactFlow()
23-
const { fitViewToBounds } = useCanvasViewport(reactFlowInstance)
24+
const { fitViewToBounds } = useCanvasViewport(reactFlowInstance, options)
2425
const snapToGridSize = useSnapToGridSize()
2526

2627
const applyAutoLayoutAndUpdateStore = useCallback(

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,9 @@ const WorkflowContent = React.memo(
264264
const router = useRouter()
265265
const reactFlowInstance = useReactFlow()
266266
const { screenToFlowPosition, getNodes, setNodes, getIntersectingNodes } = reactFlowInstance
267-
const { fitViewToBounds, getViewportCenter } = useCanvasViewport(reactFlowInstance)
267+
const { fitViewToBounds, getViewportCenter } = useCanvasViewport(reactFlowInstance, {
268+
embedded,
269+
})
268270
const { emitCursorUpdate } = useSocket()
269271
useDynamicHandleRefresh()
270272

@@ -473,7 +475,9 @@ const WorkflowContent = React.memo(
473475
[]
474476
)
475477

476-
const { handleAutoLayout: autoLayoutWithFitView } = useAutoLayout(activeWorkflowId || null)
478+
const { handleAutoLayout: autoLayoutWithFitView } = useAutoLayout(activeWorkflowId || null, {
479+
embedded,
480+
})
477481

478482
const isWorkflowEmpty = useMemo(() => Object.keys(blocks).length === 0, [blocks])
479483

apps/sim/hooks/use-canvas-viewport.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback } from 'react'
1+
import { useCallback, useMemo } from 'react'
22
import type { Node, ReactFlowInstance } from 'reactflow'
33
import { BLOCK_DIMENSIONS } from '@/lib/workflows/blocks/block-dimensions'
44

@@ -10,18 +10,34 @@ interface VisibleBounds {
1010
offsetBottom: number
1111
}
1212

13+
export interface CanvasViewportOptions {
14+
embedded?: boolean
15+
}
16+
1317
/**
1418
* Gets the visible canvas bounds accounting for sidebar, terminal, and panel overlays.
15-
* Works correctly regardless of whether the ReactFlow container extends under the sidebar or not.
19+
* When embedded, uses the container rect directly since CSS variable offsets don't apply.
1620
*/
17-
function getVisibleCanvasBounds(): VisibleBounds {
21+
function getVisibleCanvasBounds(options?: CanvasViewportOptions): VisibleBounds {
22+
const flowContainer = document.querySelector('.react-flow')
23+
24+
if (options?.embedded && flowContainer) {
25+
const rect = flowContainer.getBoundingClientRect()
26+
return {
27+
width: rect.width,
28+
height: rect.height,
29+
offsetLeft: 0,
30+
offsetRight: 0,
31+
offsetBottom: 0,
32+
}
33+
}
34+
1835
const style = getComputedStyle(document.documentElement)
1936

2037
const sidebarWidth = Number.parseInt(style.getPropertyValue('--sidebar-width') || '0', 10)
2138
const terminalHeight = Number.parseInt(style.getPropertyValue('--terminal-height') || '0', 10)
2239
const panelWidth = Number.parseInt(style.getPropertyValue('--panel-width') || '0', 10)
2340

24-
const flowContainer = document.querySelector('.react-flow')
2541
if (!flowContainer) {
2642
return {
2743
width: window.innerWidth - sidebarWidth - panelWidth,
@@ -56,8 +72,8 @@ function getVisibleCanvasBounds(): VisibleBounds {
5672
/**
5773
* Gets the center of the visible canvas in screen coordinates.
5874
*/
59-
function getVisibleCanvasCenter(): { x: number; y: number } {
60-
const bounds = getVisibleCanvasBounds()
75+
function getVisibleCanvasCenter(options?: CanvasViewportOptions): { x: number; y: number } {
76+
const bounds = getVisibleCanvasBounds(options)
6177

6278
const flowContainer = document.querySelector('.react-flow')
6379
const rect = flowContainer?.getBoundingClientRect()
@@ -81,7 +97,16 @@ interface FitViewToBoundsOptions {
8197
/**
8298
* Hook providing canvas viewport utilities that account for sidebar, panel, and terminal overlays.
8399
*/
84-
export function useCanvasViewport(reactFlowInstance: ReactFlowInstance | null) {
100+
export function useCanvasViewport(
101+
reactFlowInstance: ReactFlowInstance | null,
102+
viewportOptions?: CanvasViewportOptions
103+
) {
104+
const embedded = viewportOptions?.embedded
105+
const stableOptions = useMemo<CanvasViewportOptions | undefined>(
106+
() => (embedded ? { embedded } : undefined),
107+
[embedded]
108+
)
109+
85110
/**
86111
* Gets the center of the visible canvas in flow coordinates.
87112
*/
@@ -90,9 +115,9 @@ export function useCanvasViewport(reactFlowInstance: ReactFlowInstance | null) {
90115
return { x: 0, y: 0 }
91116
}
92117

93-
const center = getVisibleCanvasCenter()
118+
const center = getVisibleCanvasCenter(stableOptions)
94119
return reactFlowInstance.screenToFlowPosition(center)
95-
}, [reactFlowInstance])
120+
}, [reactFlowInstance, stableOptions])
96121

97122
/**
98123
* Fits the view to show all nodes within the visible canvas bounds,
@@ -116,7 +141,7 @@ export function useCanvasViewport(reactFlowInstance: ReactFlowInstance | null) {
116141
return
117142
}
118143

119-
const bounds = getVisibleCanvasBounds()
144+
const bounds = getVisibleCanvasBounds(stableOptions)
120145

121146
// Calculate node bounds
122147
let minX = Number.POSITIVE_INFINITY
@@ -160,12 +185,11 @@ export function useCanvasViewport(reactFlowInstance: ReactFlowInstance | null) {
160185

161186
reactFlowInstance.setViewport({ x, y, zoom }, { duration })
162187
},
163-
[reactFlowInstance]
188+
[reactFlowInstance, stableOptions]
164189
)
165190

166191
return {
167192
getViewportCenter,
168193
fitViewToBounds,
169-
getVisibleCanvasBounds,
170194
}
171195
}

0 commit comments

Comments
 (0)