// BVI Timeline — Form and Sidebar Components // Exported to window for use in Timeline.html const { useState, useEffect, useRef, useMemo } = React; // ── EVENT FORM MODAL ────────────────────────────────────────────────────────── function EventForm({ event, onSave, onClose }) { const isNew = !event || !event.id; const [cal, setCal] = useState(event?.cal || 'greg'); const [year, setYear] = useState(event?.year || ''); const [month, setMonth] = useState(event?.month || ''); const [day, setDay] = useState(event?.day || ''); const [precision,setPrecision]= useState(event?.precision|| 'day'); const [title, setTitle] = useState(event?.title || ''); const [desc, setDesc] = useState(event?.desc || ''); const [category, setCategory] = useState(event?.category || 'LEGAL'); const [power, setPower] = useState(event?.power || 'GBR'); const [source, setSource] = useState(event?.source || ''); const [citation, setCitation] = useState(event?.citation || ''); const [verified, setVerified] = useState(event?.verified || false); const [notes, setNotes] = useState(event?.notes || ''); const computedJDN = useMemo(() => { const y = parseInt(year), m = parseInt(month)||1, d = parseInt(day)||1; if (!y || isNaN(y)) return null; return cal === 'julian' ? TU.julianToJDN(y,m,d) : TU.gregorianToJDN(y,m,d); }, [cal, year, month, day]); const gregEquiv = computedJDN ? TU.jdnToGregorian(computedJDN) : null; const julEquiv = computedJDN ? TU.jdnToJulian(computedJDN) : null; function handleSave() { if (!title.trim()) { alert('Title required'); return; } if (!year || isNaN(parseInt(year))) { alert('Year required'); return; } if (!computedJDN) { alert('Invalid date'); return; } const saved = { id: event?.id || ('u_' + Date.now()), jdn: computedJDN, cal, year: parseInt(year), month: parseInt(month)||1, day: parseInt(day)||1, precision, title: title.trim(), desc, category, power, source, citation, verified, notes, seedData: false, addedAt: event?.addedAt || Date.now(), }; onSave(saved); } const labelStyle = { display:'block', fontSize:11, fontWeight:600, letterSpacing:'0.06em', textTransform:'uppercase', color:'#7a6a55', marginBottom:4 }; const inputStyle = { width:'100%', padding:'6px 8px', border:'1px solid #d4c8b8', borderRadius:4, fontSize:13, background:'#fdf9f4', boxSizing:'border-box' }; const rowStyle = { display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 }; return (
e.target===e.currentTarget && onClose()}>

{isNew ? 'Add Event' : 'Edit Event'}

{/* DATE */}
Calendar: {['greg','julian'].map(c => ( ))}
setYear(e.target.value)} placeholder="1627"/>
setMonth(e.target.value)} placeholder="1–12"/>
setDay(e.target.value)} placeholder="1–31"/>
{computedJDN && (
JDN: {computedJDN}  |  Gregorian: {TU.formatDate(gregEquiv)} {cal==='julian' && <>  |  Julian (O.S.): {TU.formatDate(julEquiv)}} {cal==='greg' && julEquiv && parseInt(year) <= 1752 && <>  |  Julian (O.S.): {TU.formatDate(julEquiv)}}
)}
{/* TITLE & DESCRIPTION */}
setTitle(e.target.value)} placeholder="e.g. Carlisle Letters Patent"/>