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 f67303d

Browse files
Merge pull request #19 from utkuakyuz/feature/custom-modified-viewer
We were using table elements based on json diff kit's viewer. However for virtual list of this kind, grid based structure is way more better both for style and dom manipulation
2 parents 6562d24 + a6ea905 commit f67303d

File tree

17 files changed

+761
-316
lines changed

17 files changed

+761
-316
lines changed

‎demo/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default function App() {
3636
ignoreCaseForKey: false,
3737
recursiveEqual: false,
3838
preserveKeyOrder: undefined as DifferOptions["preserveKeyOrder"],
39+
inlineDiffMode: "word",
3940
});
4041

4142
const updateConfig = (key: keyof Config, value: (Config)[keyof Config]) => {
@@ -218,6 +219,7 @@ export default function App() {
218219
height={config.height}
219220
miniMapWidth={config.miniMapWidth}
220221
hideSearch={config.hideSearch}
222+
inlineDiffOptions={{ mode: config.inlineDiffMode }}
221223
oldValue={parsedOldValue}
222224
newValue={parsedNewValue}
223225
differOptions={differOptions}

‎demo/src/components/Sidebar.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,20 @@ function Sidebar(props: Props) {
152152
</label>
153153
</div>
154154

155+
<div className="form-group">
156+
<label className="form-label">
157+
Inline Diff Method
158+
<select
159+
className="form-select"
160+
value={config.inlineDiffMode}
161+
onChange={e => updateConfig("inlineDiffMode", e.target.value)}
162+
>
163+
<option value="char">Character</option>
164+
<option value="word">Word</option>
165+
</select>
166+
</label>
167+
</div>
168+
155169
<div className="form-group">
156170
<label className="form-label">
157171
Array Diff Method

‎demo/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ export type Config = {
1919
ignoreCaseForKey: boolean;
2020
recursiveEqual: boolean;
2121
preserveKeyOrder: DifferOptions["preserveKeyOrder"];
22+
inlineDiffMode: "word" | "char";
2223
};

‎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.11",
4+
"version": "1.0.12",
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/DiffMinimap.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { DiffMinimapProps } from "../types";
44

55
import { useDragScroll } from "../hooks/useDragScroll";
66
import { useMinimapDraw } from "../hooks/useMinimapDraw";
7-
import { getRowHeightFromCSS } from "../utils/constants";
7+
import { DEFAULT_HEIGHT,DEFAULT_MINIMAP_WIDTH,getRowHeightFromCSS } from "../utils/constants";
88

99
const MINIMAP_HOVER_SCROLL_COLOR = "#7B7B7Bcc";
1010

@@ -37,7 +37,7 @@ export const DiffMinimap: React.FC<DiffMinimapProps> = ({
3737
}, [height, leftDiff.length, rightDiff.length]);
3838

3939
const { handleMouseDown, isDragging } = useDragScroll({
40-
height,
40+
height: height||DEFAULT_HEIGHT,
4141
totalLines,
4242
viewportHeight,
4343
ROW_HEIGHT,
@@ -48,8 +48,8 @@ export const DiffMinimap: React.FC<DiffMinimapProps> = ({
4848
const { drawMinimap, drawScrollBox } = useMinimapDraw({
4949
canvasRef,
5050
containerRef,
51-
height,
52-
miniMapWidth,
51+
height: height||DEFAULT_HEIGHT,
52+
miniMapWidth: miniMapWidth||DEFAULT_MINIMAP_WIDTH,
5353
leftDiff,
5454
rightDiff,
5555
currentScrollTop,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type { SearchState } from "../types";
2+
3+
import { SearchIcon } from "../../SearchIcon";
4+
5+
type Props = {
6+
searchState: SearchState;
7+
handleSearch: (term: string) => void;
8+
navigateMatch: (direction: "next" | "prev") => void;
9+
hideSearch?: boolean;
10+
};
11+
12+
function SearchboxHolder({ searchState, handleSearch, navigateMatch, hideSearch }: Props) {
13+
if (hideSearch)
14+
return null;
15+
16+
return (
17+
<div className="search-container">
18+
<div className="search-input-container">
19+
<span role="img" aria-label="search"><SearchIcon /></span>
20+
<input
21+
type="text"
22+
placeholder="Search in JSON..."
23+
value={searchState.term}
24+
onChange={e => handleSearch(e.target.value)}
25+
/>
26+
</div>
27+
{searchState.results.length > 0 && (
28+
<div className="search-results">
29+
<span>
30+
{searchState.currentIndex + 1}
31+
{" "}
32+
of
33+
{" "}
34+
{searchState.results.length}
35+
{" "}
36+
matches
37+
</span>
38+
<button onClick={() => navigateMatch("prev")}>Previous</button>
39+
<button onClick={() => navigateMatch("next")}>Next</button>
40+
</div>
41+
)}
42+
</div>
43+
);
44+
}
45+
46+
export default SearchboxHolder;

‎src/components/DiffViewer/components/ViewerRow.tsx

Lines changed: 0 additions & 56 deletions
This file was deleted.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// VirtualDiffGrid.tsx
2+
import type { InlineDiffOptions } from "json-diff-kit";
3+
import type { Dispatch } from "react";
4+
import type { ListOnScrollProps } from "react-window";
5+
6+
import React, { useCallback, useEffect, useMemo } from "react";
7+
import { VariableSizeList as List } from "react-window";
8+
9+
import type { DiffRowOrCollapsed } from "../types";
10+
11+
import { useRowHeights } from "../hooks/useRowHeights";
12+
import { COLLAPSED_ROW_HEIGHT, getRowHeightFromCSS, isCollapsed } from "../utils/constants";
13+
import RowRendererGrid from "../utils/json-diff/row-renderer-grid";
14+
15+
type ListDataType = {
16+
leftDiff: DiffRowOrCollapsed[];
17+
rightDiff: DiffRowOrCollapsed[];
18+
onExpand: (segmentIndex: number) => void;
19+
inlineDiffOptions?: InlineDiffOptions;
20+
};
21+
22+
type VirtualDiffGridProps = {
23+
leftDiff: DiffRowOrCollapsed[];
24+
rightDiff: DiffRowOrCollapsed[];
25+
outerRef: React.RefObject<Node | null>;
26+
listRef: React.RefObject<List<ListDataType>>;
27+
height: number;
28+
inlineDiffOptions?: InlineDiffOptions;
29+
className?: string;
30+
setScrollTop: Dispatch<React.SetStateAction<number>>;
31+
onExpand: (segmentIndex: number) => void;
32+
overScanCount?: number;
33+
};
34+
35+
const VirtualDiffGrid: React.FC<VirtualDiffGridProps> = ({
36+
leftDiff,
37+
rightDiff,
38+
outerRef,
39+
listRef,
40+
height,
41+
inlineDiffOptions,
42+
className,
43+
setScrollTop,
44+
onExpand,
45+
overScanCount = 10,
46+
}) => {
47+
// Virtual List Data
48+
const listData = useMemo(
49+
() => ({
50+
leftDiff,
51+
rightDiff,
52+
onExpand,
53+
inlineDiffOptions,
54+
}),
55+
[leftDiff, rightDiff, onExpand, inlineDiffOptions],
56+
);
57+
58+
const classes = [
59+
"json-diff-viewer",
60+
`json-diff-viewer-theme-custom`,
61+
className,
62+
]
63+
.filter(Boolean)
64+
.join(" ");
65+
66+
// ROW HEIGHT CALCULATION
67+
const ROW_HEIGHT = useMemo(() => getRowHeightFromCSS(), []);
68+
const rowHeights = useRowHeights(leftDiff);
69+
const dynamicRowHeights = useCallback(
70+
(index: number) => {
71+
const leftLine = leftDiff[index];
72+
if (isCollapsed(leftLine))
73+
return COLLAPSED_ROW_HEIGHT;
74+
return (rowHeights[index] ?? 1) * ROW_HEIGHT;
75+
},
76+
[leftDiff, rowHeights],
77+
);
78+
79+
useEffect(() => {
80+
listRef.current?.resetAfterIndex(0, true);
81+
}, [rowHeights]);
82+
83+
return (
84+
<div className={classes}>
85+
<List
86+
height={height}
87+
width="100%"
88+
style={{ alignItems: "start" }}
89+
outerRef={outerRef}
90+
ref={listRef}
91+
className="virtual-json-diff-list-container"
92+
itemCount={Math.max(leftDiff.length, rightDiff.length)}
93+
itemSize={dynamicRowHeights}
94+
overscanCount={overScanCount}
95+
itemData={listData}
96+
onScroll={({ scrollOffset }: ListOnScrollProps) => setScrollTop(scrollOffset)}
97+
>
98+
{RowRendererGrid}
99+
</List>
100+
</div>
101+
);
102+
};
103+
104+
export default VirtualDiffGrid;

0 commit comments

Comments
(0)

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