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.
Files changed (45) hide show
  1. package/dist/components/display/header.d.ts +40 -0
  2. package/dist/components/display/header.js +331 -18
  3. package/dist/components/display/headers.d.ts +1 -0
  4. package/dist/components/display/headers.js +15 -5
  5. package/dist/components/display/index.d.ts +1 -1
  6. package/dist/components/display/index.js +3 -1
  7. package/dist/components/display/messages.js +5 -5
  8. package/dist/components/display/progress.d.ts +17 -0
  9. package/dist/components/display/progress.js +18 -0
  10. package/dist/components/display/summary.js +72 -10
  11. package/dist/components/display/table.d.ts +2 -0
  12. package/dist/components/display/table.js +7 -6
  13. package/dist/components/inputs/language-input.js +8 -5
  14. package/dist/components/inputs/number-input.js +19 -14
  15. package/dist/components/inputs/text-input.js +50 -13
  16. package/dist/components/menus/boolean-menu.js +33 -20
  17. package/dist/components/menus/checkbox-menu.js +5 -2
  18. package/dist/components/menus/checkbox-table-menu.js +12 -9
  19. package/dist/components/menus/radio-menu-split.d.ts +1 -0
  20. package/dist/components/menus/radio-menu-split.js +26 -16
  21. package/dist/components/menus/radio-menu.js +67 -38
  22. package/dist/components.js +3 -3
  23. package/dist/config/index.d.ts +5 -0
  24. package/dist/config/index.js +21 -0
  25. package/dist/config/language-config.d.ts +73 -0
  26. package/dist/config/language-config.js +157 -0
  27. package/dist/config/user-config.d.ts +83 -0
  28. package/dist/config/user-config.js +185 -0
  29. package/dist/core/colors.d.ts +24 -18
  30. package/dist/core/colors.js +74 -7
  31. package/dist/core/renderer.js +26 -18
  32. package/dist/core/terminal.d.ts +13 -0
  33. package/dist/core/terminal.js +87 -0
  34. package/dist/features/commands.js +23 -22
  35. package/dist/index.d.ts +3 -1
  36. package/dist/index.js +21 -2
  37. package/dist/layout.d.ts +50 -51
  38. package/dist/layout.js +69 -117
  39. package/dist/page-layout.d.ts +31 -0
  40. package/dist/page-layout.js +46 -7
  41. package/dist/types/input.types.d.ts +8 -0
  42. package/dist/types/layout.types.d.ts +56 -0
  43. package/dist/types/layout.types.js +36 -0
  44. package/dist/types/menu.types.d.ts +4 -0
  45. package/package.json +4 -1
@@ -0,0 +1,83 @@
1
+ /**
2
+ * User Configuration System for CLI Menu Kit
3
+ * Provides persistent user preferences
4
+ */
5
+ export interface UserConfig {
6
+ language?: string;
7
+ theme?: string;
8
+ [key: string]: any;
9
+ }
10
+ export interface ConfigOptions {
11
+ appName: string;
12
+ configFileName?: string;
13
+ defaults?: UserConfig;
14
+ }
15
+ declare class ConfigManager {
16
+ private appName;
17
+ private configFileName;
18
+ private defaults;
19
+ private configDir;
20
+ private configPath;
21
+ constructor(options: ConfigOptions);
22
+ /**
23
+ * Ensure config directory exists
24
+ */
25
+ private ensureConfigDir;
26
+ /**
27
+ * Load configuration
28
+ */
29
+ load(): UserConfig;
30
+ /**
31
+ * Save configuration
32
+ */
33
+ save(config: Partial<UserConfig>): void;
34
+ /**
35
+ * Get a specific config value
36
+ */
37
+ get<K extends keyof UserConfig>(key: K): UserConfig[K];
38
+ /**
39
+ * Set a specific config value
40
+ */
41
+ set<K extends keyof UserConfig>(key: K, value: UserConfig[K]): void;
42
+ /**
43
+ * Reset configuration to defaults
44
+ */
45
+ reset(): void;
46
+ /**
47
+ * Get config file path
48
+ */
49
+ getConfigPath(): string;
50
+ /**
51
+ * Get config directory path
52
+ */
53
+ getConfigDir(): string;
54
+ }
55
+ /**
56
+ * Initialize config manager
57
+ */
58
+ export declare function initConfig(options: ConfigOptions): ConfigManager;
59
+ /**
60
+ * Get global config manager
61
+ */
62
+ export declare function getConfigManager(): ConfigManager;
63
+ /**
64
+ * Load configuration
65
+ */
66
+ export declare function loadConfig(): UserConfig;
67
+ /**
68
+ * Save configuration
69
+ */
70
+ export declare function saveConfig(config: Partial<UserConfig>): void;
71
+ /**
72
+ * Get config value
73
+ */
74
+ export declare function getConfig<K extends keyof UserConfig>(key: K): UserConfig[K];
75
+ /**
76
+ * Set config value
77
+ */
78
+ export declare function setConfig<K extends keyof UserConfig>(key: K, value: UserConfig[K]): void;
79
+ /**
80
+ * Reset configuration
81
+ */
82
+ export declare function resetConfig(): void;
83
+ export {};
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ /**
3
+ * User Configuration System for CLI Menu Kit
4
+ * Provides persistent user preferences
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.initConfig = initConfig;
41
+ exports.getConfigManager = getConfigManager;
42
+ exports.loadConfig = loadConfig;
43
+ exports.saveConfig = saveConfig;
44
+ exports.getConfig = getConfig;
45
+ exports.setConfig = setConfig;
46
+ exports.resetConfig = resetConfig;
47
+ const fs = __importStar(require("fs"));
48
+ const path = __importStar(require("path"));
49
+ const os = __importStar(require("os"));
50
+ class ConfigManager {
51
+ constructor(options) {
52
+ this.appName = options.appName;
53
+ this.configFileName = options.configFileName || 'config.json';
54
+ this.defaults = options.defaults || {};
55
+ // Set config directory
56
+ this.configDir = path.join(os.homedir(), `.${this.appName}`);
57
+ this.configPath = path.join(this.configDir, this.configFileName);
58
+ // Ensure config directory exists
59
+ this.ensureConfigDir();
60
+ }
61
+ /**
62
+ * Ensure config directory exists
63
+ */
64
+ ensureConfigDir() {
65
+ if (!fs.existsSync(this.configDir)) {
66
+ fs.mkdirSync(this.configDir, { recursive: true });
67
+ }
68
+ }
69
+ /**
70
+ * Load configuration
71
+ */
72
+ load() {
73
+ if (!fs.existsSync(this.configPath)) {
74
+ return { ...this.defaults };
75
+ }
76
+ try {
77
+ const content = fs.readFileSync(this.configPath, 'utf8');
78
+ const config = JSON.parse(content);
79
+ return { ...this.defaults, ...config };
80
+ }
81
+ catch (error) {
82
+ console.error('Failed to load config:', error);
83
+ return { ...this.defaults };
84
+ }
85
+ }
86
+ /**
87
+ * Save configuration
88
+ */
89
+ save(config) {
90
+ const currentConfig = this.load();
91
+ const newConfig = {
92
+ ...currentConfig,
93
+ ...config,
94
+ updated_at: new Date().toISOString()
95
+ };
96
+ try {
97
+ fs.writeFileSync(this.configPath, JSON.stringify(newConfig, null, 2), 'utf8');
98
+ }
99
+ catch (error) {
100
+ console.error('Failed to save config:', error);
101
+ throw error;
102
+ }
103
+ }
104
+ /**
105
+ * Get a specific config value
106
+ */
107
+ get(key) {
108
+ const config = this.load();
109
+ return config[key];
110
+ }
111
+ /**
112
+ * Set a specific config value
113
+ */
114
+ set(key, value) {
115
+ this.save({ [key]: value });
116
+ }
117
+ /**
118
+ * Reset configuration to defaults
119
+ */
120
+ reset() {
121
+ if (fs.existsSync(this.configPath)) {
122
+ fs.unlinkSync(this.configPath);
123
+ }
124
+ }
125
+ /**
126
+ * Get config file path
127
+ */
128
+ getConfigPath() {
129
+ return this.configPath;
130
+ }
131
+ /**
132
+ * Get config directory path
133
+ */
134
+ getConfigDir() {
135
+ return this.configDir;
136
+ }
137
+ }
138
+ // Global config manager instance
139
+ let globalConfigManager = null;
140
+ /**
141
+ * Initialize config manager
142
+ */
143
+ function initConfig(options) {
144
+ globalConfigManager = new ConfigManager(options);
145
+ return globalConfigManager;
146
+ }
147
+ /**
148
+ * Get global config manager
149
+ */
150
+ function getConfigManager() {
151
+ if (!globalConfigManager) {
152
+ throw new Error('Config manager not initialized. Call initConfig() first.');
153
+ }
154
+ return globalConfigManager;
155
+ }
156
+ /**
157
+ * Load configuration
158
+ */
159
+ function loadConfig() {
160
+ return getConfigManager().load();
161
+ }
162
+ /**
163
+ * Save configuration
164
+ */
165
+ function saveConfig(config) {
166
+ getConfigManager().save(config);
167
+ }
168
+ /**
169
+ * Get config value
170
+ */
171
+ function getConfig(key) {
172
+ return getConfigManager().get(key);
173
+ }
174
+ /**
175
+ * Set config value
176
+ */
177
+ function setConfig(key, value) {
178
+ getConfigManager().set(key, value);
179
+ }
180
+ /**
181
+ * Reset configuration
182
+ */
183
+ function resetConfig() {
184
+ getConfigManager().reset();
185
+ }
@@ -44,19 +44,21 @@ export declare const colors: {
44
44
  * Defines consistent colors for different levels of information
45
45
  */
46
46
  export declare const defaultUIColors: {
47
- readonly primary: "\u001B[36m";
48
- readonly accent: "\u001B[34m";
47
+ readonly primary: "\u001B[0m";
48
+ readonly accent: "\u001B[0m";
49
49
  readonly textPrimary: "\u001B[0m";
50
50
  readonly textSecondary: "\u001B[2m";
51
51
  readonly textMuted: "\u001B[90m";
52
52
  readonly success: "\u001B[32m";
53
53
  readonly error: "\u001B[31m";
54
54
  readonly warning: "\u001B[33m";
55
- readonly info: "\u001B[34m";
56
- readonly cursor: "\u001B[36m";
57
- readonly selected: "\u001B[32m";
55
+ readonly info: "\u001B[0m";
56
+ readonly cursor: "\u001B[0m";
57
+ readonly selected: "\u001B[0m";
58
+ readonly highlightBg: "";
59
+ readonly highlightText: "\u001B[0m";
58
60
  readonly disabled: "\u001B[2m";
59
- readonly border: "\u001B[36m";
61
+ readonly border: "\u001B[90m";
60
62
  readonly separator: "\u001B[2m";
61
63
  readonly prefix: "\u001B[2m";
62
64
  };
@@ -64,19 +66,21 @@ export declare const defaultUIColors: {
64
66
  * Get current UI colors
65
67
  */
66
68
  export declare function getUIColors(): {
67
- primary: "\u001B[36m";
68
- accent: "\u001B[34m";
69
+ primary: "\u001B[0m";
70
+ accent: "\u001B[0m";
69
71
  textPrimary: "\u001B[0m";
70
72
  textSecondary: "\u001B[2m";
71
73
  textMuted: "\u001B[90m";
72
74
  success: "\u001B[32m";
73
75
  error: "\u001B[31m";
74
76
  warning: "\u001B[33m";
75
- info: "\u001B[34m";
76
- cursor: "\u001B[36m";
77
- selected: "\u001B[32m";
77
+ info: "\u001B[0m";
78
+ cursor: "\u001B[0m";
79
+ selected: "\u001B[0m";
80
+ highlightBg: "";
81
+ highlightText: "\u001B[0m";
78
82
  disabled: "\u001B[2m";
79
- border: "\u001B[36m";
83
+ border: "\u001B[90m";
80
84
  separator: "\u001B[2m";
81
85
  prefix: "\u001B[2m";
82
86
  };
@@ -93,19 +97,21 @@ export declare function resetUIColors(): void;
93
97
  * UI colors accessor (always returns current colors)
94
98
  */
95
99
  export declare const uiColors: {
96
- readonly primary: "\u001B[36m";
97
- readonly accent: "\u001B[34m";
100
+ readonly primary: "\u001B[0m";
101
+ readonly accent: "\u001B[0m";
98
102
  readonly textPrimary: "\u001B[0m";
99
103
  readonly textSecondary: "\u001B[2m";
100
104
  readonly textMuted: "\u001B[90m";
101
105
  readonly success: "\u001B[32m";
102
106
  readonly error: "\u001B[31m";
103
107
  readonly warning: "\u001B[33m";
104
- readonly info: "\u001B[34m";
105
- readonly cursor: "\u001B[36m";
106
- readonly selected: "\u001B[32m";
108
+ readonly info: "\u001B[0m";
109
+ readonly cursor: "\u001B[0m";
110
+ readonly selected: "\u001B[0m";
111
+ readonly highlightBg: "";
112
+ readonly highlightText: "\u001B[0m";
107
113
  readonly disabled: "\u001B[2m";
108
- readonly border: "\u001B[36m";
114
+ readonly border: "\u001B[90m";
109
115
  readonly separator: "\u001B[2m";
110
116
  readonly prefix: "\u001B[2m";
111
117
  };
@@ -59,8 +59,8 @@ exports.colors = {
59
59
  */
60
60
  exports.defaultUIColors = {
61
61
  // Primary elements
62
- primary: exports.colors.cyan, // Main interactive elements, highlights
63
- accent: exports.colors.blue, // Secondary highlights, links
62
+ primary: exports.colors.reset, // Main interactive elements, follows terminal foreground
63
+ accent: exports.colors.reset, // Secondary highlights, follows terminal foreground
64
64
  // Text hierarchy
65
65
  textPrimary: exports.colors.reset, // Main text (black/default)
66
66
  textSecondary: exports.colors.dim, // Descriptions, hints, less important text
@@ -69,13 +69,15 @@ exports.defaultUIColors = {
69
69
  success: exports.colors.green, // Success states, confirmations
70
70
  error: exports.colors.red, // Errors, warnings, exit
71
71
  warning: exports.colors.yellow, // Warnings, cautions
72
- info: exports.colors.blue, // Informational messages
72
+ info: exports.colors.reset, // Informational messages
73
73
  // Interactive elements
74
- cursor: exports.colors.cyan, // Cursor indicator
75
- selected: exports.colors.green, // Selected items
74
+ cursor: exports.colors.reset, // Cursor indicator
75
+ selected: exports.colors.reset, // Selected items
76
+ highlightBg: '', // Optional background block for highlighted option
77
+ highlightText: exports.colors.reset, // Text color when highlightBg is used
76
78
  disabled: exports.colors.dim, // Disabled/inactive items
77
79
  // Structural elements
78
- border: exports.colors.cyan, // Borders, frames
80
+ border: exports.colors.brightBlack, // Borders, frames
79
81
  separator: exports.colors.dim, // Separators, dividers
80
82
  prefix: exports.colors.dim // Number/letter prefixes
81
83
  };
@@ -118,6 +120,18 @@ exports.uiColors = new Proxy({}, {
118
120
  * Supports basic 8 colors and bright variants
119
121
  */
120
122
  function parseColorToRGB(colorCode) {
123
+ const trueColorMatch = /^\x1b\[38;2;(\d{1,3});(\d{1,3});(\d{1,3})m$/.exec(colorCode);
124
+ if (trueColorMatch) {
125
+ return {
126
+ r: Math.max(0, Math.min(255, Number.parseInt(trueColorMatch[1], 10))),
127
+ g: Math.max(0, Math.min(255, Number.parseInt(trueColorMatch[2], 10))),
128
+ b: Math.max(0, Math.min(255, Number.parseInt(trueColorMatch[3], 10)))
129
+ };
130
+ }
131
+ const ansi256Match = /^\x1b\[38;5;(\d{1,3})m$/.exec(colorCode);
132
+ if (ansi256Match) {
133
+ return ansi256ToRgb(Math.max(0, Math.min(255, Number.parseInt(ansi256Match[1], 10))));
134
+ }
121
135
  // Map of ANSI codes to approximate RGB values
122
136
  const colorMap = {
123
137
  '\x1b[30m': { r: 0, g: 0, b: 0 }, // black
@@ -139,6 +153,48 @@ function parseColorToRGB(colorCode) {
139
153
  };
140
154
  return colorMap[colorCode] || { r: 170, g: 170, b: 170 };
141
155
  }
156
+ function detectColorMode(colorCode) {
157
+ if (/^\x1b\[38;2;\d{1,3};\d{1,3};\d{1,3}m$/.test(colorCode)) {
158
+ return 'truecolor';
159
+ }
160
+ if (/^\x1b\[38;5;\d{1,3}m$/.test(colorCode)) {
161
+ return 'ansi256';
162
+ }
163
+ return 'ansi16';
164
+ }
165
+ function ansi256ToRgb(code) {
166
+ if (code < 16) {
167
+ const ansi16Map = [
168
+ { r: 0, g: 0, b: 0 }, // 0 black
169
+ { r: 170, g: 0, b: 0 }, // 1 red
170
+ { r: 0, g: 170, b: 0 }, // 2 green
171
+ { r: 170, g: 85, b: 0 }, // 3 yellow
172
+ { r: 0, g: 0, b: 170 }, // 4 blue
173
+ { r: 170, g: 0, b: 170 }, // 5 magenta
174
+ { r: 0, g: 170, b: 170 }, // 6 cyan
175
+ { r: 170, g: 170, b: 170 }, // 7 white
176
+ { r: 85, g: 85, b: 85 }, // 8 bright black
177
+ { r: 255, g: 85, b: 85 }, // 9 bright red
178
+ { r: 85, g: 255, b: 85 }, // 10 bright green
179
+ { r: 255, g: 255, b: 85 }, // 11 bright yellow
180
+ { r: 85, g: 85, b: 255 }, // 12 bright blue
181
+ { r: 255, g: 85, b: 255 }, // 13 bright magenta
182
+ { r: 85, g: 255, b: 255 }, // 14 bright cyan
183
+ { r: 255, g: 255, b: 255 } // 15 bright white
184
+ ];
185
+ return ansi16Map[code];
186
+ }
187
+ if (code >= 16 && code <= 231) {
188
+ const n = code - 16;
189
+ const r = Math.floor(n / 36);
190
+ const g = Math.floor((n % 36) / 6);
191
+ const b = n % 6;
192
+ const steps = [0, 95, 135, 175, 215, 255];
193
+ return { r: steps[r], g: steps[g], b: steps[b] };
194
+ }
195
+ const gray = 8 + (code - 232) * 10;
196
+ return { r: gray, g: gray, b: gray };
197
+ }
142
198
  /**
143
199
  * Convert RGB to ANSI 256-color code
144
200
  */
@@ -147,6 +203,12 @@ function rgbToAnsi256(r, g, b) {
147
203
  const code = 16 + 36 * Math.round(r / 255 * 5) + 6 * Math.round(g / 255 * 5) + Math.round(b / 255 * 5);
148
204
  return `\x1b[38;5;${code}m`;
149
205
  }
206
+ function rgbToAnsiTrueColor(r, g, b) {
207
+ const rr = Math.max(0, Math.min(255, Math.round(r)));
208
+ const gg = Math.max(0, Math.min(255, Math.round(g)));
209
+ const bb = Math.max(0, Math.min(255, Math.round(b)));
210
+ return `\x1b[38;2;${rr};${gg};${bb}m`;
211
+ }
150
212
  /**
151
213
  * Interpolate between two RGB colors
152
214
  */
@@ -171,11 +233,16 @@ function createGradient(startColor, endColor, steps) {
171
233
  return [startColor];
172
234
  const start = parseColorToRGB(startColor);
173
235
  const end = parseColorToRGB(endColor);
236
+ const startMode = detectColorMode(startColor);
237
+ const endMode = detectColorMode(endColor);
238
+ const outputMode = startMode === 'truecolor' && endMode === 'truecolor' ? 'truecolor' : 'ansi256';
174
239
  const gradient = [];
175
240
  for (let i = 0; i < steps; i++) {
176
241
  const factor = i / (steps - 1);
177
242
  const rgb = interpolateRGB(start, end, factor);
178
- gradient.push(rgbToAnsi256(rgb.r, rgb.g, rgb.b));
243
+ gradient.push(outputMode === 'truecolor'
244
+ ? rgbToAnsiTrueColor(rgb.r, rgb.g, rgb.b)
245
+ : rgbToAnsi256(rgb.r, rgb.g, rgb.b));
179
246
  }
180
247
  return gradient;
181
248
  }
@@ -69,14 +69,23 @@ function renderOption(text, isSelected, isHighlighted, prefix) {
69
69
  const parts = text.split(' - ');
70
70
  const mainText = parts[0];
71
71
  const description = parts.length > 1 ? parts.slice(1).join(' - ') : '';
72
+ const hasHighlightBlock = Boolean(colors_js_1.uiColors.highlightBg);
73
+ const blockLead = hasHighlightBlock ? ' ' : '';
72
74
  if (isHighlighted) {
73
- line += `${colors_js_1.uiColors.primary}${colors_js_1.colors.bold}${mainText}${colors_js_1.colors.reset}`;
74
- if (description) {
75
- line += ` ${colors_js_1.uiColors.textSecondary}- ${description}${colors_js_1.colors.reset}`;
75
+ if (hasHighlightBlock) {
76
+ const highlightText = colors_js_1.uiColors.highlightText || colors_js_1.uiColors.textPrimary;
77
+ const mergedText = description ? `${mainText} - ${description}` : mainText;
78
+ line += `${colors_js_1.uiColors.highlightBg}${highlightText}${colors_js_1.colors.bold}${blockLead}${mergedText} ${colors_js_1.colors.reset}`;
79
+ }
80
+ else {
81
+ line += `${colors_js_1.uiColors.primary}${colors_js_1.colors.bold}${mainText}${colors_js_1.colors.reset}`;
82
+ if (description) {
83
+ line += ` ${colors_js_1.uiColors.textSecondary}- ${description}${colors_js_1.colors.reset}`;
84
+ }
76
85
  }
77
86
  }
78
87
  else {
79
- line += `${colors_js_1.colors.bold}${mainText}${colors_js_1.colors.reset}`;
88
+ line += `${colors_js_1.uiColors.textPrimary}${colors_js_1.colors.bold}${blockLead}${mainText}${colors_js_1.colors.reset}`;
80
89
  if (description) {
81
90
  line += ` ${colors_js_1.uiColors.textSecondary}- ${description}${colors_js_1.colors.reset}`;
82
91
  }
@@ -90,12 +99,12 @@ function renderOption(text, isSelected, isHighlighted, prefix) {
90
99
  * @param showCursor - Whether to show cursor
91
100
  */
92
101
  function renderInputPrompt(prompt, value, showCursor = false) {
93
- let line = ` ${prompt} `;
102
+ let line = ` ${colors_js_1.uiColors.textPrimary}${prompt}${colors_js_1.colors.reset} `;
94
103
  if (value) {
95
- line += `${colors_js_1.colors.cyan}${value}${colors_js_1.colors.reset}`;
104
+ line += `${colors_js_1.uiColors.primary}${value}${colors_js_1.colors.reset}`;
96
105
  }
97
106
  if (showCursor) {
98
- line += `${colors_js_1.colors.cyan}_${colors_js_1.colors.reset}`;
107
+ line += `${colors_js_1.uiColors.primary}_${colors_js_1.colors.reset}`;
99
108
  }
100
109
  (0, terminal_js_1.writeLine)(line);
101
110
  }
@@ -160,8 +169,7 @@ function renderSectionLabel(label, width = 30, align = 'center') {
160
169
  dashesRight = dashesTotal - dashesLeft;
161
170
  break;
162
171
  }
163
- // Use primary color (cyan) and bold for phase labels
164
- const line = ` ${colors_js_1.colors.cyan}${colors_js_1.colors.bold}${'─'.repeat(dashesLeft)}${labelWithPadding}${'─'.repeat(dashesRight)}${colors_js_1.colors.reset}`;
172
+ const line = ` ${colors_js_1.uiColors.primary}${colors_js_1.colors.bold}${'─'.repeat(dashesLeft)}${labelWithPadding}${'─'.repeat(dashesRight)}${colors_js_1.colors.reset}`;
165
173
  (0, terminal_js_1.writeLine)(line);
166
174
  }
167
175
  else {
@@ -179,23 +187,23 @@ function renderMessage(type, message) {
179
187
  switch (type) {
180
188
  case 'success':
181
189
  icon = '✓';
182
- color = colors_js_1.colors.green;
190
+ color = colors_js_1.uiColors.success;
183
191
  break;
184
192
  case 'error':
185
193
  icon = '✗';
186
- color = colors_js_1.colors.red;
194
+ color = colors_js_1.uiColors.error;
187
195
  break;
188
196
  case 'warning':
189
197
  icon = '⚠';
190
- color = colors_js_1.colors.yellow;
198
+ color = colors_js_1.uiColors.warning;
191
199
  break;
192
200
  case 'info':
193
201
  icon = 'ℹ';
194
- color = colors_js_1.colors.blue;
202
+ color = colors_js_1.uiColors.info;
195
203
  break;
196
204
  case 'question':
197
205
  icon = '?';
198
- color = colors_js_1.colors.yellow;
206
+ color = colors_js_1.uiColors.warning;
199
207
  break;
200
208
  }
201
209
  (0, terminal_js_1.writeLine)(`${color}${icon}${colors_js_1.colors.reset} ${message}`);
@@ -209,16 +217,16 @@ function renderProgress(steps, currentStep) {
209
217
  const parts = [];
210
218
  steps.forEach((step, index) => {
211
219
  if (index === currentStep) {
212
- parts.push(`${colors_js_1.colors.cyan}${step}${colors_js_1.colors.reset}`);
220
+ parts.push(`${colors_js_1.uiColors.primary}${step}${colors_js_1.colors.reset}`);
213
221
  }
214
222
  else if (index < currentStep) {
215
- parts.push(step);
223
+ parts.push(`${colors_js_1.uiColors.textPrimary}${step}${colors_js_1.colors.reset}`);
216
224
  }
217
225
  else {
218
- parts.push(`${colors_js_1.colors.dim}${step}${colors_js_1.colors.reset}`);
226
+ parts.push(`${colors_js_1.uiColors.textSecondary}${step}${colors_js_1.colors.reset}`);
219
227
  }
220
228
  });
221
- (0, terminal_js_1.writeLine)(` ${parts.join(` ${colors_js_1.colors.dim}→${colors_js_1.colors.reset} `)}`);
229
+ (0, terminal_js_1.writeLine)(` ${parts.join(` ${colors_js_1.uiColors.textSecondary}→${colors_js_1.colors.reset} `)}`);
222
230
  }
223
231
  /**
224
232
  * Render a box with content
@@ -11,6 +11,19 @@ export interface TerminalState {
11
11
  isRawMode: boolean;
12
12
  useAltScreen: boolean;
13
13
  }
14
+ /**
15
+ * Remove ANSI escape sequences from a string.
16
+ * This is required when calculating the visible width in terminal cells.
17
+ */
18
+ export declare function stripAnsi(text: string): string;
19
+ /**
20
+ * Calculate the visible width of a string in terminal cells.
21
+ */
22
+ export declare function getDisplayWidth(text: string): number;
23
+ /**
24
+ * Count how many visual rows the text occupies after terminal wrapping.
25
+ */
26
+ export declare function countVisualLines(text: string, terminalWidth?: number): number;
14
27
  /**
15
28
  * Initialize terminal for interactive mode
16
29
  * @param useAltScreen - Whether to use alternate screen buffer (prevents scroll issues)