A React component for Ace Editor providing comprehensive code editing capabilities with syntax highlighting, themes, and customization options
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The Diff Editor component provides specialized functionality for comparing two pieces of text with visual highlighting of differences. It's built on top of the Split Editor and uses diff-match-patch for intelligent difference detection and highlighting.
Diff editor component that compares two text sources and highlights their differences with visual indicators.
/**
* Diff editor component for comparing and highlighting differences between two text sources
* Automatically detects changes and provides visual indicators for additions, deletions, and modifications
*/
declare class DiffComponent extends React.Component<IDiffEditorProps, IDiffEditorState> {}
interface IDiffEditorProps {
/** Starting cursor position */
cursorStart?: number;
/** Additional editor properties */
editorProps?: object;
/** Enable basic autocompletion */
enableBasicAutocompletion?: boolean | string[];
/** Enable live autocompletion */
enableLiveAutocompletion?: boolean | string[];
/** Auto-focus the diff editor on mount */
focus?: boolean;
/** Font size for both editor panes */
fontSize?: number;
/** Total height of the diff editor */
height?: string;
/** Highlight active line in both panes */
highlightActiveLine?: boolean;
/** Maximum lines for both editor panes */
maxLines?: number;
/** Minimum lines for both editor panes */
minLines?: number;
/** Syntax highlighting mode for both panes */
mode?: string;
/** Unique identifier for the diff editor instance */
name?: string;
/** CSS class name for the diff editor container */
className?: string;
/** Called when diff editor is fully loaded */
onLoad?: (editor: IEditorProps) => void;
/** Called when content changes in either pane */
onChange?: (value: string[], event?: any) => void;
/** Called when text is pasted into either pane */
onPaste?: (value: string) => void;
/** Called when either pane is scrolled */
onScroll?: (editor: IEditorProps) => void;
/** Split orientation ("beside" or "below") */
orientation?: string;
/** Make both editor panes read-only */
readOnly?: boolean;
/** Scroll margin for both editor panes */
scrollMargin?: number[];
/** Ace editor configuration options */
setOptions?: object;
/** Show line numbers in both panes */
showGutter?: boolean;
/** Show print margin in both panes */
showPrintMargin?: boolean;
/** Number of splits (typically 2 for diff view) */
splits?: number;
/** CSS styles for the diff editor container */
style?: object;
/** Tab size for both editor panes */
tabSize?: number;
/** Editor theme for both panes */
theme?: string;
/** Content for comparison [original, modified] */
value?: string[];
/** Total width of the diff editor */
width?: string;
/** Enable line wrapping in both panes */
wrapEnabled?: boolean;
}
interface IDiffEditorState {
/** Current content values [original, modified] */
value: string[];
}Basic Diff Comparison:
import React, { useState } from "react";
import { diff } from "react-ace";
import "ace-builds/src-noconflict/mode-javascript";
import "ace-builds/src-noconflict/theme-github";
const DiffEditor = diff;
function CodeComparison() {
const [values, setValues] = useState([
// Original code
`function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price;
}
return total;
}`,
// Modified code
`function calculateTotal(items) {
return items.reduce((total, item) => total + item.price, 0);
}`
]);
return (
<DiffEditor
mode="javascript"
theme="github"
value={values}
onChange={setValues}
name="code-diff"
width="100%"
height="400px"
fontSize={14}
showGutter={true}
highlightActiveLine={true}
/>
);
}Document Comparison with Headers:
import React, { useState } from "react";
import { diff } from "react-ace";
import "ace-builds/src-noconflict/mode-markdown";
import "ace-builds/src-noconflict/theme-github";
const DiffEditor = diff;
function DocumentDiff() {
const [originalDoc, setOriginalDoc] = useState(`# Project Documentation
## Overview
This project provides basic functionality.
## Features
- Feature A
- Feature B
## Installation
Run npm install to get started.`);
const [modifiedDoc, setModifiedDoc] = useState(`# Project Documentation
## Overview
This project provides comprehensive functionality with advanced features.
## Features
- Feature A (Enhanced)
- Feature B
- Feature C (New)
## Installation
Run npm install to get started.
## Configuration
Set environment variables before running.`);
const handleChange = (values) => {
setOriginalDoc(values[0]);
setModifiedDoc(values[1]);
};
return (
<div>
<div style={{ display: 'flex', marginBottom: '10px' }}>
<div style={{ flex: 1, textAlign: 'center', fontWeight: 'bold' }}>
Original
</div>
<div style={{ flex: 1, textAlign: 'center', fontWeight: 'bold' }}>
Modified
</div>
</div>
<DiffEditor
mode="markdown"
theme="github"
value={[originalDoc, modifiedDoc]}
onChange={handleChange}
name="document-diff"
width="100%"
height="500px"
fontSize={14}
showGutter={true}
orientation="beside"
/>
</div>
);
}Read-Only Diff Viewer:
import React from "react";
import { diff } from "react-ace";
import "ace-builds/src-noconflict/mode-json";
import "ace-builds/src-noconflict/theme-monokai";
const DiffEditor = diff;
interface DiffViewerProps {
beforeData: object;
afterData: object;
}
function DiffViewer({ beforeData, afterData }: DiffViewerProps) {
const values = [
JSON.stringify(beforeData, null, 2),
JSON.stringify(afterData, null, 2)
];
return (
<DiffEditor
mode="json"
theme="monokai"
value={values}
name="json-diff-viewer"
readOnly={true}
width="100%"
height="600px"
fontSize={14}
showGutter={true}
highlightActiveLine={false}
setOptions={{
showLineNumbers: true,
showFoldWidgets: true
}}
/>
);
}Diff with Custom Styling:
import React, { useState } from "react";
import { diff } from "react-ace";
const DiffEditor = diff;
function StyledDiffEditor() {
const [values, setValues] = useState([
"Original text content",
"Modified text content with changes"
]);
const customStyle = {
border: '2px solid #ccc',
borderRadius: '8px',
overflow: 'hidden'
};
return (
<div>
<style>{`
.diff-editor .ace_gutter {
background: #f5f5f5;
}
.diff-editor .ace_gutter-active-line {
background: #e8f4f8;
}
.diff-added {
background-color: #d4edda;
}
.diff-removed {
background-color: #f8d7da;
}
`}</style>
<DiffEditor
mode="text"
theme="github"
value={values}
onChange={setValues}
name="styled-diff"
className="diff-editor"
style={customStyle}
width="100%"
height="400px"
fontSize={14}
/>
</div>
);
}Vertical Diff Layout:
import React, { useState } from "react";
import { diff } from "react-ace";
import "ace-builds/src-noconflict/mode-html";
import "ace-builds/src-noconflict/theme-github";
const DiffEditor = diff;
function VerticalDiff() {
const [values, setValues] = useState([
'<div class="old-version">Old HTML</div>',
'<div class="new-version">New HTML with improvements</div>'
]);
return (
<DiffEditor
mode="html"
theme="github"
value={values}
onChange={setValues}
name="vertical-diff"
orientation="below"
width="100%"
height="600px"
fontSize={14}
showGutter={true}
splits={2}
/>
);
}Automatic Difference Detection:
The Diff Editor automatically detects and highlights:
Visual Indicators:
Layout Configuration:
interface DiffLayoutConfig {
/** Split orientation */
orientation?: "beside" | "below";
/** Number of comparison panes */
splits?: number;
/** Synchronized scrolling */
syncScroll?: boolean;
}Diff-Specific Options:
The Diff Editor inherits all standard Ace Editor options and adds diff-specific behavior:
Change Detection:
/** Called when content changes in either pane */
onChange?: (values: string[], event?: {
paneIndex: number;
changeType: 'addition' | 'deletion' | 'modification';
affectedLines: number[];
}) => void;Load Event:
/** Called when diff editor is fully loaded */
onLoad?: (editor: {
leftPane: Ace.Editor;
rightPane: Ace.Editor;
getDiffs: () => DiffResult[];
}) => void;The Diff Editor uses the diff-match-patch library internally for:
The Diff Editor includes accessibility features:
Install with Tessl CLI
npx tessl i tessl/npm-react-ace