DiffViewer
ComponentsText diffingText diff viewer for React — hand-written linear-space Myers engine, word-level highlighting, collapsible context, row virtualization, and a zero-dependency headless core
Live demo
Install
$ npm install @usefy/diff-viewerQuick start
import { DiffViewer } from "@usefy/diff-viewer";
function Review({ before, after }: { before: string; after: string }) {
return <DiffViewer oldText={before} newText={after} view="split" />;
}API reference
<DiffViewer />
<DiffViewer
oldText={before} // the "before" document
newText={after} // the "after" document
view="split" // "split" | "unified"
showLineNumbers // default true
wrap={false} // wrap long lines (disables virtualization)
theme="system" // "light" | "dark" | "system"
context={3} // unchanged lines around each change (Infinity = whole file)
ignoreWhitespace="none" // "none" | "trailing" | "all" — matching only
ignoreCase={false} // matching only; renders the original
inlineThreshold={0.5} // min similarity to word-diff a changed pair
maxEditDistance={6000} // cost guard — refuse "too different" pairs
virtualizeThreshold={200} // window the DOM above this row count
diff={precomputed} // optional: a DiffResult, skips computeDiff
renderContent={({ text }) => ...} // the syntax-highlighting seam
labels={{ noChanges: "…" }} // every string overridable for i18n
classNames={{ root: "…" }} // per-slot class names
onExpand={(hunkIndex, lines) => {}}
/>
See the full options table. All numeric options are NaN/Infinity-guarded.
computeDiff(oldText, newText, options?)
The headless engine — two strings in, a DiffResult out:
interface DiffResult {
hunks: DiffHunk[]; // the renderable regions
stats: { added: number; removed: number; unchanged: number };
truncated: boolean; // a guard refused the diff
truncatedReason?: "size" | "complexity"; // too big vs. too different
inlineBudgetExhausted?: true; // some word-highlighting was skipped
}
Each DiffHunk carries its collapsed lines (hiddenBefore / hiddenAfter
as real DiffLine[]), so a pre-computed diff prop can expand with no
source texts. See headless usage.
Go deeper
This page is the quick reference. For every example, prop, and edge case, read the full README — or open Storybook to change props live.