@inquirer/select 1.0.3 → 1.1.2
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/README.md +9 -6
- package/dist/cjs/index.js +26 -12
- package/dist/cjs/types/index.d.mts +10 -7
- package/dist/esm/index.mjs +26 -13
- package/dist/esm/types/index.d.mts +10 -7
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ yarn add @inquirer/select
|
|
|
15
15
|
# Usage
|
|
16
16
|
|
|
17
17
|
```js
|
|
18
|
-
import select from '@inquirer/select';
|
|
18
|
+
import select, { Separator } from '@inquirer/select';
|
|
19
19
|
|
|
20
20
|
const answer = await select({
|
|
21
21
|
message: 'Select a package manager',
|
|
@@ -30,6 +30,7 @@ const answer = await select({
|
|
|
30
30
|
value: 'yarn',
|
|
31
31
|
description: 'yarn is an awesome package manager',
|
|
32
32
|
},
|
|
33
|
+
new Separator(),
|
|
33
34
|
{
|
|
34
35
|
name: 'jspm',
|
|
35
36
|
value: 'jspm',
|
|
@@ -46,11 +47,13 @@ const answer = await select({
|
|
|
46
47
|
|
|
47
48
|
## Options
|
|
48
49
|
|
|
49
|
-
| Property | Type
|
|
50
|
-
| -------- |
|
|
51
|
-
| message | `string`
|
|
52
|
-
| choices | `Array<{ value: string, name?: string, description?: string, disabled?: boolean \| string }>` | yes | List of the available choices. The `value` will be returned as the answer, and used as display if no `name` is defined. Choices who're `disabled` will be displayed, but not selectable. The `description` will be displayed under the prompt when the cursor land over the choice. |
|
|
53
|
-
| pageSize | `number`
|
|
50
|
+
| Property | Type | Required | Description |
|
|
51
|
+
| -------- | ---------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
52
|
+
| message | `string` | yes | The question to ask |
|
|
53
|
+
| choices | `Array<{ value: string, name?: string, description?: string, disabled?: boolean \| string } \| Separator>` | yes | List of the available choices. The `value` will be returned as the answer, and used as display if no `name` is defined. Choices who're `disabled` will be displayed, but not selectable. The `description` will be displayed under the prompt when the cursor land over the choice. |
|
|
54
|
+
| pageSize | `number` | no | By default, lists of choice longer than 7 will be paginated. Use this option to control how many choices will appear on the screen at once. |
|
|
55
|
+
|
|
56
|
+
The `Separator` object can be used to render non-selectable lines in the choice list. By default it'll render a line, but you can provide the text as argument (`new Separator('-- Dependencies --')`). This option is often used to add labels to groups within long list of options.
|
|
54
57
|
|
|
55
58
|
# License
|
|
56
59
|
|
package/dist/cjs/index.js
CHANGED
|
@@ -3,28 +3,40 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Separator = void 0;
|
|
6
7
|
const core_1 = require("@inquirer/core");
|
|
8
|
+
Object.defineProperty(exports, "Separator", { enumerable: true, get: function () { return core_1.Separator; } });
|
|
7
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
10
|
const figures_1 = __importDefault(require("figures"));
|
|
9
11
|
const ansi_escapes_1 = __importDefault(require("ansi-escapes"));
|
|
12
|
+
function isSelectableChoice(choice) {
|
|
13
|
+
return choice != null && choice.type !== 'separator' && !choice.disabled;
|
|
14
|
+
}
|
|
10
15
|
exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
11
16
|
const { choices } = config;
|
|
12
|
-
const startIndex = Math.max(choices.findIndex(({ disabled }) => !disabled), 0);
|
|
13
17
|
const paginator = (0, core_1.useRef)(new core_1.Paginator()).current;
|
|
14
18
|
const firstRender = (0, core_1.useRef)(true);
|
|
15
19
|
const prefix = (0, core_1.usePrefix)();
|
|
16
20
|
const [status, setStatus] = (0, core_1.useState)('pending');
|
|
17
|
-
const [cursorPosition, setCursorPos] = (0, core_1.useState)(
|
|
21
|
+
const [cursorPosition, setCursorPos] = (0, core_1.useState)(() => {
|
|
22
|
+
const startIndex = choices.findIndex(isSelectableChoice);
|
|
23
|
+
if (startIndex < 0) {
|
|
24
|
+
throw new Error('[select prompt] No selectable choices. All choices are disabled.');
|
|
25
|
+
}
|
|
26
|
+
return startIndex;
|
|
27
|
+
});
|
|
28
|
+
// Safe to assume the cursor position always point to a Choice.
|
|
29
|
+
const choice = choices[cursorPosition];
|
|
18
30
|
(0, core_1.useKeypress)((key) => {
|
|
19
31
|
if ((0, core_1.isEnterKey)(key)) {
|
|
20
32
|
setStatus('done');
|
|
21
|
-
done(
|
|
33
|
+
done(choice.value);
|
|
22
34
|
}
|
|
23
35
|
else if ((0, core_1.isUpKey)(key) || (0, core_1.isDownKey)(key)) {
|
|
24
36
|
let newCursorPosition = cursorPosition;
|
|
25
37
|
const offset = (0, core_1.isUpKey)(key) ? -1 : 1;
|
|
26
38
|
let selectedOption;
|
|
27
|
-
while (!selectedOption
|
|
39
|
+
while (!isSelectableChoice(selectedOption)) {
|
|
28
40
|
newCursorPosition =
|
|
29
41
|
(newCursorPosition + offset + choices.length) % choices.length;
|
|
30
42
|
selectedOption = choices[newCursorPosition];
|
|
@@ -35,7 +47,7 @@ exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
|
35
47
|
// Adjust index to start at 1
|
|
36
48
|
const newCursorPosition = Number(key.name) - 1;
|
|
37
49
|
// Abort if the choice doesn't exists or if disabled
|
|
38
|
-
if (!choices[newCursorPosition]
|
|
50
|
+
if (!isSelectableChoice(choices[newCursorPosition])) {
|
|
39
51
|
return;
|
|
40
52
|
}
|
|
41
53
|
setCursorPos(newCursorPosition);
|
|
@@ -47,14 +59,17 @@ exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
|
47
59
|
firstRender.current = false;
|
|
48
60
|
}
|
|
49
61
|
if (status === 'done') {
|
|
50
|
-
const choice = choices[cursorPosition];
|
|
51
62
|
return `${prefix} ${message} ${chalk_1.default.cyan(choice.name || choice.value)}`;
|
|
52
63
|
}
|
|
53
64
|
const allChoices = choices
|
|
54
|
-
.map((
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
.map((choice, index) => {
|
|
66
|
+
if (choice.type === 'separator') {
|
|
67
|
+
return ` ${choice.separator}`;
|
|
68
|
+
}
|
|
69
|
+
const line = choice.name || choice.value;
|
|
70
|
+
if (choice.disabled) {
|
|
71
|
+
const disabledLabel = typeof choice.disabled === 'string' ? choice.disabled : '(disabled)';
|
|
72
|
+
return chalk_1.default.dim(`- ${line} ${disabledLabel}`);
|
|
58
73
|
}
|
|
59
74
|
if (index === cursorPosition) {
|
|
60
75
|
return chalk_1.default.cyan(`${figures_1.default.pointer} ${line}`);
|
|
@@ -63,7 +78,6 @@ exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
|
63
78
|
})
|
|
64
79
|
.join('\n');
|
|
65
80
|
const windowedChoices = paginator.paginate(allChoices, cursorPosition, config.pageSize);
|
|
66
|
-
const
|
|
67
|
-
const choiceDescription = choice && choice.description ? `\n${choice.description}` : ``;
|
|
81
|
+
const choiceDescription = choice.description ? `\n${choice.description}` : ``;
|
|
68
82
|
return `${prefix} ${message}\n${windowedChoices}${choiceDescription}${ansi_escapes_1.default.cursorHide}`;
|
|
69
83
|
});
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { AsyncPromptConfig } from '@inquirer/core';
|
|
1
|
+
import { Separator, AsyncPromptConfig, SeparatorType } from '@inquirer/core';
|
|
2
|
+
type Choice = {
|
|
3
|
+
type?: undefined;
|
|
4
|
+
value: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
disabled?: boolean | string;
|
|
8
|
+
};
|
|
2
9
|
type SelectConfig = AsyncPromptConfig & {
|
|
3
|
-
choices:
|
|
4
|
-
value: string;
|
|
5
|
-
name?: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
disabled?: boolean | string;
|
|
8
|
-
}[];
|
|
10
|
+
choices: Array<SeparatorType | Choice>;
|
|
9
11
|
pageSize?: number;
|
|
10
12
|
};
|
|
11
13
|
declare const _default: import("@inquirer/type").Prompt<string, SelectConfig>;
|
|
12
14
|
export default _default;
|
|
15
|
+
export { Separator };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
|
-
import { createPrompt, useState, useKeypress, useRef, usePrefix, isEnterKey, isUpKey, isDownKey, isNumberKey, Paginator, } from '@inquirer/core';
|
|
1
|
+
import { createPrompt, useState, useKeypress, useRef, usePrefix, isEnterKey, isUpKey, isDownKey, isNumberKey, Paginator, Separator, } from '@inquirer/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import figures from 'figures';
|
|
4
4
|
import ansiEscapes from 'ansi-escapes';
|
|
5
|
+
function isSelectableChoice(choice) {
|
|
6
|
+
return choice != null && choice.type !== 'separator' && !choice.disabled;
|
|
7
|
+
}
|
|
5
8
|
export default createPrompt((config, done) => {
|
|
6
9
|
const { choices } = config;
|
|
7
|
-
const startIndex = Math.max(choices.findIndex(({ disabled }) => !disabled), 0);
|
|
8
10
|
const paginator = useRef(new Paginator()).current;
|
|
9
11
|
const firstRender = useRef(true);
|
|
10
12
|
const prefix = usePrefix();
|
|
11
13
|
const [status, setStatus] = useState('pending');
|
|
12
|
-
const [cursorPosition, setCursorPos] = useState(
|
|
14
|
+
const [cursorPosition, setCursorPos] = useState(() => {
|
|
15
|
+
const startIndex = choices.findIndex(isSelectableChoice);
|
|
16
|
+
if (startIndex < 0) {
|
|
17
|
+
throw new Error('[select prompt] No selectable choices. All choices are disabled.');
|
|
18
|
+
}
|
|
19
|
+
return startIndex;
|
|
20
|
+
});
|
|
21
|
+
// Safe to assume the cursor position always point to a Choice.
|
|
22
|
+
const choice = choices[cursorPosition];
|
|
13
23
|
useKeypress((key) => {
|
|
14
24
|
if (isEnterKey(key)) {
|
|
15
25
|
setStatus('done');
|
|
16
|
-
done(
|
|
26
|
+
done(choice.value);
|
|
17
27
|
}
|
|
18
28
|
else if (isUpKey(key) || isDownKey(key)) {
|
|
19
29
|
let newCursorPosition = cursorPosition;
|
|
20
30
|
const offset = isUpKey(key) ? -1 : 1;
|
|
21
31
|
let selectedOption;
|
|
22
|
-
while (!selectedOption
|
|
32
|
+
while (!isSelectableChoice(selectedOption)) {
|
|
23
33
|
newCursorPosition =
|
|
24
34
|
(newCursorPosition + offset + choices.length) % choices.length;
|
|
25
35
|
selectedOption = choices[newCursorPosition];
|
|
@@ -30,7 +40,7 @@ export default createPrompt((config, done) => {
|
|
|
30
40
|
// Adjust index to start at 1
|
|
31
41
|
const newCursorPosition = Number(key.name) - 1;
|
|
32
42
|
// Abort if the choice doesn't exists or if disabled
|
|
33
|
-
if (!choices[newCursorPosition]
|
|
43
|
+
if (!isSelectableChoice(choices[newCursorPosition])) {
|
|
34
44
|
return;
|
|
35
45
|
}
|
|
36
46
|
setCursorPos(newCursorPosition);
|
|
@@ -42,14 +52,17 @@ export default createPrompt((config, done) => {
|
|
|
42
52
|
firstRender.current = false;
|
|
43
53
|
}
|
|
44
54
|
if (status === 'done') {
|
|
45
|
-
const choice = choices[cursorPosition];
|
|
46
55
|
return `${prefix} ${message} ${chalk.cyan(choice.name || choice.value)}`;
|
|
47
56
|
}
|
|
48
57
|
const allChoices = choices
|
|
49
|
-
.map((
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
.map((choice, index) => {
|
|
59
|
+
if (choice.type === 'separator') {
|
|
60
|
+
return ` ${choice.separator}`;
|
|
61
|
+
}
|
|
62
|
+
const line = choice.name || choice.value;
|
|
63
|
+
if (choice.disabled) {
|
|
64
|
+
const disabledLabel = typeof choice.disabled === 'string' ? choice.disabled : '(disabled)';
|
|
65
|
+
return chalk.dim(`- ${line} ${disabledLabel}`);
|
|
53
66
|
}
|
|
54
67
|
if (index === cursorPosition) {
|
|
55
68
|
return chalk.cyan(`${figures.pointer} ${line}`);
|
|
@@ -58,7 +71,7 @@ export default createPrompt((config, done) => {
|
|
|
58
71
|
})
|
|
59
72
|
.join('\n');
|
|
60
73
|
const windowedChoices = paginator.paginate(allChoices, cursorPosition, config.pageSize);
|
|
61
|
-
const
|
|
62
|
-
const choiceDescription = choice && choice.description ? `\n${choice.description}` : ``;
|
|
74
|
+
const choiceDescription = choice.description ? `\n${choice.description}` : ``;
|
|
63
75
|
return `${prefix} ${message}\n${windowedChoices}${choiceDescription}${ansiEscapes.cursorHide}`;
|
|
64
76
|
});
|
|
77
|
+
export { Separator };
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { AsyncPromptConfig } from '@inquirer/core';
|
|
1
|
+
import { Separator, AsyncPromptConfig, SeparatorType } from '@inquirer/core';
|
|
2
|
+
type Choice = {
|
|
3
|
+
type?: undefined;
|
|
4
|
+
value: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
disabled?: boolean | string;
|
|
8
|
+
};
|
|
2
9
|
type SelectConfig = AsyncPromptConfig & {
|
|
3
|
-
choices:
|
|
4
|
-
value: string;
|
|
5
|
-
name?: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
disabled?: boolean | string;
|
|
8
|
-
}[];
|
|
10
|
+
choices: Array<SeparatorType | Choice>;
|
|
9
11
|
pageSize?: number;
|
|
10
12
|
};
|
|
11
13
|
declare const _default: import("@inquirer/type").Prompt<string, SelectConfig>;
|
|
12
14
|
export default _default;
|
|
15
|
+
export { Separator };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inquirer/select",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Inquirer select/list prompt",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"typings": "./dist/cjs/types/index.d.mts",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"license": "MIT",
|
|
55
55
|
"homepage": "https://github.com/SBoudrias/Inquirer.js/blob/master/packages/select/README.md",
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@inquirer/core": "^1.
|
|
57
|
+
"@inquirer/core": "^1.1.2",
|
|
58
58
|
"@inquirer/type": "^1.0.3",
|
|
59
59
|
"ansi-escapes": "^4.3.2",
|
|
60
60
|
"chalk": "^4.1.2",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "fbeb06c92f1e64a88bb77028c7a038768c4291b2"
|
|
89
89
|
}
|