You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.5 KiB
77 lines
2.5 KiB
"use client";
|
|
|
|
import { useCallback, useEffect, useRef } from "react";
|
|
import { useHardwareBackHandler } from "@/hooks/use-hardware-back-handler";
|
|
|
|
let activeSheetCount = 0;
|
|
let bodyHadDropdownClass = false;
|
|
let initialBodyOverflow = "";
|
|
let initialHtmlOverflow = "";
|
|
let initialAppShellOverflow = "";
|
|
let initialAppShellTouchAction = "";
|
|
let lockedAppShell: HTMLElement | null = null;
|
|
|
|
type SheetScrollLockOptions = {
|
|
onBack?: () => void;
|
|
};
|
|
|
|
export function useSheetScrollLock(
|
|
isOpen: boolean,
|
|
options: SheetScrollLockOptions = {},
|
|
) {
|
|
const { onBack } = options;
|
|
const onBackRef = useRef(onBack);
|
|
onBackRef.current = onBack;
|
|
|
|
// Register in the hardware-back handler stack so that Flutter's
|
|
// __habibHandleHardwareBackSync() closes the sheet instead of exiting the screen.
|
|
const handleHardwareBack = useCallback(() => {
|
|
if (onBackRef.current) {
|
|
onBackRef.current();
|
|
return true; // handled — sheet closed
|
|
}
|
|
return false;
|
|
}, []);
|
|
|
|
useHardwareBackHandler(handleHardwareBack, isOpen);
|
|
|
|
useEffect(() => {
|
|
if (!isOpen) return;
|
|
|
|
if (activeSheetCount === 0) {
|
|
bodyHadDropdownClass = document.body.classList.contains("dropdown-open");
|
|
initialBodyOverflow = document.body.style.overflow;
|
|
initialHtmlOverflow = document.documentElement.style.overflow;
|
|
lockedAppShell = document.querySelector<HTMLElement>(".app-shell");
|
|
initialAppShellOverflow = lockedAppShell?.style.overflowY ?? "";
|
|
initialAppShellTouchAction = lockedAppShell?.style.touchAction ?? "";
|
|
}
|
|
activeSheetCount += 1;
|
|
|
|
document.body.classList.add("dropdown-open");
|
|
document.body.classList.add("question-sheet-open");
|
|
document.body.style.overflow = "hidden";
|
|
document.documentElement.style.overflow = "hidden";
|
|
if (lockedAppShell) {
|
|
lockedAppShell.style.overflowY = "hidden";
|
|
lockedAppShell.style.touchAction = "none";
|
|
}
|
|
|
|
return () => {
|
|
activeSheetCount = Math.max(0, activeSheetCount - 1);
|
|
if (activeSheetCount === 0) {
|
|
document.body.style.overflow = initialBodyOverflow;
|
|
document.documentElement.style.overflow = initialHtmlOverflow;
|
|
if (lockedAppShell) {
|
|
lockedAppShell.style.overflowY = initialAppShellOverflow;
|
|
lockedAppShell.style.touchAction = initialAppShellTouchAction;
|
|
lockedAppShell = null;
|
|
}
|
|
if (!bodyHadDropdownClass) {
|
|
document.body.classList.remove("dropdown-open");
|
|
}
|
|
document.body.classList.remove("question-sheet-open");
|
|
}
|
|
};
|
|
}, [isOpen]);
|
|
}
|