UNPKG

@fastkit/body-scroll-lock

Version:
160 lines (158 loc) 5.03 kB
import { IN_WINDOW } from '@fastkit/helpers'; var isIosDevice = IN_WINDOW && !!window.navigator && !!window.navigator.platform && /iP(ad|hone|od)/.test(window.navigator.platform); var locks = []; var documentListenerAdded = false; var initialClientY = -1; var previousBodyOverflowSetting; var previousBodyPaddingRight; var allowTouchMove = (el) => locks.some((lock) => { if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) { return true; } return false; }); var preventDefault = (rawEvent) => { const e = rawEvent || window.event; if (allowTouchMove(e.target)) { return true; } if (e.touches.length > 1) return true; if (e.preventDefault) e.preventDefault(); return false; }; var setOverflowHidden = (options) => { setTimeout(() => { if (previousBodyPaddingRight === void 0) { const reserveScrollBarGap = !!options && options.reserveScrollBarGap === true; const scrollBarGap = window.innerWidth - document.documentElement.clientWidth; if (reserveScrollBarGap && scrollBarGap > 0) { previousBodyPaddingRight = document.body.style.paddingRight; document.body.style.paddingRight = `${scrollBarGap}px`; } } if (previousBodyOverflowSetting === void 0) { previousBodyOverflowSetting = document.body.style.overflow; document.body.style.overflow = "hidden"; } }); }; var restoreOverflowSetting = () => { setTimeout(() => { if (previousBodyPaddingRight !== void 0) { document.body.style.paddingRight = previousBodyPaddingRight; previousBodyPaddingRight = void 0; } if (previousBodyOverflowSetting !== void 0) { document.body.style.overflow = previousBodyOverflowSetting; previousBodyOverflowSetting = void 0; } }); }; var isTargetElementTotallyScrolled = (targetElement) => targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false; var handleScroll = (event, targetElement) => { const clientY = event.targetTouches[0].clientY - initialClientY; if (allowTouchMove(event.target)) { return false; } if (targetElement && targetElement.scrollTop === 0 && clientY > 0) { return preventDefault(event); } if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) { return preventDefault(event); } event.stopPropagation(); return true; }; var disableBodyScroll = (targetElement, options) => { if (!IN_WINDOW) return; if (isIosDevice) { if (!targetElement) { console.error( "disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices." ); return; } if (targetElement && !locks.some((lock) => lock.targetElement === targetElement)) { const lock = { targetElement, options: options || {} }; locks = [...locks, lock]; targetElement.ontouchstart = (event) => { if (event.targetTouches.length === 1) { initialClientY = event.targetTouches[0].clientY; } }; targetElement.ontouchmove = (event) => { if (event.targetTouches.length === 1) { handleScroll(event, targetElement); } }; if (!documentListenerAdded) { document.addEventListener("touchmove", preventDefault, { passive: false }); documentListenerAdded = true; } } } else { setOverflowHidden(options); const lock = { targetElement, options: options || {} }; locks = [...locks, lock]; } }; var clearAllBodyScrollLocks = () => { if (!IN_WINDOW) return; if (isIosDevice) { locks.forEach((lock) => { lock.targetElement.ontouchstart = null; lock.targetElement.ontouchmove = null; }); if (documentListenerAdded) { document.removeEventListener( "touchmove", preventDefault, { passive: false } ); documentListenerAdded = false; } locks = []; initialClientY = -1; } else { restoreOverflowSetting(); locks = []; } }; var enableBodyScroll = (targetElement) => { if (!IN_WINDOW) return; if (isIosDevice) { if (!targetElement) { console.error( "enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices." ); return; } targetElement.ontouchstart = null; targetElement.ontouchmove = null; locks = locks.filter((lock) => lock.targetElement !== targetElement); if (documentListenerAdded && locks.length === 0) { document.removeEventListener( "touchmove", preventDefault, { passive: false } ); documentListenerAdded = false; } } else { locks = locks.filter((lock) => lock.targetElement !== targetElement); if (!locks.length) { restoreOverflowSetting(); } } }; export { clearAllBodyScrollLocks, disableBodyScroll, enableBodyScroll }; //# sourceMappingURL=body-scroll-lock.mjs.map //# sourceMappingURL=body-scroll-lock.mjs.map