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
package/dist/page-layout.d.ts
CHANGED
|
@@ -10,14 +10,34 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export interface HeaderConfig {
|
|
12
12
|
type: 'simple' | 'section' | 'full' | 'none';
|
|
13
|
+
topBlankLines?: number;
|
|
13
14
|
text?: string;
|
|
14
15
|
width?: number;
|
|
15
16
|
asciiArt?: string[];
|
|
17
|
+
figletText?: string;
|
|
18
|
+
figletFont?: string;
|
|
19
|
+
figletSize?: 'small' | 'medium' | 'large';
|
|
20
|
+
figletScale?: number;
|
|
21
|
+
boxWidth?: number;
|
|
22
|
+
showBoxBorder?: boolean;
|
|
23
|
+
fillBox?: boolean;
|
|
24
|
+
fillBoxColor?: string;
|
|
25
|
+
fillBoxGradientStart?: string;
|
|
26
|
+
fillBoxGradientEnd?: string;
|
|
16
27
|
title?: string;
|
|
28
|
+
titleColor?: string;
|
|
29
|
+
titleGradientStart?: string;
|
|
30
|
+
titleGradientEnd?: string;
|
|
17
31
|
description?: string;
|
|
32
|
+
descriptionColor?: string;
|
|
33
|
+
descriptionGradientStart?: string;
|
|
34
|
+
descriptionGradientEnd?: string;
|
|
35
|
+
asciiArtColor?: string;
|
|
18
36
|
version?: string;
|
|
19
37
|
url?: string;
|
|
20
38
|
menuTitle?: string;
|
|
39
|
+
asciiArtGradientStart?: string;
|
|
40
|
+
asciiArtGradientEnd?: string;
|
|
21
41
|
}
|
|
22
42
|
/**
|
|
23
43
|
* Main Area configuration
|
|
@@ -29,6 +49,8 @@ export interface MainAreaConfig {
|
|
|
29
49
|
allowLetterKeys?: boolean;
|
|
30
50
|
allowNumberKeys?: boolean;
|
|
31
51
|
preserveOnSelect?: boolean;
|
|
52
|
+
preserveOnExit?: boolean;
|
|
53
|
+
onExit?: () => void;
|
|
32
54
|
};
|
|
33
55
|
render?: () => void | Promise<void>;
|
|
34
56
|
}
|
|
@@ -41,16 +63,25 @@ export interface FooterConfig {
|
|
|
41
63
|
allowLetterKeys?: boolean;
|
|
42
64
|
allowNumberKeys?: boolean;
|
|
43
65
|
preserveOnSelect?: boolean;
|
|
66
|
+
preserveOnExit?: boolean;
|
|
67
|
+
onExit?: () => void;
|
|
44
68
|
};
|
|
45
69
|
ask?: {
|
|
46
70
|
question: string;
|
|
71
|
+
helperText?: string;
|
|
47
72
|
defaultValue?: boolean;
|
|
48
73
|
horizontal?: boolean;
|
|
74
|
+
preserveOnSelect?: boolean;
|
|
75
|
+
preserveOnExit?: boolean;
|
|
76
|
+
onExit?: () => void;
|
|
49
77
|
};
|
|
50
78
|
input?: {
|
|
51
79
|
prompt: string;
|
|
52
80
|
defaultValue?: string;
|
|
53
81
|
allowEmpty?: boolean;
|
|
82
|
+
lang?: 'zh' | 'en';
|
|
83
|
+
preserveOnExit?: boolean;
|
|
84
|
+
onExit?: () => void;
|
|
54
85
|
};
|
|
55
86
|
hints?: string[];
|
|
56
87
|
}
|
package/dist/page-layout.js
CHANGED
|
@@ -18,6 +18,10 @@ function renderHeaderSection(config) {
|
|
|
18
18
|
if (!config || config.type === 'none') {
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
+
const topBlankLines = Math.max(0, config.topBlankLines ?? 0);
|
|
22
|
+
for (let i = 0; i < topBlankLines; i += 1) {
|
|
23
|
+
console.log('');
|
|
24
|
+
}
|
|
21
25
|
if (config.type === 'simple' && config.text) {
|
|
22
26
|
(0, headers_js_1.renderSimpleHeader)(config.text);
|
|
23
27
|
}
|
|
@@ -30,11 +34,30 @@ function renderHeaderSection(config) {
|
|
|
30
34
|
// Render full header WITHOUT menuTitle
|
|
31
35
|
(0, header_js_1.renderHeader)({
|
|
32
36
|
asciiArt: config.asciiArt || [],
|
|
37
|
+
figletText: config.figletText,
|
|
38
|
+
figletFont: config.figletFont,
|
|
39
|
+
figletSize: config.figletSize,
|
|
40
|
+
figletScale: config.figletScale,
|
|
33
41
|
title: config.title || '',
|
|
42
|
+
titleColor: config.titleColor,
|
|
43
|
+
titleGradientStart: config.titleGradientStart,
|
|
44
|
+
titleGradientEnd: config.titleGradientEnd,
|
|
34
45
|
description: config.description,
|
|
46
|
+
descriptionColor: config.descriptionColor,
|
|
47
|
+
descriptionGradientStart: config.descriptionGradientStart,
|
|
48
|
+
descriptionGradientEnd: config.descriptionGradientEnd,
|
|
35
49
|
version: config.version,
|
|
36
50
|
url: config.url,
|
|
37
|
-
menuTitle: undefined // Don't render menuTitle in header
|
|
51
|
+
menuTitle: undefined, // Don't render menuTitle in header
|
|
52
|
+
boxWidth: config.boxWidth,
|
|
53
|
+
showBoxBorder: config.showBoxBorder,
|
|
54
|
+
fillBox: config.fillBox,
|
|
55
|
+
fillBoxColor: config.fillBoxColor,
|
|
56
|
+
fillBoxGradientStart: config.fillBoxGradientStart,
|
|
57
|
+
fillBoxGradientEnd: config.fillBoxGradientEnd,
|
|
58
|
+
asciiArtGradientStart: config.asciiArtGradientStart,
|
|
59
|
+
asciiArtGradientEnd: config.asciiArtGradientEnd,
|
|
60
|
+
asciiArtColor: config.asciiArtColor
|
|
38
61
|
});
|
|
39
62
|
}
|
|
40
63
|
}
|
|
@@ -57,7 +80,9 @@ async function renderMainArea(config, hints) {
|
|
|
57
80
|
options: config.menu.options,
|
|
58
81
|
allowLetterKeys: config.menu.allowLetterKeys ?? true,
|
|
59
82
|
allowNumberKeys: config.menu.allowNumberKeys ?? true,
|
|
60
|
-
preserveOnSelect: config.menu.preserveOnSelect ?? true
|
|
83
|
+
preserveOnSelect: config.menu.preserveOnSelect ?? true,
|
|
84
|
+
preserveOnExit: config.menu.preserveOnExit ?? config.menu.preserveOnSelect ?? false,
|
|
85
|
+
onExit: config.menu.onExit
|
|
61
86
|
}, hints); // Pass hints as second parameter
|
|
62
87
|
return result;
|
|
63
88
|
}
|
|
@@ -82,7 +107,9 @@ async function renderFooterSection(config, hints) {
|
|
|
82
107
|
options: config.menu.options,
|
|
83
108
|
allowLetterKeys: config.menu.allowLetterKeys ?? true,
|
|
84
109
|
allowNumberKeys: config.menu.allowNumberKeys ?? true,
|
|
85
|
-
preserveOnSelect: config.menu.preserveOnSelect ?? true
|
|
110
|
+
preserveOnSelect: config.menu.preserveOnSelect ?? true,
|
|
111
|
+
preserveOnExit: config.menu.preserveOnExit ?? config.menu.preserveOnSelect ?? false,
|
|
112
|
+
onExit: config.menu.onExit
|
|
86
113
|
}, hints || config.hints);
|
|
87
114
|
}
|
|
88
115
|
// 2. Input (if present)
|
|
@@ -90,14 +117,23 @@ async function renderFooterSection(config, hints) {
|
|
|
90
117
|
result = await api_js_1.inputAPI.text({
|
|
91
118
|
prompt: config.input.prompt,
|
|
92
119
|
defaultValue: config.input.defaultValue,
|
|
93
|
-
allowEmpty: config.input.allowEmpty ?? false
|
|
120
|
+
allowEmpty: config.input.allowEmpty ?? false,
|
|
121
|
+
lang: config.input.lang,
|
|
122
|
+
preserveOnExit: config.input.preserveOnExit,
|
|
123
|
+
onExit: config.input.onExit
|
|
94
124
|
});
|
|
95
125
|
}
|
|
96
126
|
// 3. Ask (if present)
|
|
97
127
|
else if (config.ask) {
|
|
98
|
-
const askResult =
|
|
99
|
-
|
|
100
|
-
:
|
|
128
|
+
const askResult = await api_js_1.menuAPI.boolean({
|
|
129
|
+
question: config.ask.question,
|
|
130
|
+
helperText: config.ask.helperText,
|
|
131
|
+
defaultValue: config.ask.defaultValue ?? false,
|
|
132
|
+
orientation: config.ask.horizontal ? 'horizontal' : 'vertical',
|
|
133
|
+
preserveOnSelect: config.ask.preserveOnSelect ?? false,
|
|
134
|
+
preserveOnExit: config.ask.preserveOnExit ?? config.ask.preserveOnSelect ?? false,
|
|
135
|
+
onExit: config.ask.onExit
|
|
136
|
+
});
|
|
101
137
|
result = askResult;
|
|
102
138
|
}
|
|
103
139
|
return result;
|
|
@@ -143,6 +179,9 @@ async function renderPage(config) {
|
|
|
143
179
|
}
|
|
144
180
|
else if (config.mainArea.render) {
|
|
145
181
|
await config.mainArea.render();
|
|
182
|
+
// Add newline after custom render to separate from footer menu
|
|
183
|
+
// This ensures the escape codes from initTerminal don't interfere
|
|
184
|
+
console.log('');
|
|
146
185
|
}
|
|
147
186
|
// Render footer with hints
|
|
148
187
|
const footerResult = await renderFooterSection(config.footer, config.footer.hints);
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* Base input configuration
|
|
6
6
|
*/
|
|
7
7
|
export interface BaseInputConfig {
|
|
8
|
+
/** UI language (default: current i18n language) */
|
|
9
|
+
lang?: 'zh' | 'en';
|
|
8
10
|
/** Input prompt text */
|
|
9
11
|
prompt: string;
|
|
10
12
|
/** Default value */
|
|
@@ -15,6 +17,8 @@ export interface BaseInputConfig {
|
|
|
15
17
|
errorMessage?: string;
|
|
16
18
|
/** Goodbye message function */
|
|
17
19
|
onExit?: () => void;
|
|
20
|
+
/** Keep current input rendered on Ctrl+C exit instead of clearing (default: false) */
|
|
21
|
+
preserveOnExit?: boolean;
|
|
18
22
|
}
|
|
19
23
|
/**
|
|
20
24
|
* Text input configuration
|
|
@@ -58,6 +62,8 @@ export interface LanguageSelectorConfig {
|
|
|
58
62
|
prompt?: string;
|
|
59
63
|
/** Goodbye message function */
|
|
60
64
|
onExit?: () => void;
|
|
65
|
+
/** Keep current selector rendered on Ctrl+C exit instead of clearing (default: false) */
|
|
66
|
+
preserveOnExit?: boolean;
|
|
61
67
|
}
|
|
62
68
|
/**
|
|
63
69
|
* Modify field configuration
|
|
@@ -75,6 +81,8 @@ export interface ModifyFieldConfig {
|
|
|
75
81
|
validate?: (value: string) => boolean | string;
|
|
76
82
|
/** Goodbye message function */
|
|
77
83
|
onExit?: () => void;
|
|
84
|
+
/** Keep current prompt rendered on Ctrl+C exit instead of clearing (default: false) */
|
|
85
|
+
preserveOnExit?: boolean;
|
|
78
86
|
}
|
|
79
87
|
/**
|
|
80
88
|
* Input result types
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout system types for CLI Menu Kit
|
|
3
|
+
* Defines how components are composed and rendered
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Layout element types that can be arranged
|
|
7
|
+
*/
|
|
8
|
+
export type LayoutElement = 'header' | 'options' | 'input' | 'hints' | 'progress';
|
|
9
|
+
/**
|
|
10
|
+
* Visibility configuration for layout elements
|
|
11
|
+
*/
|
|
12
|
+
export interface LayoutVisibility {
|
|
13
|
+
header?: boolean;
|
|
14
|
+
input?: boolean;
|
|
15
|
+
hints?: boolean;
|
|
16
|
+
progress?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Spacing configuration for layout elements
|
|
20
|
+
* Values represent number of blank lines
|
|
21
|
+
*/
|
|
22
|
+
export interface LayoutSpacing {
|
|
23
|
+
beforeHeader?: number;
|
|
24
|
+
afterHeader?: number;
|
|
25
|
+
beforeOptions?: number;
|
|
26
|
+
afterOptions?: number;
|
|
27
|
+
beforeInput?: number;
|
|
28
|
+
afterInput?: number;
|
|
29
|
+
beforeHints?: number;
|
|
30
|
+
beforeProgress?: number;
|
|
31
|
+
afterProgress?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Complete menu layout configuration
|
|
35
|
+
*/
|
|
36
|
+
export interface MenuLayout {
|
|
37
|
+
/** Order in which elements are rendered */
|
|
38
|
+
order: LayoutElement[];
|
|
39
|
+
/** Which elements are visible */
|
|
40
|
+
visible: LayoutVisibility;
|
|
41
|
+
/** Spacing between elements */
|
|
42
|
+
spacing?: LayoutSpacing;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Preset layout configurations
|
|
46
|
+
*/
|
|
47
|
+
export declare const LAYOUT_PRESETS: {
|
|
48
|
+
/** Main menu with header */
|
|
49
|
+
MAIN_MENU: MenuLayout;
|
|
50
|
+
/** Sub menu without header */
|
|
51
|
+
SUB_MENU: MenuLayout;
|
|
52
|
+
/** Wizard step with progress indicator */
|
|
53
|
+
WIZARD_STEP: MenuLayout;
|
|
54
|
+
/** Minimal layout (options only) */
|
|
55
|
+
MINIMAL: MenuLayout;
|
|
56
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Layout system types for CLI Menu Kit
|
|
4
|
+
* Defines how components are composed and rendered
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.LAYOUT_PRESETS = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Preset layout configurations
|
|
10
|
+
*/
|
|
11
|
+
exports.LAYOUT_PRESETS = {
|
|
12
|
+
/** Main menu with header */
|
|
13
|
+
MAIN_MENU: {
|
|
14
|
+
order: ['header', 'options', 'input', 'hints'],
|
|
15
|
+
visible: { header: true, input: true, hints: true },
|
|
16
|
+
spacing: { afterHeader: 1, afterOptions: 1, beforeHints: 1 }
|
|
17
|
+
},
|
|
18
|
+
/** Sub menu without header */
|
|
19
|
+
SUB_MENU: {
|
|
20
|
+
order: ['options', 'input', 'hints'],
|
|
21
|
+
visible: { header: false, input: true, hints: true },
|
|
22
|
+
spacing: { afterOptions: 1, beforeHints: 1 }
|
|
23
|
+
},
|
|
24
|
+
/** Wizard step with progress indicator */
|
|
25
|
+
WIZARD_STEP: {
|
|
26
|
+
order: ['header', 'progress', 'options', 'input', 'hints'],
|
|
27
|
+
visible: { header: true, progress: true, input: true, hints: true },
|
|
28
|
+
spacing: { afterHeader: 1, afterProgress: 1, afterOptions: 1, beforeHints: 1 }
|
|
29
|
+
},
|
|
30
|
+
/** Minimal layout (options only) */
|
|
31
|
+
MINIMAL: {
|
|
32
|
+
order: ['options'],
|
|
33
|
+
visible: { header: false, input: false, hints: false },
|
|
34
|
+
spacing: {}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -27,6 +27,8 @@ export interface BaseMenuConfig {
|
|
|
27
27
|
separatorWidth?: number;
|
|
28
28
|
/** Keep menu rendered after selection instead of clearing (default: false) */
|
|
29
29
|
preserveOnSelect?: boolean;
|
|
30
|
+
/** Keep current menu rendered on Ctrl+C exit instead of clearing (default: false) */
|
|
31
|
+
preserveOnExit?: boolean;
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
32
34
|
* Radio menu (single-select) configuration
|
|
@@ -64,6 +66,8 @@ export interface CheckboxMenuConfig extends BaseMenuConfig {
|
|
|
64
66
|
export interface BooleanMenuConfig extends BaseMenuConfig {
|
|
65
67
|
/** Question text */
|
|
66
68
|
question: string;
|
|
69
|
+
/** Optional helper text rendered on the next line */
|
|
70
|
+
helperText?: string;
|
|
67
71
|
/** Default value */
|
|
68
72
|
defaultValue?: boolean;
|
|
69
73
|
/** Yes text */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cli-menu-kit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "A lightweight, customizable CLI menu system with keyboard shortcuts and real-time rendering",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -31,5 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=14.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"figlet": "^1.10.0"
|
|
34
37
|
}
|
|
35
38
|
}
|