@mirawision/reactive-hooks
Version:
A comprehensive collection of 50+ React hooks for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Full TypeScript support with SSR safety.
60 lines (59 loc) • 2.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useWindowScrollLock = useWindowScrollLock;
const react_1 = require("react");
/**
* A hook that locks/unlocks window scrolling by setting overflow on document.body.
* Preserves the original overflow value and restores it when unlocked or unmounted.
*
* @param locked Whether scrolling should be locked
*
* @example
* // In a modal component
* useWindowScrollLock(isOpen);
*/
function useWindowScrollLock(locked) {
// Store the original overflow value
const originalOverflow = (0, react_1.useRef)();
(0, react_1.useEffect)(() => {
if (typeof document === 'undefined')
return;
const { body } = document;
if (!body)
return;
if (locked) {
// Store current overflow only when locking
originalOverflow.current = body.style.overflow;
// Get current scroll position
const scrollY = window.scrollY;
// Lock scroll
body.style.overflow = 'hidden';
// Prevent content jump by setting top margin
body.style.marginTop = `-${scrollY}px`;
body.style.width = '100%';
body.style.position = 'fixed';
}
else if (originalOverflow.current !== undefined) {
// Get the margin top value (scroll position)
const scrollY = parseInt(body.style.marginTop || '0', 10);
// Restore original styles
body.style.overflow = originalOverflow.current;
body.style.marginTop = '';
body.style.width = '';
body.style.position = '';
// Restore scroll position
window.scrollTo(0, Math.abs(scrollY));
}
return () => {
// Cleanup on unmount - restore original overflow
if (originalOverflow.current !== undefined) {
const scrollY = parseInt(body.style.marginTop || '0', 10);
body.style.overflow = originalOverflow.current;
body.style.marginTop = '';
body.style.width = '';
body.style.position = '';
window.scrollTo(0, Math.abs(scrollY));
}
};
}, [locked]);
}