({
oldContent,
newContent,
lang = "text",
defaultMode = "unified",
className,
}: DiffViewProps)
| 329 | } |
| 330 | |
| 331 | export function DiffView({ |
| 332 | oldContent, |
| 333 | newContent, |
| 334 | lang = "text", |
| 335 | defaultMode = "unified", |
| 336 | className, |
| 337 | }: DiffViewProps) { |
| 338 | const [mode, setMode] = useState<"unified" | "side-by-side">(defaultMode); |
| 339 | |
| 340 | const lines = useMemo( |
| 341 | () => computeDiff(oldContent, newContent), |
| 342 | [oldContent, newContent] |
| 343 | ); |
| 344 | |
| 345 | const addCount = lines.filter((l) => l.type === "add").length; |
| 346 | const removeCount = lines.filter((l) => l.type === "remove").length; |
| 347 | |
| 348 | return ( |
| 349 | <div className={cn("rounded-lg overflow-hidden border border-surface-700", className)}> |
| 350 | {/* Header */} |
| 351 | <div className="flex items-center justify-between px-3 py-2 bg-surface-800 border-b border-surface-700"> |
| 352 | <div className="flex items-center gap-2 text-xs"> |
| 353 | <span className="text-green-400 font-mono">+{addCount}</span> |
| 354 | <span className="text-red-400 font-mono">−{removeCount}</span> |
| 355 | </div> |
| 356 | <div className="flex items-center gap-1"> |
| 357 | <CopyButton text={newContent} /> |
| 358 | <div className="flex items-center rounded overflow-hidden border border-surface-700"> |
| 359 | <button |
| 360 | onClick={() => setMode("unified")} |
| 361 | className={cn( |
| 362 | "px-2 py-1 text-xs flex items-center gap-1 transition-colors", |
| 363 | mode === "unified" |
| 364 | ? "bg-brand-600 text-white" |
| 365 | : "text-surface-400 hover:text-surface-200 hover:bg-surface-700" |
| 366 | )} |
| 367 | > |
| 368 | <AlignLeft className="w-3 h-3" /> |
| 369 | Unified |
| 370 | </button> |
| 371 | <button |
| 372 | onClick={() => setMode("side-by-side")} |
| 373 | className={cn( |
| 374 | "px-2 py-1 text-xs flex items-center gap-1 transition-colors", |
| 375 | mode === "side-by-side" |
| 376 | ? "bg-brand-600 text-white" |
| 377 | : "text-surface-400 hover:text-surface-200 hover:bg-surface-700" |
| 378 | )} |
| 379 | > |
| 380 | <Columns2 className="w-3 h-3" /> |
| 381 | Side by side |
| 382 | </button> |
| 383 | </div> |
| 384 | </div> |
| 385 | </div> |
| 386 | |
| 387 | {/* Diff content */} |
| 388 | <div className="bg-surface-900 overflow-auto max-h-[480px]"> |
nothing calls this directly
no test coverage detected