cli-menu-kit 0.1.0

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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +716 -0
  3. package/dist/api.d.ts +158 -0
  4. package/dist/api.js +128 -0
  5. package/dist/components/display/headers.d.ts +32 -0
  6. package/dist/components/display/headers.js +84 -0
  7. package/dist/components/display/index.d.ts +8 -0
  8. package/dist/components/display/index.js +31 -0
  9. package/dist/components/display/messages.d.ts +41 -0
  10. package/dist/components/display/messages.js +90 -0
  11. package/dist/components/display/progress.d.ts +41 -0
  12. package/dist/components/display/progress.js +82 -0
  13. package/dist/components/display/summary.d.ts +33 -0
  14. package/dist/components/display/summary.js +82 -0
  15. package/dist/components/inputs/index.d.ts +8 -0
  16. package/dist/components/inputs/index.js +15 -0
  17. package/dist/components/inputs/language-input.d.ts +11 -0
  18. package/dist/components/inputs/language-input.js +104 -0
  19. package/dist/components/inputs/modify-field.d.ts +11 -0
  20. package/dist/components/inputs/modify-field.js +42 -0
  21. package/dist/components/inputs/number-input.d.ts +11 -0
  22. package/dist/components/inputs/number-input.js +143 -0
  23. package/dist/components/inputs/text-input.d.ts +11 -0
  24. package/dist/components/inputs/text-input.js +114 -0
  25. package/dist/components/menus/boolean-menu.d.ts +11 -0
  26. package/dist/components/menus/boolean-menu.js +169 -0
  27. package/dist/components/menus/checkbox-menu.d.ts +11 -0
  28. package/dist/components/menus/checkbox-menu.js +161 -0
  29. package/dist/components/menus/index.d.ts +7 -0
  30. package/dist/components/menus/index.js +13 -0
  31. package/dist/components/menus/radio-menu.d.ts +11 -0
  32. package/dist/components/menus/radio-menu.js +158 -0
  33. package/dist/components.d.ts +55 -0
  34. package/dist/components.js +166 -0
  35. package/dist/core/colors.d.ts +64 -0
  36. package/dist/core/colors.js +139 -0
  37. package/dist/core/keyboard.d.ts +124 -0
  38. package/dist/core/keyboard.js +185 -0
  39. package/dist/core/renderer.d.ts +74 -0
  40. package/dist/core/renderer.js +217 -0
  41. package/dist/core/terminal.d.ts +89 -0
  42. package/dist/core/terminal.js +170 -0
  43. package/dist/features/commands.d.ts +57 -0
  44. package/dist/features/commands.js +161 -0
  45. package/dist/features/wizard.d.ts +62 -0
  46. package/dist/features/wizard.js +112 -0
  47. package/dist/i18n/languages/en.d.ts +5 -0
  48. package/dist/i18n/languages/en.js +54 -0
  49. package/dist/i18n/languages/zh.d.ts +5 -0
  50. package/dist/i18n/languages/zh.js +54 -0
  51. package/dist/i18n/registry.d.ts +36 -0
  52. package/dist/i18n/registry.js +82 -0
  53. package/dist/i18n/types.d.ts +65 -0
  54. package/dist/i18n/types.js +5 -0
  55. package/dist/index.d.ts +27 -0
  56. package/dist/index.js +104 -0
  57. package/dist/input.d.ts +40 -0
  58. package/dist/input.js +211 -0
  59. package/dist/menu-core.d.ts +52 -0
  60. package/dist/menu-core.js +201 -0
  61. package/dist/menu-multi.d.ts +21 -0
  62. package/dist/menu-multi.js +119 -0
  63. package/dist/menu-single.d.ts +18 -0
  64. package/dist/menu-single.js +138 -0
  65. package/dist/menu.d.ts +66 -0
  66. package/dist/menu.js +78 -0
  67. package/dist/types/display.types.d.ts +57 -0
  68. package/dist/types/display.types.js +5 -0
  69. package/dist/types/input.types.d.ts +88 -0
  70. package/dist/types/input.types.js +5 -0
  71. package/dist/types/layout.types.d.ts +56 -0
  72. package/dist/types/layout.types.js +36 -0
  73. package/dist/types/menu.types.d.ts +85 -0
  74. package/dist/types/menu.types.js +5 -0
  75. package/dist/types.d.ts +49 -0
  76. package/dist/types.js +5 -0
  77. package/package.json +35 -0
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ /**
3
+ * CLI Menu Kit - UI Components
4
+ * Handles all display-related UI components
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.symbols = exports.theme = exports.colors = void 0;
8
+ exports.formatSection = formatSection;
9
+ exports.buildHint = buildHint;
10
+ exports.showSubMenuTitle = showSubMenuTitle;
11
+ exports.showProgress = showProgress;
12
+ exports.showInfo = showInfo;
13
+ exports.showSuccess = showSuccess;
14
+ exports.showError = showError;
15
+ exports.showWarning = showWarning;
16
+ exports.showGoodbye = showGoodbye;
17
+ exports.printHeader = printHeader;
18
+ // ANSI Colors
19
+ exports.colors = {
20
+ reset: '\x1b[0m',
21
+ red: '\x1b[31m',
22
+ green: '\x1b[32m',
23
+ yellow: '\x1b[33m',
24
+ blue: '\x1b[34m',
25
+ cyan: '\x1b[36m',
26
+ gray: '\x1b[90m',
27
+ };
28
+ // Additional color codes
29
+ const colorCodes = {
30
+ bright: '\x1b[1m',
31
+ dim: '\x1b[2m',
32
+ magenta: '\x1b[35m',
33
+ };
34
+ // Theme colors
35
+ exports.theme = {
36
+ active: `${colorCodes.bright}${exports.colors.cyan}`, // Selected item - bright cyan
37
+ primary: exports.colors.cyan, // Standard - cyan (numbers, separators)
38
+ title: exports.colors.reset, // Title - white (menu titles)
39
+ muted: exports.colors.gray, // Auxiliary - gray (descriptions, hints)
40
+ success: exports.colors.green, // Success - green
41
+ warning: exports.colors.yellow, // Warning - yellow
42
+ error: exports.colors.red, // Error - red
43
+ };
44
+ // Message symbols with colors
45
+ exports.symbols = {
46
+ success: { icon: '✓', color: exports.colors.green },
47
+ error: { icon: 'x', color: exports.colors.red },
48
+ warning: { icon: '!', color: exports.colors.yellow },
49
+ info: { icon: 'ℹ', color: exports.colors.blue },
50
+ };
51
+ /**
52
+ * Format section title with separator
53
+ */
54
+ function formatSection(text) {
55
+ const separator = '─'.repeat(10);
56
+ return `${separator} ${text} ${separator}`;
57
+ }
58
+ /**
59
+ * Build hint text for interactive menus
60
+ */
61
+ function buildHint(keys, lang = 'zh') {
62
+ const hints = {
63
+ zh: {
64
+ arrows: `${exports.colors.reset}↑↓${exports.theme.muted} 方向键`,
65
+ space: `${exports.colors.reset}空格${exports.theme.muted} 选中/取消`,
66
+ number: `${exports.colors.reset}0-9${exports.theme.muted} 输入序号`,
67
+ letter: `${exports.colors.reset}字母${exports.theme.muted} 快捷键`,
68
+ all: `${exports.colors.reset}A${exports.theme.muted} 全选`,
69
+ invert: `${exports.colors.reset}I${exports.theme.muted} 反选`,
70
+ enter: `${exports.colors.reset}⏎${exports.theme.muted} 确认`,
71
+ esc: `${exports.colors.reset}Esc${exports.theme.muted} 退出`,
72
+ },
73
+ en: {
74
+ arrows: `${exports.colors.reset}↑↓${exports.theme.muted} Navigate`,
75
+ space: `${exports.colors.reset}Space${exports.theme.muted} Select`,
76
+ number: `${exports.colors.reset}0-9${exports.theme.muted} Type number`,
77
+ letter: `${exports.colors.reset}Letter${exports.theme.muted} Shortcut`,
78
+ all: `${exports.colors.reset}A${exports.theme.muted} All`,
79
+ invert: `${exports.colors.reset}I${exports.theme.muted} Invert`,
80
+ enter: `${exports.colors.reset}⏎${exports.theme.muted} Submit`,
81
+ esc: `${exports.colors.reset}Esc${exports.theme.muted} Exit`,
82
+ }
83
+ };
84
+ const langHints = hints[lang] || hints.zh;
85
+ const parts = keys.map(key => langHints[key]).filter(Boolean);
86
+ return parts.join(` ${exports.theme.muted}•${exports.colors.reset} `) + exports.colors.reset;
87
+ }
88
+ /**
89
+ * Show submenu title with section format
90
+ */
91
+ function showSubMenuTitle(title, lang, indent = ' ') {
92
+ console.log();
93
+ console.log(`${indent}${exports.theme.primary}${formatSection(title)}${exports.colors.reset}`);
94
+ console.log();
95
+ }
96
+ /**
97
+ * Show progress indicator
98
+ */
99
+ function showProgress(steps, currentStep, lang, indent = ' ') {
100
+ const progress = steps.map((step, index) => {
101
+ if (index <= currentStep) {
102
+ return `${exports.colors.reset}${step}${exports.colors.reset}`;
103
+ }
104
+ else {
105
+ return `${exports.theme.muted}${step}${exports.colors.reset}`;
106
+ }
107
+ }).join(` ${exports.theme.muted}→${exports.colors.reset} `);
108
+ console.log(`${indent}${progress}`);
109
+ console.log();
110
+ }
111
+ /**
112
+ * Show info message
113
+ */
114
+ function showInfo(message, indent = '') {
115
+ console.log(`${indent}${exports.symbols.info.color}${exports.symbols.info.icon} ${message}${exports.colors.reset}`);
116
+ }
117
+ /**
118
+ * Show success message
119
+ */
120
+ function showSuccess(message, indent = '') {
121
+ console.log(`${indent}${exports.symbols.success.color}${exports.symbols.success.icon} ${message}${exports.colors.reset}`);
122
+ }
123
+ /**
124
+ * Show error message
125
+ */
126
+ function showError(message, indent = '') {
127
+ console.log(`${indent}${exports.symbols.error.color}${exports.symbols.error.icon} ${message}${exports.colors.reset}`);
128
+ }
129
+ /**
130
+ * Show warning message
131
+ */
132
+ function showWarning(message, indent = '') {
133
+ console.log(`${indent}${exports.symbols.warning.color}${exports.symbols.warning.icon} ${message}${exports.colors.reset}`);
134
+ }
135
+ /**
136
+ * Show goodbye message
137
+ */
138
+ function showGoodbye(lang = 'zh') {
139
+ console.log('\n');
140
+ const message = lang === 'zh'
141
+ ? '👋 感谢使用,再见!'
142
+ : '👋 Thank you for using CLI Menu Kit. Goodbye!';
143
+ console.log(`${exports.theme.active}${message}${exports.colors.reset}`);
144
+ console.log();
145
+ }
146
+ function printHeader(options) {
147
+ const { asciiArt, title, subtitle, version, github } = options;
148
+ const indent = ' ';
149
+ console.log(`${exports.theme.primary}${'═'.repeat(71)}${exports.colors.reset}`);
150
+ console.log();
151
+ asciiArt.forEach(line => {
152
+ console.log(`${indent}${exports.theme.active}${line}${exports.colors.reset}`);
153
+ });
154
+ console.log();
155
+ console.log(`${indent}${colorCodes.bright}${title}${exports.colors.reset}${subtitle ? ` ${exports.theme.muted}${subtitle}${exports.colors.reset}` : ''}`);
156
+ console.log();
157
+ console.log(`${exports.theme.primary}${'═'.repeat(71)}${exports.colors.reset}`);
158
+ console.log();
159
+ if (version || github) {
160
+ const versionText = version ? `${exports.theme.muted}Version: ${exports.colors.reset}${exports.theme.primary}${version}${exports.colors.reset}` : '';
161
+ const githubText = github ? `${exports.theme.primary}${github}${exports.colors.reset}` : '';
162
+ const separator = version && github ? ` ${exports.theme.muted}|${exports.colors.reset} ` : '';
163
+ console.log(`${indent}${versionText}${separator}${githubText}`);
164
+ console.log();
165
+ }
166
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Color system for CLI Menu Kit
3
+ * Supports single colors and two-color gradients
4
+ */
5
+ /**
6
+ * ANSI color codes
7
+ */
8
+ export declare const colors: {
9
+ readonly reset: "\u001B[0m";
10
+ readonly black: "\u001B[30m";
11
+ readonly red: "\u001B[31m";
12
+ readonly green: "\u001B[32m";
13
+ readonly yellow: "\u001B[33m";
14
+ readonly blue: "\u001B[34m";
15
+ readonly magenta: "\u001B[35m";
16
+ readonly cyan: "\u001B[36m";
17
+ readonly white: "\u001B[37m";
18
+ readonly brightBlack: "\u001B[90m";
19
+ readonly brightRed: "\u001B[91m";
20
+ readonly brightGreen: "\u001B[92m";
21
+ readonly brightYellow: "\u001B[93m";
22
+ readonly brightBlue: "\u001B[94m";
23
+ readonly brightMagenta: "\u001B[95m";
24
+ readonly brightCyan: "\u001B[96m";
25
+ readonly brightWhite: "\u001B[97m";
26
+ readonly bgBlack: "\u001B[40m";
27
+ readonly bgRed: "\u001B[41m";
28
+ readonly bgGreen: "\u001B[42m";
29
+ readonly bgYellow: "\u001B[43m";
30
+ readonly bgBlue: "\u001B[44m";
31
+ readonly bgMagenta: "\u001B[45m";
32
+ readonly bgCyan: "\u001B[46m";
33
+ readonly bgWhite: "\u001B[47m";
34
+ readonly bold: "\u001B[1m";
35
+ readonly dim: "\u001B[2m";
36
+ readonly italic: "\u001B[3m";
37
+ readonly underline: "\u001B[4m";
38
+ readonly inverse: "\u001B[7m";
39
+ readonly hidden: "\u001B[8m";
40
+ readonly strikethrough: "\u001B[9m";
41
+ };
42
+ /**
43
+ * Create a gradient between two colors
44
+ * @param startColor - Starting ANSI color code
45
+ * @param endColor - Ending ANSI color code
46
+ * @param steps - Number of steps in the gradient
47
+ * @returns Array of ANSI color codes for each step
48
+ */
49
+ export declare function createGradient(startColor: string, endColor: string, steps: number): string[];
50
+ /**
51
+ * Apply gradient to text
52
+ * @param text - Text to colorize
53
+ * @param startColor - Starting color
54
+ * @param endColor - Ending color
55
+ * @returns Colorized text with gradient
56
+ */
57
+ export declare function applyGradient(text: string, startColor: string, endColor: string): string;
58
+ /**
59
+ * Apply single color to text
60
+ * @param text - Text to colorize
61
+ * @param color - ANSI color code
62
+ * @returns Colorized text
63
+ */
64
+ export declare function colorize(text: string, color: string): string;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ /**
3
+ * Color system for CLI Menu Kit
4
+ * Supports single colors and two-color gradients
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.colors = void 0;
8
+ exports.createGradient = createGradient;
9
+ exports.applyGradient = applyGradient;
10
+ exports.colorize = colorize;
11
+ /**
12
+ * ANSI color codes
13
+ */
14
+ exports.colors = {
15
+ // Reset
16
+ reset: '\x1b[0m',
17
+ // Basic colors
18
+ black: '\x1b[30m',
19
+ red: '\x1b[31m',
20
+ green: '\x1b[32m',
21
+ yellow: '\x1b[33m',
22
+ blue: '\x1b[34m',
23
+ magenta: '\x1b[35m',
24
+ cyan: '\x1b[36m',
25
+ white: '\x1b[37m',
26
+ // Bright colors
27
+ brightBlack: '\x1b[90m',
28
+ brightRed: '\x1b[91m',
29
+ brightGreen: '\x1b[92m',
30
+ brightYellow: '\x1b[93m',
31
+ brightBlue: '\x1b[94m',
32
+ brightMagenta: '\x1b[95m',
33
+ brightCyan: '\x1b[96m',
34
+ brightWhite: '\x1b[97m',
35
+ // Background colors
36
+ bgBlack: '\x1b[40m',
37
+ bgRed: '\x1b[41m',
38
+ bgGreen: '\x1b[42m',
39
+ bgYellow: '\x1b[43m',
40
+ bgBlue: '\x1b[44m',
41
+ bgMagenta: '\x1b[45m',
42
+ bgCyan: '\x1b[46m',
43
+ bgWhite: '\x1b[47m',
44
+ // Styles
45
+ bold: '\x1b[1m',
46
+ dim: '\x1b[2m',
47
+ italic: '\x1b[3m',
48
+ underline: '\x1b[4m',
49
+ inverse: '\x1b[7m',
50
+ hidden: '\x1b[8m',
51
+ strikethrough: '\x1b[9m'
52
+ };
53
+ /**
54
+ * Parse ANSI color code to RGB values
55
+ * Supports basic 8 colors and bright variants
56
+ */
57
+ function parseColorToRGB(colorCode) {
58
+ // Map of ANSI codes to approximate RGB values
59
+ const colorMap = {
60
+ '\x1b[30m': { r: 0, g: 0, b: 0 }, // black
61
+ '\x1b[31m': { r: 170, g: 0, b: 0 }, // red
62
+ '\x1b[32m': { r: 0, g: 170, b: 0 }, // green
63
+ '\x1b[33m': { r: 170, g: 85, b: 0 }, // yellow
64
+ '\x1b[34m': { r: 0, g: 0, b: 170 }, // blue
65
+ '\x1b[35m': { r: 170, g: 0, b: 170 }, // magenta
66
+ '\x1b[36m': { r: 0, g: 170, b: 170 }, // cyan
67
+ '\x1b[37m': { r: 170, g: 170, b: 170 }, // white
68
+ '\x1b[90m': { r: 85, g: 85, b: 85 }, // bright black
69
+ '\x1b[91m': { r: 255, g: 85, b: 85 }, // bright red
70
+ '\x1b[92m': { r: 85, g: 255, b: 85 }, // bright green
71
+ '\x1b[93m': { r: 255, g: 255, b: 85 }, // bright yellow
72
+ '\x1b[94m': { r: 85, g: 85, b: 255 }, // bright blue
73
+ '\x1b[95m': { r: 255, g: 85, b: 255 }, // bright magenta
74
+ '\x1b[96m': { r: 85, g: 255, b: 255 }, // bright cyan
75
+ '\x1b[97m': { r: 255, g: 255, b: 255 } // bright white
76
+ };
77
+ return colorMap[colorCode] || { r: 170, g: 170, b: 170 };
78
+ }
79
+ /**
80
+ * Convert RGB to ANSI 256-color code
81
+ */
82
+ function rgbToAnsi256(r, g, b) {
83
+ // Use 256-color mode for better gradient quality
84
+ const code = 16 + 36 * Math.round(r / 255 * 5) + 6 * Math.round(g / 255 * 5) + Math.round(b / 255 * 5);
85
+ return `\x1b[38;5;${code}m`;
86
+ }
87
+ /**
88
+ * Interpolate between two RGB colors
89
+ */
90
+ function interpolateRGB(color1, color2, factor) {
91
+ return {
92
+ r: Math.round(color1.r + (color2.r - color1.r) * factor),
93
+ g: Math.round(color1.g + (color2.g - color1.g) * factor),
94
+ b: Math.round(color1.b + (color2.b - color1.b) * factor)
95
+ };
96
+ }
97
+ /**
98
+ * Create a gradient between two colors
99
+ * @param startColor - Starting ANSI color code
100
+ * @param endColor - Ending ANSI color code
101
+ * @param steps - Number of steps in the gradient
102
+ * @returns Array of ANSI color codes for each step
103
+ */
104
+ function createGradient(startColor, endColor, steps) {
105
+ if (steps <= 0)
106
+ return [];
107
+ if (steps === 1)
108
+ return [startColor];
109
+ const start = parseColorToRGB(startColor);
110
+ const end = parseColorToRGB(endColor);
111
+ const gradient = [];
112
+ for (let i = 0; i < steps; i++) {
113
+ const factor = i / (steps - 1);
114
+ const rgb = interpolateRGB(start, end, factor);
115
+ gradient.push(rgbToAnsi256(rgb.r, rgb.g, rgb.b));
116
+ }
117
+ return gradient;
118
+ }
119
+ /**
120
+ * Apply gradient to text
121
+ * @param text - Text to colorize
122
+ * @param startColor - Starting color
123
+ * @param endColor - Ending color
124
+ * @returns Colorized text with gradient
125
+ */
126
+ function applyGradient(text, startColor, endColor) {
127
+ const chars = text.split('');
128
+ const gradient = createGradient(startColor, endColor, chars.length);
129
+ return chars.map((char, i) => `${gradient[i]}${char}`).join('') + exports.colors.reset;
130
+ }
131
+ /**
132
+ * Apply single color to text
133
+ * @param text - Text to colorize
134
+ * @param color - ANSI color code
135
+ * @returns Colorized text
136
+ */
137
+ function colorize(text, color) {
138
+ return `${color}${text}${exports.colors.reset}`;
139
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Keyboard handling utilities for CLI Menu Kit
3
+ * Handles key detection and special key combinations
4
+ */
5
+ /**
6
+ * Key codes for special keys
7
+ */
8
+ export declare const KEY_CODES: {
9
+ readonly UP: "\u001B[A";
10
+ readonly DOWN: "\u001B[B";
11
+ readonly RIGHT: "\u001B[C";
12
+ readonly LEFT: "\u001B[D";
13
+ readonly ENTER: "\r";
14
+ readonly SPACE: " ";
15
+ readonly BACKSPACE: "";
16
+ readonly DELETE: "\u001B[3~";
17
+ readonly ESCAPE: "\u001B";
18
+ readonly TAB: "\t";
19
+ readonly CTRL_C: "\u0003";
20
+ readonly CTRL_D: "\u0004";
21
+ readonly CTRL_Z: "\u001A";
22
+ readonly CTRL_A: "\u0001";
23
+ readonly CTRL_E: "\u0005";
24
+ readonly CTRL_U: "\u0015";
25
+ readonly CTRL_K: "\v";
26
+ readonly CTRL_L: "\f";
27
+ readonly HOME: "\u001B[H";
28
+ readonly END: "\u001B[F";
29
+ };
30
+ /**
31
+ * Check if key is an arrow key
32
+ * @param key - Key input
33
+ * @returns True if arrow key
34
+ */
35
+ export declare function isArrowKey(key: string): boolean;
36
+ /**
37
+ * Check if key is a number key (0-9)
38
+ * @param key - Key input
39
+ * @returns True if number key
40
+ */
41
+ export declare function isNumberKey(key: string): boolean;
42
+ /**
43
+ * Check if key is a letter key (a-z, A-Z)
44
+ * @param key - Key input
45
+ * @returns True if letter key
46
+ */
47
+ export declare function isLetterKey(key: string): boolean;
48
+ /**
49
+ * Check if key is alphanumeric (0-9, a-z, A-Z)
50
+ * @param key - Key input
51
+ * @returns True if alphanumeric
52
+ */
53
+ export declare function isAlphanumeric(key: string): boolean;
54
+ /**
55
+ * Check if key is printable character
56
+ * @param key - Key input
57
+ * @returns True if printable
58
+ */
59
+ export declare function isPrintable(key: string): boolean;
60
+ /**
61
+ * Check if key is Ctrl+C
62
+ * @param key - Key input
63
+ * @returns True if Ctrl+C
64
+ */
65
+ export declare function isCtrlC(key: string): boolean;
66
+ /**
67
+ * Check if key is Enter
68
+ * @param key - Key input
69
+ * @returns True if Enter
70
+ */
71
+ export declare function isEnter(key: string): boolean;
72
+ /**
73
+ * Check if key is Space
74
+ * @param key - Key input
75
+ * @returns True if Space
76
+ */
77
+ export declare function isSpace(key: string): boolean;
78
+ /**
79
+ * Check if key is Backspace
80
+ * @param key - Key input
81
+ * @returns True if Backspace
82
+ */
83
+ export declare function isBackspace(key: string): boolean;
84
+ /**
85
+ * Check if key is Escape
86
+ * @param key - Key input
87
+ * @returns True if Escape
88
+ */
89
+ export declare function isEscape(key: string): boolean;
90
+ /**
91
+ * Parse number from key input
92
+ * @param key - Key input
93
+ * @returns Number or null if not a number
94
+ */
95
+ export declare function parseNumber(key: string): number | null;
96
+ /**
97
+ * Normalize letter key to lowercase
98
+ * @param key - Key input
99
+ * @returns Lowercase letter or original key
100
+ */
101
+ export declare function normalizeLetter(key: string): string;
102
+ /**
103
+ * Check if input is a command (starts with /)
104
+ * @param input - Input string
105
+ * @returns True if command
106
+ */
107
+ export declare function isCommand(input: string): boolean;
108
+ /**
109
+ * Parse command from input
110
+ * @param input - Input string
111
+ * @returns Command name (without /) or null
112
+ */
113
+ export declare function parseCommand(input: string): string | null;
114
+ /**
115
+ * Key event handler type
116
+ */
117
+ export type KeyHandler = (key: string) => void;
118
+ /**
119
+ * Create a keyboard listener
120
+ * @param stdin - Input stream
121
+ * @param handler - Key handler function
122
+ * @returns Cleanup function
123
+ */
124
+ export declare function createKeyboardListener(stdin: NodeJS.ReadStream, handler: KeyHandler): () => void;
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ /**
3
+ * Keyboard handling utilities for CLI Menu Kit
4
+ * Handles key detection and special key combinations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.KEY_CODES = void 0;
8
+ exports.isArrowKey = isArrowKey;
9
+ exports.isNumberKey = isNumberKey;
10
+ exports.isLetterKey = isLetterKey;
11
+ exports.isAlphanumeric = isAlphanumeric;
12
+ exports.isPrintable = isPrintable;
13
+ exports.isCtrlC = isCtrlC;
14
+ exports.isEnter = isEnter;
15
+ exports.isSpace = isSpace;
16
+ exports.isBackspace = isBackspace;
17
+ exports.isEscape = isEscape;
18
+ exports.parseNumber = parseNumber;
19
+ exports.normalizeLetter = normalizeLetter;
20
+ exports.isCommand = isCommand;
21
+ exports.parseCommand = parseCommand;
22
+ exports.createKeyboardListener = createKeyboardListener;
23
+ /**
24
+ * Key codes for special keys
25
+ */
26
+ exports.KEY_CODES = {
27
+ // Arrow keys
28
+ UP: '\x1b[A',
29
+ DOWN: '\x1b[B',
30
+ RIGHT: '\x1b[C',
31
+ LEFT: '\x1b[D',
32
+ // Control keys
33
+ ENTER: '\r',
34
+ SPACE: ' ',
35
+ BACKSPACE: '\x7f',
36
+ DELETE: '\x1b[3~',
37
+ ESCAPE: '\x1b',
38
+ TAB: '\t',
39
+ // Ctrl combinations
40
+ CTRL_C: '\x03',
41
+ CTRL_D: '\x04',
42
+ CTRL_Z: '\x1a',
43
+ CTRL_A: '\x01',
44
+ CTRL_E: '\x05',
45
+ CTRL_U: '\x15',
46
+ CTRL_K: '\x0b',
47
+ CTRL_L: '\x0c',
48
+ // Home/End
49
+ HOME: '\x1b[H',
50
+ END: '\x1b[F'
51
+ };
52
+ /**
53
+ * Check if key is an arrow key
54
+ * @param key - Key input
55
+ * @returns True if arrow key
56
+ */
57
+ function isArrowKey(key) {
58
+ return key === exports.KEY_CODES.UP || key === exports.KEY_CODES.DOWN ||
59
+ key === exports.KEY_CODES.LEFT || key === exports.KEY_CODES.RIGHT;
60
+ }
61
+ /**
62
+ * Check if key is a number key (0-9)
63
+ * @param key - Key input
64
+ * @returns True if number key
65
+ */
66
+ function isNumberKey(key) {
67
+ return /^[0-9]$/.test(key);
68
+ }
69
+ /**
70
+ * Check if key is a letter key (a-z, A-Z)
71
+ * @param key - Key input
72
+ * @returns True if letter key
73
+ */
74
+ function isLetterKey(key) {
75
+ return /^[a-zA-Z]$/.test(key);
76
+ }
77
+ /**
78
+ * Check if key is alphanumeric (0-9, a-z, A-Z)
79
+ * @param key - Key input
80
+ * @returns True if alphanumeric
81
+ */
82
+ function isAlphanumeric(key) {
83
+ return /^[0-9a-zA-Z]$/.test(key);
84
+ }
85
+ /**
86
+ * Check if key is printable character
87
+ * @param key - Key input
88
+ * @returns True if printable
89
+ */
90
+ function isPrintable(key) {
91
+ return key.length === 1 && key >= ' ' && key <= '~';
92
+ }
93
+ /**
94
+ * Check if key is Ctrl+C
95
+ * @param key - Key input
96
+ * @returns True if Ctrl+C
97
+ */
98
+ function isCtrlC(key) {
99
+ return key === exports.KEY_CODES.CTRL_C;
100
+ }
101
+ /**
102
+ * Check if key is Enter
103
+ * @param key - Key input
104
+ * @returns True if Enter
105
+ */
106
+ function isEnter(key) {
107
+ return key === exports.KEY_CODES.ENTER || key === '\n';
108
+ }
109
+ /**
110
+ * Check if key is Space
111
+ * @param key - Key input
112
+ * @returns True if Space
113
+ */
114
+ function isSpace(key) {
115
+ return key === exports.KEY_CODES.SPACE;
116
+ }
117
+ /**
118
+ * Check if key is Backspace
119
+ * @param key - Key input
120
+ * @returns True if Backspace
121
+ */
122
+ function isBackspace(key) {
123
+ return key === exports.KEY_CODES.BACKSPACE || key === '\b';
124
+ }
125
+ /**
126
+ * Check if key is Escape
127
+ * @param key - Key input
128
+ * @returns True if Escape
129
+ */
130
+ function isEscape(key) {
131
+ return key === exports.KEY_CODES.ESCAPE;
132
+ }
133
+ /**
134
+ * Parse number from key input
135
+ * @param key - Key input
136
+ * @returns Number or null if not a number
137
+ */
138
+ function parseNumber(key) {
139
+ if (isNumberKey(key)) {
140
+ return parseInt(key, 10);
141
+ }
142
+ return null;
143
+ }
144
+ /**
145
+ * Normalize letter key to lowercase
146
+ * @param key - Key input
147
+ * @returns Lowercase letter or original key
148
+ */
149
+ function normalizeLetter(key) {
150
+ if (isLetterKey(key)) {
151
+ return key.toLowerCase();
152
+ }
153
+ return key;
154
+ }
155
+ /**
156
+ * Check if input is a command (starts with /)
157
+ * @param input - Input string
158
+ * @returns True if command
159
+ */
160
+ function isCommand(input) {
161
+ return input.startsWith('/');
162
+ }
163
+ /**
164
+ * Parse command from input
165
+ * @param input - Input string
166
+ * @returns Command name (without /) or null
167
+ */
168
+ function parseCommand(input) {
169
+ if (isCommand(input)) {
170
+ return input.slice(1).toLowerCase();
171
+ }
172
+ return null;
173
+ }
174
+ /**
175
+ * Create a keyboard listener
176
+ * @param stdin - Input stream
177
+ * @param handler - Key handler function
178
+ * @returns Cleanup function
179
+ */
180
+ function createKeyboardListener(stdin, handler) {
181
+ stdin.on('data', handler);
182
+ return () => {
183
+ stdin.removeListener('data', handler);
184
+ };
185
+ }