import { Box, Text, useInput } from "ink"; import React, { useState } from "react"; /** * Simple scrollable view for displaying a diff. * The component is intentionally lightweight and mirrors the UX of * HistoryOverlay: Up/Down or j/k to scroll, PgUp/PgDn for paging and Esc to * close. The caller is responsible for computing the diff text. */ export default function DiffOverlay({ diffText, onExit, }: { diffText: string; onExit: () => void; }): JSX.Element { const lines = diffText.length > 0 ? diffText.split("\n") : ["(no changes)"]; const [cursor, setCursor] = useState(0); // Determine how many rows we can display – similar to HistoryOverlay. const rows = process.stdout.rows || 24; const headerRows = 2; const footerRows = 1; const maxVisible = Math.max(4, rows - headerRows - footerRows); useInput((input, key) => { if (key.escape || input === "q") { onExit(); return; } if (key.downArrow || input === "j") { setCursor((c) => Math.min(lines.length - 1, c + 1)); } else if (key.upArrow || input === "k") { setCursor((c) => Math.max(0, c - 1)); } else if (key.pageDown) { setCursor((c) => Math.min(lines.length - 1, c + maxVisible)); } else if (key.pageUp) { setCursor((c) => Math.max(0, c - maxVisible)); } else if (input === "g") { setCursor(0); } else if (input === "G") { setCursor(lines.length - 1); } }); const firstVisible = Math.min( Math.max(0, cursor - Math.floor(maxVisible / 2)), Math.max(0, lines.length - maxVisible), ); const visible = lines.slice(firstVisible, firstVisible + maxVisible); // Very small helper to colorize diff lines in a basic way. function renderLine(line: string, idx: number): JSX.Element { let color: "green" | "red" | "cyan" | undefined = undefined; if (line.startsWith("+")) { color = "green"; } else if (line.startsWith("-")) { color = "red"; } else if (line.startsWith("@@") || line.startsWith("diff --git")) { color = "cyan"; } return ( {line === "" ? " " : line} ); } return ( Working tree diff ({lines.length} lines) {visible.map((line, idx) => { return renderLine(line, firstVisible + idx); })} esc Close ↑↓ Scroll PgUp/PgDn g/G First/Last ); }