@trap_stevo/terminal-plus
Version:
Transform your CLI into a visually striking, feature-rich command layer. Blend animated gradients, stylish badges, dynamic progress bars, sleek tables, and precise formatting utilities — all turning terminal output into a powerful visual experience.
179 lines (178 loc) • 5.15 kB
JavaScript
;
const chalk = require("chalk");
const easing = {
easeInOutQuad: t => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
easeInOut: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
cosine: t => (1 - Math.cos(t * Math.PI)) / 2,
linear: t => t
};
function convertHexToRGB(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 [r, g, b];
}
;
function hexToRGB(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
;
function generateLerp(a, b, t) {
return a + (b - a) * t;
}
;
function generateColorInterpolation(color1, color2, factor) {
const result = color1.slice();
for (let i = 0; i < 3; i++) {
result[i] = Math.round(generateLerp(color1[i], color2[i], factor));
}
return result;
}
;
function generateGradientColors(colors, steps, easingType = "linear") {
let gradient = [];
const sections = colors.length - 1;
const stepsPerSection = Math.floor(steps / sections);
for (let section = 0; section < sections; section++) {
for (let step = 0; step < stepsPerSection; step++) {
const color1 = convertHexToRGB(colors[section]);
const color2 = convertHexToRGB(colors[section + 1]);
const t = step / stepsPerSection;
const factor = easing[easingType] ? easing[easingType](t) : t;
gradient.push(generateColorInterpolation(color1, color2, factor));
}
}
gradient.push(convertHexToRGB(colors[colors.length - 1]));
while (gradient.length < steps) {
gradient.push(convertHexToRGB(colors[colors.length - 1]));
}
return gradient;
}
;
function generateGradientText(text, colors = ["#ffffff", "#000000"]) {
if (!Array.isArray(colors) || colors.length === 0) {
return text;
}
const segments = colors.length - 1;
const segmentLength = text.length / segments;
let gradientText = "";
for (let i = 0; i < text.length; i++) {
const seg = Math.min(Math.floor(i / segmentLength), segments - 1);
const ratio = i % segmentLength / segmentLength;
const startRGB = convertHexToRGB(colors[seg]);
const endRGB = convertHexToRGB(colors[seg + 1]);
if (!startRGB || !endRGB) {
gradientText += text[i];
continue;
}
const [r, g, b] = generateColorInterpolation(startRGB, endRGB, ratio);
gradientText += chalk.rgb(r, g, b)(text[i]);
}
return gradientText;
}
;
function outputGradient(text, colors) {
const gradient = generateGradientColors(colors, text.length);
let coloredText = "";
for (let i = 0; i < text.length; i++) {
const [r, g, b] = gradient[i];
coloredText += chalk.rgb(r, g, b)(text[i]);
}
console.log(coloredText);
}
;
function movingGradientRenderer(text, colors, interval = 100, skipRange = [0, 0], options = {}) {
const readline = require("readline");
const {
inlinePosition = "left"
} = options;
let offset = 0;
let intervalID = null;
let running = false;
let inlineFollower = "";
const renderFrame = () => {
const gradientColors = generateGradientColors(colors, text.length);
let coloredText = "";
for (let i = 0; i < text.length; i++) {
if (i >= skipRange[0] && i < skipRange[1]) {
coloredText += text[i];
continue;
}
const colorIndex = (i + offset) % gradientColors.length;
const [r, g, b] = gradientColors[colorIndex];
coloredText += chalk.rgb(r, g, b)(text[i]);
}
readline.cursorTo(process.stdout, 0);
readline.clearLine(process.stdout, 0);
process.stdout.write(inlinePosition === "left" ? (inlineFollower ? inlineFollower + " " : "") + coloredText : coloredText + (inlineFollower ? " " + inlineFollower : ""));
offset = (offset + 1) % text.length;
};
return {
start() {
if (running) {
return;
}
running = true;
renderFrame();
intervalID = setInterval(renderFrame, interval);
},
stop() {
if (!running) {
return;
}
clearInterval(intervalID);
running = false;
process.stdout.write("\n");
},
moving() {
return running;
},
setFollower(content) {
inlineFollower = content;
}
};
}
;
function outputGradientToString(text, colors) {
const gradient = generateGradientColors(colors, text.length);
let coloredText = "";
for (let i = 0; i < text.length; i++) {
const [r, g, b] = gradient[i];
coloredText += chalk.rgb(r, g, b)(text[i]);
}
return coloredText;
}
;
function applyColor(text, options = {}) {
const {
backgroundColor = null,
textColor = null
} = options;
let styled = text;
if (backgroundColor) {
styled = chalk.bgHex(backgroundColor)(styled);
}
if (textColor) {
styled = chalk.hex(textColor)(styled);
}
return styled;
}
;
module.exports = {
convertHexToRGB,
hexToRGB,
generateLerp,
generateColorInterpolation,
generateGradientColors,
generateGradientText,
outputGradient,
outputGradientToString,
movingGradientRenderer,
applyColor,
chalk
};