import { useEffect } from "react";
// `overflow: hidden` on
is not enough on iOS Safari — the page still
// rubber-bands behind the overlay. Pinning the body and restoring scroll on
// release is the only approach that holds across engines.
let locks = 0;
let savedScrollY = 0;
let saved: Partial = {};
function lock() {
if (locks++ > 0) return;
const body = document.body;
savedScrollY = window.scrollY;
saved = {
position: body.style.position,
top: body.style.top,
left: body.style.left,
right: body.style.right,
width: body.style.width,
overflow: body.style.overflow,
};
body.style.position = "fixed";
body.style.top = `-${savedScrollY}px`;
body.style.left = "0";
body.style.right = "0";
body.style.width = "100%";
body.style.overflow = "hidden";
}
function unlock() {
if (--locks > 0) return;
locks = 0;
Object.assign(document.body.style, saved);
window.scrollTo(0, savedScrollY);
}
export function useScrollLock(active: boolean) {
useEffect(() => {
if (!active) return;
lock();
return unlock;
}, [active]);
}