Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bd0ec0b

Browse files
Merge pull request #22 from utkuakyuz/feature/accessible-diff-objects
feature: accessible difference data with callback
2 parents 8fbb2ed + c38ea84 commit bd0ec0b

File tree

6 files changed

+100
-22
lines changed

6 files changed

+100
-22
lines changed

‎README.md‎

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ The theme is fully customizable, all colors can be changed. (And soon new themes
4949

5050
Modify DifferOptions and InlineDiffOptions and see the output.
5151

52-
Dual Minimap is defaultly shown, to hide middle minimap, just pass ShowSingleMinimap prop to Viewer.
52+
Dual Minimap is defaultly shown, to hide middle minimap, just pass `ShowSingleMinimap` prop to Viewer.
5353

54-
To change Diff methods please see DifferOptions. By default virtual-react-json-diff uses following configuration.
54+
To change Diff methods please see `DifferOptions`. By default `virtual-react-json-diff` uses following configuration.
5555

5656
```
5757
new Differ({
@@ -67,7 +67,6 @@ new Differ({
6767
Simply pass your json objects into Viewer Component. It will find differences and show.
6868

6969
```
70-
import React from "react";
7170
import { VirtualDiffViewer } from "virtual-react-json-diff";
7271
7372
const oldData = { name: "Alice", age: 25 };
@@ -85,6 +84,39 @@ export default function App() {
8584
}
8685
```
8786

87+
---
88+
89+
If you need to see or make some calculations on difference objects, you can get the diff data using `getDifferData` callback prop
90+
91+
```
92+
import { type DiffResult, VirtualDiffViewer } from "virtual-react-json-diff";
93+
94+
const [differData, setDifferData] = useState<[DiffResult[], DiffResult[]]>();
95+
96+
<VirtualDiffViewer {...props} getDiffData={diffData => setDifferData(diffData)} />
97+
```
98+
99+
Or if you have a custom Differ or a custom viewer, you can import `Differ` class to create diff objects using your own differ. Moreover you can pass that differ to `VirtualizedDiffViewer`.
100+
101+
p.s. This is not recommended because you can modify all variables in Differ using `differOptions` prop in Viewer.
102+
103+
```
104+
import { Differ, VirtualDiffViewer } from "virtual-react-json-diff";
105+
---
106+
const differOptions: DifferOptions = {
107+
showModifications: config.showModifications,
108+
arrayDiffMethod: config.arrayDiffMethod,
109+
};
110+
const differ = new Differ(differOptions);
111+
112+
---
113+
114+
// Pass it into Viewer with 'customDiffer' prop
115+
<VirtualDiffViewer {...props} customDiffer={differ} />
116+
```
117+
118+
---
119+
88120
The component exposes a root container with the class:
89121

90122
```
@@ -95,21 +127,24 @@ You can pass your own class name via the className prop to apply custom themes.
95127

96128
## Props
97129

98-
| Prop | Type | Default | Description |
99-
| ------------------- | ------------------------- | ------------------ | ---------------------------------------------------------------------- |
100-
| `oldValue` | `object` || The original JSON object to compare (left side). |
101-
| `newValue` | `object` || The updated JSON object to compare (right side). |
102-
| `height` | `number` || Height of the diff viewer in pixels. |
103-
| `hideSearch` | `boolean` | `false` | Hides the search bar if set to `true`. |
104-
| `searchTerm` | `string` | `""` | Initial search keyword to highlight within the diff. |
105-
| `leftTitle` | `string` || Optional title to display above the left diff panel. |
106-
| `rightTitle` | `string` || Optional title to display above the right diff panel. |
107-
| `onSearchMatch` | `(index: number) => void` || Callback fired when a search match is found. Receives the match index. |
108-
| `differOptions` | `DifferOptions` | `Given Above` | Advanced options passed to the diffing engine. |
109-
| `showSingleMinimap` | `boolean` | `false` | If `true`, shows only one minimap instead of two. |
110-
| `className` | `string` || Custom CSS class for styling the viewer container. |
111-
| `miniMapWidth` | `number` | `40` | Width of each minimap in pixels. |
112-
| `inlineDiffOptions` | `InlineDiffOptions` | `{'mode': 'char'}` | Options for fine-tuning inline diff rendering. |
130+
| Prop | Type | Default | Description |
131+
| ------------------- | -------------------------------------------------- | ------------------ | ---------------------------------------------------------------------- |
132+
| `oldValue` | `object` || The original JSON object to compare (left side). |
133+
| `newValue` | `object` || The updated JSON object to compare (right side). |
134+
| `height` | `number` || Height of the diff viewer in pixels. |
135+
| `hideSearch` | `boolean` | `false` | Hides the search bar if set to `true`. |
136+
| `searchTerm` | `string` | `""` | Initial search keyword to highlight within the diff. |
137+
| `leftTitle` | `string` || Optional title to display above the left diff panel. |
138+
| `rightTitle` | `string` || Optional title to display above the right diff panel. |
139+
| `onSearchMatch` | `(index: number) => void` || Callback fired when a search match is found. Receives the match index. |
140+
| `differOptions` | `DifferOptions` | `Given Above` | Advanced options passed to the diffing engine. |
141+
| `showSingleMinimap` | `boolean` | `false` | If `true`, shows only one minimap instead of two. |
142+
| `className` | `string` || Custom CSS class for styling the viewer container. |
143+
| `overScanCount` | `number` | `28` | Number of rendered rows outside of the viewport for virtualization |
144+
| `miniMapWidth` | `number` | `40` | Width of each minimap in pixels. |
145+
| `inlineDiffOptions` | `InlineDiffOptions` | `{'mode': 'char'}` | Options for fine-tuning inline diff rendering. |
146+
| `getDiffData` | `(diffData: [DiffResult[], DiffResult[]]) => void` | - | Get difference data and make operations |
147+
| `customDiffer` | `Differ` | - | Pass custom differ - not recommended |
113148

114149
## 🙌 Acknowledgements
115150

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "virtual-react-json-diff",
33
"type": "module",
4-
"version": "1.0.12",
4+
"version": "1.0.13",
55
"description": "Fast, virtualized React component for visually comparing large JSON objects. Includes search, theming, and minimap.",
66
"author": {
77
"name": "Utku Akyüz"

‎src/components/DiffViewer/components/VirtualizedDiffViewer.tsx‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { DiffResult } from "json-diff-kit";
12
import type { VariableSizeList as List } from "react-window";
23

34
import { Differ } from "json-diff-kit";
@@ -7,6 +8,7 @@ import type { DiffRowOrCollapsed, SegmentItem, VirtualizedDiffViewerProps } from
78

89
import "../styles/JsonDiffCustomTheme.css";
910
import { useSearch } from "../hooks/useSearch";
11+
import { fastHash } from "../utils/json-diff/diff-hash";
1012
import { expandSegment, hasExpandedSegments, hideAllSegments } from "../utils/json-diff/segment-util";
1113
import { buildViewFromSegments, generateSegments } from "../utils/preprocessDiff";
1214
import { DiffMinimap } from "./DiffMinimap";
@@ -21,6 +23,8 @@ export const VirtualizedDiffViewer: React.FC<VirtualizedDiffViewerProps> = ({
2123
leftTitle,
2224
rightTitle,
2325
hideSearch,
26+
customDiffer,
27+
getDiffData,
2428
showSingleMinimap,
2529
onSearchMatch,
2630
differOptions,
@@ -31,8 +35,10 @@ export const VirtualizedDiffViewer: React.FC<VirtualizedDiffViewerProps> = ({
3135
}) => {
3236
const outerRef = useRef<Node>(null);
3337
const listRef = useRef<List>(null);
38+
const getDiffDataRef = useRef<typeof getDiffData>();
39+
const lastSent = useRef<number>();
3440

35-
const differ = useMemo(
41+
const differ = customDiffer??useMemo(
3642
() =>
3743
new Differ({
3844
detectCircular: true,
@@ -101,6 +107,23 @@ export const VirtualizedDiffViewer: React.FC<VirtualizedDiffViewerProps> = ({
101107
setRightView(rightBuilt);
102108
}, [segments, rawLeftDiff, rawRightDiff]);
103109

110+
useEffect(() => {
111+
getDiffDataRef.current = getDiffData;
112+
}, [getDiffData]);
113+
114+
useEffect(() => {
115+
if (!getDiffDataRef.current)
116+
return;
117+
118+
const data: [DiffResult[], DiffResult[]] = [rawLeftDiff, rawRightDiff];
119+
const hash = fastHash(data);
120+
121+
if (lastSent.current !== hash) {
122+
lastSent.current = hash;
123+
getDiffDataRef.current(data);
124+
}
125+
}, [rawLeftDiff, rawRightDiff]);
126+
104127
return (
105128
<div className={`diff-viewer-container${className ? ` ${className}` : ""}`}>
106129

‎src/components/DiffViewer/types/index.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { DifferOptions, DiffResult, InlineDiffOptions } from "json-diff-kit";
1+
import type { Differ,DifferOptions, DiffResult, InlineDiffOptions } from "json-diff-kit";
22

33
export type DiffRow = {
44
originalIndex: number;
@@ -41,7 +41,9 @@ export type VirtualizedDiffViewerProps = {
4141
leftTitle?: string;
4242
rightTitle?: string;
4343
onSearchMatch?: (index: number) => void;
44+
getDiffData?: (diffData: [DiffResult[], DiffResult[]]) => void;
4445
differOptions?: DifferOptions;
46+
customDiffer?: Differ;
4547
showSingleMinimap?: boolean;
4648
className?: string;
4749
miniMapWidth?: number;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { DiffResult } from "json-diff-kit";
2+
3+
export function fastHash(diff: [DiffResult[], DiffResult[]]) {
4+
let hash = 5381; // djb2 seed
5+
for (const arr of diff) {
6+
for (const row of arr) {
7+
const text = row.text;
8+
for (let i = 0; i < text.length; i++) {
9+
hash = ((hash << 5) + hash) + text.charCodeAt(i);
10+
}
11+
const type = row.type;
12+
for (let i = 0; i < type.length; i++) {
13+
hash = ((hash << 5) + hash) + type.charCodeAt(i);
14+
}
15+
}
16+
}
17+
return hash >>> 0;
18+
}

‎src/index.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
// Buttons
21
export { default as VirtualDiffViewer } from "./components/DiffViewer";
2+
export { Differ, type DiffResult } from "json-diff-kit";

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /