@kitlangton/ghui 0.3.0 → 0.3.2
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.
- package/bin/ghui.js +6 -1
- package/dist/index.js +9419 -0
- package/package.json +7 -4
- package/src/App.tsx +0 -2779
- package/src/appCommands.ts +0 -409
- package/src/commands.ts +0 -73
- package/src/config.ts +0 -20
- package/src/date.ts +0 -20
- package/src/domain.ts +0 -149
- package/src/errors.ts +0 -10
- package/src/index.tsx +0 -50
- package/src/keyboard/opentuiAdapter.ts +0 -43
- package/src/keymap/all.ts +0 -116
- package/src/keymap/changedFilesModal.ts +0 -23
- package/src/keymap/closeModal.ts +0 -13
- package/src/keymap/commandPalette.ts +0 -16
- package/src/keymap/commentModal.ts +0 -73
- package/src/keymap/commentThreadModal.ts +0 -24
- package/src/keymap/detailView.ts +0 -30
- package/src/keymap/diffView.ts +0 -93
- package/src/keymap/filterMode.ts +0 -13
- package/src/keymap/helpers.ts +0 -24
- package/src/keymap/labelModal.ts +0 -16
- package/src/keymap/listNav.ts +0 -119
- package/src/keymap/mergeModal.ts +0 -23
- package/src/keymap/openRepositoryModal.ts +0 -13
- package/src/keymap/submitReviewModal.ts +0 -48
- package/src/keymap/themeModal.ts +0 -49
- package/src/mergeActions.ts +0 -88
- package/src/observability.ts +0 -46
- package/src/pullRequestCache.ts +0 -19
- package/src/pullRequestViews.ts +0 -43
- package/src/services/BrowserOpener.ts +0 -22
- package/src/services/Clipboard.ts +0 -46
- package/src/services/CommandRunner.ts +0 -91
- package/src/services/GitHubService.ts +0 -756
- package/src/services/MockGitHubService.ts +0 -182
- package/src/themeStore.ts +0 -60
- package/src/ui/CommandPalette.tsx +0 -176
- package/src/ui/DetailsPane.tsx +0 -656
- package/src/ui/FooterHints.tsx +0 -90
- package/src/ui/LoadingLogo.tsx +0 -75
- package/src/ui/PullRequestDiffPane.tsx +0 -249
- package/src/ui/PullRequestList.tsx +0 -194
- package/src/ui/colors.ts +0 -821
- package/src/ui/commentEditor.ts +0 -126
- package/src/ui/comments.tsx +0 -143
- package/src/ui/diff.ts +0 -650
- package/src/ui/diffStats.tsx +0 -25
- package/src/ui/modals.tsx +0 -964
- package/src/ui/primitives.tsx +0 -350
- package/src/ui/pullRequests.ts +0 -106
- package/src/ui/singleLineInput.ts +0 -26
- package/src/ui/spinner.ts +0 -1
package/src/ui/colors.ts
DELETED
|
@@ -1,821 +0,0 @@
|
|
|
1
|
-
export type ThemeId =
|
|
2
|
-
| "system"
|
|
3
|
-
| "ghui"
|
|
4
|
-
| "tokyo-night"
|
|
5
|
-
| "catppuccin"
|
|
6
|
-
| "rose-pine"
|
|
7
|
-
| "gruvbox"
|
|
8
|
-
| "nord"
|
|
9
|
-
| "dracula"
|
|
10
|
-
| "kanagawa"
|
|
11
|
-
| "one-dark"
|
|
12
|
-
| "monokai"
|
|
13
|
-
| "solarized-dark"
|
|
14
|
-
| "everforest"
|
|
15
|
-
| "vesper"
|
|
16
|
-
| "opencode"
|
|
17
|
-
|
|
18
|
-
export interface ColorPalette {
|
|
19
|
-
readonly background: string
|
|
20
|
-
readonly modalBackground: string
|
|
21
|
-
readonly text: string
|
|
22
|
-
readonly muted: string
|
|
23
|
-
readonly separator: string
|
|
24
|
-
readonly accent: string
|
|
25
|
-
readonly inlineCode: string
|
|
26
|
-
readonly error: string
|
|
27
|
-
readonly selectedBg: string
|
|
28
|
-
readonly selectedText: string
|
|
29
|
-
readonly count: string
|
|
30
|
-
readonly status: {
|
|
31
|
-
readonly draft: string
|
|
32
|
-
readonly approved: string
|
|
33
|
-
readonly changes: string
|
|
34
|
-
readonly review: string
|
|
35
|
-
readonly none: string
|
|
36
|
-
readonly passing: string
|
|
37
|
-
readonly pending: string
|
|
38
|
-
readonly failing: string
|
|
39
|
-
}
|
|
40
|
-
readonly repos: {
|
|
41
|
-
readonly opencode: string
|
|
42
|
-
readonly "effect-smol": string
|
|
43
|
-
readonly "opencode-console": string
|
|
44
|
-
readonly opencontrol: string
|
|
45
|
-
readonly default: string
|
|
46
|
-
}
|
|
47
|
-
readonly diff: {
|
|
48
|
-
readonly addedBg: string
|
|
49
|
-
readonly removedBg: string
|
|
50
|
-
readonly contextBg: string
|
|
51
|
-
readonly lineNumberBg: string
|
|
52
|
-
readonly addedLineNumberBg: string
|
|
53
|
-
readonly removedLineNumberBg: string
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface ThemeDefinition {
|
|
58
|
-
readonly id: ThemeId
|
|
59
|
-
readonly name: string
|
|
60
|
-
readonly description: string
|
|
61
|
-
readonly colors: ColorPalette
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
interface TerminalThemeColors {
|
|
65
|
-
readonly palette: readonly (string | null)[]
|
|
66
|
-
readonly defaultForeground: string | null
|
|
67
|
-
readonly defaultBackground: string | null
|
|
68
|
-
readonly highlightBackground: string | null
|
|
69
|
-
readonly highlightForeground: string | null
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const readableHex = (value: string | null | undefined, fallback: string) =>
|
|
73
|
-
typeof value === "string" && /^#[0-9a-fA-F]{6}(?:[0-9a-fA-F]{2})?$/.test(value) ? value : fallback
|
|
74
|
-
|
|
75
|
-
const hexToRgb = (hex: string) => {
|
|
76
|
-
const value = hex.replace(/^#/, "").slice(0, 6)
|
|
77
|
-
return {
|
|
78
|
-
r: parseInt(value.slice(0, 2), 16),
|
|
79
|
-
g: parseInt(value.slice(2, 4), 16),
|
|
80
|
-
b: parseInt(value.slice(4, 6), 16),
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const luminance = (hex: string) => {
|
|
85
|
-
const { r, g, b } = hexToRgb(hex)
|
|
86
|
-
return 0.299 * r + 0.587 * g + 0.114 * b
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const rgbToHex = ({ r, g, b }: { readonly r: number; readonly g: number; readonly b: number }) =>
|
|
90
|
-
`#${[r, g, b].map((component) => Math.max(0, Math.min(255, Math.round(component))).toString(16).padStart(2, "0")).join("")}`
|
|
91
|
-
|
|
92
|
-
export const mixHex = (base: string, overlay: string, amount: number) => {
|
|
93
|
-
const from = hexToRgb(base)
|
|
94
|
-
const to = hexToRgb(overlay)
|
|
95
|
-
return rgbToHex({
|
|
96
|
-
r: from.r + (to.r - from.r) * amount,
|
|
97
|
-
g: from.g + (to.g - from.g) * amount,
|
|
98
|
-
b: from.b + (to.b - from.b) * amount,
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const grayscaleRamp = (background: string) => {
|
|
103
|
-
const bg = hexToRgb(background)
|
|
104
|
-
const bgLum = luminance(background)
|
|
105
|
-
const isDark = bgLum < 128
|
|
106
|
-
const grays: Record<number, string> = {}
|
|
107
|
-
|
|
108
|
-
for (let i = 1; i <= 12; i++) {
|
|
109
|
-
const factor = i / 12
|
|
110
|
-
let r: number
|
|
111
|
-
let g: number
|
|
112
|
-
let b: number
|
|
113
|
-
|
|
114
|
-
if (isDark) {
|
|
115
|
-
if (bgLum < 10) {
|
|
116
|
-
const value = Math.floor(factor * 0.4 * 255)
|
|
117
|
-
r = value
|
|
118
|
-
g = value
|
|
119
|
-
b = value
|
|
120
|
-
} else {
|
|
121
|
-
const nextLum = bgLum + (255 - bgLum) * factor * 0.4
|
|
122
|
-
const ratio = nextLum / bgLum
|
|
123
|
-
r = Math.min(bg.r * ratio, 255)
|
|
124
|
-
g = Math.min(bg.g * ratio, 255)
|
|
125
|
-
b = Math.min(bg.b * ratio, 255)
|
|
126
|
-
}
|
|
127
|
-
} else if (bgLum > 245) {
|
|
128
|
-
const value = Math.floor(255 - factor * 0.4 * 255)
|
|
129
|
-
r = value
|
|
130
|
-
g = value
|
|
131
|
-
b = value
|
|
132
|
-
} else {
|
|
133
|
-
const nextLum = bgLum * (1 - factor * 0.4)
|
|
134
|
-
const ratio = nextLum / bgLum
|
|
135
|
-
r = Math.max(bg.r * ratio, 0)
|
|
136
|
-
g = Math.max(bg.g * ratio, 0)
|
|
137
|
-
b = Math.max(bg.b * ratio, 0)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
grays[i] = rgbToHex({ r, g, b })
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return grays
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const mutedTextColor = (background: string) => {
|
|
147
|
-
const bgLum = luminance(background)
|
|
148
|
-
const isDark = bgLum < 128
|
|
149
|
-
const value = isDark
|
|
150
|
-
? bgLum < 10 ? 180 : Math.min(Math.floor(160 + bgLum * 0.3), 200)
|
|
151
|
-
: bgLum > 245 ? 75 : Math.max(Math.floor(100 - (255 - bgLum) * 0.2), 60)
|
|
152
|
-
return rgbToHex({ r: value, g: value, b: value })
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const contrastText = (background: string) => luminance(background) > 128 ? "#000000" : "#ffffff"
|
|
156
|
-
|
|
157
|
-
export const lineNumberTextColor = (background: string, foreground: string) => {
|
|
158
|
-
const bg = readableHex(background, foreground)
|
|
159
|
-
const fg = readableHex(foreground, contrastText(bg))
|
|
160
|
-
const contrast = Math.abs(luminance(bg) - luminance(fg))
|
|
161
|
-
return mixHex(bg, fg, contrast < 90 ? 0.62 : 0.5)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const ghuiColors: ColorPalette = {
|
|
165
|
-
background: "#111018",
|
|
166
|
-
modalBackground: "#1a1a2e",
|
|
167
|
-
text: "#ede7da",
|
|
168
|
-
muted: "#9f9788",
|
|
169
|
-
separator: "#6f685d",
|
|
170
|
-
accent: "#f4a51c",
|
|
171
|
-
inlineCode: "#d7c5a1",
|
|
172
|
-
error: "#f97316",
|
|
173
|
-
selectedBg: "#1d2430",
|
|
174
|
-
selectedText: "#f8fafc",
|
|
175
|
-
count: "#d7c5a1",
|
|
176
|
-
status: {
|
|
177
|
-
draft: "#f59e0b",
|
|
178
|
-
approved: "#7dd3a3",
|
|
179
|
-
changes: "#f87171",
|
|
180
|
-
review: "#93c5fd",
|
|
181
|
-
none: "#9f9788",
|
|
182
|
-
passing: "#7dd3a3",
|
|
183
|
-
pending: "#f4a51c",
|
|
184
|
-
failing: "#f87171",
|
|
185
|
-
},
|
|
186
|
-
repos: {
|
|
187
|
-
opencode: "#60a5fa",
|
|
188
|
-
"effect-smol": "#34d399",
|
|
189
|
-
"opencode-console": "#f472b6",
|
|
190
|
-
opencontrol: "#f59e0b",
|
|
191
|
-
default: "#93c5fd",
|
|
192
|
-
},
|
|
193
|
-
diff: {
|
|
194
|
-
addedBg: "#17351f",
|
|
195
|
-
removedBg: "#3a1e22",
|
|
196
|
-
contextBg: "transparent",
|
|
197
|
-
lineNumberBg: "#151515",
|
|
198
|
-
addedLineNumberBg: "#12301a",
|
|
199
|
-
removedLineNumberBg: "#35171b",
|
|
200
|
-
},
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const makeSystemColors = (terminal?: TerminalThemeColors): ColorPalette => {
|
|
204
|
-
const palette = terminal?.palette ?? []
|
|
205
|
-
const terminalBackground = readableHex(terminal?.defaultBackground, readableHex(palette[0], "#000000"))
|
|
206
|
-
const text = readableHex(terminal?.defaultForeground, readableHex(palette[7], "#ffffff"))
|
|
207
|
-
const grays = grayscaleRamp(terminalBackground)
|
|
208
|
-
const isDark = luminance(terminalBackground) < 128
|
|
209
|
-
const red = readableHex(palette[1], "#cc0000")
|
|
210
|
-
const green = readableHex(palette[2], "#4e9a06")
|
|
211
|
-
const yellow = readableHex(palette[3], "#c4a000")
|
|
212
|
-
const blue = readableHex(palette[4], "#3465a4")
|
|
213
|
-
const magenta = readableHex(palette[5], "#75507b")
|
|
214
|
-
const brightBlack = readableHex(palette[8], mutedTextColor(terminalBackground))
|
|
215
|
-
const brightGreen = readableHex(palette[10], green)
|
|
216
|
-
const brightBlue = readableHex(palette[12], blue)
|
|
217
|
-
const brightMagenta = readableHex(palette[13], magenta)
|
|
218
|
-
const primary = brightBlue
|
|
219
|
-
const panel = grays[2] ?? mixHex(terminalBackground, text, isDark ? 0.07 : 0.08)
|
|
220
|
-
const element = grays[3] ?? mixHex(terminalBackground, text, isDark ? 0.1 : 0.1)
|
|
221
|
-
const border = grays[7] ?? mixHex(terminalBackground, text, isDark ? 0.24 : 0.24)
|
|
222
|
-
const borderSubtle = grays[6] ?? border
|
|
223
|
-
const diffAlpha = isDark ? 0.22 : 0.14
|
|
224
|
-
|
|
225
|
-
return {
|
|
226
|
-
background: "transparent",
|
|
227
|
-
modalBackground: panel,
|
|
228
|
-
text,
|
|
229
|
-
muted: mutedTextColor(terminalBackground),
|
|
230
|
-
separator: border,
|
|
231
|
-
accent: primary,
|
|
232
|
-
inlineCode: brightGreen,
|
|
233
|
-
error: red,
|
|
234
|
-
selectedBg: primary,
|
|
235
|
-
selectedText: contrastText(primary),
|
|
236
|
-
count: primary,
|
|
237
|
-
status: {
|
|
238
|
-
draft: yellow,
|
|
239
|
-
approved: green,
|
|
240
|
-
changes: red,
|
|
241
|
-
review: primary,
|
|
242
|
-
none: brightBlack,
|
|
243
|
-
passing: green,
|
|
244
|
-
pending: yellow,
|
|
245
|
-
failing: red,
|
|
246
|
-
},
|
|
247
|
-
repos: {
|
|
248
|
-
opencode: primary,
|
|
249
|
-
"effect-smol": green,
|
|
250
|
-
"opencode-console": brightMagenta,
|
|
251
|
-
opencontrol: yellow,
|
|
252
|
-
default: blue,
|
|
253
|
-
},
|
|
254
|
-
diff: {
|
|
255
|
-
addedBg: mixHex(terminalBackground, green, diffAlpha),
|
|
256
|
-
removedBg: mixHex(terminalBackground, red, diffAlpha),
|
|
257
|
-
contextBg: panel,
|
|
258
|
-
lineNumberBg: borderSubtle,
|
|
259
|
-
addedLineNumberBg: mixHex(element, green, diffAlpha),
|
|
260
|
-
removedLineNumberBg: mixHex(element, red, diffAlpha),
|
|
261
|
-
},
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const systemColors: ColorPalette = makeSystemColors()
|
|
266
|
-
|
|
267
|
-
const tokyoNightColors: ColorPalette = {
|
|
268
|
-
background: "#1a1b26",
|
|
269
|
-
modalBackground: "#24283b",
|
|
270
|
-
text: "#c0caf5",
|
|
271
|
-
muted: "#787c99",
|
|
272
|
-
separator: "#3b4261",
|
|
273
|
-
accent: "#7aa2f7",
|
|
274
|
-
inlineCode: "#bb9af7",
|
|
275
|
-
error: "#f7768e",
|
|
276
|
-
selectedBg: "#283457",
|
|
277
|
-
selectedText: "#ffffff",
|
|
278
|
-
count: "#ff9e64",
|
|
279
|
-
status: {
|
|
280
|
-
draft: "#e0af68",
|
|
281
|
-
approved: "#9ece6a",
|
|
282
|
-
changes: "#f7768e",
|
|
283
|
-
review: "#7dcfff",
|
|
284
|
-
none: "#787c99",
|
|
285
|
-
passing: "#9ece6a",
|
|
286
|
-
pending: "#e0af68",
|
|
287
|
-
failing: "#f7768e",
|
|
288
|
-
},
|
|
289
|
-
repos: {
|
|
290
|
-
opencode: "#7aa2f7",
|
|
291
|
-
"effect-smol": "#9ece6a",
|
|
292
|
-
"opencode-console": "#bb9af7",
|
|
293
|
-
opencontrol: "#ff9e64",
|
|
294
|
-
default: "#7dcfff",
|
|
295
|
-
},
|
|
296
|
-
diff: {
|
|
297
|
-
addedBg: "#203326",
|
|
298
|
-
removedBg: "#3a222c",
|
|
299
|
-
contextBg: "transparent",
|
|
300
|
-
lineNumberBg: "#16161e",
|
|
301
|
-
addedLineNumberBg: "#1b2f23",
|
|
302
|
-
removedLineNumberBg: "#33202a",
|
|
303
|
-
},
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const opencodeColors: ColorPalette = {
|
|
307
|
-
background: "#0a0a0a",
|
|
308
|
-
modalBackground: "#1e1e1e",
|
|
309
|
-
text: "#eeeeee",
|
|
310
|
-
muted: "#808080",
|
|
311
|
-
separator: "#484848",
|
|
312
|
-
accent: "#fab283",
|
|
313
|
-
inlineCode: "#7fd88f",
|
|
314
|
-
error: "#e06c75",
|
|
315
|
-
selectedBg: "#323232",
|
|
316
|
-
selectedText: "#eeeeee",
|
|
317
|
-
count: "#fab283",
|
|
318
|
-
status: {
|
|
319
|
-
draft: "#f5a742",
|
|
320
|
-
approved: "#7fd88f",
|
|
321
|
-
changes: "#e06c75",
|
|
322
|
-
review: "#5c9cf5",
|
|
323
|
-
none: "#808080",
|
|
324
|
-
passing: "#7fd88f",
|
|
325
|
-
pending: "#f5a742",
|
|
326
|
-
failing: "#e06c75",
|
|
327
|
-
},
|
|
328
|
-
repos: {
|
|
329
|
-
opencode: "#fab283",
|
|
330
|
-
"effect-smol": "#7fd88f",
|
|
331
|
-
"opencode-console": "#9d7cd8",
|
|
332
|
-
opencontrol: "#f5a742",
|
|
333
|
-
default: "#5c9cf5",
|
|
334
|
-
},
|
|
335
|
-
diff: {
|
|
336
|
-
addedBg: "#20303b",
|
|
337
|
-
removedBg: "#37222c",
|
|
338
|
-
contextBg: "transparent",
|
|
339
|
-
lineNumberBg: "#141414",
|
|
340
|
-
addedLineNumberBg: "#1b2b34",
|
|
341
|
-
removedLineNumberBg: "#2d1f26",
|
|
342
|
-
},
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
const catppuccinColors: ColorPalette = {
|
|
346
|
-
background: "#1e1e2e",
|
|
347
|
-
modalBackground: "#313244",
|
|
348
|
-
text: "#cdd6f4",
|
|
349
|
-
muted: "#7f849c",
|
|
350
|
-
separator: "#45475a",
|
|
351
|
-
accent: "#cba6f7",
|
|
352
|
-
inlineCode: "#f5c2e7",
|
|
353
|
-
error: "#f38ba8",
|
|
354
|
-
selectedBg: "#45475a",
|
|
355
|
-
selectedText: "#f5e0dc",
|
|
356
|
-
count: "#fab387",
|
|
357
|
-
status: {
|
|
358
|
-
draft: "#f9e2af",
|
|
359
|
-
approved: "#a6e3a1",
|
|
360
|
-
changes: "#f38ba8",
|
|
361
|
-
review: "#89b4fa",
|
|
362
|
-
none: "#7f849c",
|
|
363
|
-
passing: "#a6e3a1",
|
|
364
|
-
pending: "#f9e2af",
|
|
365
|
-
failing: "#f38ba8",
|
|
366
|
-
},
|
|
367
|
-
repos: {
|
|
368
|
-
opencode: "#89b4fa",
|
|
369
|
-
"effect-smol": "#a6e3a1",
|
|
370
|
-
"opencode-console": "#f5c2e7",
|
|
371
|
-
opencontrol: "#fab387",
|
|
372
|
-
default: "#74c7ec",
|
|
373
|
-
},
|
|
374
|
-
diff: {
|
|
375
|
-
addedBg: "#243927",
|
|
376
|
-
removedBg: "#3b2532",
|
|
377
|
-
contextBg: "transparent",
|
|
378
|
-
lineNumberBg: "#181825",
|
|
379
|
-
addedLineNumberBg: "#203524",
|
|
380
|
-
removedLineNumberBg: "#36232f",
|
|
381
|
-
},
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const rosePineColors: ColorPalette = {
|
|
385
|
-
background: "#191724",
|
|
386
|
-
modalBackground: "#26233a",
|
|
387
|
-
text: "#e0def4",
|
|
388
|
-
muted: "#908caa",
|
|
389
|
-
separator: "#524f67",
|
|
390
|
-
accent: "#c4a7e7",
|
|
391
|
-
inlineCode: "#f6c177",
|
|
392
|
-
error: "#eb6f92",
|
|
393
|
-
selectedBg: "#403d52",
|
|
394
|
-
selectedText: "#f6f1ff",
|
|
395
|
-
count: "#ebbcba",
|
|
396
|
-
status: {
|
|
397
|
-
draft: "#f6c177",
|
|
398
|
-
approved: "#9ccfd8",
|
|
399
|
-
changes: "#eb6f92",
|
|
400
|
-
review: "#31748f",
|
|
401
|
-
none: "#908caa",
|
|
402
|
-
passing: "#9ccfd8",
|
|
403
|
-
pending: "#f6c177",
|
|
404
|
-
failing: "#eb6f92",
|
|
405
|
-
},
|
|
406
|
-
repos: {
|
|
407
|
-
opencode: "#31748f",
|
|
408
|
-
"effect-smol": "#9ccfd8",
|
|
409
|
-
"opencode-console": "#c4a7e7",
|
|
410
|
-
opencontrol: "#f6c177",
|
|
411
|
-
default: "#ebbcba",
|
|
412
|
-
},
|
|
413
|
-
diff: {
|
|
414
|
-
addedBg: "#23343a",
|
|
415
|
-
removedBg: "#3a2534",
|
|
416
|
-
contextBg: "transparent",
|
|
417
|
-
lineNumberBg: "#1f1d2e",
|
|
418
|
-
addedLineNumberBg: "#203137",
|
|
419
|
-
removedLineNumberBg: "#352330",
|
|
420
|
-
},
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
const gruvboxColors: ColorPalette = {
|
|
424
|
-
background: "#282828",
|
|
425
|
-
modalBackground: "#3c3836",
|
|
426
|
-
text: "#ebdbb2",
|
|
427
|
-
muted: "#928374",
|
|
428
|
-
separator: "#665c54",
|
|
429
|
-
accent: "#fabd2f",
|
|
430
|
-
inlineCode: "#d3869b",
|
|
431
|
-
error: "#fb4934",
|
|
432
|
-
selectedBg: "#504945",
|
|
433
|
-
selectedText: "#fbf1c7",
|
|
434
|
-
count: "#fe8019",
|
|
435
|
-
status: {
|
|
436
|
-
draft: "#fabd2f",
|
|
437
|
-
approved: "#b8bb26",
|
|
438
|
-
changes: "#fb4934",
|
|
439
|
-
review: "#83a598",
|
|
440
|
-
none: "#928374",
|
|
441
|
-
passing: "#b8bb26",
|
|
442
|
-
pending: "#fabd2f",
|
|
443
|
-
failing: "#fb4934",
|
|
444
|
-
},
|
|
445
|
-
repos: {
|
|
446
|
-
opencode: "#83a598",
|
|
447
|
-
"effect-smol": "#b8bb26",
|
|
448
|
-
"opencode-console": "#d3869b",
|
|
449
|
-
opencontrol: "#fe8019",
|
|
450
|
-
default: "#8ec07c",
|
|
451
|
-
},
|
|
452
|
-
diff: {
|
|
453
|
-
addedBg: "#32361f",
|
|
454
|
-
removedBg: "#3c2927",
|
|
455
|
-
contextBg: "transparent",
|
|
456
|
-
lineNumberBg: "#1d2021",
|
|
457
|
-
addedLineNumberBg: "#2f331e",
|
|
458
|
-
removedLineNumberBg: "#382726",
|
|
459
|
-
},
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
const nordColors: ColorPalette = {
|
|
463
|
-
background: "#2e3440",
|
|
464
|
-
modalBackground: "#3b4252",
|
|
465
|
-
text: "#eceff4",
|
|
466
|
-
muted: "#8892a7",
|
|
467
|
-
separator: "#4c566a",
|
|
468
|
-
accent: "#88c0d0",
|
|
469
|
-
inlineCode: "#b48ead",
|
|
470
|
-
error: "#bf616a",
|
|
471
|
-
selectedBg: "#434c5e",
|
|
472
|
-
selectedText: "#eceff4",
|
|
473
|
-
count: "#ebcb8b",
|
|
474
|
-
status: {
|
|
475
|
-
draft: "#ebcb8b",
|
|
476
|
-
approved: "#a3be8c",
|
|
477
|
-
changes: "#bf616a",
|
|
478
|
-
review: "#81a1c1",
|
|
479
|
-
none: "#8892a7",
|
|
480
|
-
passing: "#a3be8c",
|
|
481
|
-
pending: "#ebcb8b",
|
|
482
|
-
failing: "#bf616a",
|
|
483
|
-
},
|
|
484
|
-
repos: {
|
|
485
|
-
opencode: "#81a1c1",
|
|
486
|
-
"effect-smol": "#a3be8c",
|
|
487
|
-
"opencode-console": "#b48ead",
|
|
488
|
-
opencontrol: "#d08770",
|
|
489
|
-
default: "#88c0d0",
|
|
490
|
-
},
|
|
491
|
-
diff: {
|
|
492
|
-
addedBg: "#334033",
|
|
493
|
-
removedBg: "#433238",
|
|
494
|
-
contextBg: "transparent",
|
|
495
|
-
lineNumberBg: "#242933",
|
|
496
|
-
addedLineNumberBg: "#303d31",
|
|
497
|
-
removedLineNumberBg: "#3f3036",
|
|
498
|
-
},
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
const draculaColors: ColorPalette = {
|
|
502
|
-
background: "#282a36",
|
|
503
|
-
modalBackground: "#343746",
|
|
504
|
-
text: "#f8f8f2",
|
|
505
|
-
muted: "#8f94b8",
|
|
506
|
-
separator: "#4f5268",
|
|
507
|
-
accent: "#bd93f9",
|
|
508
|
-
inlineCode: "#ff79c6",
|
|
509
|
-
error: "#ff5555",
|
|
510
|
-
selectedBg: "#44475a",
|
|
511
|
-
selectedText: "#f8f8f2",
|
|
512
|
-
count: "#ffb86c",
|
|
513
|
-
status: {
|
|
514
|
-
draft: "#f1fa8c",
|
|
515
|
-
approved: "#50fa7b",
|
|
516
|
-
changes: "#ff5555",
|
|
517
|
-
review: "#8be9fd",
|
|
518
|
-
none: "#8f94b8",
|
|
519
|
-
passing: "#50fa7b",
|
|
520
|
-
pending: "#f1fa8c",
|
|
521
|
-
failing: "#ff5555",
|
|
522
|
-
},
|
|
523
|
-
repos: {
|
|
524
|
-
opencode: "#8be9fd",
|
|
525
|
-
"effect-smol": "#50fa7b",
|
|
526
|
-
"opencode-console": "#ff79c6",
|
|
527
|
-
opencontrol: "#ffb86c",
|
|
528
|
-
default: "#bd93f9",
|
|
529
|
-
},
|
|
530
|
-
diff: {
|
|
531
|
-
addedBg: "#203a29",
|
|
532
|
-
removedBg: "#43272f",
|
|
533
|
-
contextBg: "transparent",
|
|
534
|
-
lineNumberBg: "#21222c",
|
|
535
|
-
addedLineNumberBg: "#1d3627",
|
|
536
|
-
removedLineNumberBg: "#3d252c",
|
|
537
|
-
},
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const kanagawaColors: ColorPalette = {
|
|
541
|
-
background: "#1f1f28",
|
|
542
|
-
modalBackground: "#2a2a37",
|
|
543
|
-
text: "#dcd7ba",
|
|
544
|
-
muted: "#727169",
|
|
545
|
-
separator: "#54546d",
|
|
546
|
-
accent: "#7e9cd8",
|
|
547
|
-
inlineCode: "#d27e99",
|
|
548
|
-
error: "#c34043",
|
|
549
|
-
selectedBg: "#363646",
|
|
550
|
-
selectedText: "#fff7d6",
|
|
551
|
-
count: "#ffa066",
|
|
552
|
-
status: {
|
|
553
|
-
draft: "#c0a36e",
|
|
554
|
-
approved: "#76946a",
|
|
555
|
-
changes: "#c34043",
|
|
556
|
-
review: "#7e9cd8",
|
|
557
|
-
none: "#727169",
|
|
558
|
-
passing: "#76946a",
|
|
559
|
-
pending: "#c0a36e",
|
|
560
|
-
failing: "#c34043",
|
|
561
|
-
},
|
|
562
|
-
repos: {
|
|
563
|
-
opencode: "#7e9cd8",
|
|
564
|
-
"effect-smol": "#98bb6c",
|
|
565
|
-
"opencode-console": "#957fb8",
|
|
566
|
-
opencontrol: "#ffa066",
|
|
567
|
-
default: "#7fb4ca",
|
|
568
|
-
},
|
|
569
|
-
diff: {
|
|
570
|
-
addedBg: "#253326",
|
|
571
|
-
removedBg: "#3a2528",
|
|
572
|
-
contextBg: "transparent",
|
|
573
|
-
lineNumberBg: "#16161d",
|
|
574
|
-
addedLineNumberBg: "#223025",
|
|
575
|
-
removedLineNumberBg: "#352326",
|
|
576
|
-
},
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
const oneDarkColors: ColorPalette = {
|
|
580
|
-
background: "#282c34",
|
|
581
|
-
modalBackground: "#2c313c",
|
|
582
|
-
text: "#abb2bf",
|
|
583
|
-
muted: "#7f848e",
|
|
584
|
-
separator: "#4b5263",
|
|
585
|
-
accent: "#61afef",
|
|
586
|
-
inlineCode: "#c678dd",
|
|
587
|
-
error: "#e06c75",
|
|
588
|
-
selectedBg: "#3e4451",
|
|
589
|
-
selectedText: "#ffffff",
|
|
590
|
-
count: "#d19a66",
|
|
591
|
-
status: {
|
|
592
|
-
draft: "#e5c07b",
|
|
593
|
-
approved: "#98c379",
|
|
594
|
-
changes: "#e06c75",
|
|
595
|
-
review: "#61afef",
|
|
596
|
-
none: "#7f848e",
|
|
597
|
-
passing: "#98c379",
|
|
598
|
-
pending: "#e5c07b",
|
|
599
|
-
failing: "#e06c75",
|
|
600
|
-
},
|
|
601
|
-
repos: {
|
|
602
|
-
opencode: "#61afef",
|
|
603
|
-
"effect-smol": "#98c379",
|
|
604
|
-
"opencode-console": "#c678dd",
|
|
605
|
-
opencontrol: "#d19a66",
|
|
606
|
-
default: "#56b6c2",
|
|
607
|
-
},
|
|
608
|
-
diff: {
|
|
609
|
-
addedBg: "#27362b",
|
|
610
|
-
removedBg: "#3a282c",
|
|
611
|
-
contextBg: "transparent",
|
|
612
|
-
lineNumberBg: "#21252b",
|
|
613
|
-
addedLineNumberBg: "#243228",
|
|
614
|
-
removedLineNumberBg: "#35262a",
|
|
615
|
-
},
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
const monokaiColors: ColorPalette = {
|
|
619
|
-
background: "#272822",
|
|
620
|
-
modalBackground: "#383830",
|
|
621
|
-
text: "#f8f8f2",
|
|
622
|
-
muted: "#90908a",
|
|
623
|
-
separator: "#5b5b50",
|
|
624
|
-
accent: "#66d9ef",
|
|
625
|
-
inlineCode: "#ae81ff",
|
|
626
|
-
error: "#f92672",
|
|
627
|
-
selectedBg: "#49483e",
|
|
628
|
-
selectedText: "#ffffff",
|
|
629
|
-
count: "#fd971f",
|
|
630
|
-
status: {
|
|
631
|
-
draft: "#e6db74",
|
|
632
|
-
approved: "#a6e22e",
|
|
633
|
-
changes: "#f92672",
|
|
634
|
-
review: "#66d9ef",
|
|
635
|
-
none: "#90908a",
|
|
636
|
-
passing: "#a6e22e",
|
|
637
|
-
pending: "#e6db74",
|
|
638
|
-
failing: "#f92672",
|
|
639
|
-
},
|
|
640
|
-
repos: {
|
|
641
|
-
opencode: "#66d9ef",
|
|
642
|
-
"effect-smol": "#a6e22e",
|
|
643
|
-
"opencode-console": "#ae81ff",
|
|
644
|
-
opencontrol: "#fd971f",
|
|
645
|
-
default: "#a1efe4",
|
|
646
|
-
},
|
|
647
|
-
diff: {
|
|
648
|
-
addedBg: "#2f3a22",
|
|
649
|
-
removedBg: "#3d2430",
|
|
650
|
-
contextBg: "transparent",
|
|
651
|
-
lineNumberBg: "#1f201b",
|
|
652
|
-
addedLineNumberBg: "#2b3620",
|
|
653
|
-
removedLineNumberBg: "#38222d",
|
|
654
|
-
},
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
const solarizedDarkColors: ColorPalette = {
|
|
658
|
-
background: "#002b36",
|
|
659
|
-
modalBackground: "#123d48",
|
|
660
|
-
text: "#eee8d5",
|
|
661
|
-
muted: "#839496",
|
|
662
|
-
separator: "#586e75",
|
|
663
|
-
accent: "#268bd2",
|
|
664
|
-
inlineCode: "#2aa198",
|
|
665
|
-
error: "#dc322f",
|
|
666
|
-
selectedBg: "#174652",
|
|
667
|
-
selectedText: "#fdf6e3",
|
|
668
|
-
count: "#cb4b16",
|
|
669
|
-
status: {
|
|
670
|
-
draft: "#b58900",
|
|
671
|
-
approved: "#859900",
|
|
672
|
-
changes: "#dc322f",
|
|
673
|
-
review: "#268bd2",
|
|
674
|
-
none: "#839496",
|
|
675
|
-
passing: "#859900",
|
|
676
|
-
pending: "#b58900",
|
|
677
|
-
failing: "#dc322f",
|
|
678
|
-
},
|
|
679
|
-
repos: {
|
|
680
|
-
opencode: "#268bd2",
|
|
681
|
-
"effect-smol": "#859900",
|
|
682
|
-
"opencode-console": "#d33682",
|
|
683
|
-
opencontrol: "#cb4b16",
|
|
684
|
-
default: "#2aa198",
|
|
685
|
-
},
|
|
686
|
-
diff: {
|
|
687
|
-
addedBg: "#123c2e",
|
|
688
|
-
removedBg: "#3c262a",
|
|
689
|
-
contextBg: "transparent",
|
|
690
|
-
lineNumberBg: "#073642",
|
|
691
|
-
addedLineNumberBg: "#10372b",
|
|
692
|
-
removedLineNumberBg: "#362429",
|
|
693
|
-
},
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
const everforestColors: ColorPalette = {
|
|
697
|
-
background: "#2d353b",
|
|
698
|
-
modalBackground: "#343f44",
|
|
699
|
-
text: "#d3c6aa",
|
|
700
|
-
muted: "#859289",
|
|
701
|
-
separator: "#56635f",
|
|
702
|
-
accent: "#7fbbb3",
|
|
703
|
-
inlineCode: "#d699b6",
|
|
704
|
-
error: "#e67e80",
|
|
705
|
-
selectedBg: "#465258",
|
|
706
|
-
selectedText: "#fff4d6",
|
|
707
|
-
count: "#e69875",
|
|
708
|
-
status: {
|
|
709
|
-
draft: "#dbbc7f",
|
|
710
|
-
approved: "#a7c080",
|
|
711
|
-
changes: "#e67e80",
|
|
712
|
-
review: "#7fbbb3",
|
|
713
|
-
none: "#859289",
|
|
714
|
-
passing: "#a7c080",
|
|
715
|
-
pending: "#dbbc7f",
|
|
716
|
-
failing: "#e67e80",
|
|
717
|
-
},
|
|
718
|
-
repos: {
|
|
719
|
-
opencode: "#7fbbb3",
|
|
720
|
-
"effect-smol": "#a7c080",
|
|
721
|
-
"opencode-console": "#d699b6",
|
|
722
|
-
opencontrol: "#e69875",
|
|
723
|
-
default: "#83c092",
|
|
724
|
-
},
|
|
725
|
-
diff: {
|
|
726
|
-
addedBg: "#33422f",
|
|
727
|
-
removedBg: "#463333",
|
|
728
|
-
contextBg: "transparent",
|
|
729
|
-
lineNumberBg: "#232a2e",
|
|
730
|
-
addedLineNumberBg: "#303d2d",
|
|
731
|
-
removedLineNumberBg: "#403030",
|
|
732
|
-
},
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
const vesperColors: ColorPalette = {
|
|
736
|
-
background: "#101010",
|
|
737
|
-
modalBackground: "#1A1A1A",
|
|
738
|
-
text: "#FFFFFF",
|
|
739
|
-
muted: "#A0A0A0",
|
|
740
|
-
separator: "#282828",
|
|
741
|
-
accent: "#FFC799",
|
|
742
|
-
inlineCode: "#99FFE4",
|
|
743
|
-
error: "#FF8080",
|
|
744
|
-
selectedBg: "#232323",
|
|
745
|
-
selectedText: "#FFFFFF",
|
|
746
|
-
count: "#FFC799",
|
|
747
|
-
status: {
|
|
748
|
-
draft: "#FFC799",
|
|
749
|
-
approved: "#99FFE4",
|
|
750
|
-
changes: "#FF8080",
|
|
751
|
-
review: "#B0B0B0",
|
|
752
|
-
none: "#7E7E7E",
|
|
753
|
-
passing: "#99FFE4",
|
|
754
|
-
pending: "#FFC799",
|
|
755
|
-
failing: "#FF8080",
|
|
756
|
-
},
|
|
757
|
-
repos: {
|
|
758
|
-
opencode: "#FFC799",
|
|
759
|
-
"effect-smol": "#99FFE4",
|
|
760
|
-
"opencode-console": "#FFD1A8",
|
|
761
|
-
opencontrol: "#FFC799",
|
|
762
|
-
default: "#B0B0B0",
|
|
763
|
-
},
|
|
764
|
-
diff: {
|
|
765
|
-
addedBg: "#17312d",
|
|
766
|
-
removedBg: "#351f1f",
|
|
767
|
-
contextBg: "transparent",
|
|
768
|
-
lineNumberBg: "#101010",
|
|
769
|
-
addedLineNumberBg: "#142b28",
|
|
770
|
-
removedLineNumberBg: "#2f1c1c",
|
|
771
|
-
},
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
export const themeDefinitions: readonly ThemeDefinition[] = [
|
|
775
|
-
{ id: "system", name: "System", description: "Use the terminal foreground, background, and ANSI palette", colors: systemColors },
|
|
776
|
-
{ id: "ghui", name: "GHUI", description: "Warm parchment accents on a deep slate background", colors: ghuiColors },
|
|
777
|
-
{ id: "tokyo-night", name: "Tokyo Night", description: "Cool indigo surfaces with neon editor accents", colors: tokyoNightColors },
|
|
778
|
-
{ id: "catppuccin", name: "Catppuccin", description: "Mocha lavender, peach, and soft pastel contrast", colors: catppuccinColors },
|
|
779
|
-
{ id: "rose-pine", name: "Rose Pine", description: "Muted rose, pine, and gold on dusky violet", colors: rosePineColors },
|
|
780
|
-
{ id: "gruvbox", name: "Gruvbox", description: "Retro warm earth tones with punchy semantic accents", colors: gruvboxColors },
|
|
781
|
-
{ id: "nord", name: "Nord", description: "Arctic blue-gray surfaces with frosty accents", colors: nordColors },
|
|
782
|
-
{ id: "dracula", name: "Dracula", description: "High-contrast purple, pink, cyan, and green", colors: draculaColors },
|
|
783
|
-
{ id: "kanagawa", name: "Kanagawa", description: "Ink-wash indigo, wave blues, and autumn accents", colors: kanagawaColors },
|
|
784
|
-
{ id: "one-dark", name: "One Dark", description: "Atom-style charcoal with clean blue and green accents", colors: oneDarkColors },
|
|
785
|
-
{ id: "monokai", name: "Monokai", description: "Classic dark olive with electric syntax colors", colors: monokaiColors },
|
|
786
|
-
{ id: "solarized-dark", name: "Solarized Dark", description: "Low-contrast blue-green base with calibrated accents", colors: solarizedDarkColors },
|
|
787
|
-
{ id: "everforest", name: "Everforest", description: "Soft green-gray forest tones with warm highlights", colors: everforestColors },
|
|
788
|
-
{ id: "vesper", name: "Vesper", description: "Minimal black surfaces with peach and aqua accents", colors: vesperColors },
|
|
789
|
-
{ id: "opencode", name: "OpenCode", description: "Charcoal panels with peach, violet, and blue highlights", colors: opencodeColors },
|
|
790
|
-
] as const
|
|
791
|
-
|
|
792
|
-
let activeTheme = themeDefinitions.find((theme) => theme.id === "ghui") ?? themeDefinitions[0]!
|
|
793
|
-
|
|
794
|
-
export const colors: ColorPalette = { ...ghuiColors }
|
|
795
|
-
|
|
796
|
-
export const getThemeDefinition = (id: ThemeId) => themeDefinitions.find((theme) => theme.id === id) ?? themeDefinitions[0]!
|
|
797
|
-
|
|
798
|
-
export const isThemeId = (value: unknown): value is ThemeId => typeof value === "string" && themeDefinitions.some((theme) => theme.id === value)
|
|
799
|
-
|
|
800
|
-
export const filterThemeDefinitions = (query: string) => {
|
|
801
|
-
const normalized = query.trim().toLowerCase()
|
|
802
|
-
if (normalized.length === 0) return themeDefinitions
|
|
803
|
-
return themeDefinitions.filter((theme) =>
|
|
804
|
-
theme.id.includes(normalized) ||
|
|
805
|
-
theme.name.toLowerCase().includes(normalized) ||
|
|
806
|
-
theme.description.toLowerCase().includes(normalized),
|
|
807
|
-
)
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
export const setActiveTheme = (id: ThemeId) => {
|
|
811
|
-
if (activeTheme.id === id) return
|
|
812
|
-
activeTheme = getThemeDefinition(id)
|
|
813
|
-
Object.assign(colors, activeTheme.colors)
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
export const setSystemThemeColors = (terminalColors: TerminalThemeColors) => {
|
|
817
|
-
Object.assign(systemColors, makeSystemColors(terminalColors))
|
|
818
|
-
if (activeTheme.id === "system") {
|
|
819
|
-
Object.assign(colors, systemColors)
|
|
820
|
-
}
|
|
821
|
-
}
|