import { useEffect } from "react"; import { commitUrl, compareUrl, KIND_LABEL, specUrl, type Entry, type Note, } from "../../shared/changelog.ts"; import { asOfLabel } from "../../shared/routines.ts"; import { REPO_URL } from "./Colophon.tsx"; const link = "underline decoration-hairline underline-offset-2 transition-colors hover:text-ink"; /** * The fuller record (PRD F18): release notes, each a few paragraphs from the * history and the specs, with the commit range and the specs it draws on, and * the short entries it covers listed under it. Entries that belong to no note * follow, by month. * * The detail sheet's shape — the same scrim, the same Escape — because it is * the same kind of thing: something opened to read, then closed. */ export function ChangelogSheet({ notes, entries, onClose, }: { notes: readonly Note[]; entries: readonly Entry[]; onClose: () => void; }) { useEffect(() => { const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [onClose]); return (
); } export function ChangelogContent({ notes, entries }: { notes: readonly Note[]; entries: readonly Entry[] }) { const loose = entries.filter((e) => e.note === undefined); const months = [...new Set(loose.map((e) => e.date.slice(0, 7)))]; return (<>

Changelog

What changed, summarised from the project's history and design notes. Each links to the commits it covers.

{notes.map((note) => { const covered = entries.filter((e) => e.note === note.id); return (

{asOfLabel(note.date)}

{note.title}

{note.summary.map((paragraph, i) => (

{paragraph}

))} {covered.length > 0 && ( )}

commits {note.from}…{note.to} {(note.specs ?? []).map((path) => ( {path.split("/").at(-1)} ))}

); })} {months.length > 0 && (

Other changes

{months.map((month) => (

{asOfLabel(`${month}-01`).replace(/^1 /, "")}

))}
)} ); } function EntryLine({ entry }: { entry: Entry }) { return (
  • {KIND_LABEL[entry.kind]} {entry.title} {entry.ref}
  • ); }