theme redux
This commit is contained in:
110
src/utils/system-theme.ts
Normal file
110
src/utils/system-theme.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { RGBA, type TerminalColors } from "@opentui/core"
|
||||
import { ansiToRgba } from "./ansi-to-rgba"
|
||||
import { generateGrayScale, generateMutedTextColor, tint } from "./color-generation"
|
||||
import type { ThemeJson } from "../types/theme-schema"
|
||||
|
||||
let cached: TerminalColors | null = null
|
||||
|
||||
export function clearPaletteCache() {
|
||||
cached = null
|
||||
}
|
||||
|
||||
export function detectSystemTheme(colors: TerminalColors) {
|
||||
const bg = RGBA.fromHex(colors.defaultBackground ?? colors.palette[0] ?? "#000000")
|
||||
const luminance = 0.299 * bg.r + 0.587 * bg.g + 0.114 * bg.b
|
||||
const mode = luminance > 0.5 ? "light" : "dark"
|
||||
return { mode, background: bg }
|
||||
}
|
||||
|
||||
export function generateSystemTheme(colors: TerminalColors, mode: "dark" | "light"): ThemeJson {
|
||||
cached = colors
|
||||
const bg = RGBA.fromHex(colors.defaultBackground ?? colors.palette[0] ?? "#000000")
|
||||
const fg = RGBA.fromHex(colors.defaultForeground ?? colors.palette[7] ?? "#ffffff")
|
||||
const transparent = RGBA.fromInts(0, 0, 0, 0)
|
||||
const isDark = mode === "dark"
|
||||
|
||||
const col = (i: number) => {
|
||||
const value = colors.palette[i]
|
||||
if (value) return RGBA.fromHex(value)
|
||||
return ansiToRgba(i)
|
||||
}
|
||||
|
||||
const grays = generateGrayScale(bg, isDark)
|
||||
const textMuted = generateMutedTextColor(bg, isDark)
|
||||
|
||||
const ansi = {
|
||||
black: col(0),
|
||||
red: col(1),
|
||||
green: col(2),
|
||||
yellow: col(3),
|
||||
blue: col(4),
|
||||
magenta: col(5),
|
||||
cyan: col(6),
|
||||
white: col(7),
|
||||
redBright: col(9),
|
||||
greenBright: col(10),
|
||||
}
|
||||
|
||||
const diffAlpha = isDark ? 0.22 : 0.14
|
||||
const diffAddedBg = tint(bg, ansi.green, diffAlpha)
|
||||
const diffRemovedBg = tint(bg, ansi.red, diffAlpha)
|
||||
const diffAddedLineNumberBg = tint(grays[3], ansi.green, diffAlpha)
|
||||
const diffRemovedLineNumberBg = tint(grays[3], ansi.red, diffAlpha)
|
||||
|
||||
return {
|
||||
theme: {
|
||||
primary: ansi.cyan,
|
||||
secondary: ansi.magenta,
|
||||
accent: ansi.cyan,
|
||||
error: ansi.red,
|
||||
warning: ansi.yellow,
|
||||
success: ansi.green,
|
||||
info: ansi.cyan,
|
||||
text: fg,
|
||||
textMuted,
|
||||
selectedListItemText: bg,
|
||||
background: transparent,
|
||||
backgroundPanel: grays[2],
|
||||
backgroundElement: grays[3],
|
||||
backgroundMenu: grays[3],
|
||||
borderSubtle: grays[6],
|
||||
border: grays[7],
|
||||
borderActive: grays[8],
|
||||
diffAdded: ansi.green,
|
||||
diffRemoved: ansi.red,
|
||||
diffContext: grays[7],
|
||||
diffHunkHeader: grays[7],
|
||||
diffHighlightAdded: ansi.greenBright,
|
||||
diffHighlightRemoved: ansi.redBright,
|
||||
diffAddedBg,
|
||||
diffRemovedBg,
|
||||
diffContextBg: grays[1],
|
||||
diffLineNumber: grays[6],
|
||||
diffAddedLineNumberBg,
|
||||
diffRemovedLineNumberBg,
|
||||
markdownText: fg,
|
||||
markdownHeading: fg,
|
||||
markdownLink: ansi.blue,
|
||||
markdownLinkText: ansi.cyan,
|
||||
markdownCode: ansi.green,
|
||||
markdownBlockQuote: ansi.yellow,
|
||||
markdownEmph: ansi.yellow,
|
||||
markdownStrong: fg,
|
||||
markdownHorizontalRule: grays[7],
|
||||
markdownListItem: ansi.blue,
|
||||
markdownListEnumeration: ansi.cyan,
|
||||
markdownImage: ansi.blue,
|
||||
markdownImageText: ansi.cyan,
|
||||
markdownCodeBlock: fg,
|
||||
syntaxComment: textMuted,
|
||||
syntaxKeyword: ansi.magenta,
|
||||
syntaxFunction: ansi.blue,
|
||||
syntaxVariable: fg,
|
||||
syntaxString: ansi.green,
|
||||
syntaxNumber: ansi.yellow,
|
||||
syntaxType: ansi.cyan,
|
||||
syntaxOperator: ansi.cyan,
|
||||
syntaxPunctuation: fg,
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user