UNPKG

@ariakit/react-core

Version:

Ariakit React core

76 lines (73 loc) 2.66 kB
"use client"; import { useRootDialog } from "./W6WVJJEY.js"; import { assignStyle, setCSSProperty } from "./K2ZF5NU7.js"; // src/dialog/utils/use-prevent-body-scroll.ts import { getDocument, getWindow } from "@ariakit/core/utils/dom"; import { chain } from "@ariakit/core/utils/misc"; import { isApple, isMac } from "@ariakit/core/utils/platform"; import { useEffect } from "react"; function getPaddingProperty(documentElement) { const documentLeft = documentElement.getBoundingClientRect().left; const scrollbarX = Math.round(documentLeft) + documentElement.scrollLeft; return scrollbarX ? "paddingLeft" : "paddingRight"; } function usePreventBodyScroll(contentElement, contentId, enabled) { const isRootDialog = useRootDialog({ attribute: "data-dialog-prevent-body-scroll", contentElement, contentId, enabled }); useEffect(() => { if (!isRootDialog()) return; if (!contentElement) return; const doc = getDocument(contentElement); const win = getWindow(contentElement); const { documentElement, body } = doc; const cssScrollbarWidth = documentElement.style.getPropertyValue("--scrollbar-width"); const scrollbarWidth = cssScrollbarWidth ? Number.parseInt(cssScrollbarWidth) : win.innerWidth - documentElement.clientWidth; const setScrollbarWidthProperty = () => setCSSProperty( documentElement, "--scrollbar-width", `${scrollbarWidth}px` ); const paddingProperty = getPaddingProperty(documentElement); const setStyle = () => assignStyle(body, { overflow: "hidden", [paddingProperty]: `${scrollbarWidth}px` }); const setIOSStyle = () => { var _a, _b; const { scrollX, scrollY, visualViewport } = win; const offsetLeft = (_a = visualViewport == null ? void 0 : visualViewport.offsetLeft) != null ? _a : 0; const offsetTop = (_b = visualViewport == null ? void 0 : visualViewport.offsetTop) != null ? _b : 0; const restoreStyle = assignStyle(body, { position: "fixed", overflow: "hidden", top: `${-(scrollY - Math.floor(offsetTop))}px`, left: `${-(scrollX - Math.floor(offsetLeft))}px`, right: "0", [paddingProperty]: `${scrollbarWidth}px` }); return () => { restoreStyle(); if (process.env.NODE_ENV !== "test") { win.scrollTo({ left: scrollX, top: scrollY, behavior: "instant" }); } }; }; const isIOS = isApple() && !isMac(); return chain( setScrollbarWidthProperty(), isIOS ? setIOSStyle() : setStyle() ); }, [isRootDialog, contentElement]); } export { usePreventBodyScroll };