cli-menu-kit 0.1.17 → 0.1.19
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.
|
@@ -14,18 +14,18 @@ const colors_js_1 = require("../../core/colors.js");
|
|
|
14
14
|
* @returns Promise resolving to boolean result
|
|
15
15
|
*/
|
|
16
16
|
async function showBooleanMenu(config) {
|
|
17
|
-
const { question, defaultValue = true, yesText = '是', noText = '否', orientation = 'horizontal', onExit } = config;
|
|
17
|
+
const { question, defaultValue = true, yesText = '是', noText = '否', orientation = 'horizontal', onExit, preserveOnSelect = false } = config;
|
|
18
18
|
if (orientation === 'horizontal') {
|
|
19
|
-
return showBooleanMenuHorizontal(question, defaultValue, yesText, noText, onExit);
|
|
19
|
+
return showBooleanMenuHorizontal(question, defaultValue, yesText, noText, onExit, preserveOnSelect);
|
|
20
20
|
}
|
|
21
21
|
else {
|
|
22
|
-
return showBooleanMenuVertical(question, defaultValue, yesText, noText, onExit);
|
|
22
|
+
return showBooleanMenuVertical(question, defaultValue, yesText, noText, onExit, preserveOnSelect);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Show horizontal boolean menu (side by side)
|
|
27
27
|
*/
|
|
28
|
-
async function showBooleanMenuHorizontal(question, defaultValue, yesText, noText, onExit) {
|
|
28
|
+
async function showBooleanMenuHorizontal(question, defaultValue, yesText, noText, onExit, preserveOnSelect = false) {
|
|
29
29
|
const state = (0, terminal_js_1.initTerminal)();
|
|
30
30
|
let selected = defaultValue;
|
|
31
31
|
const render = () => {
|
|
@@ -61,7 +61,9 @@ async function showBooleanMenuHorizontal(question, defaultValue, yesText, noText
|
|
|
61
61
|
// Handle Enter
|
|
62
62
|
if ((0, keyboard_js_1.isEnter)(key)) {
|
|
63
63
|
state.stdin.removeListener('data', onData);
|
|
64
|
-
|
|
64
|
+
if (!preserveOnSelect) {
|
|
65
|
+
(0, terminal_js_1.clearMenu)(state);
|
|
66
|
+
}
|
|
65
67
|
(0, terminal_js_1.restoreTerminal)(state);
|
|
66
68
|
resolve(selected);
|
|
67
69
|
return;
|
|
@@ -96,7 +98,7 @@ async function showBooleanMenuHorizontal(question, defaultValue, yesText, noText
|
|
|
96
98
|
/**
|
|
97
99
|
* Show vertical boolean menu (stacked)
|
|
98
100
|
*/
|
|
99
|
-
async function showBooleanMenuVertical(question, defaultValue, yesText, noText, onExit) {
|
|
101
|
+
async function showBooleanMenuVertical(question, defaultValue, yesText, noText, onExit, preserveOnSelect = false) {
|
|
100
102
|
const state = (0, terminal_js_1.initTerminal)();
|
|
101
103
|
let selected = defaultValue;
|
|
102
104
|
const render = () => {
|
|
@@ -135,7 +137,9 @@ async function showBooleanMenuVertical(question, defaultValue, yesText, noText,
|
|
|
135
137
|
// Handle Enter
|
|
136
138
|
if ((0, keyboard_js_1.isEnter)(key)) {
|
|
137
139
|
state.stdin.removeListener('data', onData);
|
|
138
|
-
|
|
140
|
+
if (!preserveOnSelect) {
|
|
141
|
+
(0, terminal_js_1.clearMenu)(state);
|
|
142
|
+
}
|
|
139
143
|
(0, terminal_js_1.restoreTerminal)(state);
|
|
140
144
|
resolve(selected);
|
|
141
145
|
return;
|
|
@@ -30,7 +30,7 @@ function generateHints(allowSelectAll, allowInvert) {
|
|
|
30
30
|
* @returns Promise resolving to selected options
|
|
31
31
|
*/
|
|
32
32
|
async function showCheckboxMenu(config) {
|
|
33
|
-
const { options, title, prompt, hints, layout = { ...layout_types_js_1.LAYOUT_PRESETS.SUB_MENU, order: ['input', 'options', 'hints'] }, defaultSelected = [], minSelections = 0, maxSelections, allowSelectAll = true, allowInvert = true, separatorWidth = 30, onExit } = config;
|
|
33
|
+
const { options, title, prompt, hints, layout = { ...layout_types_js_1.LAYOUT_PRESETS.SUB_MENU, order: ['input', 'options', 'hints'] }, defaultSelected = [], minSelections = 0, maxSelections, allowSelectAll = true, allowInvert = true, separatorWidth = 30, onExit, preserveOnSelect = false } = config;
|
|
34
34
|
// Use i18n for default prompt if not provided
|
|
35
35
|
const displayPrompt = prompt || (0, registry_js_1.t)('menus.multiSelectPrompt');
|
|
36
36
|
// Generate hints dynamically if not provided
|
|
@@ -160,7 +160,9 @@ async function showCheckboxMenu(config) {
|
|
|
160
160
|
return;
|
|
161
161
|
}
|
|
162
162
|
state.stdin.removeListener('data', onData);
|
|
163
|
-
|
|
163
|
+
if (!preserveOnSelect) {
|
|
164
|
+
(0, terminal_js_1.clearMenu)(state);
|
|
165
|
+
}
|
|
164
166
|
(0, terminal_js_1.restoreTerminal)(state);
|
|
165
167
|
const indices = Array.from(selected).sort((a, b) => a - b);
|
|
166
168
|
const values = indices.map(i => {
|
|
@@ -12,15 +12,39 @@ const renderer_js_1 = require("../../core/renderer.js");
|
|
|
12
12
|
const colors_js_1 = require("../../core/colors.js");
|
|
13
13
|
const registry_js_1 = require("../../i18n/registry.js");
|
|
14
14
|
/**
|
|
15
|
-
* Generate hints based on menu configuration
|
|
15
|
+
* Generate hints based on menu configuration and actual options
|
|
16
16
|
*/
|
|
17
|
-
function generateHints(allowNumberKeys, allowLetterKeys) {
|
|
18
|
-
const hints = [
|
|
17
|
+
function generateHints(options, allowNumberKeys, allowLetterKeys) {
|
|
18
|
+
const hints = [];
|
|
19
|
+
// Count selectable options
|
|
20
|
+
const selectableCount = options.filter(opt => !(typeof opt === 'object' && 'type' in opt && opt.type === 'separator')).length;
|
|
21
|
+
// Only show arrow hints if there are multiple options
|
|
22
|
+
if (selectableCount > 1) {
|
|
23
|
+
hints.push((0, registry_js_1.t)('hints.arrows'));
|
|
24
|
+
}
|
|
25
|
+
// Check if there are actually number-prefixed options
|
|
19
26
|
if (allowNumberKeys) {
|
|
20
|
-
|
|
27
|
+
const hasNumberOptions = options.some(opt => {
|
|
28
|
+
if (typeof opt === 'string') {
|
|
29
|
+
return /^\d+\./.test(opt);
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
});
|
|
33
|
+
if (hasNumberOptions) {
|
|
34
|
+
hints.push((0, registry_js_1.t)('hints.numbers'));
|
|
35
|
+
}
|
|
21
36
|
}
|
|
37
|
+
// Check if there are actually letter-prefixed options
|
|
22
38
|
if (allowLetterKeys) {
|
|
23
|
-
|
|
39
|
+
const hasLetterOptions = options.some(opt => {
|
|
40
|
+
if (typeof opt === 'string') {
|
|
41
|
+
return /^[a-zA-Z]\./.test(opt);
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
});
|
|
45
|
+
if (hasLetterOptions) {
|
|
46
|
+
hints.push((0, registry_js_1.t)('hints.letters'));
|
|
47
|
+
}
|
|
24
48
|
}
|
|
25
49
|
hints.push((0, registry_js_1.t)('hints.enter'));
|
|
26
50
|
return hints;
|
|
@@ -31,11 +55,11 @@ function generateHints(allowNumberKeys, allowLetterKeys) {
|
|
|
31
55
|
* @returns Promise resolving to selected option
|
|
32
56
|
*/
|
|
33
57
|
async function showRadioMenu(config) {
|
|
34
|
-
const { options, title, prompt, hints, layout = layout_types_js_1.LAYOUT_PRESETS.MAIN_MENU, defaultIndex = 0, allowNumberKeys = true, allowLetterKeys = false, separatorWidth = 30, onExit } = config;
|
|
58
|
+
const { options, title, prompt, hints, layout = layout_types_js_1.LAYOUT_PRESETS.MAIN_MENU, defaultIndex = 0, allowNumberKeys = true, allowLetterKeys = false, separatorWidth = 30, onExit, preserveOnSelect = false } = config;
|
|
35
59
|
// Use i18n for default prompt if not provided
|
|
36
60
|
const displayPrompt = prompt || (0, registry_js_1.t)('menus.selectPrompt');
|
|
37
61
|
// Generate hints dynamically if not provided
|
|
38
|
-
const displayHints = hints || generateHints(allowNumberKeys, allowLetterKeys);
|
|
62
|
+
const displayHints = hints || generateHints(options, allowNumberKeys, allowLetterKeys);
|
|
39
63
|
// Validate options
|
|
40
64
|
if (!options || options.length === 0) {
|
|
41
65
|
throw new Error('RadioMenu requires at least one option');
|
|
@@ -186,7 +210,12 @@ async function showRadioMenu(config) {
|
|
|
186
210
|
// Handle Enter
|
|
187
211
|
if ((0, keyboard_js_1.isEnter)(key)) {
|
|
188
212
|
state.stdin.removeListener('data', onData);
|
|
189
|
-
|
|
213
|
+
if (!preserveOnSelect) {
|
|
214
|
+
(0, terminal_js_1.clearMenu)(state);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
(0, terminal_js_1.writeLine)('');
|
|
218
|
+
}
|
|
190
219
|
(0, terminal_js_1.restoreTerminal)(state);
|
|
191
220
|
const selectedOption = options[selectedIndex];
|
|
192
221
|
let value;
|
|
@@ -30,6 +30,8 @@ export interface BaseMenuConfig {
|
|
|
30
30
|
onExit?: () => void;
|
|
31
31
|
/** Separator width for section labels (default: 30) */
|
|
32
32
|
separatorWidth?: number;
|
|
33
|
+
/** Keep menu rendered after selection instead of clearing (default: false) */
|
|
34
|
+
preserveOnSelect?: boolean;
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* Radio menu (single-select) configuration
|
package/package.json
CHANGED