1597c110d4
The session section and the Files/Changes panel drop their cards; one vertical divider separates them (none at full width), and the collapsed rail keeps only that divider. The terminal goes back to the page colour (--surface-0), and the panel's two sticky bars cover scrolled content in the page colour instead of the card's. Inside, the git row loses its bordered box for a bottom divider, and the ended-session prompt box drops its own fill and shadow.
96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
/**
|
|
* @file terminalTheme.ts
|
|
* @description The xterm colour theme for lane terminals. The terminal is
|
|
* ALWAYS dark — Claude Code's TUI picks its own colours for a dark background,
|
|
* so a light terminal would make its text unreadable — and is painted with the
|
|
* palette of the DARK theme the user picked (`themeFor.dark`). Colours are read
|
|
* from the CSS variables in `index.css` on a hidden probe carrying
|
|
* `class="dark" data-theme=<id>`, so no hex is duplicated here.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
import type { ITheme } from "@xterm/xterm";
|
|
|
|
/** Reads one CSS variable (an RGB triplet like `17 17 19`) by name. */
|
|
export type VarReader = (name: string) => string;
|
|
|
|
function toHex(triplet: string): string | undefined {
|
|
const parts = triplet
|
|
.trim()
|
|
.split(/[\s,]+/)
|
|
.map(Number);
|
|
if (parts.length !== 3 || parts.some((n) => !Number.isFinite(n))) return undefined;
|
|
return "#" + parts.map((n) => Math.round(n).toString(16).padStart(2, "0")).join("");
|
|
}
|
|
|
|
/** Mix a hex colour toward white by `amount` (0..1) — the ANSI "bright" twin. */
|
|
function lighten(hex: string | undefined, amount: number): string | undefined {
|
|
if (!hex) return undefined;
|
|
const rgb = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16));
|
|
return (
|
|
"#" +
|
|
rgb
|
|
.map((c) =>
|
|
Math.round(c + (255 - c) * amount)
|
|
.toString(16)
|
|
.padStart(2, "0")
|
|
)
|
|
.join("")
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Build an xterm theme from a theme's CSS variables. red/green/yellow come from
|
|
* `--status-*`, blue from `--accent`, black/white from the surface/fg ramp.
|
|
* Magenta and cyan stay the classic ANSI hues: no token keeps that hue in every
|
|
* theme (darcula's keyword is orange), and a program printing "magenta" should
|
|
* get magenta.
|
|
*/
|
|
export function buildTerminalTheme(read: VarReader): ITheme {
|
|
const v = (name: string) => toHex(read(name));
|
|
const red = v("--status-danger");
|
|
const green = v("--status-success");
|
|
const yellow = v("--status-warning");
|
|
const blue = v("--accent");
|
|
const magenta = "#c678dd";
|
|
const cyan = "#56b6c2";
|
|
return {
|
|
// The page's colour: the console sits on the page, with no card or frame.
|
|
background: v("--surface-0"),
|
|
foreground: v("--fg-primary"),
|
|
cursor: v("--fg-primary"),
|
|
cursorAccent: v("--surface-0"),
|
|
selectionBackground: v("--border-light"),
|
|
black: v("--border-light"),
|
|
red,
|
|
green,
|
|
yellow,
|
|
blue,
|
|
magenta,
|
|
cyan,
|
|
white: v("--fg-secondary"),
|
|
brightBlack: v("--fg-muted"),
|
|
brightRed: lighten(red, 0.25),
|
|
brightGreen: lighten(green, 0.25),
|
|
brightYellow: lighten(yellow, 0.25),
|
|
brightBlue: lighten(blue, 0.25),
|
|
brightMagenta: lighten(magenta, 0.25),
|
|
brightCyan: lighten(cyan, 0.25),
|
|
brightWhite: v("--fg-primary"),
|
|
};
|
|
}
|
|
|
|
/** Resolve the dark theme `id`'s variables on a hidden probe and build the theme. */
|
|
export function terminalThemeFor(id: string): ITheme {
|
|
const probe = document.createElement("div");
|
|
probe.className = "dark";
|
|
if (id !== "default") probe.dataset.theme = id;
|
|
probe.style.display = "none";
|
|
document.body.appendChild(probe);
|
|
try {
|
|
const style = getComputedStyle(probe);
|
|
return buildTerminalTheme((name) => style.getPropertyValue(name));
|
|
} finally {
|
|
probe.remove();
|
|
}
|
|
}
|