@heinrichb/console-toolkit 1.0.10 → 1.0.13

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.
@@ -5,7 +5,7 @@ export type StandardColor = "black" | "red" | "green" | "yellow" | "blue" | "mag
5
5
  /**
6
6
  * Text style modifiers.
7
7
  */
8
- export type StyleModifier = "bold" | "dim" | "italic" | "underline" | "default" | "hidden" | "inverse" | "strikethrough";
8
+ export type StyleModifier = "bold" | "dim" | "italic" | "underline" | "hidden" | "inverse" | "strikethrough";
9
9
  /**
10
10
  * A valid Hex color string (e.g., "#FF0000").
11
11
  */
@@ -14,6 +14,14 @@ export type HexColor = `#${string}`;
14
14
  * A color can be a standard color name or a hex color string.
15
15
  */
16
16
  export type Color = StandardColor | HexColor;
17
+ /**
18
+ * Represents an RGB color value.
19
+ */
20
+ export interface RGB {
21
+ r: number;
22
+ g: number;
23
+ b: number;
24
+ }
17
25
  /**
18
26
  * Represents the style configuration for a text segment, line, or block.
19
27
  */
@@ -24,6 +32,12 @@ export interface PrintStyle {
24
32
  * - An array of colors applies a gradient.
25
33
  */
26
34
  color?: Color | Color[];
35
+ /**
36
+ * The background color to apply.
37
+ * - A single color (string) applies a solid background.
38
+ * - An array of colors applies a background gradient.
39
+ */
40
+ bgColor?: Color | Color[];
27
41
  /**
28
42
  * A list of style modifiers (e.g., bold, italic) to apply.
29
43
  */
@@ -23,3 +23,10 @@ export declare function computeMaxWidth(lines: PrintLine[]): number;
23
23
  * @returns A new PrintLine with padding added if necessary.
24
24
  */
25
25
  export declare function padLine(inputLine: PrintLine, targetWidth: number, padStyle?: PrintStyle): PrintLine;
26
+ /**
27
+ * Strips all ANSI escape sequences from a string, returning plain text.
28
+ *
29
+ * @param text - The string potentially containing ANSI codes.
30
+ * @returns The plain text with all ANSI sequences removed.
31
+ */
32
+ export declare function stripAnsi(text: string): string;
package/dist/index.d.ts CHANGED
@@ -6,4 +6,6 @@ export * from "./core/printer";
6
6
  export * from "./core/layout";
7
7
  export * from "./components/progress";
8
8
  export * from "./components/spinner";
9
+ export * from "./components/table";
9
10
  export * from "./presets/ascii";
11
+ export * from "./presets/gradients";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/core/style.ts
2
2
  var ESC = "\x1B";
3
3
  var RESET = `${ESC}[0m`;
4
- var STANDARD_COLORS = {
4
+ var STANDARD_COLORS = Object.assign(Object.create(null), {
5
5
  black: "#000000",
6
6
  red: "#EF4444",
7
7
  green: "#10B981",
@@ -12,9 +12,8 @@ var STANDARD_COLORS = {
12
12
  white: "#FFFFFF",
13
13
  gray: "#6B7280",
14
14
  grey: "#6B7280"
15
- };
16
- var MODIFIER_CODES = {
17
- default: "0",
15
+ });
16
+ var MODIFIER_CODES = Object.assign(Object.create(null), {
18
17
  bold: "1",
19
18
  dim: "2",
20
19
  italic: "3",
@@ -22,7 +21,7 @@ var MODIFIER_CODES = {
22
21
  inverse: "7",
23
22
  hidden: "8",
24
23
  strikethrough: "9"
25
- };
24
+ });
26
25
  function colorToHex(color) {
27
26
  if (color.startsWith("#"))
28
27
  return color;
@@ -44,11 +43,17 @@ function hexToRgb(hex) {
44
43
  function rgbToAnsi(r, g, b) {
45
44
  return `${ESC}[38;2;${r};${g};${b}m`;
46
45
  }
46
+ function rgbToBgAnsi(r, g, b) {
47
+ return `${ESC}[48;2;${r};${g};${b}m`;
48
+ }
47
49
  function resolveColorToAnsi(color) {
48
- const hex = colorToHex(color);
49
- const { r, g, b } = hexToRgb(hex);
50
+ const { r, g, b } = resolveColorToRgb(color);
50
51
  return rgbToAnsi(r, g, b);
51
52
  }
53
+ function resolveColorToRgb(color) {
54
+ const hex = colorToHex(color);
55
+ return hexToRgb(hex);
56
+ }
52
57
  function resolveModifiersToAnsi(modifiers) {
53
58
  if (!modifiers || modifiers.length === 0)
54
59
  return "";
@@ -70,22 +75,38 @@ function interpolateHex(color1, color2, factor) {
70
75
  const b = c1.b + f * (c2.b - c1.b);
71
76
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
72
77
  }
73
- function interpolateColor(color1, color2, factor) {
74
- return interpolateHex(colorToHex(color1), colorToHex(color2), factor);
78
+ function gradientSegment(colorCount, factor) {
79
+ const f = Math.max(0, Math.min(1, factor));
80
+ const segmentLength = 1 / (colorCount - 1);
81
+ const index = Math.min(Math.floor(f / segmentLength), colorCount - 2);
82
+ return { index, factor: (f - index * segmentLength) / segmentLength };
75
83
  }
76
- function getGradientColor(colors, factor) {
84
+ function getGradientAnsiFromRgb(colors, factor, toAnsi) {
77
85
  if (colors.length === 0)
78
86
  return "";
79
87
  if (colors.length === 1)
80
- return resolveColorToAnsi(colors[0]);
81
- const f = Math.max(0, Math.min(1, factor));
82
- const segmentLength = 1 / (colors.length - 1);
83
- const segmentIndex = Math.min(Math.floor(f / segmentLength), colors.length - 2);
84
- const segmentFactor = (f - segmentIndex * segmentLength) / segmentLength;
85
- const c1 = colors[segmentIndex];
86
- const c2 = colors[segmentIndex + 1];
87
- const hex = interpolateColor(c1, c2, segmentFactor);
88
- return resolveColorToAnsi(hex);
88
+ return toAnsi(colors[0].r, colors[0].g, colors[0].b);
89
+ const seg = gradientSegment(colors.length, factor);
90
+ const c1 = colors[seg.index];
91
+ const c2 = colors[seg.index + 1];
92
+ const r = Math.round(c1.r + seg.factor * (c2.r - c1.r));
93
+ const g = Math.round(c1.g + seg.factor * (c2.g - c1.g));
94
+ const b = Math.round(c1.b + seg.factor * (c2.b - c1.b));
95
+ return toAnsi(r, g, b);
96
+ }
97
+ function getGradientColorFromRgb(colors, factor) {
98
+ return getGradientAnsiFromRgb(colors, factor, rgbToAnsi);
99
+ }
100
+ function getGradientBgColorFromRgb(colors, factor) {
101
+ return getGradientAnsiFromRgb(colors, factor, rgbToBgAnsi);
102
+ }
103
+ function interpolateGradient(colors, factor) {
104
+ if (colors.length === 0)
105
+ return "#FFFFFF";
106
+ if (colors.length === 1)
107
+ return colorToHex(colors[0]);
108
+ const seg = gradientSegment(colors.length, factor);
109
+ return interpolateHex(colorToHex(colors[seg.index]), colorToHex(colors[seg.index + 1]), seg.factor);
89
110
  }
90
111
  function mergeStyles(parent, child) {
91
112
  if (!parent && !child)
@@ -94,10 +115,17 @@ function mergeStyles(parent, child) {
94
115
  return child ?? {};
95
116
  if (!child)
96
117
  return parent;
97
- const mergedModifiers = Array.from(new Set([...parent.modifiers ?? [], ...child.modifiers ?? []]));
118
+ const parentMods = parent.modifiers ?? [];
119
+ const childMods = child.modifiers ?? [];
120
+ const mergedModifiers = [...parentMods];
121
+ for (const mod of childMods) {
122
+ if (!mergedModifiers.includes(mod))
123
+ mergedModifiers.push(mod);
124
+ }
98
125
  return {
99
126
  modifiers: mergedModifiers,
100
- color: child.color ?? parent.color
127
+ color: child.color ?? parent.color,
128
+ bgColor: child.bgColor ?? parent.bgColor
101
129
  };
102
130
  }
103
131
  function resolveStyle(style, gradientFactor = 0) {
@@ -109,12 +137,21 @@ function resolveStyle(style, gradientFactor = 0) {
109
137
  }
110
138
  if (style.color) {
111
139
  if (Array.isArray(style.color)) {
112
- const hex = getGradientColor(style.color, gradientFactor);
113
- ansi += hex;
140
+ const rgbColors = style.color.map(resolveColorToRgb);
141
+ ansi += getGradientColorFromRgb(rgbColors, gradientFactor);
114
142
  } else {
115
143
  ansi += resolveColorToAnsi(style.color);
116
144
  }
117
145
  }
146
+ if (style.bgColor) {
147
+ if (Array.isArray(style.bgColor)) {
148
+ const bgRgbColors = style.bgColor.map(resolveColorToRgb);
149
+ ansi += getGradientBgColorFromRgb(bgRgbColors, gradientFactor);
150
+ } else {
151
+ const { r, g, b } = resolveColorToRgb(style.bgColor);
152
+ ansi += rgbToBgAnsi(r, g, b);
153
+ }
154
+ }
118
155
  return ansi;
119
156
  }
120
157
  // src/core/builders.ts
@@ -133,7 +170,7 @@ function getLineLength(line2) {
133
170
  return line2.segments.reduce((acc, seg) => acc + seg.text.length, 0);
134
171
  }
135
172
  function computeMaxWidth(lines) {
136
- return lines.length > 0 ? Math.max(...lines.map(getLineLength)) : 0;
173
+ return lines.reduce((max, l) => Math.max(max, getLineLength(l)), 0);
137
174
  }
138
175
  function padLine(inputLine, targetWidth, padStyle) {
139
176
  const currentLength = getLineLength(inputLine);
@@ -142,9 +179,11 @@ function padLine(inputLine, targetWidth, padStyle) {
142
179
  }
143
180
  return inputLine;
144
181
  }
182
+ var ANSI_REGEX = /\x1b\[[0-9;]*m/g;
183
+ function stripAnsi(text) {
184
+ return text.replace(ANSI_REGEX, "");
185
+ }
145
186
  // src/core/printer.ts
146
- var ESC2 = "\x1B";
147
-
148
187
  class Printer {
149
188
  linesRendered = 0;
150
189
  isLive;
@@ -156,7 +195,7 @@ class Printer {
156
195
  getClearSequence() {
157
196
  if (!this.isLive || this.linesRendered === 0)
158
197
  return "";
159
- return `${ESC2}[1A${ESC2}[2K\r`.repeat(this.linesRendered);
198
+ return `${ESC}[1A${ESC}[2K\r`.repeat(this.linesRendered);
160
199
  }
161
200
  clear() {
162
201
  if (this.linesRendered > 0) {
@@ -164,6 +203,14 @@ class Printer {
164
203
  this.linesRendered = 0;
165
204
  }
166
205
  }
206
+ renderToString(data) {
207
+ if (data) {
208
+ this.data = data;
209
+ }
210
+ if (!this.data)
211
+ return "";
212
+ return this.renderBlock(this.data);
213
+ }
167
214
  print(data) {
168
215
  if (data) {
169
216
  this.data = data;
@@ -171,51 +218,67 @@ class Printer {
171
218
  if (!this.data) {
172
219
  return;
173
220
  }
174
- let output = this.getClearSequence();
175
- const lines = this.data.lines;
176
- const blockStyle = this.data.style ?? {};
177
- lines.forEach((line2, lineIndex) => {
178
- output += this.renderLine(line2, lineIndex, lines.length, blockStyle);
221
+ const output = this.getClearSequence() + this.renderBlock(this.data);
222
+ process.stdout.write(output);
223
+ this.linesRendered = this.data.lines.length;
224
+ }
225
+ renderBlock(blockData) {
226
+ let output = "";
227
+ const lines = blockData.lines;
228
+ const blockStyle = blockData.style ?? {};
229
+ lines.forEach((ln, lineIndex) => {
230
+ output += this.renderLine(ln, lineIndex, lines.length, blockStyle);
179
231
  output += `
180
232
  `;
181
233
  });
182
- process.stdout.write(output);
183
- this.linesRendered = lines.length;
234
+ return output;
184
235
  }
185
- resolveBlockColorForLine(blockStyle, lineIndex, totalLines) {
186
- if (!blockStyle.color)
236
+ resolveBlockStyleForLine(blockStyle, lineIndex, totalLines) {
237
+ return {
238
+ modifiers: blockStyle.modifiers,
239
+ color: this.resolveGradientForLine(blockStyle.color, lineIndex, totalLines),
240
+ bgColor: this.resolveGradientForLine(blockStyle.bgColor, lineIndex, totalLines)
241
+ };
242
+ }
243
+ resolveGradientForLine(color, lineIndex, totalLines) {
244
+ if (!color)
187
245
  return;
188
- if (Array.isArray(blockStyle.color)) {
246
+ if (Array.isArray(color)) {
189
247
  if (totalLines <= 1)
190
- return blockStyle.color[0];
191
- const colors = blockStyle.color;
192
- const factor = lineIndex / (totalLines - 1);
193
- const f = Math.max(0, Math.min(1, factor));
194
- const segmentLength = 1 / (colors.length - 1);
195
- const segmentIndex = Math.min(Math.floor(f / segmentLength), colors.length - 2);
196
- const segmentFactor = (f - segmentIndex * segmentLength) / segmentLength;
197
- const c1 = colors[segmentIndex];
198
- const c2 = colors[segmentIndex + 1];
199
- return interpolateColor(c1, c2, segmentFactor);
248
+ return color[0];
249
+ return interpolateGradient(color, lineIndex / (totalLines - 1));
200
250
  }
201
- return blockStyle.color;
251
+ return color;
202
252
  }
203
253
  renderLine(line2, lineIndex, totalLines, parentBlockStyle) {
204
- const blockColorForLine = this.resolveBlockColorForLine(parentBlockStyle, lineIndex, totalLines);
205
- const baseLineStyle = {
206
- modifiers: parentBlockStyle.modifiers,
207
- color: blockColorForLine
208
- };
254
+ const baseLineStyle = this.resolveBlockStyleForLine(parentBlockStyle, lineIndex, totalLines);
209
255
  const effectiveLineStyle = mergeStyles(baseLineStyle, line2.style);
210
256
  const totalChars = line2.segments.reduce((acc, seg) => acc + seg.text.length, 0);
211
257
  let currentCharIndex = 0;
212
258
  let lineOutput = "";
213
259
  line2.segments.forEach((seg) => {
214
260
  const effectiveSegmentStyle = mergeStyles(effectiveLineStyle, seg.style);
215
- if (Array.isArray(effectiveSegmentStyle.color)) {
216
- const colors = effectiveSegmentStyle.color;
261
+ const hasFgGradient = Array.isArray(effectiveSegmentStyle.color);
262
+ const hasBgGradient = Array.isArray(effectiveSegmentStyle.bgColor);
263
+ if (hasFgGradient || hasBgGradient) {
217
264
  const text = seg.text;
218
265
  const isGlobalGradient = effectiveSegmentStyle.color === effectiveLineStyle.color;
266
+ let fgRgbColors;
267
+ let solidFgAnsi = "";
268
+ if (hasFgGradient) {
269
+ fgRgbColors = effectiveSegmentStyle.color.map(resolveColorToRgb);
270
+ } else if (effectiveSegmentStyle.color) {
271
+ const { r, g, b } = resolveColorToRgb(effectiveSegmentStyle.color);
272
+ solidFgAnsi = rgbToAnsi(r, g, b);
273
+ }
274
+ let bgRgbColors;
275
+ let solidBgAnsi = "";
276
+ if (hasBgGradient) {
277
+ bgRgbColors = effectiveSegmentStyle.bgColor.map(resolveColorToRgb);
278
+ } else if (effectiveSegmentStyle.bgColor) {
279
+ const { r, g, b } = resolveColorToRgb(effectiveSegmentStyle.bgColor);
280
+ solidBgAnsi = rgbToBgAnsi(r, g, b);
281
+ }
219
282
  const modifiersAnsi = resolveModifiersToAnsi(effectiveSegmentStyle.modifiers);
220
283
  for (let i = 0;i < text.length; i++) {
221
284
  let factor = 0;
@@ -224,8 +287,9 @@ class Printer {
224
287
  } else if (!isGlobalGradient && text.length > 1) {
225
288
  factor = i / (text.length - 1);
226
289
  }
227
- const colorAnsi = getGradientColor(colors, factor);
228
- lineOutput += `${modifiersAnsi}${colorAnsi}${text[i]}`;
290
+ const fgAnsi = fgRgbColors ? getGradientColorFromRgb(fgRgbColors, factor) : solidFgAnsi;
291
+ const bgAnsi = bgRgbColors ? getGradientBgColorFromRgb(bgRgbColors, factor) : solidBgAnsi;
292
+ lineOutput += `${modifiersAnsi}${fgAnsi}${bgAnsi}${text[i]}`;
229
293
  }
230
294
  lineOutput += RESET;
231
295
  } else {
@@ -241,7 +305,7 @@ class Printer {
241
305
  function mergeColumns(columns, separator = " ", defaultStyle, widths) {
242
306
  if (columns.length === 0)
243
307
  return [];
244
- const maxLines = Math.max(...columns.map((c) => c.length));
308
+ const maxLines = columns.reduce((max, c) => Math.max(max, c.length), 0);
245
309
  const colWidths = columns.map((col, i) => {
246
310
  if (widths?.[i] !== undefined)
247
311
  return widths[i];
@@ -249,14 +313,14 @@ function mergeColumns(columns, separator = " ", defaultStyle, widths) {
249
313
  });
250
314
  const output = [];
251
315
  for (let i = 0;i < maxLines; i++) {
252
- let segments = [];
316
+ const segments = [];
253
317
  for (let j = 0;j < columns.length; j++) {
254
318
  const currentLine = columns[j][i] || line();
255
319
  if (j < columns.length - 1) {
256
320
  const padded = padLine(currentLine, colWidths[j], defaultStyle);
257
- segments = [...segments, ...padded.segments, segment(separator, defaultStyle)];
321
+ segments.push(...padded.segments, segment(separator, defaultStyle));
258
322
  } else {
259
- segments = [...segments, ...currentLine.segments];
323
+ segments.push(...currentLine.segments);
260
324
  }
261
325
  }
262
326
  output.push(line(segments));
@@ -264,8 +328,8 @@ function mergeColumns(columns, separator = " ", defaultStyle, widths) {
264
328
  return output;
265
329
  }
266
330
  function printColumns(columns, options = {}) {
267
- const { widths, separator = " ", printer = new Printer } = options;
268
- const mergedLines = mergeColumns(columns, separator, undefined, widths);
331
+ const { widths, separator = " ", defaultStyle, printer = new Printer } = options;
332
+ const mergedLines = mergeColumns(columns, separator, defaultStyle, widths);
269
333
  printer.print(block(mergedLines));
270
334
  }
271
335
  // src/components/progress.ts
@@ -284,7 +348,9 @@ function createProgressBar(options) {
284
348
  startChar = "[",
285
349
  endChar = "]",
286
350
  fillChar = "█",
351
+ completeChar,
287
352
  emptyChar = "░",
353
+ completeStyle,
288
354
  showPercentage = true,
289
355
  formatPercentage
290
356
  } = options;
@@ -295,15 +361,17 @@ function createProgressBar(options) {
295
361
  const resolvedStartStyle = startStyle ?? resolvedBracketStyle;
296
362
  const resolvedEndStyle = endStyle ?? resolvedBracketStyle;
297
363
  const resolvedBarStyle = barStyle ?? style;
298
- const resolvedFillStyle = fillStyle ?? resolvedBarStyle;
364
+ const isComplete = p >= 1;
365
+ const resolvedFillStyle = isComplete ? completeStyle ?? fillStyle ?? resolvedBarStyle : fillStyle ?? resolvedBarStyle;
299
366
  const resolvedEmptyStyle = emptyStyle ?? resolvedBarStyle;
300
367
  const resolvedPercentageStyle = percentageStyle ?? style;
301
368
  const segments = [];
302
369
  if (startChar) {
303
370
  segments.push(segment(startChar, resolvedStartStyle));
304
371
  }
372
+ const effectiveFillChar = isComplete ? completeChar ?? fillChar : fillChar;
305
373
  if (filledWidth > 0) {
306
- segments.push(segment(fillChar.repeat(filledWidth), resolvedFillStyle));
374
+ segments.push(segment(effectiveFillChar.repeat(filledWidth), resolvedFillStyle));
307
375
  }
308
376
  if (emptyWidth > 0) {
309
377
  segments.push(segment(emptyChar.repeat(emptyWidth), resolvedEmptyStyle));
@@ -342,8 +410,133 @@ class Spinner {
342
410
  return this.frames[index];
343
411
  }
344
412
  }
413
+ // src/components/table.ts
414
+ var BORDERS = {
415
+ single: {
416
+ tl: "┌",
417
+ t: "─",
418
+ tr: "┐",
419
+ l: "│",
420
+ r: "│",
421
+ bl: "└",
422
+ b: "─",
423
+ br: "┘",
424
+ ml: "├",
425
+ m: "─",
426
+ mr: "┤",
427
+ tj: "┬",
428
+ bj: "┴",
429
+ mj: "┼"
430
+ },
431
+ double: {
432
+ tl: "╔",
433
+ t: "═",
434
+ tr: "╗",
435
+ l: "║",
436
+ r: "║",
437
+ bl: "╚",
438
+ b: "═",
439
+ br: "╝",
440
+ ml: "╠",
441
+ m: "═",
442
+ mr: "╣",
443
+ tj: "╦",
444
+ bj: "╩",
445
+ mj: "╬"
446
+ },
447
+ rounded: {
448
+ tl: "╭",
449
+ t: "─",
450
+ tr: "╮",
451
+ l: "│",
452
+ r: "│",
453
+ bl: "╰",
454
+ b: "─",
455
+ br: "╯",
456
+ ml: "├",
457
+ m: "─",
458
+ mr: "┤",
459
+ tj: "┬",
460
+ bj: "┴",
461
+ mj: "┼"
462
+ }
463
+ };
464
+ function buildBorderLine(left, fill, junction, right, colWidths, padding, borderStyle) {
465
+ const parts = [left];
466
+ for (let i = 0;i < colWidths.length; i++) {
467
+ parts.push(fill.repeat(colWidths[i] + padding * 2));
468
+ if (i < colWidths.length - 1)
469
+ parts.push(junction);
470
+ }
471
+ parts.push(right);
472
+ return line([segment(parts.join(""), borderStyle)]);
473
+ }
474
+ function buildDataRow(cells, colWidths, padding, colCount, borderChar, cellStyle, borderStyle) {
475
+ const segments = [];
476
+ segments.push(segment(borderChar, borderStyle));
477
+ for (let i = 0;i < colCount; i++) {
478
+ const cellText = cells[i] ?? "";
479
+ const padded = " ".repeat(padding) + cellText.padEnd(colWidths[i]) + " ".repeat(padding);
480
+ segments.push(segment(padded, cellStyle));
481
+ if (i < colCount - 1) {
482
+ segments.push(segment(borderChar, borderStyle));
483
+ }
484
+ }
485
+ segments.push(segment(borderChar, borderStyle));
486
+ return line(segments);
487
+ }
488
+ function createTable(options) {
489
+ const { headers, rows, style, headerStyle, borderStyle, border = "single", columnWidths, cellPadding = 1 } = options;
490
+ const colCount = rows.reduce((max, r) => Math.max(max, r.length), headers?.length ?? 0);
491
+ if (colCount === 0)
492
+ return [];
493
+ const colWidths = [];
494
+ for (let i = 0;i < colCount; i++) {
495
+ if (columnWidths?.[i] !== undefined) {
496
+ colWidths.push(columnWidths[i]);
497
+ } else {
498
+ const headerWidth = headers?.[i]?.length ?? 0;
499
+ const maxRowWidth = rows.reduce((max, row) => Math.max(max, row[i]?.length ?? 0), 0);
500
+ colWidths.push(Math.max(headerWidth, maxRowWidth));
501
+ }
502
+ }
503
+ if (border === "none") {
504
+ return buildNoBorderTable(headers, rows, colWidths, cellPadding, colCount, style, headerStyle);
505
+ }
506
+ const chars = BORDERS[border];
507
+ const output = [];
508
+ output.push(buildBorderLine(chars.tl, chars.t, chars.tj, chars.tr, colWidths, cellPadding, borderStyle));
509
+ if (headers) {
510
+ output.push(buildDataRow(headers, colWidths, cellPadding, colCount, chars.l, headerStyle ?? style, borderStyle));
511
+ output.push(buildBorderLine(chars.ml, chars.m, chars.mj, chars.mr, colWidths, cellPadding, borderStyle));
512
+ }
513
+ for (const row of rows) {
514
+ output.push(buildDataRow(row, colWidths, cellPadding, colCount, chars.l, style, borderStyle));
515
+ }
516
+ output.push(buildBorderLine(chars.bl, chars.b, chars.bj, chars.br, colWidths, cellPadding, borderStyle));
517
+ return output;
518
+ }
519
+ function buildNoBorderTable(headers, rows, colWidths, padding, colCount, style, headerStyle) {
520
+ const output = [];
521
+ const space = " ".repeat(padding);
522
+ function buildRow(cells, cellStyle) {
523
+ const segments = [];
524
+ for (let i = 0;i < colCount; i++) {
525
+ const cellText = cells[i] ?? "";
526
+ segments.push(segment(space + cellText.padEnd(colWidths[i]) + space, cellStyle));
527
+ }
528
+ return line(segments);
529
+ }
530
+ if (headers) {
531
+ output.push(buildRow(headers, headerStyle ?? style));
532
+ }
533
+ for (const row of rows) {
534
+ output.push(buildRow(row, style));
535
+ }
536
+ return output;
537
+ }
345
538
  // src/presets/ascii.ts
346
- function getDragon(startColor = "#EF4444", endColor = "#F59E0B") {
539
+ function getDragon(colors = ["#EF4444", "#F59E0B"]) {
347
540
  const rawDragon = [
348
541
  " ^ ^",
349
542
  " / \\ //\\",
@@ -365,15 +558,27 @@ function getDragon(startColor = "#EF4444", endColor = "#F59E0B") {
365
558
  ];
366
559
  return rawDragon.map((text, i) => {
367
560
  const factor = rawDragon.length <= 1 ? 0 : i / (rawDragon.length - 1);
368
- const colorStyle = interpolateColor(startColor, endColor, factor);
369
- return line([segment(text, { color: colorStyle })]);
561
+ const color = interpolateGradient(colors, factor);
562
+ return line([segment(text, { color })]);
370
563
  });
371
564
  }
565
+ // src/presets/gradients.ts
566
+ var GRADIENTS = {
567
+ rainbow: ["#EF4444", "#F59E0B", "#10B981", "#06B6D4", "#3B82F6", "#8B5CF6"],
568
+ ocean: ["#1E3A5F", "#0E7490", "#06B6D4", "#67E8F9"],
569
+ fire: ["#7F1D1D", "#EF4444", "#F59E0B", "#FDE047"],
570
+ sunset: ["#7C3AED", "#EC4899", "#F97316", "#FBBF24"],
571
+ forest: ["#064E3B", "#10B981", "#84CC16", "#BEF264"],
572
+ monochrome: ["#000000", "#6B7280", "#FFFFFF"]
573
+ };
372
574
  export {
575
+ stripAnsi,
373
576
  segment,
577
+ rgbToBgAnsi,
374
578
  rgbToAnsi,
375
579
  resolveStyle,
376
580
  resolveModifiersToAnsi,
581
+ resolveColorToRgb,
377
582
  resolveColorToAnsi,
378
583
  printColumns,
379
584
  padLine,
@@ -381,11 +586,13 @@ export {
381
586
  mergeColumns,
382
587
  line,
383
588
  interpolateHex,
384
- interpolateColor,
589
+ interpolateGradient,
385
590
  hexToRgb,
386
591
  getLineLength,
387
- getGradientColor,
592
+ getGradientColorFromRgb,
593
+ getGradientBgColorFromRgb,
388
594
  getDragon,
595
+ createTable,
389
596
  createProgressBar,
390
597
  computeMaxWidth,
391
598
  colorToHex,
@@ -393,5 +600,7 @@ export {
393
600
  Spinner,
394
601
  SPINNERS,
395
602
  RESET,
396
- Printer
603
+ Printer,
604
+ GRADIENTS,
605
+ ESC
397
606
  };