Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ export const MothershipView = memo(function MothershipView({
<div
className={cn(
'relative z-10 flex h-full flex-col overflow-hidden border-[var(--border)] bg-[var(--bg)] transition-[width,min-width,border-width] duration-300 ease-out',
isCollapsed ? 'w-0 min-w-0 border-l-0' : 'w-[50%] min-w-[400px] border-l',
isCollapsed ? 'w-0 min-w-0 border-l-0' : 'w-[60%] border-l',
className
)}
>
<div className='flex min-h-0 min-w-[400px] flex-1 flex-col'>
<div className='flex min-h-0 flex-1 flex-col'>
<ResourceTabs
workspaceId={workspaceId}
chatId={chatId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useReactFlow } from 'reactflow'
import type { AutoLayoutOptions } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils/auto-layout-utils'
import { applyAutoLayoutAndUpdateStore as applyAutoLayoutStandalone } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils/auto-layout-utils'
import { useSnapToGridSize } from '@/hooks/queries/general-settings'
import type { CanvasViewportOptions } from '@/hooks/use-canvas-viewport'
import { useCanvasViewport } from '@/hooks/use-canvas-viewport'

export type { AutoLayoutOptions }
Expand All @@ -18,9 +19,9 @@ const logger = createLogger('useAutoLayout')
*
* Note: This hook requires a ReactFlowProvider ancestor.
*/
export function useAutoLayout(workflowId: string | null) {
export function useAutoLayout(workflowId: string | null, options?: CanvasViewportOptions) {
const reactFlowInstance = useReactFlow()
const { fitViewToBounds } = useCanvasViewport(reactFlowInstance)
const { fitViewToBounds } = useCanvasViewport(reactFlowInstance, options)
const snapToGridSize = useSnapToGridSize()

const applyAutoLayoutAndUpdateStore = useCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ const WorkflowContent = React.memo(
const router = useRouter()
const reactFlowInstance = useReactFlow()
const { screenToFlowPosition, getNodes, setNodes, getIntersectingNodes } = reactFlowInstance
const { fitViewToBounds, getViewportCenter } = useCanvasViewport(reactFlowInstance)
const { fitViewToBounds, getViewportCenter } = useCanvasViewport(reactFlowInstance, {
embedded,
})
const { emitCursorUpdate } = useSocket()
useDynamicHandleRefresh()

Expand Down Expand Up @@ -473,7 +475,9 @@ const WorkflowContent = React.memo(
[]
)

const { handleAutoLayout: autoLayoutWithFitView } = useAutoLayout(activeWorkflowId || null)
const { handleAutoLayout: autoLayoutWithFitView } = useAutoLayout(activeWorkflowId || null, {
embedded,
})

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

Expand Down
48 changes: 36 additions & 12 deletions apps/sim/hooks/use-canvas-viewport.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback } from 'react'
import { useCallback, useMemo } from 'react'
import type { Node, ReactFlowInstance } from 'reactflow'
import { BLOCK_DIMENSIONS } from '@/lib/workflows/blocks/block-dimensions'

Expand All @@ -10,18 +10,34 @@ interface VisibleBounds {
offsetBottom: number
}

export interface CanvasViewportOptions {
embedded?: boolean
}

/**
* Gets the visible canvas bounds accounting for sidebar, terminal, and panel overlays.
* Works correctly regardless of whether the ReactFlow container extends under the sidebar or not.
* When embedded, uses the container rect directly since CSS variable offsets don't apply.
*/
function getVisibleCanvasBounds(): VisibleBounds {
function getVisibleCanvasBounds(options?: CanvasViewportOptions): VisibleBounds {
const flowContainer = document.querySelector('.react-flow')

if (options?.embedded && flowContainer) {
const rect = flowContainer.getBoundingClientRect()
return {
width: rect.width,
height: rect.height,
offsetLeft: 0,
offsetRight: 0,
offsetBottom: 0,
}
}

const style = getComputedStyle(document.documentElement)

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

const flowContainer = document.querySelector('.react-flow')
if (!flowContainer) {
return {
width: window.innerWidth - sidebarWidth - panelWidth,
Expand Down Expand Up @@ -56,8 +72,8 @@ function getVisibleCanvasBounds(): VisibleBounds {
/**
* Gets the center of the visible canvas in screen coordinates.
*/
function getVisibleCanvasCenter(): { x: number; y: number } {
const bounds = getVisibleCanvasBounds()
function getVisibleCanvasCenter(options?: CanvasViewportOptions): { x: number; y: number } {
const bounds = getVisibleCanvasBounds(options)

const flowContainer = document.querySelector('.react-flow')
const rect = flowContainer?.getBoundingClientRect()
Expand All @@ -81,7 +97,16 @@ interface FitViewToBoundsOptions {
/**
* Hook providing canvas viewport utilities that account for sidebar, panel, and terminal overlays.
*/
export function useCanvasViewport(reactFlowInstance: ReactFlowInstance | null) {
export function useCanvasViewport(
reactFlowInstance: ReactFlowInstance | null,
viewportOptions?: CanvasViewportOptions
) {
const embedded = viewportOptions?.embedded
const stableOptions = useMemo<CanvasViewportOptions | undefined>(
() => (embedded ? { embedded } : undefined),
[embedded]
)

/**
* Gets the center of the visible canvas in flow coordinates.
*/
Expand All @@ -90,9 +115,9 @@ export function useCanvasViewport(reactFlowInstance: ReactFlowInstance | null) {
return { x: 0, y: 0 }
}

const center = getVisibleCanvasCenter()
const center = getVisibleCanvasCenter(stableOptions)
return reactFlowInstance.screenToFlowPosition(center)
}, [reactFlowInstance])
}, [reactFlowInstance, stableOptions])

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

const bounds = getVisibleCanvasBounds()
const bounds = getVisibleCanvasBounds(stableOptions)

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

reactFlowInstance.setViewport({ x, y, zoom }, { duration })
},
[reactFlowInstance]
[reactFlowInstance, stableOptions]
)

return {
getViewportCenter,
fitViewToBounds,
getVisibleCanvasBounds,
}
}
Loading