'use client' import { X } from 'lucide-react' import { AnimatePresence, motion } from 'motion/react' import Image from 'next/image' import { type ReactNode, useEffect, useState } from 'react' import { createPortal } from 'react-dom' import useEditor from '../../../store/use-editor' interface MobilePanelSheetProps { open: boolean onClose: () => void icon?: string title: string children: ReactNode } const HEIGHT_VH = 50 const DRAG_CLOSE_THRESHOLD_PX = 120 export function MobilePanelSheet({ open, onClose, icon, title, children }: MobilePanelSheetProps) { const [mounted, setMounted] = useState(false) const setMobilePanelSheetHeight = useEditor((s) => s.setMobilePanelSheetHeight) useEffect(() => { setMounted(true) }, []) // Publish the sheet's pixel height to the shared store so the mobile layout // can shrink the viewer container and preview edits live. 0 means closed. // Tracks visualViewport so the value follows the on-screen keyboard on iOS. useEffect(() => { if (!open) { setMobilePanelSheetHeight(0) return } const compute = () => { const vh = window.visualViewport?.height ?? window.innerHeight setMobilePanelSheetHeight(Math.round((vh * HEIGHT_VH) / 100)) } compute() const vv = window.visualViewport vv?.addEventListener('resize', compute) window.addEventListener('resize', compute) return () => { vv?.removeEventListener('resize', compute) window.removeEventListener('resize', compute) setMobilePanelSheetHeight(0) } }, [open, setMobilePanelSheetHeight]) if (!mounted) return null return createPortal( {open && ( { if (info.offset.y > DRAG_CLOSE_THRESHOLD_PX) onClose() }} style={{ height: `${HEIGHT_VH}dvh` }} transition={{ type: 'spring', stiffness: 320, damping: 32, mass: 0.8 }} >
{icon && ( )}

{title}

{children}
)} , document.body, ) }