cli-menu-kit 0.2.0 → 0.2.1
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.
- package/dist/components/display/header.d.ts +40 -0
- package/dist/components/display/header.js +331 -18
- package/dist/components/display/headers.d.ts +1 -0
- package/dist/components/display/headers.js +15 -5
- package/dist/components/display/index.d.ts +1 -1
- package/dist/components/display/index.js +3 -1
- package/dist/components/display/messages.js +5 -5
- package/dist/components/display/progress.d.ts +17 -0
- package/dist/components/display/progress.js +18 -0
- package/dist/components/display/summary.js +72 -10
- package/dist/components/display/table.d.ts +2 -0
- package/dist/components/display/table.js +7 -6
- package/dist/components/inputs/language-input.js +8 -5
- package/dist/components/inputs/number-input.js +19 -14
- package/dist/components/inputs/text-input.js +50 -13
- package/dist/components/menus/boolean-menu.js +33 -20
- package/dist/components/menus/checkbox-menu.js +5 -2
- package/dist/components/menus/checkbox-table-menu.js +12 -9
- package/dist/components/menus/radio-menu-split.d.ts +1 -0
- package/dist/components/menus/radio-menu-split.js +26 -16
- package/dist/components/menus/radio-menu.js +67 -38
- package/dist/components.js +3 -3
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.js +21 -0
- package/dist/config/language-config.d.ts +73 -0
- package/dist/config/language-config.js +157 -0
- package/dist/config/user-config.d.ts +83 -0
- package/dist/config/user-config.js +185 -0
- package/dist/core/colors.d.ts +24 -18
- package/dist/core/colors.js +74 -7
- package/dist/core/renderer.js +26 -18
- package/dist/core/terminal.d.ts +13 -0
- package/dist/core/terminal.js +87 -0
- package/dist/features/commands.js +23 -22
- package/dist/index.d.ts +3 -1
- package/dist/index.js +21 -2
- package/dist/layout.d.ts +50 -51
- package/dist/layout.js +69 -117
- package/dist/page-layout.d.ts +31 -0
- package/dist/page-layout.js +46 -7
- package/dist/types/input.types.d.ts +8 -0
- package/dist/types/layout.types.d.ts +56 -0
- package/dist/types/layout.types.js +36 -0
- package/dist/types/menu.types.d.ts +4 -0
- package/package.json +4 -1
|
@@ -2,16 +2,39 @@
|
|
|
2
2
|
* Header component for CLI applications
|
|
3
3
|
* Displays ASCII art, title, description, version and URL
|
|
4
4
|
*/
|
|
5
|
+
type FigletSize = 'small' | 'medium' | 'large';
|
|
5
6
|
/**
|
|
6
7
|
* Header configuration
|
|
7
8
|
*/
|
|
8
9
|
export interface HeaderConfig {
|
|
9
10
|
/** ASCII art lines (array of strings) */
|
|
10
11
|
asciiArt?: string[];
|
|
12
|
+
/** Generate ASCII art from figlet text (overrides asciiArt when provided) */
|
|
13
|
+
figletText?: string;
|
|
14
|
+
/** Figlet font name (raw figlet name, e.g. "ANSI Shadow", "Standard", "Block") */
|
|
15
|
+
figletFont?: string;
|
|
16
|
+
/** Figlet size preset (default: medium) */
|
|
17
|
+
figletSize?: FigletSize;
|
|
18
|
+
/** Scale figlet output (1-4, default: 1) */
|
|
19
|
+
figletScale?: number;
|
|
20
|
+
/** Optional vertical scale override (0.4-4) */
|
|
21
|
+
figletScaleY?: number;
|
|
11
22
|
/** Application title */
|
|
12
23
|
title?: string;
|
|
24
|
+
/** Optional explicit color for title line */
|
|
25
|
+
titleColor?: string;
|
|
26
|
+
/** Optional ANSI start color for title gradient */
|
|
27
|
+
titleGradientStart?: string;
|
|
28
|
+
/** Optional ANSI end color for title gradient */
|
|
29
|
+
titleGradientEnd?: string;
|
|
13
30
|
/** Application description */
|
|
14
31
|
description?: string;
|
|
32
|
+
/** Optional explicit color for description line */
|
|
33
|
+
descriptionColor?: string;
|
|
34
|
+
/** Optional ANSI start color for description gradient */
|
|
35
|
+
descriptionGradientStart?: string;
|
|
36
|
+
/** Optional ANSI end color for description gradient */
|
|
37
|
+
descriptionGradientEnd?: string;
|
|
15
38
|
/** Version number */
|
|
16
39
|
version?: string;
|
|
17
40
|
/** Project URL */
|
|
@@ -20,11 +43,28 @@ export interface HeaderConfig {
|
|
|
20
43
|
menuTitle?: string;
|
|
21
44
|
/** Box width (default: 60) */
|
|
22
45
|
boxWidth?: number;
|
|
46
|
+
/** Toggle outer border box (default: true) */
|
|
47
|
+
showBoxBorder?: boolean;
|
|
48
|
+
/** Fill header box content area background (default: false) */
|
|
49
|
+
fillBox?: boolean;
|
|
50
|
+
/** ANSI background color for box fill (default: bgBlack) */
|
|
51
|
+
fillBoxColor?: string;
|
|
52
|
+
/** Optional ANSI background gradient start color for box fill */
|
|
53
|
+
fillBoxGradientStart?: string;
|
|
54
|
+
/** Optional ANSI background gradient end color for box fill */
|
|
55
|
+
fillBoxGradientEnd?: string;
|
|
23
56
|
/** Header color (default: cyan) */
|
|
24
57
|
color?: string;
|
|
58
|
+
/** Optional explicit color for ASCII art/logo lines */
|
|
59
|
+
asciiArtColor?: string;
|
|
60
|
+
/** Optional ANSI start color for ASCII art gradient */
|
|
61
|
+
asciiArtGradientStart?: string;
|
|
62
|
+
/** Optional ANSI end color for ASCII art gradient */
|
|
63
|
+
asciiArtGradientEnd?: string;
|
|
25
64
|
}
|
|
26
65
|
/**
|
|
27
66
|
* Render a boxed header with ASCII art, title, and description
|
|
28
67
|
* @param config - Header configuration
|
|
29
68
|
*/
|
|
30
69
|
export declare function renderHeader(config: HeaderConfig): void;
|
|
70
|
+
export {};
|
|
@@ -3,45 +3,358 @@
|
|
|
3
3
|
* Header component for CLI applications
|
|
4
4
|
* Displays ASCII art, title, description, version and URL
|
|
5
5
|
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
6
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
10
|
exports.renderHeader = renderHeader;
|
|
8
11
|
const colors_js_1 = require("../../core/colors.js");
|
|
9
12
|
const terminal_js_1 = require("../../core/terminal.js");
|
|
13
|
+
const figlet_1 = __importDefault(require("figlet"));
|
|
14
|
+
function visibleLength(value) {
|
|
15
|
+
return value.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
16
|
+
}
|
|
17
|
+
function padToVisibleWidth(value, width) {
|
|
18
|
+
const current = visibleLength(value);
|
|
19
|
+
if (current >= width) {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
return value + ' '.repeat(width - current);
|
|
23
|
+
}
|
|
24
|
+
function parseBackgroundAnsiToRgb(value) {
|
|
25
|
+
const trueColor = /^\x1b\[48;2;(\d{1,3});(\d{1,3});(\d{1,3})m$/.exec(value);
|
|
26
|
+
if (trueColor) {
|
|
27
|
+
return {
|
|
28
|
+
r: Math.max(0, Math.min(255, Number.parseInt(trueColor[1], 10))),
|
|
29
|
+
g: Math.max(0, Math.min(255, Number.parseInt(trueColor[2], 10))),
|
|
30
|
+
b: Math.max(0, Math.min(255, Number.parseInt(trueColor[3], 10)))
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const ansi256 = /^\x1b\[48;5;(\d{1,3})m$/.exec(value);
|
|
34
|
+
if (ansi256) {
|
|
35
|
+
const code = Math.max(0, Math.min(255, Number.parseInt(ansi256[1], 10)));
|
|
36
|
+
if (code >= 16 && code <= 231) {
|
|
37
|
+
const n = code - 16;
|
|
38
|
+
const r = Math.floor(n / 36);
|
|
39
|
+
const g = Math.floor((n % 36) / 6);
|
|
40
|
+
const b = n % 6;
|
|
41
|
+
const steps = [0, 95, 135, 175, 215, 255];
|
|
42
|
+
return { r: steps[r], g: steps[g], b: steps[b] };
|
|
43
|
+
}
|
|
44
|
+
if (code >= 232) {
|
|
45
|
+
const gray = 8 + (code - 232) * 10;
|
|
46
|
+
return { r: gray, g: gray, b: gray };
|
|
47
|
+
}
|
|
48
|
+
const basicMap = [
|
|
49
|
+
{ r: 0, g: 0, b: 0 },
|
|
50
|
+
{ r: 170, g: 0, b: 0 },
|
|
51
|
+
{ r: 0, g: 170, b: 0 },
|
|
52
|
+
{ r: 170, g: 85, b: 0 },
|
|
53
|
+
{ r: 0, g: 0, b: 170 },
|
|
54
|
+
{ r: 170, g: 0, b: 170 },
|
|
55
|
+
{ r: 0, g: 170, b: 170 },
|
|
56
|
+
{ r: 170, g: 170, b: 170 },
|
|
57
|
+
{ r: 85, g: 85, b: 85 },
|
|
58
|
+
{ r: 255, g: 85, b: 85 },
|
|
59
|
+
{ r: 85, g: 255, b: 85 },
|
|
60
|
+
{ r: 255, g: 255, b: 85 },
|
|
61
|
+
{ r: 85, g: 85, b: 255 },
|
|
62
|
+
{ r: 255, g: 85, b: 255 },
|
|
63
|
+
{ r: 85, g: 255, b: 255 },
|
|
64
|
+
{ r: 255, g: 255, b: 255 }
|
|
65
|
+
];
|
|
66
|
+
return basicMap[code] ?? null;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function isTrueColorBackground(value) {
|
|
71
|
+
return /^\x1b\[48;2;\d{1,3};\d{1,3};\d{1,3}m$/.test(value);
|
|
72
|
+
}
|
|
73
|
+
function supportsTrueColorTerminal() {
|
|
74
|
+
const colorterm = (process.env.COLORTERM ?? '').toLowerCase();
|
|
75
|
+
if (colorterm.includes('truecolor') || colorterm.includes('24bit')) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
const term = (process.env.TERM ?? '').toLowerCase();
|
|
79
|
+
if (term.includes('direct')) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
const program = (process.env.TERM_PROGRAM ?? '').toLowerCase();
|
|
83
|
+
if (program.includes('ghostty') || program.includes('wezterm') || program.includes('iterm') || program.includes('vscode')) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
function applyBackgroundGradient(content, startColor, endColor) {
|
|
89
|
+
// Compatibility fallback:
|
|
90
|
+
// only use per-character background gradients on truecolor terminals.
|
|
91
|
+
if (!isTrueColorBackground(startColor) || !isTrueColorBackground(endColor) || !supportsTrueColorTerminal()) {
|
|
92
|
+
return `${startColor}${content}${colors_js_1.colors.reset}`;
|
|
93
|
+
}
|
|
94
|
+
const start = parseBackgroundAnsiToRgb(startColor);
|
|
95
|
+
const end = parseBackgroundAnsiToRgb(endColor);
|
|
96
|
+
if (!start || !end) {
|
|
97
|
+
return `${startColor}${content}${colors_js_1.colors.reset}`;
|
|
98
|
+
}
|
|
99
|
+
const total = Math.max(1, visibleLength(content));
|
|
100
|
+
let out = '';
|
|
101
|
+
let visibleIndex = 0;
|
|
102
|
+
for (let i = 0; i < content.length; i += 1) {
|
|
103
|
+
const ch = content[i] ?? '';
|
|
104
|
+
if (ch === '\x1b') {
|
|
105
|
+
const endIdx = content.indexOf('m', i);
|
|
106
|
+
if (endIdx >= 0) {
|
|
107
|
+
out += content.slice(i, endIdx + 1);
|
|
108
|
+
i = endIdx;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const t = total <= 1 ? 0 : visibleIndex / (total - 1);
|
|
113
|
+
const r = Math.round(start.r + (end.r - start.r) * t);
|
|
114
|
+
const g = Math.round(start.g + (end.g - start.g) * t);
|
|
115
|
+
const b = Math.round(start.b + (end.b - start.b) * t);
|
|
116
|
+
out += `\x1b[48;2;${String(r)};${String(g)};${String(b)}m${ch}`;
|
|
117
|
+
visibleIndex += 1;
|
|
118
|
+
}
|
|
119
|
+
return `${out}${colors_js_1.colors.reset}`;
|
|
120
|
+
}
|
|
121
|
+
const figletCache = new Map();
|
|
122
|
+
function inkCount(line) {
|
|
123
|
+
let count = 0;
|
|
124
|
+
for (const ch of line) {
|
|
125
|
+
if (ch !== ' ' && ch !== '\t') {
|
|
126
|
+
count += 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return count;
|
|
130
|
+
}
|
|
131
|
+
function trimFigletTailNoise(lines) {
|
|
132
|
+
const out = [...lines];
|
|
133
|
+
while (out.length > 1) {
|
|
134
|
+
const last = out[out.length - 1] ?? '';
|
|
135
|
+
const prev = out[out.length - 2] ?? '';
|
|
136
|
+
const lastInk = inkCount(last);
|
|
137
|
+
const prevInk = inkCount(prev);
|
|
138
|
+
// Remove very small dangling tail rows (common in Bloody-like fonts).
|
|
139
|
+
if (lastInk <= 1 && prevInk >= 4) {
|
|
140
|
+
out.pop();
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
function resolveFigletFont(font, size = 'medium') {
|
|
148
|
+
if (font && font.trim().length > 0) {
|
|
149
|
+
return font;
|
|
150
|
+
}
|
|
151
|
+
if (size === 'small') {
|
|
152
|
+
return 'Small';
|
|
153
|
+
}
|
|
154
|
+
if (size === 'large') {
|
|
155
|
+
return 'Big';
|
|
156
|
+
}
|
|
157
|
+
return 'Standard';
|
|
158
|
+
}
|
|
159
|
+
function resolveFigletLines(text, font) {
|
|
160
|
+
const cacheKey = `${font}\u0000${text}`;
|
|
161
|
+
const cached = figletCache.get(cacheKey);
|
|
162
|
+
if (cached) {
|
|
163
|
+
return cached;
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const rendered = figlet_1.default.textSync(text, { font });
|
|
167
|
+
const lines = rendered.split('\n');
|
|
168
|
+
while (lines.length > 0 && lines[lines.length - 1].trim().length === 0) {
|
|
169
|
+
lines.pop();
|
|
170
|
+
}
|
|
171
|
+
const cleaned = trimFigletTailNoise(lines);
|
|
172
|
+
figletCache.set(cacheKey, cleaned);
|
|
173
|
+
return cleaned;
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
const fallback = figlet_1.default.textSync(text, { font: 'Standard' }).split('\n');
|
|
177
|
+
while (fallback.length > 0 && fallback[fallback.length - 1].trim().length === 0) {
|
|
178
|
+
fallback.pop();
|
|
179
|
+
}
|
|
180
|
+
const cleanedFallback = trimFigletTailNoise(fallback);
|
|
181
|
+
figletCache.set(cacheKey, cleanedFallback);
|
|
182
|
+
return cleanedFallback;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function scaleLineX(line, outCols) {
|
|
186
|
+
const srcCols = line.length;
|
|
187
|
+
if (srcCols === 0 || outCols <= 0) {
|
|
188
|
+
return '';
|
|
189
|
+
}
|
|
190
|
+
if (outCols === srcCols) {
|
|
191
|
+
return line;
|
|
192
|
+
}
|
|
193
|
+
let scaled = '';
|
|
194
|
+
for (let c = 0; c < outCols; c += 1) {
|
|
195
|
+
if (outCols === 1 || srcCols === 1) {
|
|
196
|
+
scaled += line[0] ?? ' ';
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const pos = (c * (srcCols - 1)) / (outCols - 1);
|
|
200
|
+
const srcCol = Math.max(0, Math.min(srcCols - 1, Math.round(pos)));
|
|
201
|
+
scaled += line[srcCol] ?? ' ';
|
|
202
|
+
}
|
|
203
|
+
return scaled;
|
|
204
|
+
}
|
|
205
|
+
function scaleAsciiLines(lines, scaleX, scaleY) {
|
|
206
|
+
const sx = Number.isFinite(scaleX) ? Math.max(0.4, Math.min(4, scaleX)) : 1;
|
|
207
|
+
const sy = Number.isFinite(scaleY) ? Math.max(0.4, Math.min(4, scaleY)) : sx;
|
|
208
|
+
if (Math.abs(sx - 1) < 0.001 && Math.abs(sy - 1) < 0.001) {
|
|
209
|
+
return lines;
|
|
210
|
+
}
|
|
211
|
+
const srcRows = lines.length;
|
|
212
|
+
if (srcRows === 0) {
|
|
213
|
+
return lines;
|
|
214
|
+
}
|
|
215
|
+
const outRows = Math.max(1, Math.round(srcRows * sy));
|
|
216
|
+
const out = [];
|
|
217
|
+
const sampleIndex = (outIndex, outCount, srcCount) => {
|
|
218
|
+
if (srcCount <= 1 || outCount <= 1) {
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
const ratio = outIndex / (outCount - 1);
|
|
222
|
+
return Math.max(0, Math.min(srcCount - 1, Math.round(ratio * (srcCount - 1))));
|
|
223
|
+
};
|
|
224
|
+
for (let r = 0; r < outRows; r += 1) {
|
|
225
|
+
const srcRow = sampleIndex(r, outRows, srcRows);
|
|
226
|
+
const srcLine = lines[srcRow] ?? '';
|
|
227
|
+
const outCols = Math.max(1, Math.round(srcLine.length * sx));
|
|
228
|
+
out.push(scaleLineX(srcLine, outCols).replace(/\s+$/g, ''));
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
function resolveFigletScale(scale, _explicitFont, _size) {
|
|
233
|
+
if (typeof scale === 'number' && Number.isFinite(scale)) {
|
|
234
|
+
return Math.max(0.4, Math.min(4, scale));
|
|
235
|
+
}
|
|
236
|
+
return 1;
|
|
237
|
+
}
|
|
238
|
+
function resolveFigletScaleY(scaleY, scaleX, explicitFont) {
|
|
239
|
+
if (typeof scaleY === 'number' && Number.isFinite(scaleY)) {
|
|
240
|
+
return Math.max(0.4, Math.min(4, scaleY));
|
|
241
|
+
}
|
|
242
|
+
const normalizedFont = (explicitFont || '').trim().toLowerCase();
|
|
243
|
+
// Keep Pagga crisp: no default Y stretch (its native height is 3 rows).
|
|
244
|
+
if (normalizedFont === 'pagga' && scaleX > 1) {
|
|
245
|
+
return 1;
|
|
246
|
+
}
|
|
247
|
+
return scaleX;
|
|
248
|
+
}
|
|
10
249
|
/**
|
|
11
250
|
* Render a boxed header with ASCII art, title, and description
|
|
12
251
|
* @param config - Header configuration
|
|
13
252
|
*/
|
|
14
253
|
function renderHeader(config) {
|
|
15
|
-
const { asciiArt = [], title = '', description = '', version, url, menuTitle, boxWidth = 60, color = colors_js_1.uiColors.border } = config;
|
|
254
|
+
const { asciiArt = [], figletText, figletFont, figletSize = 'medium', figletScale, figletScaleY, title = '', titleColor, titleGradientStart, titleGradientEnd, description = '', descriptionColor, descriptionGradientStart, descriptionGradientEnd, version, url, menuTitle, boxWidth = 60, showBoxBorder = true, fillBox = false, fillBoxColor = colors_js_1.colors.bgBlack, fillBoxGradientStart, fillBoxGradientEnd, color = colors_js_1.uiColors.border, asciiArtColor, asciiArtGradientStart, asciiArtGradientEnd } = config;
|
|
255
|
+
const resolvedFigletFont = resolveFigletFont(figletFont, figletSize);
|
|
256
|
+
const effectiveFigletScale = resolveFigletScale(figletScale, figletFont, figletSize);
|
|
257
|
+
const effectiveScaleY = resolveFigletScaleY(figletScaleY, effectiveFigletScale, resolvedFigletFont);
|
|
258
|
+
const resolvedAsciiArt = figletText
|
|
259
|
+
? scaleAsciiLines(resolveFigletLines(figletText, resolvedFigletFont), effectiveFigletScale, effectiveScaleY)
|
|
260
|
+
: asciiArt;
|
|
261
|
+
const requestedInnerWidth = Math.max(10, boxWidth - 2);
|
|
262
|
+
const contentLengths = [];
|
|
263
|
+
for (const line of resolvedAsciiArt) {
|
|
264
|
+
contentLengths.push(visibleLength(` ${line}`));
|
|
265
|
+
}
|
|
266
|
+
if (title) {
|
|
267
|
+
contentLengths.push(visibleLength(` ${title}`));
|
|
268
|
+
}
|
|
269
|
+
if (description) {
|
|
270
|
+
contentLengths.push(visibleLength(` ${description}`));
|
|
271
|
+
}
|
|
272
|
+
const innerWidth = Math.max(requestedInnerWidth, ...contentLengths, 10);
|
|
16
273
|
const boldColor = `${color}${colors_js_1.colors.bold}`;
|
|
274
|
+
const applyBoxFill = (content) => {
|
|
275
|
+
if (!fillBox) {
|
|
276
|
+
return content;
|
|
277
|
+
}
|
|
278
|
+
if (fillBoxGradientStart && fillBoxGradientEnd) {
|
|
279
|
+
return applyBackgroundGradient(content, fillBoxGradientStart, fillBoxGradientEnd);
|
|
280
|
+
}
|
|
281
|
+
const replayed = content.replace(/\x1b\[0m/g, `${colors_js_1.colors.reset}${fillBoxColor}`);
|
|
282
|
+
return `${fillBoxColor}${replayed}${colors_js_1.colors.reset}`;
|
|
283
|
+
};
|
|
284
|
+
const writeSpacer = () => {
|
|
285
|
+
if (showBoxBorder) {
|
|
286
|
+
const spacerContent = fillBox ? applyBoxFill(' '.repeat(innerWidth)) : ' '.repeat(innerWidth);
|
|
287
|
+
(0, terminal_js_1.writeLine)(`${boldColor}║${spacerContent}${boldColor}║${colors_js_1.colors.reset}`);
|
|
288
|
+
}
|
|
289
|
+
else if (fillBox) {
|
|
290
|
+
(0, terminal_js_1.writeLine)(` ${applyBoxFill(' '.repeat(innerWidth))}`);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
(0, terminal_js_1.writeLine)('');
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
const writeContentLine = (content, tint) => {
|
|
297
|
+
const normalized = showBoxBorder || fillBox ? padToVisibleWidth(content, innerWidth) : content;
|
|
298
|
+
if (showBoxBorder) {
|
|
299
|
+
const inner = tint ? `${tint}${normalized}${colors_js_1.colors.reset}` : `${colors_js_1.colors.reset}${normalized}`;
|
|
300
|
+
const body = fillBox ? applyBoxFill(inner) : inner;
|
|
301
|
+
if (tint) {
|
|
302
|
+
(0, terminal_js_1.writeLine)(`${boldColor}║${body}${boldColor}║${colors_js_1.colors.reset}`);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
(0, terminal_js_1.writeLine)(`${boldColor}║${body}${boldColor}║${colors_js_1.colors.reset}`);
|
|
306
|
+
}
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const plainLine = tint ? `${tint}${normalized}${colors_js_1.colors.reset}` : normalized;
|
|
310
|
+
if (fillBox) {
|
|
311
|
+
(0, terminal_js_1.writeLine)(` ${applyBoxFill(plainLine)}`);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
(0, terminal_js_1.writeLine)(plainLine);
|
|
315
|
+
};
|
|
17
316
|
// Top border
|
|
18
317
|
(0, terminal_js_1.writeLine)('');
|
|
19
|
-
(
|
|
20
|
-
|
|
21
|
-
|
|
318
|
+
if (showBoxBorder) {
|
|
319
|
+
(0, terminal_js_1.writeLine)(`${boldColor}╔${'═'.repeat(innerWidth)}╗${colors_js_1.colors.reset}`);
|
|
320
|
+
}
|
|
321
|
+
writeSpacer();
|
|
22
322
|
// ASCII art (left-aligned with 2 spaces padding)
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
const paddedLine = ` ${line}`.padEnd(
|
|
26
|
-
|
|
323
|
+
if (resolvedAsciiArt.length > 0) {
|
|
324
|
+
resolvedAsciiArt.forEach(line => {
|
|
325
|
+
const paddedLine = showBoxBorder ? ` ${line}`.padEnd(innerWidth, ' ') : ` ${line}`;
|
|
326
|
+
const artLine = asciiArtGradientStart && asciiArtGradientEnd
|
|
327
|
+
? `${(0, colors_js_1.applyGradient)(paddedLine, asciiArtGradientStart, asciiArtGradientEnd)}`
|
|
328
|
+
: `${(asciiArtColor || color)}${paddedLine}${colors_js_1.colors.reset}`;
|
|
329
|
+
writeContentLine(artLine);
|
|
27
330
|
});
|
|
28
|
-
(
|
|
331
|
+
writeSpacer();
|
|
29
332
|
}
|
|
30
|
-
// Title (left-aligned with 2 spaces padding
|
|
333
|
+
// Title (left-aligned with 2 spaces padding)
|
|
31
334
|
if (title) {
|
|
32
|
-
const paddedTitle = ` ${title}`.padEnd(
|
|
33
|
-
|
|
34
|
-
|
|
335
|
+
const paddedTitle = showBoxBorder ? ` ${title}`.padEnd(innerWidth, ' ') : ` ${title}`;
|
|
336
|
+
const titleLine = titleGradientStart && titleGradientEnd
|
|
337
|
+
? (0, colors_js_1.applyGradient)(paddedTitle, titleGradientStart, titleGradientEnd)
|
|
338
|
+
: paddedTitle;
|
|
339
|
+
writeContentLine(titleLine, titleGradientStart && titleGradientEnd ? undefined : titleColor);
|
|
340
|
+
writeSpacer();
|
|
35
341
|
}
|
|
36
|
-
// Description (left-aligned with 2 spaces padding
|
|
342
|
+
// Description (left-aligned with 2 spaces padding)
|
|
37
343
|
if (description) {
|
|
38
344
|
const textContent = ` ${description}`;
|
|
39
|
-
const paddedText = textContent.padEnd(
|
|
40
|
-
|
|
41
|
-
|
|
345
|
+
const paddedText = showBoxBorder ? textContent.padEnd(innerWidth, ' ') : textContent;
|
|
346
|
+
const descLine = descriptionGradientStart && descriptionGradientEnd
|
|
347
|
+
? (0, colors_js_1.applyGradient)(paddedText, descriptionGradientStart, descriptionGradientEnd)
|
|
348
|
+
: paddedText;
|
|
349
|
+
writeContentLine(descLine, descriptionGradientStart && descriptionGradientEnd
|
|
350
|
+
? undefined
|
|
351
|
+
: (descriptionColor || colors_js_1.uiColors.textSecondary));
|
|
352
|
+
writeSpacer();
|
|
42
353
|
}
|
|
43
354
|
// Bottom border
|
|
44
|
-
(
|
|
355
|
+
if (showBoxBorder) {
|
|
356
|
+
(0, terminal_js_1.writeLine)(`${boldColor}╚${'═'.repeat(innerWidth)}╝${colors_js_1.colors.reset}`);
|
|
357
|
+
}
|
|
45
358
|
// Blank line after box
|
|
46
359
|
(0, terminal_js_1.writeLine)('');
|
|
47
360
|
// Version and URL (outside the box, with colors)
|
|
@@ -10,6 +10,7 @@ import { AsciiHeaderConfig } from '../../types/display.types.js';
|
|
|
10
10
|
* @param color - Optional color (default: cyan)
|
|
11
11
|
*/
|
|
12
12
|
export declare function renderSimpleHeader(text: string, color?: string): void;
|
|
13
|
+
export declare function renderSimpleHeaderWithSpacing(text: string, color?: string, spacingAfter?: number): void;
|
|
13
14
|
/**
|
|
14
15
|
* Render a section header with double-line borders
|
|
15
16
|
* Format:
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.renderSimpleHeader = renderSimpleHeader;
|
|
8
|
+
exports.renderSimpleHeaderWithSpacing = renderSimpleHeaderWithSpacing;
|
|
8
9
|
exports.renderSectionHeader = renderSectionHeader;
|
|
9
10
|
exports.renderAsciiHeader = renderAsciiHeader;
|
|
10
11
|
exports.createSimpleHeader = createSimpleHeader;
|
|
@@ -21,10 +22,19 @@ const terminal_js_2 = require("../../core/terminal.js");
|
|
|
21
22
|
*/
|
|
22
23
|
function renderSimpleHeader(text, color) {
|
|
23
24
|
const headerColor = color || colors_js_1.uiColors.primary;
|
|
24
|
-
const line =
|
|
25
|
+
const line = ` === ${text} ===`;
|
|
25
26
|
(0, terminal_js_1.writeLine)(`${headerColor}${line}${colors_js_1.colors.reset}`);
|
|
26
27
|
(0, terminal_js_1.writeLine)('');
|
|
27
28
|
}
|
|
29
|
+
function renderSimpleHeaderWithSpacing(text, color, spacingAfter = 1) {
|
|
30
|
+
const headerColor = color || colors_js_1.uiColors.primary;
|
|
31
|
+
const line = ` === ${text} ===`;
|
|
32
|
+
(0, terminal_js_1.writeLine)(`${headerColor}${line}${colors_js_1.colors.reset}`);
|
|
33
|
+
const spacerLines = Math.max(0, Math.floor(spacingAfter));
|
|
34
|
+
for (let i = 0; i < spacerLines; i += 1) {
|
|
35
|
+
(0, terminal_js_1.writeLine)('');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
28
38
|
/**
|
|
29
39
|
* Render a section header with double-line borders
|
|
30
40
|
* Format:
|
|
@@ -53,22 +63,22 @@ function renderAsciiHeader(config) {
|
|
|
53
63
|
const termWidth = (0, terminal_js_2.getTerminalWidth)();
|
|
54
64
|
const border = borderChar.repeat(termWidth);
|
|
55
65
|
// Top border
|
|
56
|
-
(0, terminal_js_1.writeLine)(colors_js_1.
|
|
66
|
+
(0, terminal_js_1.writeLine)(colors_js_1.uiColors.border + border + colors_js_1.colors.reset);
|
|
57
67
|
(0, terminal_js_1.writeLine)('');
|
|
58
68
|
// ASCII art (centered)
|
|
59
69
|
const artLines = asciiArt.split('\n');
|
|
60
70
|
artLines.forEach(line => {
|
|
61
|
-
(0, terminal_js_1.writeLine)(colors_js_1.
|
|
71
|
+
(0, terminal_js_1.writeLine)(colors_js_1.uiColors.primary + line + colors_js_1.colors.reset);
|
|
62
72
|
});
|
|
63
73
|
// Subtitle if provided
|
|
64
74
|
if (subtitle) {
|
|
65
75
|
(0, terminal_js_1.writeLine)('');
|
|
66
76
|
const padding = Math.floor((termWidth - subtitle.length) / 2);
|
|
67
|
-
(0, terminal_js_1.writeLine)(' '.repeat(padding) + colors_js_1.
|
|
77
|
+
(0, terminal_js_1.writeLine)(' '.repeat(padding) + colors_js_1.uiColors.accent + subtitle + colors_js_1.colors.reset);
|
|
68
78
|
}
|
|
69
79
|
(0, terminal_js_1.writeLine)('');
|
|
70
80
|
// Bottom border
|
|
71
|
-
(0, terminal_js_1.writeLine)(colors_js_1.
|
|
81
|
+
(0, terminal_js_1.writeLine)(colors_js_1.uiColors.border + border + colors_js_1.colors.reset);
|
|
72
82
|
// Footer info (version and URL)
|
|
73
83
|
if (version || url) {
|
|
74
84
|
const footerParts = [];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Exports all display component functions
|
|
4
4
|
*/
|
|
5
5
|
export { renderSimpleHeader, renderSectionHeader, renderAsciiHeader, createSimpleHeader, createSectionHeader, createAsciiHeader } from './headers.js';
|
|
6
|
-
export { renderProgressIndicator, renderStageHeader, renderStageSeparator, createProgressIndicator, createStageHeader, createStageSeparator } from './progress.js';
|
|
6
|
+
export { renderProgressIndicator, renderStageHeader, renderStageSeparator, createProgressIndicator, createStageHeader, createStageSeparator, renderProgressCheckmark, createProgressCheckmark } from './progress.js';
|
|
7
7
|
export { renderMessage, showSuccess, showError, showWarning, showInfo, showQuestion, createMessage } from './messages.js';
|
|
8
8
|
export { renderSummaryTable, createSummaryTable, createSimpleSummary } from './summary.js';
|
|
9
9
|
export { renderHeader, type HeaderConfig } from './header.js';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Exports all display component functions
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.createNumberedList = exports.createBulletList = exports.createList = exports.renderList = exports.createTable = exports.renderTable = exports.HintTypes = exports.generateInputHints = exports.generateMenuHints = exports.createHints = exports.renderHintsComponent = exports.renderHeader = exports.createSimpleSummary = exports.createSummaryTable = exports.renderSummaryTable = exports.createMessage = exports.showQuestion = exports.showInfo = exports.showWarning = exports.showError = exports.showSuccess = exports.renderMessage = exports.createStageSeparator = exports.createStageHeader = exports.createProgressIndicator = exports.renderStageSeparator = exports.renderStageHeader = exports.renderProgressIndicator = exports.createAsciiHeader = exports.createSectionHeader = exports.createSimpleHeader = exports.renderAsciiHeader = exports.renderSectionHeader = exports.renderSimpleHeader = void 0;
|
|
7
|
+
exports.createNumberedList = exports.createBulletList = exports.createList = exports.renderList = exports.createTable = exports.renderTable = exports.HintTypes = exports.generateInputHints = exports.generateMenuHints = exports.createHints = exports.renderHintsComponent = exports.renderHeader = exports.createSimpleSummary = exports.createSummaryTable = exports.renderSummaryTable = exports.createMessage = exports.showQuestion = exports.showInfo = exports.showWarning = exports.showError = exports.showSuccess = exports.renderMessage = exports.createProgressCheckmark = exports.renderProgressCheckmark = exports.createStageSeparator = exports.createStageHeader = exports.createProgressIndicator = exports.renderStageSeparator = exports.renderStageHeader = exports.renderProgressIndicator = exports.createAsciiHeader = exports.createSectionHeader = exports.createSimpleHeader = exports.renderAsciiHeader = exports.renderSectionHeader = exports.renderSimpleHeader = void 0;
|
|
8
8
|
var headers_js_1 = require("./headers.js");
|
|
9
9
|
Object.defineProperty(exports, "renderSimpleHeader", { enumerable: true, get: function () { return headers_js_1.renderSimpleHeader; } });
|
|
10
10
|
Object.defineProperty(exports, "renderSectionHeader", { enumerable: true, get: function () { return headers_js_1.renderSectionHeader; } });
|
|
@@ -19,6 +19,8 @@ Object.defineProperty(exports, "renderStageSeparator", { enumerable: true, get:
|
|
|
19
19
|
Object.defineProperty(exports, "createProgressIndicator", { enumerable: true, get: function () { return progress_js_1.createProgressIndicator; } });
|
|
20
20
|
Object.defineProperty(exports, "createStageHeader", { enumerable: true, get: function () { return progress_js_1.createStageHeader; } });
|
|
21
21
|
Object.defineProperty(exports, "createStageSeparator", { enumerable: true, get: function () { return progress_js_1.createStageSeparator; } });
|
|
22
|
+
Object.defineProperty(exports, "renderProgressCheckmark", { enumerable: true, get: function () { return progress_js_1.renderProgressCheckmark; } });
|
|
23
|
+
Object.defineProperty(exports, "createProgressCheckmark", { enumerable: true, get: function () { return progress_js_1.createProgressCheckmark; } });
|
|
22
24
|
var messages_js_1 = require("./messages.js");
|
|
23
25
|
Object.defineProperty(exports, "renderMessage", { enumerable: true, get: function () { return messages_js_1.renderMessage; } });
|
|
24
26
|
Object.defineProperty(exports, "showSuccess", { enumerable: true, get: function () { return messages_js_1.showSuccess; } });
|
|
@@ -24,23 +24,23 @@ function renderMessage(config) {
|
|
|
24
24
|
switch (type) {
|
|
25
25
|
case 'success':
|
|
26
26
|
icon = '✓';
|
|
27
|
-
color = colors_js_1.
|
|
27
|
+
color = colors_js_1.uiColors.success;
|
|
28
28
|
break;
|
|
29
29
|
case 'error':
|
|
30
30
|
icon = '✗';
|
|
31
|
-
color = colors_js_1.
|
|
31
|
+
color = colors_js_1.uiColors.error;
|
|
32
32
|
break;
|
|
33
33
|
case 'warning':
|
|
34
34
|
icon = '⚠';
|
|
35
|
-
color = colors_js_1.
|
|
35
|
+
color = colors_js_1.uiColors.warning;
|
|
36
36
|
break;
|
|
37
37
|
case 'info':
|
|
38
38
|
icon = 'ℹ';
|
|
39
|
-
color = colors_js_1.
|
|
39
|
+
color = colors_js_1.uiColors.info;
|
|
40
40
|
break;
|
|
41
41
|
case 'question':
|
|
42
42
|
icon = '?';
|
|
43
|
-
color = colors_js_1.
|
|
43
|
+
color = colors_js_1.uiColors.warning;
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
46
46
|
(0, terminal_js_1.writeLine)(`${color}${icon}${colors_js_1.colors.reset} ${message}`);
|
|
@@ -39,3 +39,20 @@ export declare function createStageHeader(stageName: string, stepNumber: number)
|
|
|
39
39
|
* @param width - Optional width
|
|
40
40
|
*/
|
|
41
41
|
export declare function createStageSeparator(char?: string, width?: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* Single-line completed progress marker.
|
|
44
|
+
* Use this for execution flows that print one completed step at a time.
|
|
45
|
+
*/
|
|
46
|
+
export declare function renderProgressCheckmark(step: string, options?: {
|
|
47
|
+
icon?: string;
|
|
48
|
+
indent?: string;
|
|
49
|
+
color?: string;
|
|
50
|
+
}): void;
|
|
51
|
+
/**
|
|
52
|
+
* Alias factory for renderProgressCheckmark
|
|
53
|
+
*/
|
|
54
|
+
export declare function createProgressCheckmark(step: string, options?: {
|
|
55
|
+
icon?: string;
|
|
56
|
+
indent?: string;
|
|
57
|
+
color?: string;
|
|
58
|
+
}): void;
|
|
@@ -10,6 +10,8 @@ exports.renderStageSeparator = renderStageSeparator;
|
|
|
10
10
|
exports.createProgressIndicator = createProgressIndicator;
|
|
11
11
|
exports.createStageHeader = createStageHeader;
|
|
12
12
|
exports.createStageSeparator = createStageSeparator;
|
|
13
|
+
exports.renderProgressCheckmark = renderProgressCheckmark;
|
|
14
|
+
exports.createProgressCheckmark = createProgressCheckmark;
|
|
13
15
|
const terminal_js_1 = require("../../core/terminal.js");
|
|
14
16
|
const colors_js_1 = require("../../core/colors.js");
|
|
15
17
|
const terminal_js_2 = require("../../core/terminal.js");
|
|
@@ -80,3 +82,19 @@ function createStageHeader(stageName, stepNumber) {
|
|
|
80
82
|
function createStageSeparator(char, width) {
|
|
81
83
|
renderStageSeparator(char, width);
|
|
82
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Single-line completed progress marker.
|
|
87
|
+
* Use this for execution flows that print one completed step at a time.
|
|
88
|
+
*/
|
|
89
|
+
function renderProgressCheckmark(step, options) {
|
|
90
|
+
const icon = options?.icon ?? '✓';
|
|
91
|
+
const indent = options?.indent ?? ' ';
|
|
92
|
+
const color = options?.color ?? colors_js_1.uiColors.primary;
|
|
93
|
+
(0, terminal_js_1.writeLine)(`${indent}${color}${icon}${colors_js_1.colors.reset} ${step}`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Alias factory for renderProgressCheckmark
|
|
97
|
+
*/
|
|
98
|
+
function createProgressCheckmark(step, options) {
|
|
99
|
+
renderProgressCheckmark(step, options);
|
|
100
|
+
}
|