import { useEffect, useRef, useState } from 'react' import { X } from 'lucide-react' // Auto-dismiss back to the device grid after this long with no interaction — same // pattern as weather's DayModal (this is also a kiosk: a modal left open by // whoever last tapped it shouldn't sit there indefinitely). Longer than weather's // 20s since dialling in a setpoint takes more thought than glancing at a forecast. const IDLE_MS = 30_000 interface KioskModalProps { title: string onClose: () => void children: React.ReactNode wide?: boolean } export default function KioskModal({ title, onClose, children, wide }: KioskModalProps) { const [resetTick, setResetTick] = useState(0) const timerRef = useRef | null>(null) useEffect(() => { function reset() { if (timerRef.current) clearTimeout(timerRef.current) timerRef.current = setTimeout(onClose, IDLE_MS) setResetTick(t => t + 1) } reset() // pointerdown covers touch + mouse + stylus in one; deliberately no mousemove. const events = ['pointerdown', 'keydown', 'wheel'] as const events.forEach(e => window.addEventListener(e, reset)) window.addEventListener('scroll', reset, true) // capture — scroll doesn't bubble return () => { if (timerRef.current) clearTimeout(timerRef.current) events.forEach(e => window.removeEventListener(e, reset)) window.removeEventListener('scroll', reset, true) } }, [onClose]) return (
e.stopPropagation()}>

{title}

{children}
) }