Skip to content

Commit 518ddb9

Browse files
provider theme api for cli part
1 parent 2e1c8d9 commit 518ddb9

16 files changed

Lines changed: 306 additions & 212 deletions

packages/cli/index.d.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,37 @@ export declare enum DiffModeEnum {
10051005
Split = 3,
10061006
Unified = 4
10071007
}
1008+
export type ThemeColor = {
1009+
light: string;
1010+
dark: string;
1011+
};
1012+
export interface DiffViewColorTheme {
1013+
addContent?: ThemeColor;
1014+
delContent?: ThemeColor;
1015+
plainContent?: ThemeColor;
1016+
expandContent?: ThemeColor;
1017+
emptyContent?: ThemeColor;
1018+
addLineNumber?: ThemeColor;
1019+
delLineNumber?: ThemeColor;
1020+
plainLineNumber?: ThemeColor;
1021+
expandLineNumber?: ThemeColor;
1022+
hunkLineNumber?: ThemeColor;
1023+
plainLineNumberColor?: ThemeColor;
1024+
expandLineNumberColor?: ThemeColor;
1025+
hunkContentColor?: ThemeColor;
1026+
addContentHighlight?: ThemeColor;
1027+
delContentHighlight?: ThemeColor;
1028+
hunkContent?: ThemeColor;
1029+
border?: ThemeColor;
1030+
noBGAddContent?: ThemeColor;
1031+
noBGDelContent?: ThemeColor;
1032+
noBGAddLineNumber?: ThemeColor;
1033+
noBGDelLineNumber?: ThemeColor;
1034+
noBGAddContentHighlight?: ThemeColor;
1035+
noBGDelContentHighlight?: ThemeColor;
1036+
}
1037+
export type ResolvedDiffViewColorTheme = Required<DiffViewColorTheme>;
1038+
export declare const buildTheme: (overrides?: DiffViewColorTheme) => ResolvedDiffViewColorTheme;
10081039
export type DiffViewProps<T> = {
10091040
data?: {
10101041
oldFile?: {
@@ -1037,6 +1068,7 @@ export type DiffViewProps<T> = {
10371068
diffViewHighlight?: boolean;
10381069
diffViewHideOperator?: boolean;
10391070
diffViewNoBG?: boolean;
1071+
diffViewThemeColors?: DiffViewColorTheme;
10401072
renderExtendLine?: ({ diffFile, side, data, lineNumber, onUpdate, }: {
10411073
lineNumber: number;
10421074
side: SplitSide;
@@ -1104,6 +1136,7 @@ export type CodeViewProps<T> = {
11041136
registerHighlighter?: Omit<DiffHighlighter, "getHighlighterEngine">;
11051137
codeViewHighlight?: boolean;
11061138
codeViewNoBG?: boolean;
1139+
codeViewThemeColors?: DiffViewColorTheme;
11071140
renderExtendLine?: ({ file, data, lineNumber }: {
11081141
file: File$1;
11091142
lineNumber: number;

packages/cli/src/components/CodeContent.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import * as React from "react";
77

88
import { buildAnsiStringWithLineBreaks, buildStyledBlock, type CharStyle } from "./ansiString";
99
import { useCodeViewContext } from "./CodeViewContext";
10-
import { diffPlainContent } from "./color";
1110
import { getStyleObjectFromString, getStyleFromClassName } from "./DiffContent";
1211

12+
import type { ResolvedDiffViewColorTheme } from "./color";
1313
import type { File } from "@git-diff-view/core";
1414

1515
// Helper to get tab width value
@@ -212,6 +212,7 @@ CodePadding.displayName = "CodePadding";
212212
export const CodeContent = React.memo(
213213
({
214214
theme,
215+
themeColors,
215216
width,
216217
height,
217218
rawLine,
@@ -222,6 +223,7 @@ export const CodeContent = React.memo(
222223
width: number;
223224
height: number;
224225
theme: "light" | "dark";
226+
themeColors: ResolvedDiffViewColorTheme;
225227
rawLine: string;
226228
plainLine?: File["plainFile"][number];
227229
syntaxLine?: File["syntaxFile"][number];
@@ -232,8 +234,8 @@ export const CodeContent = React.memo(
232234

233235
const bg = React.useMemo(() => {
234236
if (noBG) return undefined;
235-
return theme === "light" ? diffPlainContent.light : diffPlainContent.dark;
236-
}, [theme, noBG]);
237+
return theme === "light" ? themeColors.plainContent.light : themeColors.plainContent.dark;
238+
}, [theme, noBG, themeColors]);
237239

238240
// Content width is total width minus 2 char padding (1 on each side)
239241
const contentWidth = width - 2;

packages/cli/src/components/CodeView.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import { CodeExtendLine } from "./CodeExtendLine";
1313
import { CodeLineNumberArea } from "./CodeLineNumber";
1414
import { createCodeConfigStore, getCurrentLineRow } from "./codeTools";
1515
import { CodeViewContext, useCodeViewContext } from "./CodeViewContext";
16-
import { diffPlainLineNumber, diffPlainLineNumberColor } from "./color";
1716

17+
import type { DiffViewColorTheme, ResolvedDiffViewColorTheme } from "./color";
1818
import type { DiffHighlighter, DiffHighlighterLang, File } from "@git-diff-view/core";
1919
import type { DOMElement } from "ink";
2020
import type { ForwardedRef, JSX, ReactNode, RefObject } from "react";
@@ -38,6 +38,8 @@ export type CodeViewProps<T> = {
3838
codeViewHighlight?: boolean;
3939
// disable background colors for transparent terminal rendering
4040
codeViewNoBG?: boolean;
41+
// custom theme colors to override defaults
42+
codeViewThemeColors?: DiffViewColorTheme;
4143
renderExtendLine?: ({ file, data, lineNumber }: { file: File; lineNumber: number; data: T }) => ReactNode;
4244
};
4345

@@ -69,6 +71,7 @@ const CodeLine = memo(
6971
lineNumWidth,
7072
enableHighlight,
7173
noBG,
74+
themeColors,
7275
}: {
7376
lineNumber: number;
7477
theme: "light" | "dark";
@@ -77,6 +80,7 @@ const CodeLine = memo(
7780
lineNumWidth: number;
7881
enableHighlight: boolean;
7982
noBG: boolean;
83+
themeColors: ResolvedDiffViewColorTheme;
8084
}) => {
8185
const rawLine = file.rawFile[lineNumber] || "";
8286
const syntaxLine = file.syntaxFile[lineNumber];
@@ -87,8 +91,12 @@ const CodeLine = memo(
8791
// Calculate row height based on actual text width (content width minus 2 char padding on both sides)
8892
const row = getCurrentLineRow({ content: rawLine, width: contentWidth - 2 });
8993

90-
const bg = noBG ? undefined : theme === "light" ? diffPlainLineNumber.light : diffPlainLineNumber.dark;
91-
const color = theme === "light" ? diffPlainLineNumberColor.light : diffPlainLineNumberColor.dark;
94+
const bg = noBG
95+
? undefined
96+
: theme === "light"
97+
? themeColors.plainLineNumber.light
98+
: themeColors.plainLineNumber.dark;
99+
const color = theme === "light" ? themeColors.plainLineNumberColor.light : themeColors.plainLineNumberColor.dark;
92100

93101
return (
94102
<Box data-line={lineNumber} height={row} width={columns}>
@@ -109,6 +117,7 @@ const CodeLine = memo(
109117
syntaxLine={syntaxLine}
110118
enableHighlight={enableHighlight}
111119
noBG={noBG}
120+
themeColors={themeColors}
112121
/>
113122
</Box>
114123
);
@@ -123,9 +132,10 @@ CodeLine.displayName = "CodeLine";
123132
const CodeViewContent = memo(({ file, theme, width }: { file: File; theme: "light" | "dark"; width?: number }) => {
124133
const { useCodeContext } = useCodeViewContext();
125134

126-
const { enableHighlight, noBG } = useCodeContext((s) => ({
135+
const { enableHighlight, noBG, themeColors } = useCodeContext((s) => ({
127136
enableHighlight: s.enableHighlight,
128137
noBG: s.noBG,
138+
themeColors: s.themeColors,
129139
}));
130140

131141
const { columns: _columns } = useCodeTerminalSize();
@@ -158,6 +168,7 @@ const CodeViewContent = memo(({ file, theme, width }: { file: File; theme: "ligh
158168
lineNumWidth={lineNumWidth}
159169
enableHighlight={enableHighlight ?? false}
160170
noBG={noBG ?? false}
171+
themeColors={themeColors}
161172
/>
162173
<CodeExtendLine columns={columns} lineNumber={lineNumber} file={file} />
163174
</Fragment>
@@ -188,6 +199,7 @@ const InternalCodeView = <T,>(
188199
codeViewTabWidth,
189200
codeViewTheme,
190201
codeViewNoBG,
202+
codeViewThemeColors,
191203
} = props;
192204

193205
const fileId = file.getId();
@@ -213,6 +225,7 @@ const InternalCodeView = <T,>(
213225
setTabWidth,
214226
noBG,
215227
setNoBG,
228+
setThemeColors,
216229
} = useCodeContext.getReadonlyState();
217230

218231
if (fileId && fileId !== id) {
@@ -246,6 +259,8 @@ const InternalCodeView = <T,>(
246259
if (codeViewNoBG !== noBG) {
247260
setNoBG(!!codeViewNoBG);
248261
}
262+
263+
setThemeColors(codeViewThemeColors);
249264
}, [
250265
_width,
251266
useCodeContext,
@@ -256,6 +271,7 @@ const InternalCodeView = <T,>(
256271
codeViewTabSpace,
257272
codeViewTabWidth,
258273
codeViewNoBG,
274+
codeViewThemeColors,
259275
props.extendData,
260276
props.renderExtendLine,
261277
]);

packages/cli/src/components/DiffContent.tsx

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,10 @@ import { Box, Text } from "ink";
55
import * as React from "react";
66

77
import { buildAnsiStringWithLineBreaks, buildStyledBlock, type CharStyle } from "./ansiString";
8-
import {
9-
diffAddContent,
10-
diffAddContentHighlight,
11-
diffDelContent,
12-
diffDelContentHighlight,
13-
diffExpandContent,
14-
diffPlainContent,
15-
noBGDiffAddContent,
16-
noBGDiffAddContentHighlight,
17-
noBGDiffDelContent,
18-
noBGDiffDelContentHighlight,
19-
GitHubDark,
20-
GitHubLight,
21-
} from "./color";
8+
import { GitHubDark, GitHubLight } from "./color";
229
import { useDiffViewContext } from "./DiffViewContext";
2310

11+
import type { ResolvedDiffViewColorTheme } from "./color";
2412
import type { DiffFile, DiffLine, File } from "@git-diff-view/core";
2513

2614
// Helper to get tab width value
@@ -115,6 +103,7 @@ const DiffString = React.memo(
115103
diffLine,
116104
operator,
117105
noBG,
106+
themeColors,
118107
}: {
119108
bg?: string;
120109
width: number;
@@ -125,6 +114,7 @@ const DiffString = React.memo(
125114
operator?: "add" | "del";
126115
plainLine?: File["plainFile"][number];
127116
noBG?: boolean;
117+
themeColors: ResolvedDiffViewColorTheme;
128118
}) => {
129119
const changes = diffLine?.changes;
130120

@@ -145,8 +135,8 @@ const DiffString = React.memo(
145135
const str2 = rawLine.slice(range.location, range.location + range.length);
146136
const str3 = rawLine.slice(range.location + range.length);
147137

148-
const addHighlight = noBG ? noBGDiffAddContentHighlight : diffAddContentHighlight;
149-
const delHighlight = noBG ? noBGDiffDelContentHighlight : diffDelContentHighlight;
138+
const addHighlight = noBG ? themeColors.noBGAddContentHighlight : themeColors.addContentHighlight;
139+
const delHighlight = noBG ? themeColors.noBGDelContentHighlight : themeColors.delContentHighlight;
150140
const highlightBG =
151141
operator === "add"
152142
? theme === "light"
@@ -176,7 +166,7 @@ const DiffString = React.memo(
176166

177167
// Use width - 2 because the operator column takes 1 character and end padding takes 1 character
178168
return buildAnsiStringWithLineBreaks(chars, width - 2);
179-
}, [bg, width, theme, rawLine, changes, operator, enableTabSpace, tabWidth, noBG]);
169+
}, [bg, width, theme, rawLine, changes, operator, enableTabSpace, tabWidth, noBG, themeColors]);
180170

181171
return (
182172
<Box width={width - 2} backgroundColor={bg}>
@@ -246,6 +236,7 @@ const DiffSyntax = React.memo(
246236
operator,
247237
syntaxLine,
248238
noBG,
239+
themeColors,
249240
}: {
250241
bg?: string;
251242
width: number;
@@ -256,6 +247,7 @@ const DiffSyntax = React.memo(
256247
syntaxLine?: File["syntaxFile"][number];
257248
operator?: "add" | "del";
258249
noBG?: boolean;
250+
themeColors: ResolvedDiffViewColorTheme;
259251
}) => {
260252
const { useDiffContext } = useDiffViewContext();
261253

@@ -273,8 +265,8 @@ const DiffSyntax = React.memo(
273265
const chars: Array<{ char: string; style?: CharStyle }> = [];
274266
const baseStyle: CharStyle = { backgroundColor: bg };
275267

276-
const addHighlight = noBG ? noBGDiffAddContentHighlight : diffAddContentHighlight;
277-
const delHighlight = noBG ? noBGDiffDelContentHighlight : diffDelContentHighlight;
268+
const addHighlight = noBG ? themeColors.noBGAddContentHighlight : themeColors.addContentHighlight;
269+
const delHighlight = noBG ? themeColors.noBGDelContentHighlight : themeColors.delContentHighlight;
278270
const highlightBG =
279271
operator === "add"
280272
? theme === "light"
@@ -355,7 +347,7 @@ const DiffSyntax = React.memo(
355347

356348
// Use width - 2 because the operator column takes 1 character and end padding takes 1 character
357349
return buildAnsiStringWithLineBreaks(chars, width - 2);
358-
}, [bg, width, theme, diffLine, operator, syntaxLine, enableTabSpace, tabWidth, noBG]);
350+
}, [bg, width, theme, diffLine, operator, syntaxLine, enableTabSpace, tabWidth, noBG, themeColors]);
359351

360352
// Fallback to DiffString if no syntax line
361353
if (!syntaxLine) {
@@ -369,6 +361,7 @@ const DiffSyntax = React.memo(
369361
diffLine={diffLine}
370362
operator={operator}
371363
noBG={noBG}
364+
themeColors={themeColors}
372365
/>
373366
);
374367
}
@@ -448,6 +441,7 @@ export const DiffContent = React.memo(
448441
syntaxLine,
449442
enableHighlight,
450443
noBG,
444+
themeColors,
451445
}: {
452446
width: number;
453447
height: number;
@@ -459,6 +453,7 @@ export const DiffContent = React.memo(
459453
diffFile: DiffFile;
460454
enableHighlight: boolean;
461455
noBG?: boolean;
456+
themeColors: ResolvedDiffViewColorTheme;
462457
}) => {
463458
const { useDiffContext } = useDiffViewContext();
464459

@@ -469,19 +464,19 @@ export const DiffContent = React.memo(
469464
const isMaxLineLengthToIgnoreSyntax = syntaxLine && syntaxLine?.nodeList?.length > 150;
470465

471466
const bg = React.useMemo(() => {
472-
const addColors = noBG ? noBGDiffAddContent : diffAddContent;
473-
const delColors = noBG ? noBGDiffDelContent : diffDelContent;
467+
const addColors = noBG ? themeColors.noBGAddContent : themeColors.addContent;
468+
const delColors = noBG ? themeColors.noBGDelContent : themeColors.delContent;
474469
if (isAdded) return theme === "light" ? addColors.light : addColors.dark;
475470
if (isDelete) return theme === "light" ? delColors.light : delColors.dark;
476471
if (noBG) return undefined;
477472
return theme === "light"
478473
? diffLine
479-
? diffPlainContent.light
480-
: diffExpandContent.light
474+
? themeColors.plainContent.light
475+
: themeColors.expandContent.light
481476
: diffLine
482-
? diffPlainContent.dark
483-
: diffExpandContent.dark;
484-
}, [theme, diffLine, isAdded, isDelete, noBG]);
477+
? themeColors.plainContent.dark
478+
: themeColors.expandContent.dark;
479+
}, [theme, diffLine, isAdded, isDelete, noBG, themeColors]);
485480

486481
const operatorChar = isAdded ? "+" : isDelete ? "-" : " ";
487482

@@ -503,6 +498,7 @@ export const DiffContent = React.memo(
503498
diffLine={diffLine}
504499
syntaxLine={syntaxLine}
505500
noBG={noBG}
501+
themeColors={themeColors}
506502
/>
507503
) : (
508504
<DiffString
@@ -515,6 +511,7 @@ export const DiffContent = React.memo(
515511
diffLine={diffLine}
516512
plainLine={plainLine}
517513
noBG={noBG}
514+
themeColors={themeColors}
518515
/>
519516
)}
520517
<DiffPadding height={height} backgroundColor={bg} />

0 commit comments

Comments
 (0)