"use client"; import { useEffect, useRef, useState } from "react"; import { NOTE_TEXT_LIMIT } from "@/lib/annotations/types"; import type { Anchor, Note, NoteOp } from "@/lib/annotations/types"; import { fmtAgo } from "@/lib/format"; // A note in the rail, and the box that writes one. Shared by the article // reader and the evidence walk. export function anchorLabel(a: Anchor, titles: Record, cites: Record): string { const sec = (id: string) => titles[id] ?? id; switch (a.kind) { case "text": return `${sec(a.section)} · “${a.quote.length > 60 ? `${a.quote.slice(0, 59)}…` : a.quote}”`; case "section": return `section · ${sec(a.section)}`; case "cite": return `citation [${cites[a.cite] ?? a.cite}]`; case "whole": return "whole article"; case "moment": return `${a.file} @ ${a.t.toFixed(1)}s`; default: return a.kind; } } export function Composer({ label, initial = "", busy, onSave, onCancel, saveLabel = "save note", }: { label: string; initial?: string; busy?: boolean; onSave: (text: string) => void | Promise; onCancel: () => void; saveLabel?: string; }) { const [text, setText] = useState(initial); const ref = useRef(null); useEffect(() => ref.current?.focus(), []); const save = () => { if (text.trim()) void onSave(text); }; return (
{label}