@git-diff-view/react 0.0.26 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/cjs/index.development.js +431 -290
  2. package/dist/cjs/index.development.js.map +1 -1
  3. package/dist/cjs/index.production.js +431 -290
  4. package/dist/cjs/index.production.js.map +1 -1
  5. package/dist/css/diff-view-pure.css +4 -0
  6. package/dist/css/diff-view.css +4 -0
  7. package/dist/esm/index.mjs +362 -224
  8. package/dist/esm/index.mjs.map +1 -1
  9. package/index.d.ts +303 -23
  10. package/package.json +4 -3
  11. package/src/_base.css +3 -0
  12. package/src/_base_pure.css +2 -0
  13. package/src/_com.css +172 -0
  14. package/src/_theme.css +2 -0
  15. package/src/components/DiffAddWidget.tsx +86 -0
  16. package/src/components/DiffContent.tsx +367 -0
  17. package/src/components/DiffContent_v2.tsx +344 -0
  18. package/src/components/DiffExpand.tsx +25 -0
  19. package/src/components/DiffNoNewLine.tsx +10 -0
  20. package/src/components/DiffSplitContentLineNormal.tsx +164 -0
  21. package/src/components/DiffSplitContentLineWrap.tsx +234 -0
  22. package/src/components/DiffSplitExtendLineNormal.tsx +150 -0
  23. package/src/components/DiffSplitExtendLineWrap.tsx +133 -0
  24. package/src/components/DiffSplitHunkLineNormal.tsx +316 -0
  25. package/src/components/DiffSplitHunkLineWrap.tsx +340 -0
  26. package/src/components/DiffSplitView.tsx +46 -0
  27. package/src/components/DiffSplitViewNormal.tsx +205 -0
  28. package/src/components/DiffSplitViewWrap.tsx +141 -0
  29. package/src/components/DiffSplitWidgetLineNormal.tsx +149 -0
  30. package/src/components/DiffSplitWidgetLineWrap.tsx +127 -0
  31. package/src/components/DiffUnifiedContentLine.tsx +342 -0
  32. package/src/components/DiffUnifiedExtendLine.tsx +103 -0
  33. package/src/components/DiffUnifiedHunkLine.tsx +148 -0
  34. package/src/components/DiffUnifiedView.tsx +159 -0
  35. package/src/components/DiffUnifiedWidgetLine.tsx +104 -0
  36. package/src/components/DiffView.tsx +365 -0
  37. package/src/components/DiffViewContext.ts +11 -0
  38. package/src/components/DiffWidgetContext.ts +17 -0
  39. package/src/components/tools.ts +132 -0
  40. package/src/components/v2/DiffSplitContentLineNormal_v2.tsx +152 -0
  41. package/src/components/v2/DiffSplitContentLineWrap_v2.tsx +259 -0
  42. package/src/components/v2/DiffSplitExtendLineNormal_v2.tsx +146 -0
  43. package/src/components/v2/DiffSplitExtendLineWrap_v2.tsx +123 -0
  44. package/src/components/v2/DiffSplitHunkLineNormal_v2.tsx +302 -0
  45. package/src/components/v2/DiffSplitHunkLineWrap_v2.tsx +326 -0
  46. package/src/components/v2/DiffSplitViewLineNormal_v2.tsx +33 -0
  47. package/src/components/v2/DiffSplitViewLineWrap_v2.tsx +24 -0
  48. package/src/components/v2/DiffSplitViewNormal_v2.tsx +159 -0
  49. package/src/components/v2/DiffSplitViewWrap_v2.tsx +104 -0
  50. package/src/components/v2/DiffSplitView_v2.tsx +47 -0
  51. package/src/components/v2/DiffSplitWidgetLineNormal_v2.tsx +132 -0
  52. package/src/components/v2/DiffSplitWidgetLineWrap_v2.tsx +119 -0
  53. package/src/global.d.ts +12 -0
  54. package/src/hooks/useCallbackRef.ts +18 -0
  55. package/src/hooks/useDomWidth.ts +67 -0
  56. package/src/hooks/useIsMounted.ts +11 -0
  57. package/src/hooks/useSafeLayout.ts +5 -0
  58. package/src/hooks/useSyncHeight.ts +87 -0
  59. package/src/hooks/useTextWidth.ts +27 -0
  60. package/src/hooks/useUnmount.ts +10 -0
  61. package/src/index.ts +3 -0
  62. package/src/tailwind.css +3 -0
  63. package/src/tailwind_pure.css +3 -0
  64. package/styles/diff-view-pure.css +4 -0
  65. package/styles/diff-view.css +4 -0
