mirror of
https://github.com/jarrodwatts/claude-hud.git
synced 2026-05-12 09:12:40 +00:00
125 lines
4.1 KiB
JavaScript
125 lines
4.1 KiB
JavaScript
export const RESET = '\x1b[0m';
|
|
const DIM = '\x1b[2m';
|
|
const RED = '\x1b[31m';
|
|
const GREEN = '\x1b[32m';
|
|
const YELLOW = '\x1b[33m';
|
|
const MAGENTA = '\x1b[35m';
|
|
const CYAN = '\x1b[36m';
|
|
const BRIGHT_BLUE = '\x1b[94m';
|
|
const BRIGHT_MAGENTA = '\x1b[95m';
|
|
const CLAUDE_ORANGE = '\x1b[38;5;208m';
|
|
const ANSI_BY_NAME = {
|
|
dim: DIM,
|
|
red: RED,
|
|
green: GREEN,
|
|
yellow: YELLOW,
|
|
magenta: MAGENTA,
|
|
cyan: CYAN,
|
|
brightBlue: BRIGHT_BLUE,
|
|
brightMagenta: BRIGHT_MAGENTA,
|
|
};
|
|
/** Convert a hex color string (#rrggbb) to a truecolor ANSI escape sequence. */
|
|
function hexToAnsi(hex) {
|
|
const r = parseInt(hex.slice(1, 3), 16);
|
|
const g = parseInt(hex.slice(3, 5), 16);
|
|
const b = parseInt(hex.slice(5, 7), 16);
|
|
return `\x1b[38;2;${r};${g};${b}m`;
|
|
}
|
|
/**
|
|
* Resolve a color value to an ANSI escape sequence.
|
|
* Accepts named presets, 256-color indices (0-255), or hex strings (#rrggbb).
|
|
*/
|
|
function resolveAnsi(value, fallback) {
|
|
if (value === undefined || value === null) {
|
|
return fallback;
|
|
}
|
|
if (typeof value === 'number') {
|
|
return `\x1b[38;5;${value}m`;
|
|
}
|
|
if (typeof value === 'string' && value.startsWith('#') && value.length === 7) {
|
|
return hexToAnsi(value);
|
|
}
|
|
return ANSI_BY_NAME[value] ?? fallback;
|
|
}
|
|
function colorize(text, color) {
|
|
return `${color}${text}${RESET}`;
|
|
}
|
|
function withOverride(text, value, fallback) {
|
|
return colorize(text, resolveAnsi(value, fallback));
|
|
}
|
|
export function green(text) {
|
|
return colorize(text, GREEN);
|
|
}
|
|
export function yellow(text) {
|
|
return colorize(text, YELLOW);
|
|
}
|
|
export function red(text) {
|
|
return colorize(text, RED);
|
|
}
|
|
export function cyan(text) {
|
|
return colorize(text, CYAN);
|
|
}
|
|
export function magenta(text) {
|
|
return colorize(text, MAGENTA);
|
|
}
|
|
export function dim(text) {
|
|
return colorize(text, DIM);
|
|
}
|
|
export function claudeOrange(text) {
|
|
return colorize(text, CLAUDE_ORANGE);
|
|
}
|
|
export function model(text, colors) {
|
|
return withOverride(text, colors?.model, CYAN);
|
|
}
|
|
export function project(text, colors) {
|
|
return withOverride(text, colors?.project, YELLOW);
|
|
}
|
|
export function git(text, colors) {
|
|
return withOverride(text, colors?.git, MAGENTA);
|
|
}
|
|
export function gitBranch(text, colors) {
|
|
return withOverride(text, colors?.gitBranch, CYAN);
|
|
}
|
|
export function label(text, colors) {
|
|
return withOverride(text, colors?.label, DIM);
|
|
}
|
|
export function custom(text, colors) {
|
|
return withOverride(text, colors?.custom, CLAUDE_ORANGE);
|
|
}
|
|
export function warning(text, colors) {
|
|
return colorize(text, resolveAnsi(colors?.warning, YELLOW));
|
|
}
|
|
export function critical(text, colors) {
|
|
return colorize(text, resolveAnsi(colors?.critical, RED));
|
|
}
|
|
export function getContextColor(percent, colors) {
|
|
if (percent >= 85)
|
|
return resolveAnsi(colors?.critical, RED);
|
|
if (percent >= 70)
|
|
return resolveAnsi(colors?.warning, YELLOW);
|
|
return resolveAnsi(colors?.context, GREEN);
|
|
}
|
|
export function getQuotaColor(percent, colors) {
|
|
if (percent >= 90)
|
|
return resolveAnsi(colors?.critical, RED);
|
|
if (percent >= 75)
|
|
return resolveAnsi(colors?.usageWarning, BRIGHT_MAGENTA);
|
|
return resolveAnsi(colors?.usage, BRIGHT_BLUE);
|
|
}
|
|
export function quotaBar(percent, width = 10, colors) {
|
|
const safeWidth = Number.isFinite(width) ? Math.max(0, Math.round(width)) : 0;
|
|
const safePercent = Number.isFinite(percent) ? Math.min(100, Math.max(0, percent)) : 0;
|
|
const filled = Math.round((safePercent / 100) * safeWidth);
|
|
const empty = safeWidth - filled;
|
|
const color = getQuotaColor(safePercent, colors);
|
|
return `${color}${'█'.repeat(filled)}${DIM}${'░'.repeat(empty)}${RESET}`;
|
|
}
|
|
export function coloredBar(percent, width = 10, colors) {
|
|
const safeWidth = Number.isFinite(width) ? Math.max(0, Math.round(width)) : 0;
|
|
const safePercent = Number.isFinite(percent) ? Math.min(100, Math.max(0, percent)) : 0;
|
|
const filled = Math.round((safePercent / 100) * safeWidth);
|
|
const empty = safeWidth - filled;
|
|
const color = getContextColor(safePercent, colors);
|
|
return `${color}${'█'.repeat(filled)}${DIM}${'░'.repeat(empty)}${RESET}`;
|
|
}
|
|
//# sourceMappingURL=colors.js.map
|