/** Snapshot of page + table scroll before a focus/layout side-effect (e.g. opening a Sheet). */ export interface PageScrollSnapshot { windowX: number windowY: number mainScrollTop: number tableScrollLeft: number mainEl: HTMLElement | null tableEl: HTMLElement | null } import { getPageScrollElement } from "./page-scroll-port" export function capturePageScrollSnapshot( tableEl?: HTMLElement | null, ): PageScrollSnapshot { if (typeof window === "undefined") { return { windowX: 0, windowY: 0, mainScrollTop: 0, tableScrollLeft: 0, mainEl: null, tableEl: tableEl ?? null, } } const mainEl = getPageScrollElement() return { windowX: window.scrollX, windowY: window.scrollY, mainScrollTop: mainEl?.scrollTop ?? 0, tableScrollLeft: tableEl?.scrollLeft ?? 0, mainEl, tableEl: tableEl ?? null, } } export function restorePageScrollSnapshot(snapshot: PageScrollSnapshot) { if (typeof window === "undefined") return window.scrollTo(snapshot.windowX, snapshot.windowY) if (snapshot.mainEl) snapshot.mainEl.scrollTop = snapshot.mainScrollTop if (snapshot.tableEl) snapshot.tableEl.scrollLeft = snapshot.tableScrollLeft } /** * Run `fn` then restore window / `#main-content` / table horizontal scroll after * Radix menu close + Sheet focus run (double rAF covers the focus frame). */ export function runWithPreservedPageScroll( fn: () => void, tableEl?: HTMLElement | null, ) { const snapshot = capturePageScrollSnapshot(tableEl) fn() if (typeof window === "undefined") return const restore = () => restorePageScrollSnapshot(snapshot) requestAnimationFrame(() => { restore() requestAnimationFrame(restore) }) }