@git-diff-view/react 0.0.26 → 0.0.27

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 +419 -287
  2. package/dist/cjs/index.development.js.map +1 -1
  3. package/dist/cjs/index.production.js +419 -287
  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 +353 -224
  8. package/dist/esm/index.mjs.map +1 -1
  9. package/index.d.ts +296 -16
  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,344 @@
1
+ import {
2
+ DiffLineType,
3
+ NewLineSymbol,
4
+ type DiffFile,
5
+ type DiffLine,
6
+ type diffChanges,
7
+ type SyntaxLine,
8
+ } from "@git-diff-view/core";
9
+ import {
10
+ addContentHighlightBGName,
11
+ delContentHighlightBGName,
12
+ diffFontSizeName,
13
+ getSymbol,
14
+ } from "@git-diff-view/utils";
15
+ import * as React from "react";
16
+
17
+ import { getStyleObjectFromString } from "./DiffContent";
18
+ import { DiffNoNewLine } from "./DiffNoNewLine";
19
+
20
+ const RenderRange = ({
21
+ str,
22
+ startIndex,
23
+ endIndex,
24
+ ranges,
25
+ isAdd,
26
+ indexRef,
27
+ }: {
28
+ str: string;
29
+ startIndex: number;
30
+ endIndex: number;
31
+ isAdd: boolean;
32
+ ranges: ReturnType<typeof diffChanges>["addRange"]["range"];
33
+ indexRef: { current: number };
34
+ }) => {
35
+ if (!str) return null;
36
+
37
+ const index = indexRef.current;
38
+
39
+ const range = ranges[index];
40
+
41
+ if (!range || endIndex < range.location || range.location + range.length < startIndex) return str.replace("\n", "");
42
+
43
+ const index1 = range.location - startIndex;
44
+ const index2 = index1 < 0 ? 0 : index1;
45
+ const str1 = str.slice(0, index2);
46
+ const str2 = str.slice(index2, index1 + range.length);
47
+ const str3 = str.slice(index1 + range.length);
48
+ const isStart = str1.length || range.location === startIndex;
49
+
50
+ const isEnd = str3.length || endIndex === range.location + range.length - 1;
51
+
52
+ if (isEnd && str3.length) indexRef.current++;
53
+
54
+ const isLast = str2.includes("\n");
55
+
56
+ const _str2 = isLast ? str2.replace("\n", "").replace("\r", "") : str2;
57
+
58
+ return (
59
+ <span
60
+ data-range-start={range.location}
61
+ data-range-end={range.location + range.length}
62
+ data-total={ranges.length}
63
+ data-index={index}
64
+ >
65
+ <span data-start={startIndex} data-end={endIndex}>
66
+ {str1}
67
+ <span
68
+ data-diff-highlight
69
+ style={{
70
+ backgroundColor: isAdd ? `var(${addContentHighlightBGName})` : `var(${delContentHighlightBGName})`,
71
+ borderTopLeftRadius: isStart ? "0.2em" : undefined,
72
+ borderBottomLeftRadius: isStart ? "0.2em" : undefined,
73
+ borderTopRightRadius: isEnd || isLast ? "0.2em" : undefined,
74
+ borderBottomRightRadius: isEnd || isLast ? "0.2em" : undefined,
75
+ }}
76
+ >
77
+ {_str2}
78
+ </span>
79
+ {/* 可能会出现一个node跨越多个range的情况 */}
80
+ {RenderRange({
81
+ str: str3,
82
+ startIndex: startIndex + str1.length + str2.length,
83
+ endIndex,
84
+ ranges,
85
+ isAdd,
86
+ indexRef,
87
+ })}
88
+ </span>
89
+ </span>
90
+ );
91
+ };
92
+
93
+ // TODO
94
+ const DiffSyntax = ({
95
+ rawLine,
96
+ diffLine,
97
+ operator,
98
+ syntaxLine,
99
+ enableWrap,
100
+ }: {
101
+ rawLine: string;
102
+ diffLine?: DiffLine;
103
+ syntaxLine?: SyntaxLine;
104
+ operator?: "add" | "del";
105
+ enableWrap?: boolean;
106
+ }) => {
107
+ if (!syntaxLine) {
108
+ return <DiffString rawLine={rawLine} diffLine={diffLine} operator={operator} />;
109
+ }
110
+
111
+ const diffRange = diffLine?.diffChanges;
112
+
113
+ if (diffRange?.hasLineChange) {
114
+ const isAdd = operator === "add";
115
+
116
+ const targetRange = diffRange.range.filter((i) => i.type === (isAdd ? 1 : -1));
117
+
118
+ const isNewLineSymbolChanged = diffRange.newLineSymbol;
119
+
120
+ const newLineSymbol = getSymbol(isNewLineSymbolChanged);
121
+
122
+ const hasNoTrailingNewLine = isNewLineSymbolChanged === NewLineSymbol.NEWLINE;
123
+
124
+ const rangeIndexRef = { current: 0 };
125
+
126
+ return (
127
+ <span className="diff-line-syntax-raw">
128
+ {syntaxLine.nodeList?.map(({ node, wrapper }, index) => {
129
+ const range = targetRange[rangeIndexRef.current];
130
+ if (!range || node.endIndex < range.location || range.location + range.length < node.startIndex) {
131
+ return (
132
+ <span
133
+ key={index}
134
+ data-start={node.startIndex}
135
+ data-end={node.endIndex}
136
+ className={wrapper?.properties?.className?.join(" ")}
137
+ style={getStyleObjectFromString(wrapper?.properties?.style || "")}
138
+ >
139
+ {node.value.replace("\n", "")}
140
+ </span>
141
+ );
142
+ } else {
143
+ return (
144
+ <span
145
+ key={index}
146
+ data-start={node.startIndex}
147
+ data-end={node.endIndex}
148
+ className={wrapper?.properties?.className?.join(" ")}
149
+ style={getStyleObjectFromString(wrapper?.properties?.style || "")}
150
+ >
151
+ {/* 将组件转换为函数调用,避免同级渲染时后续组件的index没有正确更新的问题 */}
152
+ {RenderRange({
153
+ str: node.value,
154
+ startIndex: node.startIndex,
155
+ endIndex: node.endIndex,
156
+ ranges: targetRange,
157
+ isAdd,
158
+ indexRef: rangeIndexRef,
159
+ })}
160
+ </span>
161
+ );
162
+ }
163
+ })}
164
+
165
+ {newLineSymbol && (
166
+ <span
167
+ data-newline-symbol
168
+ data-diff-highlight
169
+ className="rounded-[0.2em]"
170
+ style={{
171
+ backgroundColor: isAdd ? `var(${addContentHighlightBGName})` : `var(${delContentHighlightBGName})`,
172
+ }}
173
+ >
174
+ {newLineSymbol}
175
+ </span>
176
+ )}
177
+
178
+ {hasNoTrailingNewLine && (
179
+ <span
180
+ data-no-newline-at-end-of-file-symbol
181
+ className={enableWrap ? "block !text-red-500" : "inline-block align-middle !text-red-500"}
182
+ style={{
183
+ width: `var(${diffFontSizeName})`,
184
+ height: `var(${diffFontSizeName})`,
185
+ }}
186
+ >
187
+ <DiffNoNewLine />
188
+ </span>
189
+ )}
190
+ </span>
191
+ );
192
+ }
193
+
194
+ return (
195
+ <span className="diff-line-syntax-raw">
196
+ {syntaxLine?.nodeList?.map(({ node, wrapper }, index) => (
197
+ <span
198
+ key={index}
199
+ data-start={node.startIndex}
200
+ data-end={node.endIndex}
201
+ className={wrapper?.properties?.className?.join(" ")}
202
+ style={getStyleObjectFromString(wrapper?.properties?.style || "")}
203
+ >
204
+ {node.value}
205
+ </span>
206
+ ))}
207
+ </span>
208
+ );
209
+ };
210
+
211
+ // TODO
212
+ const DiffString = ({
213
+ rawLine,
214
+ diffLine,
215
+ operator,
216
+ enableWrap,
217
+ }: {
218
+ rawLine: string;
219
+ diffLine?: DiffLine;
220
+ operator?: "add" | "del";
221
+ enableWrap?: boolean;
222
+ }) => {
223
+ const diffRange = diffLine?.diffChanges;
224
+
225
+ const isAdd = operator === "add";
226
+
227
+ if (diffRange?.hasLineChange) {
228
+ const targetRange = diffRange.range;
229
+
230
+ const isNewLineSymbolChanged = diffRange.newLineSymbol;
231
+
232
+ const newLineSymbol = getSymbol(isNewLineSymbolChanged);
233
+
234
+ const hasNoTrailingNewLine = isNewLineSymbolChanged === NewLineSymbol.NEWLINE;
235
+
236
+ return (
237
+ <span className="diff-line-content-raw">
238
+ {targetRange.map(({ type, str, location, length }, index) => {
239
+ if (type === 0) {
240
+ return <span key={index}>{str}</span>;
241
+ } else {
242
+ return (
243
+ <span key={index} data-range-start={location} data-range-end={location + length}>
244
+ <span
245
+ data-diff-highlight
246
+ className="rounded-[0.2em]"
247
+ style={{
248
+ backgroundColor: isAdd ? `var(${addContentHighlightBGName})` : `var(${delContentHighlightBGName})`,
249
+ }}
250
+ >
251
+ {str}
252
+ </span>
253
+ </span>
254
+ );
255
+ }
256
+ })}
257
+
258
+ {newLineSymbol && (
259
+ <span
260
+ data-newline-symbol
261
+ data-diff-highlight
262
+ className="rounded-[0.2em]"
263
+ style={{
264
+ backgroundColor: isAdd ? `var(${addContentHighlightBGName})` : `var(${delContentHighlightBGName})`,
265
+ }}
266
+ >
267
+ {newLineSymbol}
268
+ </span>
269
+ )}
270
+
271
+ {hasNoTrailingNewLine && (
272
+ <span
273
+ data-no-newline-at-end-of-file-symbol
274
+ className={enableWrap ? "block !text-red-500" : "inline-block align-middle !text-red-500"}
275
+ style={{
276
+ width: `var(${diffFontSizeName})`,
277
+ height: `var(${diffFontSizeName})`,
278
+ }}
279
+ >
280
+ <DiffNoNewLine />
281
+ </span>
282
+ )}
283
+ </span>
284
+ );
285
+ } else {
286
+ return <span className="diff-line-content-raw">{rawLine}</span>;
287
+ }
288
+ };
289
+
290
+ // TODO
291
+ export const DiffContent_v2 = ({
292
+ diffLine,
293
+ rawLine,
294
+ syntaxLine,
295
+ enableWrap,
296
+ enableHighlight,
297
+ }: {
298
+ rawLine: string;
299
+ syntaxLine?: SyntaxLine;
300
+ diffLine?: DiffLine;
301
+ diffFile: DiffFile;
302
+ enableWrap: boolean;
303
+ enableHighlight: boolean;
304
+ }) => {
305
+ const isAdded = diffLine?.type === DiffLineType.Add;
306
+
307
+ const isDelete = diffLine?.type === DiffLineType.Delete;
308
+
309
+ const isMaxLineLengthToIgnoreSyntax = syntaxLine?.nodeList?.length > 150;
310
+
311
+ return (
312
+ <div
313
+ className="diff-line-content-item pl-[2.0em]"
314
+ // data-val={rawLine}
315
+ style={{
316
+ whiteSpace: enableWrap ? "pre-wrap" : "pre",
317
+ wordBreak: enableWrap ? "break-all" : "initial",
318
+ }}
319
+ >
320
+ <span
321
+ data-operator={isAdded ? "+" : isDelete ? "-" : undefined}
322
+ className="diff-line-content-operator ml-[-1.5em] inline-block w-[1.5em] select-none indent-[0.2em]"
323
+ >
324
+ {isAdded ? "+" : isDelete ? "-" : " "}
325
+ </span>
326
+ {enableHighlight && syntaxLine && !isMaxLineLengthToIgnoreSyntax ? (
327
+ <DiffSyntax
328
+ operator={isAdded ? "add" : isDelete ? "del" : undefined}
329
+ rawLine={rawLine}
330
+ diffLine={diffLine}
331
+ syntaxLine={syntaxLine}
332
+ enableWrap={enableWrap}
333
+ />
334
+ ) : (
335
+ <DiffString
336
+ operator={isAdded ? "add" : isDelete ? "del" : undefined}
337
+ rawLine={rawLine}
338
+ diffLine={diffLine}
339
+ enableWrap={enableWrap}
340
+ />
341
+ )}
342
+ </div>
343
+ );
344
+ };
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+
3
+ export const ExpandDown = ({ className }: { className?: string }) => {
4
+ return (
5
+ <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" className={className}>
6
+ <path d="m8.177 14.323 2.896-2.896a.25.25 0 0 0-.177-.427H8.75V7.764a.75.75 0 1 0-1.5 0V11H5.104a.25.25 0 0 0-.177.427l2.896 2.896a.25.25 0 0 0 .354 0ZM2.25 5a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM6 4.25a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5a.75.75 0 0 1 .75.75ZM8.25 5a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM12 4.25a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5a.75.75 0 0 1 .75.75Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5Z"></path>
7
+ </svg>
8
+ );
9
+ };
10
+
11
+ export const ExpandUp = ({ className }: { className?: string }) => {
12
+ return (
13
+ <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" className={className}>
14
+ <path d="M7.823 1.677 4.927 4.573A.25.25 0 0 0 5.104 5H7.25v3.236a.75.75 0 1 0 1.5 0V5h2.146a.25.25 0 0 0 .177-.427L8.177 1.677a.25.25 0 0 0-.354 0ZM13.75 11a.75.75 0 0 0 0 1.5h.5a.75.75 0 0 0 0-1.5h-.5Zm-3.75.75a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75ZM7.75 11a.75.75 0 0 0 0 1.5h.5a.75.75 0 0 0 0-1.5h-.5ZM4 11.75a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75ZM1.75 11a.75.75 0 0 0 0 1.5h.5a.75.75 0 0 0 0-1.5h-.5Z"></path>
15
+ </svg>
16
+ );
17
+ };
18
+
19
+ export const ExpandAll = ({ className }: { className?: string }) => {
20
+ return (
21
+ <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" className={className}>
22
+ <path d="m8.177.677 2.896 2.896a.25.25 0 0 1-.177.427H8.75v1.25a.75.75 0 0 1-1.5 0V4H5.104a.25.25 0 0 1-.177-.427L7.823.677a.25.25 0 0 1 .354 0ZM7.25 10.75a.75.75 0 0 1 1.5 0V12h2.146a.25.25 0 0 1 .177.427l-2.896 2.896a.25.25 0 0 1-.354 0l-2.896-2.896A.25.25 0 0 1 5.104 12H7.25v-1.25Zm-5-2a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM6 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 6 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM12 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 12 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5Z"></path>
23
+ </svg>
24
+ );
25
+ };
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+
3
+ export const DiffNoNewLine = () => {
4
+ return (
5
+ <svg aria-label="No newline at end of file" role="img" viewBox="0 0 16 16" version="1.1" fill="currentColor">
6
+ <path d="M4.25 7.25a.75.75 0 0 0 0 1.5h7.5a.75.75 0 0 0 0-1.5h-7.5Z"></path>
7
+ <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-1.5 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 0 0 13 0Z"></path>
8
+ </svg>
9
+ );
10
+ };
@@ -0,0 +1,164 @@
1
+ import { DiffLineType, type DiffFile, checkDiffLineIncludeChange } from "@git-diff-view/core";
2
+ import {
3
+ getContentBG,
4
+ getLineNumberBG,
5
+ plainLineNumberColorName,
6
+ diffAsideWidthName,
7
+ emptyBGName,
8
+ expandLineNumberColorName,
9
+ } from "@git-diff-view/utils";
10
+ import * as React from "react";
11
+
12
+ import { SplitSide } from "..";
13
+
14
+ import { DiffSplitAddWidget } from "./DiffAddWidget";
15
+ import { DiffContent } from "./DiffContent";
16
+ // import { DiffContent_v2 } from "./DiffContent_v2";
17
+ import { useDiffViewContext } from "./DiffViewContext";
18
+ import { useDiffWidgetContext } from "./DiffWidgetContext";
19
+
20
+ const InternalDiffSplitLine = ({
21
+ index,
22
+ diffFile,
23
+ lineNumber,
24
+ side,
25
+ enableAddWidget,
26
+ enableHighlight,
27
+ }: {
28
+ index: number;
29
+ side: SplitSide;
30
+ diffFile: DiffFile;
31
+ lineNumber: number;
32
+ enableHighlight: boolean;
33
+ enableAddWidget: boolean;
34
+ }) => {
35
+ const getCurrentSyntaxLine = side === SplitSide.old ? diffFile.getOldSyntaxLine : diffFile.getNewSyntaxLine;
36
+
37
+ const getCurrentPlainLine = side === SplitSide.old ? diffFile.getOldPlainLine : diffFile.getNewPlainLine;
38
+
39
+ const oldLine = diffFile.getSplitLeftLine(index);
40
+
41
+ const newLine = diffFile.getSplitRightLine(index);
42
+
43
+ const currentLine = side === SplitSide.old ? oldLine : newLine;
44
+
45
+ const hasDiff = !!currentLine?.diff;
46
+
47
+ const hasContent = !!currentLine.lineNumber;
48
+
49
+ const hasChange = checkDiffLineIncludeChange(currentLine?.diff);
50
+
51
+ const isAdded = currentLine?.diff?.type === DiffLineType.Add;
52
+
53
+ const isDelete = currentLine?.diff?.type === DiffLineType.Delete;
54
+
55
+ const { useDiffContext } = useDiffViewContext();
56
+
57
+ const onAddWidgetClick = useDiffContext.getReadonlyState().onAddWidgetClick;
58
+
59
+ const { useWidget } = useDiffWidgetContext();
60
+
61
+ const setWidget = useWidget.getReadonlyState().setWidget;
62
+
63
+ const contentBG = getContentBG(isAdded, isDelete, hasDiff);
64
+
65
+ const lineNumberBG = getLineNumberBG(isAdded, isDelete, hasDiff);
66
+
67
+ const syntaxLine = getCurrentSyntaxLine(currentLine.lineNumber);
68
+
69
+ const plainLine = getCurrentPlainLine(currentLine.lineNumber);
70
+
71
+ return (
72
+ <tr
73
+ data-line={lineNumber}
74
+ data-state={hasDiff || !hasContent ? "diff" : "plain"}
75
+ data-side={SplitSide[side]}
76
+ className={"diff-line" + (hasContent ? " group" : "")}
77
+ >
78
+ {hasContent ? (
79
+ <>
80
+ <td
81
+ className={`diff-line-${SplitSide[side]}-num sticky left-0 w-[1%] min-w-[40px] select-none pl-[10px] pr-[10px] text-right align-top`}
82
+ style={{
83
+ backgroundColor: lineNumberBG,
84
+ color: `var(${hasDiff ? plainLineNumberColorName : expandLineNumberColorName})`,
85
+ width: `var(${diffAsideWidthName})`,
86
+ minWidth: `var(${diffAsideWidthName})`,
87
+ maxWidth: `var(${diffAsideWidthName})`,
88
+ }}
89
+ >
90
+ {hasDiff && enableAddWidget && (
91
+ <DiffSplitAddWidget
92
+ index={index}
93
+ lineNumber={currentLine.lineNumber}
94
+ side={side}
95
+ diffFile={diffFile}
96
+ onWidgetClick={(...props) => onAddWidgetClick.current?.(...props)}
97
+ className="absolute left-[100%] z-[1] translate-x-[-50%]"
98
+ onOpenAddWidget={(lineNumber, side) => setWidget({ lineNumber: lineNumber, side: side })}
99
+ />
100
+ )}
101
+ <span data-line-num={currentLine.lineNumber} style={{ opacity: hasChange ? undefined : 0.5 }}>
102
+ {currentLine.lineNumber}
103
+ </span>
104
+ </td>
105
+ <td
106
+ className={`diff-line-${SplitSide[side]}-content pr-[10px] align-top`}
107
+ style={{ backgroundColor: contentBG }}
108
+ >
109
+ <DiffContent
110
+ enableWrap={false}
111
+ diffFile={diffFile}
112
+ rawLine={currentLine.value!}
113
+ diffLine={currentLine.diff}
114
+ plainLine={plainLine}
115
+ syntaxLine={syntaxLine}
116
+ enableHighlight={enableHighlight}
117
+ />
118
+ </td>
119
+ </>
120
+ ) : (
121
+ <td
122
+ className={`diff-line-${SplitSide[side]}-placeholder select-none`}
123
+ style={{ backgroundColor: `var(${emptyBGName})` }}
124
+ colSpan={2}
125
+ >
126
+ <span>&ensp;</span>
127
+ </td>
128
+ )}
129
+ </tr>
130
+ );
131
+ };
132
+
133
+ export const DiffSplitContentLine = ({
134
+ index,
135
+ diffFile,
136
+ lineNumber,
137
+ side,
138
+ enableAddWidget,
139
+ enableHighlight,
140
+ }: {
141
+ index: number;
142
+ side: SplitSide;
143
+ diffFile: DiffFile;
144
+ lineNumber: number;
145
+ enableHighlight: boolean;
146
+ enableAddWidget: boolean;
147
+ }) => {
148
+ const getCurrentLine = side === SplitSide.old ? diffFile.getSplitLeftLine : diffFile.getSplitRightLine;
149
+
150
+ const currentLine = getCurrentLine(index);
151
+
152
+ if (currentLine?.isHidden) return null;
153
+
154
+ return (
155
+ <InternalDiffSplitLine
156
+ index={index}
157
+ diffFile={diffFile}
158
+ lineNumber={lineNumber}
159
+ side={side}
160
+ enableAddWidget={enableAddWidget}
161
+ enableHighlight={enableHighlight}
162
+ />
163
+ );
164
+ };