@heinrichb/console-toolkit 1.0.3 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +162 -2
  2. package/dist/{progress.d.ts → components/progress.d.ts} +12 -12
  3. package/dist/{progress.js → components/progress.js} +5 -6
  4. package/dist/{progress.test.js → components/progress.test.js} +14 -10
  5. package/dist/components/spinner.d.ts +36 -0
  6. package/dist/components/spinner.js +33 -0
  7. package/dist/components/spinner.test.js +53 -0
  8. package/dist/core/layout.d.ts +25 -0
  9. package/dist/core/layout.js +55 -0
  10. package/dist/core/layout.test.d.ts +1 -0
  11. package/dist/core/layout.test.js +52 -0
  12. package/dist/core/printer.d.ts +33 -0
  13. package/dist/core/printer.js +129 -0
  14. package/dist/core/printer.test.d.ts +1 -0
  15. package/dist/core/printer.test.js +124 -0
  16. package/dist/core/style.d.ts +53 -0
  17. package/dist/core/style.js +171 -0
  18. package/dist/core/style.test.d.ts +1 -0
  19. package/dist/core/style.test.js +108 -0
  20. package/dist/core/types.d.ts +72 -0
  21. package/dist/core/types.js +4 -0
  22. package/dist/core/utils.d.ts +25 -0
  23. package/dist/core/utils.js +36 -0
  24. package/dist/core/utils.test.d.ts +1 -0
  25. package/dist/core/utils.test.js +25 -0
  26. package/dist/demo.d.ts +0 -4
  27. package/dist/demo.js +104 -43
  28. package/dist/index.d.ts +8 -99
  29. package/dist/index.js +14 -234
  30. package/dist/presets/ascii.d.ts +5 -0
  31. package/dist/presets/ascii.js +35 -0
  32. package/dist/presets/ascii.test.d.ts +1 -0
  33. package/dist/presets/ascii.test.js +21 -0
  34. package/package.json +46 -44
  35. package/dist/index.test.js +0 -126
  36. /package/dist/{progress.test.d.ts → components/progress.test.d.ts} +0 -0
  37. /package/dist/{index.test.d.ts → components/spinner.test.d.ts} +0 -0
