/* global React, ChamberChrome */ const { useState, useEffect, useRef } = React; function Journal({ onBack, onOpenPhoto }) { const entries = window.JOURNAL || []; const photos = window.DARSHAN || []; const photoById = Object.fromEntries(photos.map(p => [p.id, p])); const [openId, setOpenId] = useState(null); useEffect(() => { const onKey = (e) => { if (e.key === "Escape") { openId ? setOpenId(null) : onBack(); } }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [openId, onBack]); if (openId) { const entry = entries.find(e => e.id === openId); return setOpenId(null)} onOpenPhoto={onOpenPhoto} />; } return (

letters from the road.

field notes written between trains and on the steps of small temples — what the camera missed, what the mind kept anyway.

{entries.map((e, i) => { const p = photoById[e.photoId]; return ( ); })}

the next entry is being written. it will appear when it is ready.

); } function JournalEntry({ entry, photoById, onBack, onOpenPhoto }) { const p = photoById[entry.photoId]; return (
{entry.place} · {entry.date}

{entry.dev} {entry.title}

onOpenPhoto && onOpenPhoto(entry.photoId)} data-cursor> {p?.title}
{p?.dev} {p?.title} — {p?.coords}
{entry.body.map((para, i) => { // first paragraph gets a drop-cap if (i === 0) { const first = para.charAt(0); const rest = para.slice(1); return (

{first}{rest}

); } return

{para}

; })}
); } window.Journal = Journal;