// Slides tab โ PowerPoint-style viewer with prev/next/play controls. // Shows uploaded slide images when present; otherwise the built-in demo deck. function SlidesTab({ slides, images, deckName }){ const uploaded = Array.isArray(images) && images.length > 0; const count = uploaded ? images.length : slides.length; const [i, setI] = React.useState(() => { const s = parseInt(localStorage.getItem('cwa-slide')||'0',10); return isNaN(s) ? 0 : Math.min(Math.max(s,0), count-1); }); const [playing, setPlaying] = React.useState(false); React.useEffect(()=>{ if(i>count-1) setI(0); }, [count]); React.useEffect(()=>{ localStorage.setItem('cwa-slide', String(i)); }, [i]); React.useEffect(()=>{ if(!playing) return; const t = setTimeout(()=> setI(p => (p+1) % count), 4000); return ()=> clearTimeout(t); }, [playing, i, count]); // keyboard: โ / โ navigate, Space advances React.useEffect(()=>{ const onKey = (e)=>{ if(/input|textarea|select/i.test(e.target.tagName) || e.target.isContentEditable) return; if(e.key==='ArrowRight' || e.key==='PageDown'){ e.preventDefault(); setI(p=>Math.min(count-1,p+1)); } else if(e.key==='ArrowLeft' || e.key==='PageUp'){ e.preventDefault(); setI(p=>Math.max(0,p-1)); } else if(e.key===' '){ e.preventDefault(); setI(p=>Math.min(count-1,p+1)); } }; window.addEventListener('keydown', onKey); return ()=> window.removeEventListener('keydown', onKey); }, [count]); const go = (n)=> setI(Math.min(Math.max(n,0), count-1)); const s = uploaded ? null : (slides[i] || {}); function renderSlide(s){ if(s.kind==='title') return (