'use client'; import { X } from 'lucide-react'; import { useEffect, useRef, type ReactNode } from 'react'; import { t } from '@/i18n'; import { cn } from '@/lib/cn'; /** * Sheet primitive on a native (focus trap, Esc, inert background for free). * Mobile: bottom sheet with drag-to-close (swipe down ≥ 80 px). Desktop (md+): right-hand drawer * when `side="drawer"`, centred panel when `side="center"`. */ export function BottomSheet({ open, onClose, title, children, side = 'drawer', labelledBy, className, }: { open: boolean; onClose: () => void; title?: ReactNode; children: ReactNode; side?: 'drawer' | 'center' | 'full'; labelledBy?: string; className?: string; }) { const ref = useRef(null); const startY = useRef(null); useEffect(() => { const d = ref.current; if (!d) return; if (open && !d.open) { d.showModal(); document.documentElement.style.overflow = 'hidden'; } else if (!open && d.open) { d.close(); } return () => { document.documentElement.style.overflow = ''; }; }, [open]); useEffect(() => { const d = ref.current; if (!d) return; const onCancel = (e: Event) => { e.preventDefault(); onClose(); }; const onCloseEvt = () => { document.documentElement.style.overflow = ''; if (open) onClose(); }; d.addEventListener('cancel', onCancel); d.addEventListener('close', onCloseEvt); return () => { d.removeEventListener('cancel', onCancel); d.removeEventListener('close', onCloseEvt); }; }, [onClose, open]); const onPointerDown = (e: React.PointerEvent) => { startY.current = e.clientY; }; const onPointerUp = (e: React.PointerEvent) => { if (startY.current != null && e.clientY - startY.current > 80) onClose(); startY.current = null; }; return ( { if (e.target === e.currentTarget) onClose(); }} className={cn( 'm-0 max-h-none max-w-none bg-transparent p-0 text-ink backdrop:bg-ink/40 backdrop:backdrop-blur-[1px]', 'fixed inset-0 h-full w-full', 'open:flex open:items-end open:justify-center', side === 'drawer' && 'md:open:items-stretch md:open:justify-end', side === 'center' && 'md:open:items-center', )} > {open ? (
{title}
{children}
) : null}
); }