@@ -0,0 +1,25 @@
1
+ import { PrintLine, PrintStyle } from "./types";
2
+ /**
3
+ * Gets the plain text length of a PrintLine (ignoring ANSI codes).
4
+ *
5
+ * @param line - The PrintLine to measure.
6
+ * @returns The length of the text content.
7
+ */
8
+ export declare function getLineLength(line: PrintLine): number;
9
+ /**
10
+ * Computes the maximum width among an array of PrintLines.
11
+ * Useful for aligning columns.
12
+ *
13
+ * @param lines - Array of PrintLines.
14
+ * @returns The maximum line length found.
15
+ */
16
+ export declare function computeMaxWidth(lines: PrintLine[]): number;
17
+ /**
18
+ * Pads a PrintLine to a target width by adding an empty segment at the end.
19
+ *
20
+ * @param line - The line to pad.
21
+ * @param targetWidth - The desired minimum width.
22
+ * @param padStyle - The style to apply to the padding spaces.
23
+ * @returns A new PrintLine with padding added if necessary.
24
+ */
25
+ export declare function padLine(line: PrintLine, targetWidth: number, padStyle?: PrintStyle): PrintLine;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Gets the plain text length of a PrintLine (ignoring ANSI codes).
3
+ *
4
+ * @param line - The PrintLine to measure.
5
+ * @returns The length of the text content.
6
+ */
7
+ export function getLineLength(line) {
8
+ return line.segments.reduce((acc, seg) => acc + seg.text.length, 0);
9
+ }
10
+ /**
11
+ * Computes the maximum width among an array of PrintLines.
12
+ * Useful for aligning columns.
13
+ *
14
+ * @param lines - Array of PrintLines.
15
+ * @returns The maximum line length found.
16
+ */
17
+ export function computeMaxWidth(lines) {
18
+ return lines.length > 0 ? Math.max(...lines.map(getLineLength)) : 0;
19
+ }
20
+ /**
21
+ * Pads a PrintLine to a target width by adding an empty segment at the end.
22
+ *
23
+ * @param line - The line to pad.
24
+ * @param targetWidth - The desired minimum width.
25
+ * @param padStyle - The style to apply to the padding spaces.
26
+ * @returns A new PrintLine with padding added if necessary.
27
+ */
28
+ export function padLine(line, targetWidth, padStyle) {
29
+ const currentLength = getLineLength(line);
30
+ if (currentLength < targetWidth) {
31
+ return {
32
+ segments: [...line.segments, { text: " ".repeat(targetWidth - currentLength), style: padStyle }]
33
+ };
34
+ }
35
+ return line;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import { expect, test, describe } from "bun:test";
2
+ import { getLineLength, computeMaxWidth, padLine } from "./utils";
3
+ const lineA = { segments: [{ text: "Hello", style: {} }] };
4
+ const lineB = { segments: [{ text: "World!!", style: {} }] };
5
+ describe("Line Utilities", () => {
6
+ test("getLineLength calculates correctly", () => {
7
+ expect(getLineLength(lineA)).toBe(5);
8
+ expect(getLineLength(lineB)).toBe(7);
9
+ });
10
+ test("computeMaxWidth finds the longest line", () => {
11
+ expect(computeMaxWidth([lineA, lineB])).toBe(7);
12
+ expect(computeMaxWidth([])).toBe(0);
13
+ });
14
+ test("padLine adds padding when needed", () => {
15
+ const padded = padLine(lineA, 10, { color: "red" });
16
+ expect(getLineLength(padded)).toBe(10);
17
+ expect(padded.segments[1].style).toEqual({ color: "red" });
18
+ expect(padded.segments[1].text).toBe(" ");
19
+ });
20
+ test("padLine does nothing if line is already wide enough", () => {
21
+ const ignored = padLine(lineB, 5, { color: "red" });
22
+ expect(getLineLength(ignored)).toBe(7);
23
+ expect(ignored.segments.length).toBe(1);
24
+ });
25
+ });
package/dist/demo.d.ts CHANGED
@@ -1,5 +1 @@
1
- /**
2
- * Run this demo to visually verify terminal output:
3
- * bun run src/demo.ts
4
- */
5
1
  export declare function runDemo(): Promise<void>;
package/dist/demo.js CHANGED
@@ -1,17 +1,27 @@
1
- import { printDualColumn, getDragonLines, Printer, interpolateColor, createProgressBar } from "./index";
1
+ import { printColumns, getDragon, Printer, interpolateColor, createProgressBar, Spinner, SPINNERS } from "./index";
2
2
  import pkg from "../package.json";
3
3
  /**
4
4
  * Run this demo to visually verify terminal output:
5
5
  * bun run src/demo.ts
6
6
  */
7
+ function getProgressBarColor(factor) {
8
+ // Multi-stop gradient: Blue -> Cyan -> Green
9
+ if (factor < 0.5) {
10
+ return interpolateColor("#3B82F6", "#06B6D4", factor * 2);
11
+ }
12
+ else {
13
+ return interpolateColor("#06B6D4", "#10B981", (factor - 0.5) * 2);
14
+ }
15
+ }
7
16
  export async function runDemo() {
8
17
  console.clear();
9
- // 1. Test Static Dual Column Print
18
+ const staticPrinter = new Printer();
19
+ // 1. Static Dual Column Print
10
20
  console.log("--- Static Dual Column Demo ---");
11
- const purple = "#A78BFA";
12
- const blue = "#60A5FA";
13
- const green = "#34D399";
14
- const yellow = "#FBBF24";
21
+ const purple = { color: "#A78BFA" };
22
+ const blue = { color: "#60A5FA" };
23
+ const green = { color: "#34D399" };
24
+ const yellow = { color: "#FBBF24" };
15
25
  const leftContent = [
16
26
  { segments: [{ text: "Package:", style: purple }] },
17
27
  { segments: [{ text: "Version:", style: purple }] },
@@ -22,22 +32,34 @@ export async function runDemo() {
22
32
  { segments: [{ text: pkg.version, style: green }] },
23
33
  { segments: [{ text: "Testing live output...", style: yellow }] }
24
34
  ];
25
- printDualColumn(leftContent, rightContent, { separator: " => " });
35
+ printColumns([leftContent, rightContent], { separator: " => " });
36
+ console.log("\n");
37
+ // 2. Block Vertical Gradient Demo
38
+ console.log("--- Block Vertical Gradient Demo ---");
39
+ const gradientBlockLines = Array.from({ length: 10 }, (_, i) => ({
40
+ segments: [{ text: `Line ${i + 1} - Inherits Gradient` }]
41
+ }));
42
+ staticPrinter.print({
43
+ style: { color: ["#EF4444", "#3B82F6"] },
44
+ lines: gradientBlockLines
45
+ });
26
46
  console.log("\n");
27
- // 2. Test the Dragon Gradient Preset
47
+ // 3. Dragon Gradient Preset
28
48
  console.log("--- Dragon Gradient Preset ---");
29
- const dragon = getDragonLines("#EF4444", "#FDE047");
30
- const printer = new Printer();
31
- printer.print(dragon);
49
+ const dragon = getDragon("#EF4444", "#FDE047");
50
+ staticPrinter.print({ lines: dragon });
32
51
  console.log("\n");
33
- // 3. Test Progress Bar
34
- console.log("--- Interactive Progress Bar Demo ---");
35
- const interactivePrinter = new Printer({ interactive: true });
36
- const gray = "#4B5563";
52
+ // 4. Interactive Progress Bar Demo
53
+ console.log("--- Live Progress Bar Demo ---");
54
+ const livePrinter = new Printer({ live: true });
55
+ const gray = { color: "#4B5563" };
37
56
  for (let i = 0; i <= 100; i += 2) {
38
- const progressColor = interpolateColor("#3B82F6", "#10B981", i / 100);
57
+ const factor = i / 100;
58
+ const progressColorHex = interpolateColor("#3B82F6", "#10B981", factor);
59
+ const progressColor = { color: progressColorHex };
60
+ // Standard Bar
39
61
  const progressLine = createProgressBar({
40
- progress: i / 100,
62
+ progress: factor,
41
63
  width: 30,
42
64
  startChar: "[",
43
65
  endChar: "]",
@@ -47,38 +69,77 @@ export async function runDemo() {
47
69
  emptyStyle: gray,
48
70
  percentageStyle: progressColor
49
71
  });
50
- interactivePrinter.print([progressLine]);
51
- await new Promise((resolve) => setTimeout(resolve, 20));
72
+ // Gradient Bar
73
+ const gradientHex = getProgressBarColor(factor);
74
+ const gradientStyle = { color: gradientHex };
75
+ const complexGradientBar = createProgressBar({
76
+ progress: factor,
77
+ width: 40,
78
+ startChar: "▕",
79
+ endChar: "▏",
80
+ fillChar: "█",
81
+ emptyChar: "░",
82
+ startStyle: gradientStyle,
83
+ endStyle: gradientStyle,
84
+ fillStyle: { color: ["#3B82F6", "#EC4899"] },
85
+ emptyStyle: { color: "gray" },
86
+ percentageStyle: { modifiers: ["bold"], color: gradientHex }
87
+ });
88
+ livePrinter.print({
89
+ lines: [
90
+ progressLine,
91
+ { segments: [] },
92
+ { segments: [{ text: "Horizontal Gradient on Bar Segment:", style: { modifiers: ["bold"] } }] },
93
+ complexGradientBar
94
+ ]
95
+ });
96
+ await new Promise((resolve) => setTimeout(resolve, 30));
97
+ }
98
+ console.log("\n");
99
+ // 5. Spinners Demo
100
+ console.log("--- Spinners Demo ---");
101
+ const spinnerTypes = Object.keys(SPINNERS);
102
+ const spinners = spinnerTypes.map((type) => ({
103
+ type,
104
+ instance: new Spinner({ frames: SPINNERS[type], interval: 80 })
105
+ }));
106
+ const spinnerPrinter = new Printer({ live: true });
107
+ const spinnerStart = Date.now();
108
+ while (Date.now() - spinnerStart < 3000) {
109
+ const lines = spinners.map((s) => ({
110
+ segments: [
111
+ { text: `${s.type.charAt(0).toUpperCase() + s.type.slice(1)}:`.padEnd(10), style: { modifiers: ["dim"] } },
112
+ { text: s.instance.getFrame(), style: { color: "cyan" } }
113
+ ]
114
+ }));
115
+ spinnerPrinter.print({ lines });
116
+ await new Promise((resolve) => setTimeout(resolve, 50));
52
117
  }
53
118
  console.log("\n");
54
- // 4. Style Codes Demo
119
+ // 6. Style Codes Demo
55
120
  console.log("--- Style Codes Demo ---");
56
121
  const styles = [
57
- { name: "Default", style: "default" },
58
- { name: "Bold", style: "bold" },
59
- { name: "Dim", style: "dim" },
60
- { name: "Italic", style: "italic" },
61
- { name: "Underline", style: "underline" },
62
- { name: "Strikethrough", style: "strikethrough" },
63
- { name: "Inverse", style: "inverse" },
64
- { name: "Hidden", style: "hidden" },
65
- { name: "Black", style: "black" },
66
- { name: "Red", style: "red" },
67
- { name: "Green", style: "green" },
68
- { name: "Yellow", style: "yellow" },
69
- { name: "Blue", style: "blue" },
70
- { name: "Magenta", style: "magenta" },
71
- { name: "Cyan", style: "cyan" },
72
- { name: "White", style: "white" },
73
- { name: "Gray", style: "gray" }
122
+ { name: "Default" },
123
+ { name: "Bold + Red", style: { modifiers: ["bold"], color: "red" } },
124
+ { name: "Bold", style: { modifiers: ["bold"] } },
125
+ { name: "Dim", style: { modifiers: ["dim"] } },
126
+ { name: "Italic", style: { modifiers: ["italic"] } },
127
+ { name: "Underline", style: { modifiers: ["underline"] } },
128
+ { name: "Strikethrough", style: { modifiers: ["strikethrough"] } },
129
+ { name: "Inverse", style: { modifiers: ["inverse"] } },
130
+ { name: "Hidden", style: { modifiers: ["hidden"] } },
131
+ { name: "Red", style: { color: "red" } },
132
+ { name: "Green", style: { color: "green" } },
133
+ { name: "Yellow", style: { color: "yellow" } },
134
+ { name: "Blue", style: { color: "blue" } },
135
+ { name: "Magenta", style: { color: "magenta" } },
136
+ { name: "Cyan", style: { color: "cyan" } },
137
+ { name: "White", style: { color: "white" } },
138
+ { name: "Gray", style: { color: "gray" } }
74
139
  ];
75
140
  const styleLines = styles.map((s) => ({
76
- segments: [
77
- { text: s.name.padEnd(15), style: "default" },
78
- { text: "Sample Text", style: s.style }
79
- ]
141
+ segments: [{ text: s.name.padEnd(20) }, { text: "Sample Text", style: s.style }]
80
142
  }));
81
- const stylePrinter = new Printer();
82
- stylePrinter.print(styleLines);
143
+ staticPrinter.print({ lines: styleLines });
83
144
  console.log("\n✨ Demo Complete!");
84
145
  }
package/dist/index.d.ts CHANGED
@@ -1,99 +1,8 @@
1
- /**
2
- * Core types for styled console output.
3
- */
4
- export type StandardColor = "black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan" | "white" | "gray" | "grey";
5
- export type StyleModifier = "bold" | "dim" | "italic" | "underline" | "reset" | "default" | "hidden" | "inverse" | "strikethrough";
6
- export type HexColor = `#${string}`;
7
- /**
8
- * A style can be a standard color name, a hex color string, or a style modifier.
9
- * It can also be a raw ANSI string (though discouraged) for backward compatibility or special cases.
10
- */
11
- export type Style = StandardColor | StyleModifier | HexColor | string;
12
- export interface StyledSegment {
13
- text: string;
14
- /** Style or array of styles to apply to the text */
15
- style: Style | Style[];
16
- }
17
- export interface StyledLine {
18
- segments: StyledSegment[];
19
- }
20
- /**
21
- * Configuration for the Printer engine.
22
- */
23
- export interface PrinterOptions {
24
- /** If true, the printer will overwrite previous lines instead of appending new ones. */
25
- interactive?: boolean;
26
- /** The default style to apply to padding or separators. */
27
- defaultStyle?: Style | Style[];
28
- }
29
- export declare const RESET = "\u001B[0m";
30
- /**
31
- * Converts a hex color string to an RGB object.
32
- * @param hex - Hex color in the form "#RRGGBB".
33
- */
34
- export declare function hexToRgb(hex: string): {
35
- r: number;
36
- g: number;
37
- b: number;
38
- };
39
- /**
40
- * Converts RGB to a 24-bit ANSI foreground color escape sequence.
41
- */
42
- export declare function rgbToAnsi(r: number, g: number, b: number): string;
43
- /**
44
- * Converts a hex color string directly to an ANSI escape sequence.
45
- */
46
- export declare function hexToAnsi(hex: string): string;
47
- /**
48
- * Interpolates between two hex colors based on a factor (0 to 1) and returns a Hex color string.
49
- */
50
- export declare function interpolateColor(color1: string, color2: string, factor: number): HexColor;
51
- /**
52
- * Resolves a single Style or array of Styles into an ANSI escape sequence.
53
- */
54
- export declare function resolveStyle(style: Style | Style[]): string;
55
- /**
56
- * Gets the plain text length of a StyledLine.
57
- */
58
- export declare function getLineLength(line: StyledLine): number;
59
- /**
60
- * Computes the maximum width among an array of StyledLines.
61
- */
62
- export declare function computeMaxWidth(lines: StyledLine[]): number;
63
- /**
64
- * Pads a StyledLine to a target width by adding an empty segment at the end.
65
- */
66
- export declare function padLine(line: StyledLine, targetWidth: number, padStyle: Style | Style[]): StyledLine;
67
- /**
68
- * Handles rendering StyledLines to the terminal with support for interactive overwriting.
69
- */
70
- export declare class Printer {
71
- private linesRendered;
72
- private isInteractive;
73
- constructor(options?: PrinterOptions);
74
- /**
75
- * Generates the clear sequence to move cursor and clear previously rendered lines.
76
- */
77
- private getClearSequence;
78
- /**
79
- * Renders an array of StyledLines to the standard output.
80
- */
81
- print(lines: StyledLine[]): void;
82
- }
83
- /**
84
- * Merges two columns of StyledLines into a single layout.
85
- */
86
- export declare function mergeColumns(leftColumn: StyledLine[], rightColumn: StyledLine[], leftWidth: number, separator: string, defaultStyle: Style | Style[]): StyledLine[];
87
- /**
88
- * Prints two columns of styled content to the console.
89
- */
90
- export declare function printDualColumn(left: StyledLine[], right: StyledLine[], options?: {
91
- leftWidth?: number;
92
- separator?: string;
93
- printer?: Printer;
94
- }): void;
95
- /**
96
- * Returns the classic Dragon ASCII art as StyledLines with a vertical color gradient.
97
- */
98
- export declare function getDragonLines(startColor?: string, endColor?: string): StyledLine[];
99
- export * from "./progress";
1
+ export * from "./core/types";
2
+ export * from "./core/style";
3
+ export * from "./core/utils";
4
+ export * from "./core/printer";
5
+ export * from "./core/layout";
6
+ export * from "./components/progress";
7
+ export * from "./components/spinner";
8
+ export * from "./presets/ascii";
package/dist/index.js CHANGED
@@ -1,234 +1,14 @@
1
- /**
2
- * Core types for styled console output.
3
- */
4
- // -----------------
5
- // Color Utilities
6
- // -----------------
7
- const ESC = "\x1b";
8
- export const RESET = `${ESC}[0m`;
9
- /**
10
- * Converts a hex color string to an RGB object.
11
- * @param hex - Hex color in the form "#RRGGBB".
12
- */
13
- export function hexToRgb(hex) {
14
- const h = hex.replace(/^#/, "");
15
- if (h.length !== 6)
16
- throw new Error("Invalid hex color.");
17
- return {
18
- r: parseInt(h.substring(0, 2), 16),
19
- g: parseInt(h.substring(2, 4), 16),
20
- b: parseInt(h.substring(4, 6), 16)
21
- };
22
- }
23
- /**
24
- * Converts RGB to a 24-bit ANSI foreground color escape sequence.
25
- */
26
- export function rgbToAnsi(r, g, b) {
27
- return `${ESC}[38;2;${r};${g};${b}m`;
28
- }
29
- /**
30
- * Converts a hex color string directly to an ANSI escape sequence.
31
- */
32
- export function hexToAnsi(hex) {
33
- const { r, g, b } = hexToRgb(hex);
34
- return rgbToAnsi(r, g, b);
35
- }
36
- /**
37
- * Converts a single RGB component to a 2-digit hex string.
38
- */
39
- function toHex(c) {
40
- const hex = Math.max(0, Math.min(255, Math.round(c))).toString(16);
41
- return hex.length === 1 ? "0" + hex : hex;
42
- }
43
- /**
44
- * Interpolates between two hex colors based on a factor (0 to 1) and returns a Hex color string.
45
- */
46
- export function interpolateColor(color1, color2, factor) {
47
- const f = Math.max(0, Math.min(1, factor));
48
- const c1 = hexToRgb(color1);
49
- const c2 = hexToRgb(color2);
50
- const r = c1.r + f * (c2.r - c1.r);
51
- const g = c1.g + f * (c2.g - c1.g);
52
- const b = c1.b + f * (c2.b - c1.b);
53
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
54
- }
55
- // -----------------
56
- // Style Resolution
57
- // -----------------
58
- const STYLE_CODES = {
59
- reset: "0",
60
- default: "0",
61
- bold: "1",
62
- dim: "2",
63
- italic: "3",
64
- underline: "4",
65
- inverse: "7",
66
- hidden: "8",
67
- strikethrough: "9",
68
- black: "30",
69
- red: "31",
70
- green: "32",
71
- yellow: "33",
72
- blue: "34",
73
- magenta: "35",
74
- cyan: "36",
75
- white: "37",
76
- gray: "90",
77
- grey: "90"
78
- };
79
- /**
80
- * Resolves a single Style or array of Styles into an ANSI escape sequence.
81
- */
82
- export function resolveStyle(style) {
83
- if (Array.isArray(style)) {
84
- return style.map(resolveStyle).join("");
85
- }
86
- if (typeof style !== "string") {
87
- return "";
88
- }
89
- // Check for hex color
90
- if (style.startsWith("#")) {
91
- try {
92
- return hexToAnsi(style);
93
- }
94
- catch {
95
- return ""; // Invalid hex, ignore
96
- }
97
- }
98
- // Check for standard styles/colors
99
- const code = STYLE_CODES[style.toLowerCase()];
100
- if (code) {
101
- return `${ESC}[${code}m`;
102
- }
103
- // Fallback: return as raw string if it looks like ANSI or just text
104
- // Ideally we would validate ANSI here, but for flexibility we return it.
105
- return style;
106
- }
107
- // -----------------
108
- // Line Manipulation Helpers
109
- // -----------------
110
- /**
111
- * Gets the plain text length of a StyledLine.
112
- */
113
- export function getLineLength(line) {
114
- return line.segments.reduce((acc, seg) => acc + seg.text.length, 0);
115
- }
116
- /**
117
- * Computes the maximum width among an array of StyledLines.
118
- */
119
- export function computeMaxWidth(lines) {
120
- return lines.length > 0 ? Math.max(...lines.map(getLineLength)) : 0;
121
- }
122
- /**
123
- * Pads a StyledLine to a target width by adding an empty segment at the end.
124
- */
125
- export function padLine(line, targetWidth, padStyle) {
126
- const currentLength = getLineLength(line);
127
- if (currentLength < targetWidth) {
128
- return {
129
- segments: [...line.segments, { text: " ".repeat(targetWidth - currentLength), style: padStyle }]
130
- };
131
- }
132
- return line;
133
- }
134
- // -----------------
135
- // Printer Class
136
- // -----------------
137
- /**
138
- * Handles rendering StyledLines to the terminal with support for interactive overwriting.
139
- */
140
- export class Printer {
141
- linesRendered = 0;
142
- isInteractive;
143
- constructor(options = {}) {
144
- this.isInteractive = options.interactive ?? false;
145
- }
146
- /**
147
- * Generates the clear sequence to move cursor and clear previously rendered lines.
148
- */
149
- getClearSequence() {
150
- if (!this.isInteractive || this.linesRendered === 0)
151
- return "";
152
- return `${ESC}[1A${ESC}[2K\r`.repeat(this.linesRendered);
153
- }
154
- /**
155
- * Renders an array of StyledLines to the standard output.
156
- */
157
- print(lines) {
158
- let output = this.getClearSequence();
159
- lines.forEach((line) => {
160
- line.segments.forEach((seg) => {
161
- const ansiStyle = resolveStyle(seg.style);
162
- output += `${ansiStyle}${seg.text}${RESET}`;
163
- });
164
- output += "\n";
165
- });
166
- process.stdout.write(output);
167
- this.linesRendered = lines.length;
168
- }
169
- }
170
- // -----------------
171
- // Core Layout & Printing
172
- // -----------------
173
- const defaultPrinter = new Printer();
174
- /**
175
- * Merges two columns of StyledLines into a single layout.
176
- */
177
- export function mergeColumns(leftColumn, rightColumn, leftWidth, separator, defaultStyle) {
178
- const maxLines = Math.max(leftColumn.length, rightColumn.length);
179
- const output = [];
180
- for (let i = 0; i < maxLines; i++) {
181
- const left = padLine(leftColumn[i] || { segments: [] }, leftWidth, defaultStyle);
182
- const right = rightColumn[i] || { segments: [] };
183
- output.push({
184
- segments: [...left.segments, { text: separator, style: defaultStyle }, ...right.segments]
185
- });
186
- }
187
- return output;
188
- }
189
- /**
190
- * Prints two columns of styled content to the console.
191
- */
192
- export function printDualColumn(left, right, options = {}) {
193
- const { leftWidth, separator = " ", printer = defaultPrinter } = options;
194
- const defaultStyle = RESET;
195
- const finalLeftWidth = leftWidth ?? computeMaxWidth(left);
196
- const mergedLines = mergeColumns(left, right, finalLeftWidth, separator, defaultStyle);
197
- printer.print(mergedLines);
198
- }
199
- // -----------------
200
- // Presets
201
- // -----------------
202
- /**
203
- * Returns the classic Dragon ASCII art as StyledLines with a vertical color gradient.
204
- */
205
- export function getDragonLines(startColor = "#EF4444", endColor = "#F59E0B") {
206
- const rawDragon = [
207
- " ^ ^",
208
- " / \\ //\\",
209
- " |\\___/| / \\// .\\",
210
- " /O O \\__ / // | \\ \\",
211
- "/ / \\_/_/ // | \\ \\",
212
- "@___@' \\_// // | \\ \\ ",
213
- " | \\_// // | \\ \\ ",
214
- " | \\/// | \\ \\ ",
215
- " _|_ / ) // | \\ _\\",
216
- " '/,_ _ _/ ( ; -. | _ _\\.-~ .-~~~^-.",
217
- " ,-{ _ `-.|.-~-. .~ `.",
218
- " '/\\ / ~-. _ .-~ .-~^-. \\",
219
- " `. { } / \\ \\",
220
- " .----~-\\. \\-' .~ \\ `. \\^-.",
221
- " ///.----..> c \\ _ -~ `. ^-` ^-_",
222
- " ///-._ _ _ _ _ _ _}^ - - - - ~ ~--, .-~",
223
- " /.-'"
224
- ];
225
- return rawDragon.map((text, i) => {
226
- const factor = rawDragon.length <= 1 ? 0 : i / (rawDragon.length - 1);
227
- const colorStyle = interpolateColor(startColor, endColor, factor);
228
- return { segments: [{ text, style: colorStyle }] };
229
- });
230
- }
231
- // -----------------
232
- // Progress Bar
233
- // -----------------
234
- export * from "./progress";
1
+ // Export Core Types
2
+ export * from "./core/types";
3
+ // Export Core Utilities
4
+ export * from "./core/style";
5
+ export * from "./core/utils";
6
+ // Export Printer Engine
7
+ export * from "./core/printer";
8
+ // Export Layout Helpers
9
+ export * from "./core/layout";
10
+ // Export Components
11
+ export * from "./components/progress";
12
+ export * from "./components/spinner";
13
+ // Export Presets
14
+ export * from "./presets/ascii";
@@ -0,0 +1,5 @@
1
+ import { PrintLine, Color } from "../core/types";
2
+ /**
3
+ * Returns the classic Dragon ASCII art as PrintLines with a vertical color gradient.
4
+ */
5
+ export declare function getDragon(startColor?: Color, endColor?: Color): PrintLine[];