import { PropsWithChildren, Suspense, useCallback, useEffect, useRef, useState, } from "react"; import { useIsMobile } from "@/hooks/use-is-mobile"; import Drawer from "./drawer"; import Modal from "./modal"; import { Box, Flex, Loader } from "@mantine/core"; interface SheetProps extends PropsWithChildren { title?: string; opened: boolean; onChange: (next: boolean) => void; } const DRAWER_EXIT_MS = 500; const MODAL_EXIT_MS = 200; const EXIT_BUFFER_MS = 100; const Sheet: React.FC = ({ title, children, opened, onChange }) => { const isMobile = useIsMobile(); const handleClose = useCallback(() => onChange(false), [onChange]); const [mounted, setMounted] = useState(opened); const openedRef = useRef(opened); openedRef.current = opened; const handleExited = useCallback(() => { if (!openedRef.current) setMounted(false); }, []); useEffect(() => { if (opened) { setMounted(true); return; } const exitDuration = (isMobile ? DRAWER_EXIT_MS : MODAL_EXIT_MS) + EXIT_BUFFER_MS; const timer = window.setTimeout(() => setMounted(false), exitDuration); return () => window.clearTimeout(timer); }, [opened, isMobile]); const SheetComponent = isMobile ? Drawer : Modal; if (!opened && !mounted) return null; return ( }> {/* Native overflow, not ScrollArea: vaul's drag-vs-scroll detection only recognizes natively scrollable elements. */} {children} ); }; export default Sheet;