@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,316 @@
1
+ import { composeLen, type DiffFile } from "@git-diff-view/core";
2
+ import {
3
+ hunkLineNumberBGName,
4
+ plainLineNumberColorName,
5
+ diffAsideWidthName,
6
+ hunkContentBGName,
7
+ hunkContentColorName,
8
+ } from "@git-diff-view/utils";
9
+ import * as React from "react";
10
+
11
+ import { DiffModeEnum, SplitSide } from "..";
12
+ import { useSyncHeight } from "../hooks/useSyncHeight";
13
+
14
+ import { ExpandAll, ExpandDown, ExpandUp } from "./DiffExpand";
15
+ import { useDiffViewContext } from "./DiffViewContext";
16
+
17
+ const InternalDiffSplitHunkLineGitHub = ({
18
+ index,
19
+ diffFile,
20
+ side,
21
+ lineNumber,
22
+ }: {
23
+ index: number;
24
+ side: SplitSide;
25
+ diffFile: DiffFile;
26
+ lineNumber: number;
27
+ }) => {
28
+ const currentHunk = diffFile.getSplitHunkLine(index);
29
+
30
+ const expandEnabled = diffFile.getExpandEnabled();
31
+
32
+ useSyncHeight({
33
+ selector: `tr[data-line="${lineNumber}-hunk"]`,
34
+ side: SplitSide[SplitSide.old],
35
+ enable: side === SplitSide.new,
36
+ });
37
+
38
+ const enableHunkAction = side === SplitSide.old;
39
+
40
+ const couldExpand = expandEnabled && currentHunk && currentHunk.splitInfo;
41
+
42
+ const isExpandAll =
43
+ currentHunk &&
44
+ currentHunk.splitInfo &&
45
+ currentHunk.splitInfo.endHiddenIndex - currentHunk.splitInfo.startHiddenIndex < composeLen;
46
+
47
+ const isFirstLine = currentHunk && currentHunk.isFirst;
48
+
49
+ const isLastLine = currentHunk && currentHunk.isLast;
50
+
51
+ return (
52
+ <tr
53
+ data-line={`${lineNumber}-hunk`}
54
+ data-state="hunk"
55
+ data-side={SplitSide[side]}
56
+ className="diff-line diff-line-hunk"
57
+ >
58
+ {enableHunkAction ? (
59
+ <>
60
+ <td
61
+ className="diff-line-hunk-action sticky left-0 w-[1%] min-w-[40px] select-none p-[1px]"
62
+ style={{
63
+ backgroundColor: `var(${hunkLineNumberBGName})`,
64
+ color: `var(${plainLineNumberColorName})`,
65
+ width: `var(${diffAsideWidthName})`,
66
+ minWidth: `var(${diffAsideWidthName})`,
67
+ maxWidth: `var(${diffAsideWidthName})`,
68
+ }}
69
+ >
70
+ {couldExpand ? (
71
+ isFirstLine ? (
72
+ <button
73
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
74
+ title="Expand Up"
75
+ data-title="Expand Up"
76
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
77
+ >
78
+ <ExpandUp className="fill-current" />
79
+ </button>
80
+ ) : isLastLine ? (
81
+ <button
82
+ className="diff-widget-tooltip relative flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
83
+ title="Expand Down"
84
+ data-title="Expand Down"
85
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
86
+ >
87
+ <ExpandDown className="fill-current" />
88
+ </button>
89
+ ) : isExpandAll ? (
90
+ <button
91
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
92
+ title="Expand All"
93
+ data-title="Expand All"
94
+ onClick={() => diffFile.onSplitHunkExpand("all", index)}
95
+ >
96
+ <ExpandAll className="fill-current" />
97
+ </button>
98
+ ) : (
99
+ <>
100
+ <button
101
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
102
+ title="Expand Down"
103
+ data-title="Expand Down"
104
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
105
+ >
106
+ <ExpandDown className="fill-current" />
107
+ </button>
108
+ <button
109
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
110
+ title="Expand Up"
111
+ data-title="Expand Up"
112
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
113
+ >
114
+ <ExpandUp className="fill-current" />
115
+ </button>
116
+ </>
117
+ )
118
+ ) : (
119
+ <div className="min-h-[28px]">&ensp;</div>
120
+ )}
121
+ </td>
122
+ <td
123
+ className="diff-line-hunk-content pr-[10px] align-middle"
124
+ style={{ backgroundColor: `var(${hunkContentBGName})` }}
125
+ >
126
+ <div
127
+ className="pl-[1.5em]"
128
+ style={{
129
+ color: `var(${hunkContentColorName})`,
130
+ }}
131
+ >
132
+ {currentHunk.splitInfo?.plainText || currentHunk.text}
133
+ </div>
134
+ </td>
135
+ </>
136
+ ) : (
137
+ <td
138
+ className="diff-line-hunk-placeholder select-none"
139
+ colSpan={2}
140
+ style={{ backgroundColor: `var(${hunkContentBGName})` }}
141
+ >
142
+ <div className="min-h-[28px]">&ensp;</div>
143
+ </td>
144
+ )}
145
+ </tr>
146
+ );
147
+ };
148
+
149
+ const InternalDiffSplitHunkLineGitLab = ({
150
+ index,
151
+ diffFile,
152
+ side,
153
+ lineNumber,
154
+ }: {
155
+ index: number;
156
+ side: SplitSide;
157
+ diffFile: DiffFile;
158
+ lineNumber: number;
159
+ }) => {
160
+ const currentHunk = diffFile.getSplitHunkLine(index);
161
+
162
+ const expandEnabled = diffFile.getExpandEnabled();
163
+
164
+ useSyncHeight({
165
+ selector: `tr[data-line="${lineNumber}-hunk"]`,
166
+ side: SplitSide[side],
167
+ enable: true,
168
+ });
169
+
170
+ const couldExpand = expandEnabled && currentHunk && currentHunk.splitInfo;
171
+
172
+ const isExpandAll =
173
+ currentHunk &&
174
+ currentHunk.splitInfo &&
175
+ currentHunk.splitInfo.endHiddenIndex - currentHunk.splitInfo.startHiddenIndex < composeLen;
176
+
177
+ const isFirstLine = currentHunk && currentHunk.isFirst;
178
+
179
+ const isLastLine = currentHunk && currentHunk.isLast;
180
+
181
+ return (
182
+ <tr
183
+ data-line={`${lineNumber}-hunk`}
184
+ data-state="hunk"
185
+ data-side={SplitSide[side]}
186
+ className="diff-line diff-line-hunk"
187
+ >
188
+ <td
189
+ className="diff-line-hunk-action sticky left-0 w-[1%] min-w-[40px] select-none p-[1px]"
190
+ style={{
191
+ backgroundColor: `var(${hunkLineNumberBGName})`,
192
+ color: `var(${plainLineNumberColorName})`,
193
+ width: `var(${diffAsideWidthName})`,
194
+ minWidth: `var(${diffAsideWidthName})`,
195
+ maxWidth: `var(${diffAsideWidthName})`,
196
+ }}
197
+ >
198
+ {couldExpand ? (
199
+ isFirstLine ? (
200
+ <button
201
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
202
+ title="Expand Up"
203
+ data-title="Expand Up"
204
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
205
+ >
206
+ <ExpandUp className="fill-current" />
207
+ </button>
208
+ ) : isLastLine ? (
209
+ <button
210
+ className="diff-widget-tooltip relative flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
211
+ title="Expand Down"
212
+ data-title="Expand Down"
213
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
214
+ >
215
+ <ExpandDown className="fill-current" />
216
+ </button>
217
+ ) : isExpandAll ? (
218
+ <button
219
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
220
+ title="Expand All"
221
+ data-title="Expand All"
222
+ onClick={() => diffFile.onSplitHunkExpand("all", index)}
223
+ >
224
+ <ExpandAll className="fill-current" />
225
+ </button>
226
+ ) : (
227
+ <>
228
+ <button
229
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
230
+ title="Expand Down"
231
+ data-title="Expand Down"
232
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
233
+ >
234
+ <ExpandDown className="fill-current" />
235
+ </button>
236
+ <button
237
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
238
+ title="Expand Up"
239
+ data-title="Expand Up"
240
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
241
+ >
242
+ <ExpandUp className="fill-current" />
243
+ </button>
244
+ </>
245
+ )
246
+ ) : (
247
+ <div className="min-h-[28px]">&ensp;</div>
248
+ )}
249
+ </td>
250
+ <td
251
+ className="diff-line-hunk-content pr-[10px] align-middle"
252
+ style={{ backgroundColor: `var(${hunkContentBGName})` }}
253
+ >
254
+ <div
255
+ className="pl-[1.5em]"
256
+ style={{
257
+ color: `var(${hunkContentColorName})`,
258
+ }}
259
+ >
260
+ {currentHunk.splitInfo?.plainText || currentHunk.text}
261
+ </div>
262
+ </td>
263
+ </tr>
264
+ );
265
+ };
266
+
267
+ const InternalDiffSplitHunkLine = ({
268
+ index,
269
+ diffFile,
270
+ side,
271
+ lineNumber,
272
+ }: {
273
+ index: number;
274
+ side: SplitSide;
275
+ diffFile: DiffFile;
276
+ lineNumber: number;
277
+ }) => {
278
+ const { useDiffContext } = useDiffViewContext();
279
+
280
+ const diffViewMode = useDiffContext.useShallowStableSelector((s) => s.mode);
281
+
282
+ if (
283
+ diffViewMode === DiffModeEnum.SplitGitHub ||
284
+ diffViewMode === DiffModeEnum.Split ||
285
+ diffViewMode === DiffModeEnum.Unified
286
+ ) {
287
+ return <InternalDiffSplitHunkLineGitHub index={index} diffFile={diffFile} side={side} lineNumber={lineNumber} />;
288
+ } else {
289
+ return <InternalDiffSplitHunkLineGitLab index={index} diffFile={diffFile} side={side} lineNumber={lineNumber} />;
290
+ }
291
+ };
292
+
293
+ export const DiffSplitHunkLine = ({
294
+ index,
295
+ diffFile,
296
+ side,
297
+ lineNumber,
298
+ }: {
299
+ index: number;
300
+ side: SplitSide;
301
+ diffFile: DiffFile;
302
+ lineNumber: number;
303
+ }) => {
304
+ const currentHunk = diffFile.getSplitHunkLine(index);
305
+
306
+ const currentIsShow =
307
+ currentHunk &&
308
+ currentHunk.splitInfo &&
309
+ currentHunk.splitInfo.startHiddenIndex < currentHunk.splitInfo.endHiddenIndex;
310
+
311
+ const currentIsPureHunk = currentHunk && diffFile._getIsPureDiffRender() && !currentHunk.splitInfo;
312
+
313
+ if (!currentIsShow && !currentIsPureHunk) return null;
314
+
315
+ return <InternalDiffSplitHunkLine index={index} diffFile={diffFile} side={side} lineNumber={lineNumber} />;
316
+ };
@@ -0,0 +1,340 @@
1
+ import { composeLen, type DiffFile } from "@git-diff-view/core";
2
+ import {
3
+ hunkLineNumberBGName,
4
+ plainLineNumberColorName,
5
+ hunkContentBGName,
6
+ hunkContentColorName,
7
+ borderColorName,
8
+ } from "@git-diff-view/utils";
9
+ import * as React from "react";
10
+
11
+ import { DiffModeEnum } from "..";
12
+
13
+ import { ExpandAll, ExpandDown, ExpandUp } from "./DiffExpand";
14
+ import { useDiffViewContext } from "./DiffViewContext";
15
+
16
+ const DiffSplitHunkLineGitHub = ({
17
+ index,
18
+ diffFile,
19
+ lineNumber,
20
+ }: {
21
+ index: number;
22
+ diffFile: DiffFile;
23
+ lineNumber: number;
24
+ }) => {
25
+ const currentHunk = diffFile.getSplitHunkLine(index);
26
+
27
+ const expandEnabled = diffFile.getExpandEnabled();
28
+
29
+ const couldExpand = expandEnabled && currentHunk && currentHunk.splitInfo;
30
+
31
+ const isExpandAll =
32
+ currentHunk &&
33
+ currentHunk.splitInfo &&
34
+ currentHunk.splitInfo.endHiddenIndex - currentHunk.splitInfo.startHiddenIndex < composeLen;
35
+
36
+ const isFirstLine = currentHunk && currentHunk.isFirst;
37
+
38
+ const isLastLine = currentHunk && currentHunk.isLast;
39
+
40
+ return (
41
+ <tr data-line={`${lineNumber}-hunk`} data-state="hunk" className="diff-line diff-line-hunk">
42
+ <td
43
+ className="diff-line-hunk-action relative w-[1%] min-w-[40px] select-none p-[1px]"
44
+ style={{
45
+ backgroundColor: `var(${hunkLineNumberBGName})`,
46
+ color: `var(${plainLineNumberColorName})`,
47
+ }}
48
+ >
49
+ {couldExpand ? (
50
+ isFirstLine ? (
51
+ <button
52
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
53
+ title="Expand Up"
54
+ data-title="Expand Up"
55
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
56
+ >
57
+ <ExpandUp className="fill-current" />
58
+ </button>
59
+ ) : isLastLine ? (
60
+ <button
61
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
62
+ title="Expand Down"
63
+ data-title="Expand Down"
64
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
65
+ >
66
+ <ExpandDown className="fill-current" />
67
+ </button>
68
+ ) : isExpandAll ? (
69
+ <button
70
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
71
+ title="Expand All"
72
+ data-title="Expand All"
73
+ onClick={() => diffFile.onSplitHunkExpand("all", index)}
74
+ >
75
+ <ExpandAll className="fill-current" />
76
+ </button>
77
+ ) : (
78
+ <>
79
+ <button
80
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
81
+ title="Expand Down"
82
+ data-title="Expand Down"
83
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
84
+ >
85
+ <ExpandDown className="fill-current" />
86
+ </button>
87
+ <button
88
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
89
+ title="Expand Up"
90
+ data-title="Expand Up"
91
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
92
+ >
93
+ <ExpandUp className="fill-current" />
94
+ </button>
95
+ </>
96
+ )
97
+ ) : (
98
+ <div className="min-h-[28px]">&ensp;</div>
99
+ )}
100
+ </td>
101
+ <td
102
+ className="diff-line-hunk-content pr-[10px] align-middle"
103
+ style={{ backgroundColor: `var(${hunkContentBGName})` }}
104
+ colSpan={3}
105
+ >
106
+ <div
107
+ className="pl-[1.5em]"
108
+ style={{
109
+ color: `var(${hunkContentColorName})`,
110
+ }}
111
+ >
112
+ {currentHunk.splitInfo?.plainText || currentHunk.text}
113
+ </div>
114
+ </td>
115
+ </tr>
116
+ );
117
+ };
118
+
119
+ const DiffSplitHunkLineGitLab = ({
120
+ index,
121
+ diffFile,
122
+ lineNumber,
123
+ }: {
124
+ index: number;
125
+ diffFile: DiffFile;
126
+ lineNumber: number;
127
+ }) => {
128
+ const currentHunk = diffFile.getSplitHunkLine(index);
129
+
130
+ const expandEnabled = diffFile.getExpandEnabled();
131
+
132
+ const couldExpand = expandEnabled && currentHunk && currentHunk.splitInfo;
133
+
134
+ const isExpandAll =
135
+ currentHunk &&
136
+ currentHunk.splitInfo &&
137
+ currentHunk.splitInfo.endHiddenIndex - currentHunk.splitInfo.startHiddenIndex < composeLen;
138
+
139
+ const isFirstLine = currentHunk && currentHunk.isFirst;
140
+
141
+ const isLastLine = currentHunk && currentHunk.isLast;
142
+
143
+ return (
144
+ <tr data-line={`${lineNumber}-hunk`} data-state="hunk" className="diff-line diff-line-hunk">
145
+ <td
146
+ className="diff-line-hunk-action relative w-[1%] min-w-[40px] select-none p-[1px]"
147
+ style={{
148
+ backgroundColor: `var(${hunkLineNumberBGName})`,
149
+ color: `var(${plainLineNumberColorName})`,
150
+ }}
151
+ >
152
+ {couldExpand ? (
153
+ isFirstLine ? (
154
+ <button
155
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
156
+ title="Expand Up"
157
+ data-title="Expand Up"
158
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
159
+ >
160
+ <ExpandUp className="fill-current" />
161
+ </button>
162
+ ) : isLastLine ? (
163
+ <button
164
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
165
+ title="Expand Down"
166
+ data-title="Expand Down"
167
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
168
+ >
169
+ <ExpandDown className="fill-current" />
170
+ </button>
171
+ ) : isExpandAll ? (
172
+ <button
173
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
174
+ title="Expand All"
175
+ data-title="Expand All"
176
+ onClick={() => diffFile.onSplitHunkExpand("all", index)}
177
+ >
178
+ <ExpandAll className="fill-current" />
179
+ </button>
180
+ ) : (
181
+ <>
182
+ <button
183
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
184
+ title="Expand Down"
185
+ data-title="Expand Down"
186
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
187
+ >
188
+ <ExpandDown className="fill-current" />
189
+ </button>
190
+ <button
191
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
192
+ title="Expand Up"
193
+ data-title="Expand Up"
194
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
195
+ >
196
+ <ExpandUp className="fill-current" />
197
+ </button>
198
+ </>
199
+ )
200
+ ) : (
201
+ <div className="min-h-[28px]">&ensp;</div>
202
+ )}
203
+ </td>
204
+ <td
205
+ className="diff-line-hunk-content pr-[10px] align-middle"
206
+ style={{ backgroundColor: `var(${hunkContentBGName})` }}
207
+ >
208
+ <div
209
+ className="pl-[1.5em]"
210
+ style={{
211
+ color: `var(${hunkContentColorName})`,
212
+ }}
213
+ >
214
+ {currentHunk.splitInfo?.plainText || currentHunk.text}
215
+ </div>
216
+ </td>
217
+ <td
218
+ className="diff-line-hunk-action relative z-[1] w-[1%] min-w-[40px] select-none border-l-[1px] p-[1px]"
219
+ style={{
220
+ backgroundColor: `var(${hunkLineNumberBGName})`,
221
+ color: `var(${plainLineNumberColorName})`,
222
+ borderLeftColor: `var(${borderColorName})`,
223
+ borderLeftStyle: "solid",
224
+ }}
225
+ >
226
+ {couldExpand ? (
227
+ isFirstLine ? (
228
+ <button
229
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
230
+ title="Expand Up"
231
+ data-title="Expand Up"
232
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
233
+ >
234
+ <ExpandUp className="fill-current" />
235
+ </button>
236
+ ) : isLastLine ? (
237
+ <button
238
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
239
+ title="Expand Down"
240
+ data-title="Expand Down"
241
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
242
+ >
243
+ <ExpandDown className="fill-current" />
244
+ </button>
245
+ ) : isExpandAll ? (
246
+ <button
247
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[6px]"
248
+ title="Expand All"
249
+ data-title="Expand All"
250
+ onClick={() => diffFile.onSplitHunkExpand("all", index)}
251
+ >
252
+ <ExpandAll className="fill-current" />
253
+ </button>
254
+ ) : (
255
+ <>
256
+ <button
257
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
258
+ title="Expand Down"
259
+ data-title="Expand Down"
260
+ onClick={() => diffFile.onSplitHunkExpand("down", index)}
261
+ >
262
+ <ExpandDown className="fill-current" />
263
+ </button>
264
+ <button
265
+ className="diff-widget-tooltip flex w-full cursor-pointer items-center justify-center rounded-[2px] py-[2px]"
266
+ title="Expand Up"
267
+ data-title="Expand Up"
268
+ onClick={() => diffFile.onSplitHunkExpand("up", index)}
269
+ >
270
+ <ExpandUp className="fill-current" />
271
+ </button>
272
+ </>
273
+ )
274
+ ) : (
275
+ <div className="min-h-[28px]">&ensp;</div>
276
+ )}
277
+ </td>
278
+ <td
279
+ className="diff-line-hunk-content relative pr-[10px] align-middle"
280
+ style={{ backgroundColor: `var(${hunkContentBGName})` }}
281
+ >
282
+ <div
283
+ className="pl-[1.5em]"
284
+ style={{
285
+ color: `var(${hunkContentColorName})`,
286
+ }}
287
+ >
288
+ {currentHunk.splitInfo?.plainText || currentHunk.text}
289
+ </div>
290
+ </td>
291
+ </tr>
292
+ );
293
+ };
294
+
295
+ const InternalDiffSplitHunkLine = ({
296
+ index,
297
+ diffFile,
298
+ lineNumber,
299
+ }: {
300
+ index: number;
301
+ diffFile: DiffFile;
302
+ lineNumber: number;
303
+ }) => {
304
+ const { useDiffContext } = useDiffViewContext();
305
+
306
+ const diffViewMode = useDiffContext.useShallowStableSelector((s) => s.mode);
307
+
308
+ if (
309
+ diffViewMode === DiffModeEnum.SplitGitHub ||
310
+ diffViewMode === DiffModeEnum.Split ||
311
+ diffViewMode === DiffModeEnum.Unified
312
+ ) {
313
+ return <DiffSplitHunkLineGitHub index={index} diffFile={diffFile} lineNumber={lineNumber} />;
314
+ } else {
315
+ return <DiffSplitHunkLineGitLab index={index} diffFile={diffFile} lineNumber={lineNumber} />;
316
+ }
317
+ };
318
+
319
+ export const DiffSplitHunkLine = ({
320
+ index,
321
+ diffFile,
322
+ lineNumber,
323
+ }: {
324
+ index: number;
325
+ diffFile: DiffFile;
326
+ lineNumber: number;
327
+ }) => {
328
+ const currentHunk = diffFile.getSplitHunkLine(index);
329
+
330
+ const currentIsShow =
331
+ currentHunk &&
332
+ currentHunk.splitInfo &&
333
+ currentHunk.splitInfo.startHiddenIndex < currentHunk.splitInfo.endHiddenIndex;
334
+
335
+ const currentIsPureHunk = currentHunk && diffFile._getIsPureDiffRender() && !currentHunk.splitInfo;
336
+
337
+ if (!currentIsShow && !currentIsPureHunk) return null;
338
+
339
+ return <InternalDiffSplitHunkLine index={index} diffFile={diffFile} lineNumber={lineNumber} />;
340
+ };
@@ -0,0 +1,46 @@
1
+ import { memo, useEffect, useMemo, useRef } from "react";
2
+ import * as React from "react";
3
+
4
+ import { DiffSplitViewNormal } from "./DiffSplitViewNormal";
5
+ import { DiffSplitViewWrap } from "./DiffSplitViewWrap";
6
+ import { useDiffViewContext } from "./DiffViewContext";
7
+ import { DiffWidgetContext } from "./DiffWidgetContext";
8
+ import { createDiffWidgetStore } from "./tools";
9
+
10
+ import type { DiffFile } from "@git-diff-view/core";
11
+
12
+ export const DiffSplitView = memo(({ diffFile }: { diffFile: DiffFile }) => {
13
+ const { useDiffContext } = useDiffViewContext();
14
+
15
+ const useDiffContextRef = useRef(useDiffContext);
16
+
17
+ useDiffContextRef.current = useDiffContext;
18
+
19
+ const { enableWrap, onCreateUseWidgetHook } = useDiffContext.useShallowStableSelector((s) => ({
20
+ enableWrap: s.enableWrap,
21
+ onCreateUseWidgetHook: s.onCreateUseWidgetHook,
22
+ }));
23
+
24
+ // performance optimization
25
+ const useWidget = useMemo(() => createDiffWidgetStore(useDiffContextRef), []);
26
+
27
+ const contextValue = useMemo(() => ({ useWidget }), [useWidget]);
28
+
29
+ useEffect(() => {
30
+ const { setWidget } = useWidget.getReadonlyState();
31
+
32
+ setWidget({});
33
+ }, [diffFile, useWidget]);
34
+
35
+ useEffect(() => {
36
+ onCreateUseWidgetHook?.(useWidget);
37
+ }, [useWidget, onCreateUseWidgetHook]);
38
+
39
+ return (
40
+ <DiffWidgetContext.Provider value={contextValue}>
41
+ {enableWrap ? <DiffSplitViewWrap diffFile={diffFile} /> : <DiffSplitViewNormal diffFile={diffFile} />}
42
+ </DiffWidgetContext.Provider>
43
+ );
44
+ });
45
+
46
+ DiffSplitView.displayName = "DiffSplitView";