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
31 changes: 27 additions & 4 deletions apps/editor/src/ui/editor/EditorCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1104,13 +1104,36 @@ export default function EditorCanvas({ onBack, onSaveToServer, isPublishedToOpen
didInitialViewportRef.current = true
}

// Two rAFs to let React Flow apply any pending node measurements/positions.
const id = globalThis.requestAnimationFrame(() => center())
const id2 = globalThis.requestAnimationFrame(() => center())
// Switching back from Tree View unhides this container (display:none →
// visible) in the same tick that triggers this effect, but the browser
// doesn't recompute layout — and React Flow's own ResizeObserver doesn't
// refresh its cached container size — until a later frame. Centering
// immediately would compute pan/zoom against a stale 0x0 size, so poll
// until the container actually has a measurable size (bounded, in case
// it's genuinely hidden for some other reason).
const MAX_ATTEMPTS = 30
let attempts = 0
let rafId: number

const waitForSizeThenCenter = () => {
const { width, height } = reactFlowWrapRef.current?.getBoundingClientRect() ?? { width: 0, height: 0 }
if ((width > 0 && height > 0) || attempts >= MAX_ATTEMPTS) {
center()
return
}
attempts += 1
rafId = globalThis.requestAnimationFrame(waitForSizeThenCenter)
}

// One rAF to let React Flow apply any pending node measurements/positions
// before the size-polling loop starts.
const id = globalThis.requestAnimationFrame(() => {
rafId = globalThis.requestAnimationFrame(waitForSizeThenCenter)
})

return () => {
globalThis.cancelAnimationFrame(id)
globalThis.cancelAnimationFrame(id2)
globalThis.cancelAnimationFrame(rafId)
}
}, [])

Expand Down
9 changes: 6 additions & 3 deletions apps/editor/src/ui/editor/components/CanvasHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ type MenuItem = {
disabled?: boolean
}

// Hierarchy layout is hidden (redundant with Canvas View) but kept wired up for now; slated for removal.
const SHOW_HIERARCHY_LAYOUT_MENU_ITEM = false

function PopoverMenu({
label,
icon: Icon,
Expand Down Expand Up @@ -380,9 +383,9 @@ export default function CanvasHeader({
icon={Cog6ToothIcon}
items={[
{ label: 'Settings', icon: Cog6ToothIcon, onClick: onOpenSettings },
{ label: 'Hierarchy layout', icon: Bars3BottomLeftIcon, onClick: onResetHierarchy, disabled: !onResetHierarchy },
{ label: 'Star layout', icon: SparklesIcon, onClick: onResetStar, disabled: !onResetStar },
{ label: activeView === 'tree' ? '✓ Tree view' : 'Tree view', icon: QueueListIcon, onClick: onSwitchTreeView, disabled: !onSwitchTreeView },
...(SHOW_HIERARCHY_LAYOUT_MENU_ITEM ? [{ label: 'Hierarchy layout', icon: Bars3BottomLeftIcon, onClick: onResetHierarchy, disabled: !onResetHierarchy }] : []),
{ label: 'Canvas View', icon: SparklesIcon, onClick: onResetStar, disabled: !onResetStar },
{ label: activeView === 'tree' ? '✓ Tree View' : 'Tree View', icon: QueueListIcon, onClick: onSwitchTreeView, disabled: !onSwitchTreeView },
'divider',
{ label: 'Help', icon: QuestionMarkCircleIcon, onClick: () => {} },
]}
Expand Down
Loading