TypeScript 55.4%
Python 43.2%
SQL 1.2%
1import type { FieldChange } from "@/lib/api";2import { fmtPctDelta } from "@/lib/format";34/**5 * WHAT CHANGED — field-level before → after table (spec §21, §78). Pure server-renderable component.6 */7export function FieldChanges({ items, compact = false, max }: { items: FieldChange[] | null | undefined; compact?: boolean; max?: number }) {8 if (!items?.length) return null;9 const rows = max ? items.slice(0, max) : items;10 return (11 <div className={`overflow-hidden rounded-md border border-line ${compact ? "text-[12px]" : "text-[12.5px]"}`}>12 <table className="w-full">13 <tbody className="divide-y divide-line">14 {rows.map((f, i) => (15 <tr key={i} className="align-top">16 <td className={`${compact ? "px-2 py-1" : "px-3 py-1.5"} w-[34%] text-fg-muted`}>17 <span className="block truncate" title={f.label}>{f.label}</span>18 <span className="label !text-[9.5px] !tracking-wider">{f.kind}</span>19 </td>20 <td className={`${compact ? "px-2 py-1" : "px-3 py-1.5"} font-mono tabular`}>21 <span className="diff-line-del rounded px-1 break-words">{f.before ?? "∅"}</span>22 <span className="mx-1.5 text-fg-subtle">→</span>23 <span className="diff-line-add rounded px-1 break-words">{f.after ?? "∅"}</span>24 {f.deltaPct !== null && f.deltaPct !== undefined && <span className={`ml-2 font-semibold ${f.deltaPct > 0 ? "text-high" : "text-signal"}`}>{fmtPctDelta(f.deltaPct)}</span>}25 </td>26 </tr>27 ))}28 </tbody>29 </table>30 {max && items.length > max && <div className="border-t border-line px-3 py-1 text-[11px] text-fg-subtle">+{items.length - max} more field change{items.length - max === 1 ? "" : "s"}</div>}31 </div>32 );33}3435/** One-line inline version for feed rows / drawer headers. */36export function FieldChangeInline({ items, max = 2 }: { items: FieldChange[] | null | undefined; max?: number }) {37 if (!items?.length) return null;38 return (39 <span className="inline-flex flex-wrap items-center gap-x-2 font-mono text-[11px] text-fg-muted tabular">40 {items.slice(0, max).map((f, i) => (41 <span key={i} className="inline-flex items-center gap-1 whitespace-nowrap">42 <span className="text-fg-subtle">{f.label.length > 22 ? f.label.slice(0, 21) + "…" : f.label}</span>43 <span className="diff-line-del rounded px-0.5">{f.before ?? "∅"}</span>44 <span className="text-fg-subtle">→</span>45 <span className="diff-line-add rounded px-0.5">{f.after ?? "∅"}</span>46 {f.deltaPct !== null && f.deltaPct !== undefined && <span className={f.deltaPct > 0 ? "text-high" : "text-signal"}>{fmtPctDelta(f.deltaPct)}</span>}47 </span>48 ))}49 {items.length > max && <span className="text-fg-subtle">+{items.length - max}</span>}50 </span>51 );52}53