{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "file-diff",
  "title": "File diff",
  "description": "A change to one file as a coding agent proposes it, from a unified diff.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/manniche/file-diff/file-diff.tsx",
      "content": "import { FileDiff as FileDiffIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport type FileDiffProps = {\n  /** The file the change is in. */\n  filename: string\n  /** A unified diff, as `git diff` writes it. Header lines (diff, index, ---, +++) are skipped. */\n  diff: string\n  className?: string\n}\n\ntype Line = { kind: 'add' | 'del' | 'same' | 'hunk'; text: string; oldNo?: number; newNo?: number }\n\nfunction parse(diff: string): Line[] {\n  const out: Line[] = []\n  let oldNo = 0\n  let newNo = 0\n  for (const raw of diff.replace(/\\n$/, '').split('\\n')) {\n    if (/^(diff |index |--- |\\+\\+\\+ )/.test(raw)) continue\n    const hunk = raw.match(/^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@(.*)/)\n    if (hunk) {\n      oldNo = Number(hunk[1])\n      newNo = Number(hunk[2])\n      out.push({ kind: 'hunk', text: hunk[3].trim() })\n    } else if (raw.startsWith('+')) out.push({ kind: 'add', text: raw.slice(1), newNo: newNo++ })\n    else if (raw.startsWith('-')) out.push({ kind: 'del', text: raw.slice(1), oldNo: oldNo++ })\n    else out.push({ kind: 'same', text: raw.slice(1), oldNo: oldNo++, newNo: newNo++ })\n  }\n  return out\n}\n\nconst ROW = {\n  add: 'bg-success/10',\n  del: 'bg-destructive/10',\n  same: '',\n  hunk: 'bg-muted/60 text-muted-foreground',\n}\n\n/** A change to one file, the way a coding agent proposes it. Added and removed lines are told apart by colour and by a + or − sign. */\nexport function FileDiff({ filename, diff, className }: FileDiffProps) {\n  const lines = parse(diff)\n  const added = lines.filter((l) => l.kind === 'add').length\n  const removed = lines.filter((l) => l.kind === 'del').length\n\n  return (\n    <figure className={cn('overflow-hidden rounded-2xl border bg-card text-card-foreground', className)}>\n      <figcaption className=\"flex min-h-11 items-center gap-2 border-b bg-muted/50 px-4\">\n        <FileDiffIcon className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden />\n        <span className=\"min-w-0 flex-1 truncate font-mono text-[0.8125rem]\">{filename}</span>\n        <span className=\"text-sm tabular-nums\">\n          <span className=\"text-success\">+{added}</span> <span className=\"text-destructive\">−{removed}</span>\n          <span className=\"sr-only\">\n            : {added} lines added, {removed} removed\n          </span>\n        </span>\n      </figcaption>\n      <div className=\"max-h-[28rem] overflow-auto\" tabIndex={0} role=\"region\" aria-label={`Changes in ${filename}`}>\n        <table className=\"w-full border-collapse font-mono text-[0.8125rem] leading-6\">\n          <tbody>\n            {lines.map((l, i) => (\n              <tr key={i} className={ROW[l.kind]}>\n                {l.kind === 'hunk' ? (\n                  <td colSpan={4} className=\"px-4 py-0.5 text-xs\">\n                    {l.text || '…'}\n                  </td>\n                ) : (\n                  <>\n                    <td className=\"w-0 pr-2 pl-3 text-right text-muted-foreground tabular-nums select-none\">{l.oldNo ?? ''}</td>\n                    <td className=\"w-0 pr-2 text-right text-muted-foreground tabular-nums select-none\">{l.newNo ?? ''}</td>\n                    <td\n                      className={cn(\n                        'w-0 pr-2 select-none',\n                        l.kind === 'add' && 'text-success',\n                        l.kind === 'del' && 'text-destructive',\n                      )}\n                    >\n                      <span aria-hidden>{l.kind === 'add' ? '+' : l.kind === 'del' ? '−' : ' '}</span>\n                      <span className=\"sr-only\">{l.kind === 'add' ? 'added' : l.kind === 'del' ? 'removed' : ''}</span>\n                    </td>\n                    <td className=\"pr-4 whitespace-pre\">{l.text}</td>\n                  </>\n                )}\n              </tr>\n            ))}\n          </tbody>\n        </table>\n      </div>\n    </figure>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "agent"
  ],
  "type": "registry:component"
}