UNPKG

@pompeii-labs/cli

Version:

Magma CLI

188 lines (186 loc) 5.15 kB
import chalk from "chalk"; const MAGMA_COLOR = "#FF7500"; class Spinner { constructor(message) { this.frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]; this.i = 0; this.message = message; } start() { this.intervalId = setInterval(() => { const frame = this.frames[this.i]; process.stdout.write(`\r${UI.colors.white}${frame}${UI.colors.reset} ${this.message}`); this.i = (this.i + 1) % this.frames.length; }, 80); return this; } stop() { if (this.intervalId) { clearInterval(this.intervalId); process.stdout.write("\r\x1B[K"); } return this; } succeed(finalMessage) { this.stop(); process.stdout.write( `\r${UI.colors.green}\u2713${UI.colors.reset} ${finalMessage || this.message} ` ); return this; } fail(finalMessage) { this.stop(); process.stdout.write( `\r${UI.colors.red}\u2716${UI.colors.reset} ${finalMessage || this.message} ` ); return this; } } class ThinkingSpinner { constructor() { this.interval = null; this.frames = ["thinking", "thinking.", "thinking..", "thinking..."]; this.currentFrame = 0; } start() { this.interval = setInterval(() => { process.stdout.write("\r\x1B[K"); process.stdout.write(chalk.dim(this.frames[this.currentFrame])); this.currentFrame = (this.currentFrame + 1) % this.frames.length; }, 500); } stop() { if (this.interval) { clearInterval(this.interval); process.stdout.write("\r\x1B[K"); } } } class ProgressBar { constructor(total, options) { this.current = 0; this.total = total; this.width = options?.width || 30; this.message = options?.message; } render() { const percent = Math.round(this.current / this.total * 100); const filled = Math.round(this.current / this.total * this.width); const empty = this.width - filled; const filledBar = "\u2588".repeat(filled); const emptyBar = "\u2591".repeat(empty); const bar = `${UI.colors.cyan}${filledBar}${UI.colors.dim}${emptyBar}${UI.colors.reset}`; const percentage = `${percent}%`; const message = this.message ? ` ${this.message}` : ""; process.stdout.write(`\r${bar} ${percentage}${message}`); } update(n) { this.current = n; this.render(); if (this.current === this.total) { process.stdout.write("\n"); } return this; } increment(n = 1) { this.current = Math.min(this.current + n, this.total); this.render(); if (this.current === this.total) { process.stdout.write("\n"); } return this; } } class UI { static { this.colors = { reset: "\x1B[0m", cyan: "\x1B[36m", green: "\x1B[32m", red: "\x1B[31m", dim: "\x1B[2m", blue: "\x1B[34m", white: "\x1B[37m", orange: "\x1B[38;5;208m" }; } static spinner(message) { return new Spinner(message); } static thinkingSpinner() { return new ThinkingSpinner(); } static progress(total, options) { return new ProgressBar(total, options); } } const magma = (text, bold = true) => chalk.hex(MAGMA_COLOR)(bold ? chalk.bold(text) : text); class MagmaFlow { // How many frames to complete a full cycle constructor(asciiArt, staticContent) { this.interval = null; this.position = 0; this.CYCLE_LENGTH = 200; this.text = asciiArt.split("\n"); this.staticContent = staticContent; } getColorGradient(position, charPosition) { const offset = (-charPosition + position) % this.CYCLE_LENGTH; const baseR = 255; const baseG = 140; const baseB = 0; const wave1 = Math.sin(offset * 0.1) * 0.2; const wave2 = Math.sin(offset * 0.05) * 0.1; const brightness = 0.7 + wave1 + wave2; const r = Math.floor(baseR * Math.min(Math.max(brightness, 0.4), 1)); const g = Math.floor(baseG * Math.min(Math.max(brightness, 0.4), 1)); const b = Math.floor(baseB * Math.min(Math.max(brightness, 0.4), 1)); return `\x1B[38;2;${r};${g};${b}m`; } renderFrame(position) { const animatedLogo = this.text.map((line) => { let coloredLine = ""; for (let i = 0; i < line.length; i++) { const char = line[i]; if (char === " ") { coloredLine += char; } else { const color = this.getColorGradient(position, i); coloredLine += `${color}${char}\x1B[0m`; } } return coloredLine; }).join("\n"); return `${animatedLogo} ${this.staticContent}`; } start() { console.clear(); process.stdout.write("\x1B[?25l"); this.interval = setInterval(() => { process.stdout.write("\x1B[H"); process.stdout.write(this.renderFrame(this.position)); this.position = (this.position + 1) % this.CYCLE_LENGTH; }, 40); process.on("SIGINT", () => { this.stop(); process.exit(0); }); } stop() { if (this.interval) { clearInterval(this.interval); process.stdout.write("\x1B[?25h"); } } } export { MagmaFlow, ProgressBar, Spinner, ThinkingSpinner, UI, magma };