@@ -0,0 +1,342 @@
1
+ import { type DiffFile, type DiffLine, checkDiffLineIncludeChange, type File } from "@git-diff-view/core";
2
+ import {
3
+ diffAsideWidthName,
4
+ addContentBGName,
5
+ addLineNumberBGName,
6
+ delContentBGName,
7
+ delLineNumberBGName,
8
+ expandContentBGName,
9
+ plainContentBGName,
10
+ plainLineNumberBGName,
11
+ plainLineNumberColorName,
12
+ expandLineNumberColorName,
13
+ } from "@git-diff-view/utils";
14
+ import * as React from "react";
15
+ import { memo } from "react";
16
+
17
+ import { SplitSide } from "..";
18
+
19
+ import { DiffUnifiedAddWidget } from "./DiffAddWidget";
20
+ import { DiffContent } from "./DiffContent";
21
+ import { useDiffViewContext } from "./DiffViewContext";
22
+ import { useDiffWidgetContext } from "./DiffWidgetContext";
23
+
24
+ import type { DiffViewProps } from "..";
25
+
26
+ const DiffUnifiedOldLine = ({
27
+ index,
28
+ diffLine,
29
+ rawLine,
30
+ plainLine,
31
+ syntaxLine,
32
+ lineNumber,
33
+ diffFile,
34
+ setWidget,
35
+ enableWrap,
36
+ enableAddWidget,
37
+ enableHighlight,
38
+ onAddWidgetClick,
39
+ }: {
40
+ index: number;
41
+ lineNumber: number;
42
+ rawLine: string;
43
+ plainLine?: File["plainFile"][number];
44
+ syntaxLine?: File["syntaxFile"][number];
45
+ diffLine?: DiffLine;
46
+ diffFile: DiffFile;
47
+ enableWrap: boolean;
48
+ enableAddWidget: boolean;
49
+ enableHighlight: boolean;
50
+ onAddWidgetClick?: DiffViewProps<any>["onAddWidgetClick"];
51
+ setWidget: (props: { side?: SplitSide; lineNumber?: number }) => void;
52
+ }) => {
53
+ return (
54
+ <tr data-line={index} data-state="diff" className="diff-line group">
55
+ <td
56
+ className="diff-line-num sticky left-0 w-[1%] min-w-[100px] select-none whitespace-nowrap pl-[10px] pr-[10px] text-right align-top"
57
+ style={{
58
+ color: `var(${plainLineNumberColorName})`,
59
+ backgroundColor: `var(${delLineNumberBGName})`,
60
+ width: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
61
+ maxWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
62
+ minWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
63
+ }}
64
+ >
65
+ {enableAddWidget && (
66
+ <DiffUnifiedAddWidget
67
+ index={index - 1}
68
+ lineNumber={lineNumber}
69
+ diffFile={diffFile}
70
+ side={SplitSide.old}
71
+ onWidgetClick={onAddWidgetClick}
72
+ onOpenAddWidget={(lineNumber, side) => setWidget({ lineNumber, side })}
73
+ />
74
+ )}
75
+ <div className="flex">
76
+ <span data-line-old-num={lineNumber} className="inline-block w-[50%]">
77
+ {lineNumber}
78
+ </span>
79
+ <span className="w-[10px] shrink-0" />
80
+ <span className="inline-block w-[50%]" />
81
+ </div>
82
+ </td>
83
+ <td className="diff-line-content pr-[10px] align-top" style={{ backgroundColor: `var(${delContentBGName})` }}>
84
+ <DiffContent
85
+ enableWrap={enableWrap}
86
+ diffFile={diffFile}
87
+ enableHighlight={enableHighlight}
88
+ rawLine={rawLine}
89
+ diffLine={diffLine}
90
+ plainLine={plainLine}
91
+ syntaxLine={syntaxLine}
92
+ />
93
+ </td>
94
+ </tr>
95
+ );
96
+ };
97
+
98
+ const DiffUnifiedNewLine = ({
99
+ index,
100
+ diffLine,
101
+ rawLine,
102
+ plainLine,
103
+ syntaxLine,
104
+ lineNumber,
105
+ diffFile,
106
+ setWidget,
107
+ enableWrap,
108
+ enableAddWidget,
109
+ enableHighlight,
110
+ onAddWidgetClick,
111
+ }: {
112
+ index: number;
113
+ lineNumber: number;
114
+ rawLine: string;
115
+ plainLine?: File["plainFile"][number];
116
+ syntaxLine?: File["syntaxFile"][number];
117
+ diffLine?: DiffLine;
118
+ diffFile: DiffFile;
119
+ enableWrap: boolean;
120
+ enableAddWidget: boolean;
121
+ enableHighlight: boolean;
122
+ onAddWidgetClick?: DiffViewProps<any>["onAddWidgetClick"];
123
+ setWidget: (props: { side?: SplitSide; lineNumber?: number }) => void;
124
+ }) => {
125
+ return (
126
+ <tr data-line={index} data-state="diff" className="diff-line group">
127
+ <td
128
+ className="diff-line-num sticky left-0 w-[1%] min-w-[100px] select-none whitespace-nowrap pl-[10px] pr-[10px] text-right align-top"
129
+ style={{
130
+ color: `var(${plainLineNumberColorName})`,
131
+ backgroundColor: `var(${addLineNumberBGName})`,
132
+ width: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
133
+ maxWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
134
+ minWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
135
+ }}
136
+ >
137
+ {enableAddWidget && (
138
+ <DiffUnifiedAddWidget
139
+ index={index - 1}
140
+ lineNumber={lineNumber}
141
+ diffFile={diffFile}
142
+ side={SplitSide.new}
143
+ onWidgetClick={onAddWidgetClick}
144
+ onOpenAddWidget={(lineNumber, side) => setWidget({ lineNumber, side })}
145
+ />
146
+ )}
147
+ <div className="flex">
148
+ <span className="inline-block w-[50%]" />
149
+ <span className="w-[10px] shrink-0" />
150
+ <span data-line-new-num={lineNumber} className="inline-block w-[50%]">
151
+ {lineNumber}
152
+ </span>
153
+ </div>
154
+ </td>
155
+ <td className="diff-line-content pr-[10px] align-top" style={{ backgroundColor: `var(${addContentBGName})` }}>
156
+ <DiffContent
157
+ enableWrap={enableWrap}
158
+ diffFile={diffFile}
159
+ enableHighlight={enableHighlight}
160
+ rawLine={rawLine}
161
+ diffLine={diffLine}
162
+ plainLine={plainLine}
163
+ syntaxLine={syntaxLine}
164
+ />
165
+ </td>
166
+ </tr>
167
+ );
168
+ };
169
+
170
+ const _DiffUnifiedLine = memo(
171
+ ({
172
+ index,
173
+ diffFile,
174
+ lineNumber,
175
+ enableWrap,
176
+ enableAddWidget,
177
+ enableHighlight,
178
+ }: {
179
+ index: number;
180
+ diffFile: DiffFile;
181
+ lineNumber: number;
182
+ enableWrap: boolean;
183
+ enableHighlight: boolean;
184
+ enableAddWidget: boolean;
185
+ }) => {
186
+ const unifiedLine = diffFile.getUnifiedLine(index);
187
+
188
+ const { useDiffContext } = useDiffViewContext();
189
+
190
+ const onAddWidgetClick = useDiffContext.getReadonlyState().onAddWidgetClick;
191
+
192
+ const { useWidget } = useDiffWidgetContext();
193
+
194
+ const setWidget = useWidget.getReadonlyState().setWidget;
195
+
196
+ const hasDiff = unifiedLine.diff;
197
+
198
+ const hasChange = checkDiffLineIncludeChange(unifiedLine.diff);
199
+
200
+ const rawLine = unifiedLine.value || "";
201
+
202
+ const diffLine = unifiedLine.diff;
203
+
204
+ const newLineNumber = unifiedLine.newLineNumber;
205
+
206
+ const oldLinenumber = unifiedLine.oldLineNumber;
207
+
208
+ const syntaxLine = newLineNumber
209
+ ? diffFile.getNewSyntaxLine(newLineNumber)
210
+ : oldLinenumber
211
+ ? diffFile.getOldSyntaxLine(oldLinenumber)
212
+ : undefined;
213
+
214
+ const plainLine = newLineNumber
215
+ ? diffFile.getNewPlainLine(newLineNumber)
216
+ : oldLinenumber
217
+ ? diffFile.getOldPlainLine(oldLinenumber)
218
+ : undefined;
219
+
220
+ if (hasChange) {
221
+ if (unifiedLine.oldLineNumber) {
222
+ return (
223
+ <DiffUnifiedOldLine
224
+ index={lineNumber}
225
+ enableWrap={enableWrap}
226
+ diffFile={diffFile}
227
+ rawLine={rawLine}
228
+ diffLine={diffLine}
229
+ setWidget={setWidget}
230
+ plainLine={plainLine}
231
+ syntaxLine={syntaxLine}
232
+ enableHighlight={enableHighlight}
233
+ enableAddWidget={enableAddWidget}
234
+ lineNumber={unifiedLine.oldLineNumber}
235
+ onAddWidgetClick={(...props) => onAddWidgetClick.current?.(...props)}
236
+ />
237
+ );
238
+ } else {
239
+ return (
240
+ <DiffUnifiedNewLine
241
+ index={lineNumber}
242
+ enableWrap={enableWrap}
243
+ rawLine={rawLine}
244
+ diffLine={diffLine}
245
+ diffFile={diffFile}
246
+ setWidget={setWidget}
247
+ plainLine={plainLine}
248
+ syntaxLine={syntaxLine}
249
+ enableHighlight={enableHighlight}
250
+ enableAddWidget={enableAddWidget}
251
+ lineNumber={unifiedLine.newLineNumber!}
252
+ onAddWidgetClick={(...props) => onAddWidgetClick.current?.(...props)}
253
+ />
254
+ );
255
+ }
256
+ } else {
257
+ return (
258
+ <tr data-line={lineNumber} data-state={unifiedLine.diff ? "diff" : "plain"} className="diff-line group">
259
+ <td
260
+ className="diff-line-num sticky left-0 w-[1%] min-w-[100px] select-none whitespace-nowrap pl-[10px] pr-[10px] text-right align-top"
261
+ style={{
262
+ color: `var(${hasDiff ? plainLineNumberColorName : expandLineNumberColorName})`,
263
+ width: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
264
+ maxWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
265
+ minWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
266
+ backgroundColor: hasDiff ? `var(${plainLineNumberBGName})` : `var(${expandContentBGName})`,
267
+ }}
268
+ >
269
+ {enableAddWidget && hasDiff && (
270
+ <DiffUnifiedAddWidget
271
+ index={index}
272
+ diffFile={diffFile}
273
+ lineNumber={unifiedLine.newLineNumber}
274
+ side={SplitSide.new}
275
+ onWidgetClick={(...props) => onAddWidgetClick.current?.(...props)}
276
+ onOpenAddWidget={(lineNumber, side) => setWidget({ lineNumber, side })}
277
+ />
278
+ )}
279
+ <div className="flex opacity-[0.5]">
280
+ <span data-line-old-num={unifiedLine.oldLineNumber} className="inline-block w-[50%]">
281
+ {unifiedLine.oldLineNumber}
282
+ </span>
283
+ <span className="w-[10px] shrink-0" />
284
+ <span data-line-new-num={unifiedLine.newLineNumber} className="inline-block w-[50%]">
285
+ {unifiedLine.newLineNumber}
286
+ </span>
287
+ </div>
288
+ </td>
289
+ <td
290
+ className="diff-line-content pr-[10px] align-top"
291
+ style={{
292
+ backgroundColor: hasDiff ? `var(${plainContentBGName})` : `var(${expandContentBGName})`,
293
+ }}
294
+ >
295
+ <DiffContent
296
+ enableWrap={enableWrap}
297
+ diffFile={diffFile}
298
+ enableHighlight={enableHighlight}
299
+ rawLine={rawLine}
300
+ diffLine={diffLine}
301
+ plainLine={plainLine}
302
+ syntaxLine={syntaxLine}
303
+ />
304
+ </td>
305
+ </tr>
306
+ );
307
+ }
308
+ }
309
+ );
310
+
311
+ _DiffUnifiedLine.displayName = "_DiffUnifiedLine";
312
+
313
+ export const DiffUnifiedContentLine = ({
314
+ index,
315
+ diffFile,
316
+ lineNumber,
317
+ enableWrap,
318
+ enableHighlight,
319
+ enableAddWidget,
320
+ }: {
321
+ index: number;
322
+ diffFile: DiffFile;
323
+ lineNumber: number;
324
+ enableWrap: boolean;
325
+ enableHighlight: boolean;
326
+ enableAddWidget: boolean;
327
+ }) => {
328
+ const unifiedLine = diffFile.getUnifiedLine(index);
329
+
330
+ if (unifiedLine?.isHidden) return null;
331
+
332
+ return (
333
+ <_DiffUnifiedLine
334
+ index={index}
335
+ diffFile={diffFile}
336
+ lineNumber={lineNumber}
337
+ enableWrap={enableWrap}
338
+ enableHighlight={enableHighlight}
339
+ enableAddWidget={enableAddWidget}
340
+ />
341
+ );
342
+ };
@@ -0,0 +1,103 @@
1
+ import * as React from "react";
2
+ import { useCallback } from "react";
3
+
4
+ import { SplitSide } from "..";
5
+ import { useDomWidth } from "../hooks/useDomWidth";
6
+
7
+ import { useDiffViewContext } from "./DiffViewContext";
8
+
9
+ import type { DiffFile } from "@git-diff-view/core";
10
+
11
+ const InternalDiffUnifiedExtendLine = ({
12
+ index,
13
+ diffFile,
14
+ lineNumber,
15
+ oldLineExtend,
16
+ newLineExtend,
17
+ }: {
18
+ index: number;
19
+ diffFile: DiffFile;
20
+ lineNumber: number;
21
+ oldLineExtend: { data: any };
22
+ newLineExtend: { data: any };
23
+ }) => {
24
+ const { useDiffContext } = useDiffViewContext();
25
+
26
+ const renderExtendLine = useDiffContext.useShallowStableSelector((s) => s.renderExtendLine);
27
+
28
+ const unifiedItem = diffFile.getUnifiedLine(index);
29
+
30
+ const width = useDomWidth({
31
+ selector: ".unified-diff-table-wrapper",
32
+ enable: typeof renderExtendLine === "function",
33
+ });
34
+
35
+ if (!renderExtendLine) return null;
36
+
37
+ return (
38
+ <tr data-line={`${lineNumber}-extend`} data-state="extend" className="diff-line diff-line-extend">
39
+ <td className="diff-line-extend-content p-0 align-top" colSpan={2}>
40
+ <div className="diff-line-extend-wrapper sticky left-0 z-[1]" style={{ width }}>
41
+ {width > 0 &&
42
+ oldLineExtend?.data !== undefined &&
43
+ oldLineExtend?.data !== null &&
44
+ renderExtendLine?.({
45
+ diffFile,
46
+ side: SplitSide.old,
47
+ lineNumber: unifiedItem.oldLineNumber,
48
+ data: oldLineExtend.data,
49
+ onUpdate: diffFile.notifyAll,
50
+ })}
51
+ {width > 0 &&
52
+ newLineExtend?.data !== undefined &&
53
+ newLineExtend?.data !== null &&
54
+ renderExtendLine?.({
55
+ diffFile,
56
+ side: SplitSide.new,
57
+ lineNumber: unifiedItem.newLineNumber,
58
+ data: newLineExtend.data,
59
+ onUpdate: diffFile.notifyAll,
60
+ })}
61
+ </div>
62
+ </td>
63
+ </tr>
64
+ );
65
+ };
66
+
67
+ export const DiffUnifiedExtendLine = ({
68
+ index,
69
+ diffFile,
70
+ lineNumber,
71
+ }: {
72
+ index: number;
73
+ diffFile: DiffFile;
74
+ lineNumber: number;
75
+ }) => {
76
+ const { useDiffContext } = useDiffViewContext();
77
+
78
+ const unifiedItem = diffFile.getUnifiedLine(index);
79
+
80
+ const { oldLineExtend, newLineExtend } = useDiffContext(
81
+ useCallback(
82
+ (s) => ({
83
+ oldLineExtend: s.extendData?.oldFile?.[unifiedItem?.oldLineNumber],
84
+ newLineExtend: s.extendData?.newFile?.[unifiedItem?.newLineNumber],
85
+ }),
86
+ [unifiedItem.oldLineNumber, unifiedItem.newLineNumber]
87
+ )
88
+ );
89
+
90
+ const hasExtend = oldLineExtend?.data || newLineExtend?.data;
91
+
92
+ if (!hasExtend || !unifiedItem || unifiedItem.isHidden) return null;
93
+
94
+ return (
95
+ <InternalDiffUnifiedExtendLine
96
+ index={index}
97
+ diffFile={diffFile}
98
+ lineNumber={lineNumber}
99
+ oldLineExtend={oldLineExtend}
100
+ newLineExtend={newLineExtend}
101
+ />
102
+ );
103
+ };
@@ -0,0 +1,148 @@
1
+ import { composeLen } from "@git-diff-view/core";
2
+ import {
3
+ diffAsideWidthName,
4
+ hunkContentBGName,
5
+ hunkContentColorName,
6
+ hunkLineNumberBGName,
7
+ plainLineNumberColorName,
8
+ } from "@git-diff-view/utils";
9
+ import * as React from "react";
10
+
11
+ import { ExpandAll, ExpandDown, ExpandUp } from "./DiffExpand";
12
+ import { useDiffViewContext } from "./DiffViewContext";
13
+
14
+ import type { DiffFile } from "@git-diff-view/core";
15
+
16
+ const InternalDiffUnifiedHunkLine = ({
17
+ index,
18
+ diffFile,
19
+ lineNumber,
20
+ }: {
21
+ index: number;
22
+ diffFile: DiffFile;
23
+ lineNumber: number;
24
+ }) => {
25
+ const currentHunk = diffFile.getUnifiedHunkLine(index);
26
+
27
+ const expandEnabled = diffFile.getExpandEnabled();
28
+
29
+ const { useDiffContext } = useDiffViewContext();
30
+
31
+ const enableWrap = useDiffContext.useShallowStableSelector((s) => s.enableWrap);
32
+
33
+ const couldExpand = expandEnabled && currentHunk && currentHunk.unifiedInfo;
34
+
35
+ const isExpandAll =
36
+ currentHunk &&
37
+ currentHunk.unifiedInfo &&
38
+ currentHunk.unifiedInfo.endHiddenIndex - currentHunk.unifiedInfo.startHiddenIndex < composeLen;
39
+
40
+ const isFirstLine = currentHunk && currentHunk.isFirst;
41
+
42
+ const isLastLine = currentHunk && currentHunk.isLast;
43
+
44
+ return (
45
+ <tr data-line={`${lineNumber}-hunk`} data-state="hunk" className="diff-line diff-line-hunk">
46
+ <td
47
+ className="diff-line-hunk-action sticky left-0 w-[1%] min-w-[100px] select-none p-[1px]"
48
+ style={{
49
+ backgroundColor: `var(${hunkLineNumberBGName})`,
50
+ color: `var(${plainLineNumberColorName})`,
51
+ width: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
52
+ maxWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
53
+ minWidth: `calc(calc(var(${diffAsideWidthName}) + 5px) * 2)`,
54
+ }}
55
+ >
56
+ {couldExpand ? (
57
+ isFirstLine ? (
58
+ <button
59
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
60
+ title="Expand Up"
61
+ data-title="Expand Up"
62
+ onClick={() => diffFile.onUnifiedHunkExpand("up", index)}
63
+ >
64
+ <ExpandUp className="fill-current" />
65
+ </button>
66
+ ) : isLastLine ? (
67
+ <button
68
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
69
+ title="Expand Down"
70
+ data-title="Expand Down"
71
+ onClick={() => diffFile.onUnifiedHunkExpand("down", index)}
72
+ >
73
+ <ExpandDown className="fill-current" />
74
+ </button>
75
+ ) : isExpandAll ? (
76
+ <button
77
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
78
+ title="Expand All"
79
+ data-title="Expand All"
80
+ onClick={() => diffFile.onUnifiedHunkExpand("all", index)}
81
+ >
82
+ <ExpandAll className="fill-current" />
83
+ </button>
84
+ ) : (
85
+ <>
86
+ <button
87
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
88
+ title="Expand Down"
89
+ data-title="Expand Down"
90
+ onClick={() => diffFile.onUnifiedHunkExpand("down", index)}
91
+ >
92
+ <ExpandDown className="fill-current" />
93
+ </button>
94
+ <button
95
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
96
+ title="Expand Up"
97
+ data-title="Expand Up"
98
+ onClick={() => diffFile.onUnifiedHunkExpand("up", index)}
99
+ >
100
+ <ExpandUp className="fill-current" />
101
+ </button>
102
+ </>
103
+ )
104
+ ) : (
105
+ <div className="min-h-[28px]">&ensp;</div>
106
+ )}
107
+ </td>
108
+ <td
109
+ className="diff-line-hunk-content pr-[10px] align-middle"
110
+ style={{ backgroundColor: `var(${hunkContentBGName})` }}
111
+ >
112
+ <div
113
+ className="pl-[1.5em]"
114
+ style={{
115
+ whiteSpace: enableWrap ? "pre-wrap" : "pre",
116
+ wordBreak: enableWrap ? "break-all" : "initial",
117
+ color: `var(${hunkContentColorName})`,
118
+ }}
119
+ >
120
+ {currentHunk.unifiedInfo?.plainText || currentHunk.text}
121
+ </div>
122
+ </td>
123
+ </tr>
124
+ );
125
+ };
126
+
127
+ export const DiffUnifiedHunkLine = ({
128
+ index,
129
+ diffFile,
130
+ lineNumber,
131
+ }: {
132
+ index: number;
133
+ diffFile: DiffFile;
134
+ lineNumber: number;
135
+ }) => {
136
+ const currentHunk = diffFile.getUnifiedHunkLine(index);
137
+
138
+ const currentIsShow =
139
+ currentHunk &&
140
+ currentHunk.unifiedInfo &&
141
+ currentHunk.unifiedInfo.startHiddenIndex < currentHunk.unifiedInfo.endHiddenIndex;
142
+
143
+ const currentIsPureHunk = currentHunk && diffFile._getIsPureDiffRender() && !currentHunk.unifiedInfo;
144
+
145
+ if (!currentIsShow && !currentIsPureHunk) return null;
146
+
147
+ return <InternalDiffUnifiedHunkLine index={index} diffFile={diffFile} lineNumber={lineNumber} />;
148
+ };