@inquirer/select 2.4.7 → 3.0.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.
- package/README.md +4 -2
- package/dist/cjs/index.js +32 -15
- package/dist/cjs/types/index.d.ts +4 -2
- package/dist/esm/index.mjs +31 -15
- package/dist/esm/types/index.d.mts +4 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -118,20 +118,22 @@ Here's each property:
|
|
|
118
118
|
- `short`: Once the prompt is done (press enter), we'll use `short` if defined to render next to the question. By default we'll use `name`.
|
|
119
119
|
- `disabled`: Disallow the option from being selected. If `disabled` is a string, it'll be used as a help tip explaining why the choice isn't available.
|
|
120
120
|
|
|
121
|
+
`choices` can also be an array of string, in which case the string will be used both as the `value` and the `name`.
|
|
122
|
+
|
|
121
123
|
## Theming
|
|
122
124
|
|
|
123
125
|
You can theme a prompt by passing a `theme` object option. The theme object only need to includes the keys you wish to modify, we'll fallback on the defaults for the rest.
|
|
124
126
|
|
|
125
127
|
```ts
|
|
126
128
|
type Theme = {
|
|
127
|
-
prefix: string;
|
|
129
|
+
prefix: string | { idle: string; done: string };
|
|
128
130
|
spinner: {
|
|
129
131
|
interval: number;
|
|
130
132
|
frames: string[];
|
|
131
133
|
};
|
|
132
134
|
style: {
|
|
133
135
|
answer: (text: string) => string;
|
|
134
|
-
message: (text: string) => string;
|
|
136
|
+
message: (text: string, status: 'idle' | 'done' | 'loading') => string;
|
|
135
137
|
error: (text: string) => string;
|
|
136
138
|
help: (text: string) => string;
|
|
137
139
|
highlight: (text: string) => string;
|
package/dist/cjs/index.js
CHANGED
|
@@ -19,14 +19,37 @@ const selectTheme = {
|
|
|
19
19
|
function isSelectable(item) {
|
|
20
20
|
return !core_1.Separator.isSeparator(item) && !item.disabled;
|
|
21
21
|
}
|
|
22
|
+
function normalizeChoices(choices) {
|
|
23
|
+
return choices.map((choice) => {
|
|
24
|
+
var _a, _b, _c;
|
|
25
|
+
if (core_1.Separator.isSeparator(choice))
|
|
26
|
+
return choice;
|
|
27
|
+
if (typeof choice === 'string') {
|
|
28
|
+
return {
|
|
29
|
+
value: choice,
|
|
30
|
+
name: choice,
|
|
31
|
+
short: choice,
|
|
32
|
+
disabled: false,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const name = (_a = choice.name) !== null && _a !== void 0 ? _a : String(choice.value);
|
|
36
|
+
return {
|
|
37
|
+
value: choice.value,
|
|
38
|
+
name,
|
|
39
|
+
description: choice.description,
|
|
40
|
+
short: (_b = choice.short) !== null && _b !== void 0 ? _b : name,
|
|
41
|
+
disabled: (_c = choice.disabled) !== null && _c !== void 0 ? _c : false,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
22
45
|
exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
23
|
-
|
|
24
|
-
const { choices: items, loop = true, pageSize = 7 } = config;
|
|
46
|
+
const { loop = true, pageSize = 7 } = config;
|
|
25
47
|
const firstRender = (0, core_1.useRef)(true);
|
|
26
48
|
const theme = (0, core_1.makeTheme)(selectTheme, config.theme);
|
|
27
|
-
const
|
|
28
|
-
const
|
|
49
|
+
const [status, setStatus] = (0, core_1.useState)('idle');
|
|
50
|
+
const prefix = (0, core_1.usePrefix)({ status, theme });
|
|
29
51
|
const searchTimeoutRef = (0, core_1.useRef)();
|
|
52
|
+
const items = (0, core_1.useMemo)(() => normalizeChoices(config.choices), [config.choices]);
|
|
30
53
|
const bounds = (0, core_1.useMemo)(() => {
|
|
31
54
|
const first = items.findIndex(isSelectable);
|
|
32
55
|
const last = items.findLastIndex(isSelectable);
|
|
@@ -79,9 +102,7 @@ exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
|
79
102
|
const matchIndex = items.findIndex((item) => {
|
|
80
103
|
if (core_1.Separator.isSeparator(item) || !isSelectable(item))
|
|
81
104
|
return false;
|
|
82
|
-
return
|
|
83
|
-
.toLowerCase()
|
|
84
|
-
.startsWith(searchTerm);
|
|
105
|
+
return item.name.toLowerCase().startsWith(searchTerm);
|
|
85
106
|
});
|
|
86
107
|
if (matchIndex >= 0) {
|
|
87
108
|
setActive(matchIndex);
|
|
@@ -94,7 +115,7 @@ exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
|
94
115
|
(0, core_1.useEffect)(() => () => {
|
|
95
116
|
clearTimeout(searchTimeoutRef.current);
|
|
96
117
|
}, []);
|
|
97
|
-
const message = theme.style.message(config.message);
|
|
118
|
+
const message = theme.style.message(config.message, status);
|
|
98
119
|
let helpTipTop = '';
|
|
99
120
|
let helpTipBottom = '';
|
|
100
121
|
if (theme.helpMode === 'always' ||
|
|
@@ -114,23 +135,19 @@ exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
|
114
135
|
if (core_1.Separator.isSeparator(item)) {
|
|
115
136
|
return ` ${item.separator}`;
|
|
116
137
|
}
|
|
117
|
-
const line = String(item.name || item.value);
|
|
118
138
|
if (item.disabled) {
|
|
119
139
|
const disabledLabel = typeof item.disabled === 'string' ? item.disabled : '(disabled)';
|
|
120
|
-
return theme.style.disabled(`${
|
|
140
|
+
return theme.style.disabled(`${item.name} ${disabledLabel}`);
|
|
121
141
|
}
|
|
122
142
|
const color = isActive ? theme.style.highlight : (x) => x;
|
|
123
143
|
const cursor = isActive ? theme.icon.cursor : ` `;
|
|
124
|
-
return color(`${cursor} ${
|
|
144
|
+
return color(`${cursor} ${item.name}`);
|
|
125
145
|
},
|
|
126
146
|
pageSize,
|
|
127
147
|
loop,
|
|
128
148
|
});
|
|
129
149
|
if (status === 'done') {
|
|
130
|
-
|
|
131
|
-
// TODO: Could we enforce that at the type level? Name should be defined for non-string values.
|
|
132
|
-
String(selectedChoice.value);
|
|
133
|
-
return `${prefix} ${message} ${theme.style.answer(answer)}`;
|
|
150
|
+
return `${prefix} ${message} ${theme.style.answer(selectedChoice.short)}`;
|
|
134
151
|
}
|
|
135
152
|
const choiceDescription = selectedChoice.description
|
|
136
153
|
? `\n${theme.style.description(selectedChoice.description)}`
|
|
@@ -20,11 +20,13 @@ type Choice<Value> = {
|
|
|
20
20
|
};
|
|
21
21
|
declare const _default: <Value>(config: {
|
|
22
22
|
message: string;
|
|
23
|
-
choices: readonly (Separator | Choice<Value>)[];
|
|
23
|
+
choices: readonly (string | Separator)[] | readonly (Separator | Choice<Value>)[];
|
|
24
24
|
pageSize?: number | undefined;
|
|
25
25
|
loop?: boolean | undefined;
|
|
26
26
|
default?: unknown;
|
|
27
27
|
theme?: PartialDeep<Theme<SelectTheme>> | undefined;
|
|
28
|
-
}, context?: import("@inquirer/type").Context) =>
|
|
28
|
+
}, context?: import("@inquirer/type").Context) => Promise<Value> & {
|
|
29
|
+
cancel: () => void;
|
|
30
|
+
};
|
|
29
31
|
export default _default;
|
|
30
32
|
export { Separator } from '@inquirer/core';
|
package/dist/esm/index.mjs
CHANGED
|
@@ -13,13 +13,36 @@ const selectTheme = {
|
|
|
13
13
|
function isSelectable(item) {
|
|
14
14
|
return !Separator.isSeparator(item) && !item.disabled;
|
|
15
15
|
}
|
|
16
|
+
function normalizeChoices(choices) {
|
|
17
|
+
return choices.map((choice) => {
|
|
18
|
+
if (Separator.isSeparator(choice))
|
|
19
|
+
return choice;
|
|
20
|
+
if (typeof choice === 'string') {
|
|
21
|
+
return {
|
|
22
|
+
value: choice,
|
|
23
|
+
name: choice,
|
|
24
|
+
short: choice,
|
|
25
|
+
disabled: false,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const name = choice.name ?? String(choice.value);
|
|
29
|
+
return {
|
|
30
|
+
value: choice.value,
|
|
31
|
+
name,
|
|
32
|
+
description: choice.description,
|
|
33
|
+
short: choice.short ?? name,
|
|
34
|
+
disabled: choice.disabled ?? false,
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
}
|
|
16
38
|
export default createPrompt((config, done) => {
|
|
17
|
-
const {
|
|
39
|
+
const { loop = true, pageSize = 7 } = config;
|
|
18
40
|
const firstRender = useRef(true);
|
|
19
41
|
const theme = makeTheme(selectTheme, config.theme);
|
|
20
|
-
const
|
|
21
|
-
const
|
|
42
|
+
const [status, setStatus] = useState('idle');
|
|
43
|
+
const prefix = usePrefix({ status, theme });
|
|
22
44
|
const searchTimeoutRef = useRef();
|
|
45
|
+
const items = useMemo(() => normalizeChoices(config.choices), [config.choices]);
|
|
23
46
|
const bounds = useMemo(() => {
|
|
24
47
|
const first = items.findIndex(isSelectable);
|
|
25
48
|
const last = items.findLastIndex(isSelectable);
|
|
@@ -72,9 +95,7 @@ export default createPrompt((config, done) => {
|
|
|
72
95
|
const matchIndex = items.findIndex((item) => {
|
|
73
96
|
if (Separator.isSeparator(item) || !isSelectable(item))
|
|
74
97
|
return false;
|
|
75
|
-
return
|
|
76
|
-
.toLowerCase()
|
|
77
|
-
.startsWith(searchTerm);
|
|
98
|
+
return item.name.toLowerCase().startsWith(searchTerm);
|
|
78
99
|
});
|
|
79
100
|
if (matchIndex >= 0) {
|
|
80
101
|
setActive(matchIndex);
|
|
@@ -87,7 +108,7 @@ export default createPrompt((config, done) => {
|
|
|
87
108
|
useEffect(() => () => {
|
|
88
109
|
clearTimeout(searchTimeoutRef.current);
|
|
89
110
|
}, []);
|
|
90
|
-
const message = theme.style.message(config.message);
|
|
111
|
+
const message = theme.style.message(config.message, status);
|
|
91
112
|
let helpTipTop = '';
|
|
92
113
|
let helpTipBottom = '';
|
|
93
114
|
if (theme.helpMode === 'always' ||
|
|
@@ -107,24 +128,19 @@ export default createPrompt((config, done) => {
|
|
|
107
128
|
if (Separator.isSeparator(item)) {
|
|
108
129
|
return ` ${item.separator}`;
|
|
109
130
|
}
|
|
110
|
-
const line = String(item.name || item.value);
|
|
111
131
|
if (item.disabled) {
|
|
112
132
|
const disabledLabel = typeof item.disabled === 'string' ? item.disabled : '(disabled)';
|
|
113
|
-
return theme.style.disabled(`${
|
|
133
|
+
return theme.style.disabled(`${item.name} ${disabledLabel}`);
|
|
114
134
|
}
|
|
115
135
|
const color = isActive ? theme.style.highlight : (x) => x;
|
|
116
136
|
const cursor = isActive ? theme.icon.cursor : ` `;
|
|
117
|
-
return color(`${cursor} ${
|
|
137
|
+
return color(`${cursor} ${item.name}`);
|
|
118
138
|
},
|
|
119
139
|
pageSize,
|
|
120
140
|
loop,
|
|
121
141
|
});
|
|
122
142
|
if (status === 'done') {
|
|
123
|
-
|
|
124
|
-
selectedChoice.name ??
|
|
125
|
-
// TODO: Could we enforce that at the type level? Name should be defined for non-string values.
|
|
126
|
-
String(selectedChoice.value);
|
|
127
|
-
return `${prefix} ${message} ${theme.style.answer(answer)}`;
|
|
143
|
+
return `${prefix} ${message} ${theme.style.answer(selectedChoice.short)}`;
|
|
128
144
|
}
|
|
129
145
|
const choiceDescription = selectedChoice.description
|
|
130
146
|
? `\n${theme.style.description(selectedChoice.description)}`
|
|
@@ -20,11 +20,13 @@ type Choice<Value> = {
|
|
|
20
20
|
};
|
|
21
21
|
declare const _default: <Value>(config: {
|
|
22
22
|
message: string;
|
|
23
|
-
choices: readonly (Separator | Choice<Value>)[];
|
|
23
|
+
choices: readonly (string | Separator)[] | readonly (Separator | Choice<Value>)[];
|
|
24
24
|
pageSize?: number | undefined;
|
|
25
25
|
loop?: boolean | undefined;
|
|
26
26
|
default?: unknown;
|
|
27
27
|
theme?: PartialDeep<Theme<SelectTheme>> | undefined;
|
|
28
|
-
}, context?: import("@inquirer/type").Context) =>
|
|
28
|
+
}, context?: import("@inquirer/type").Context) => Promise<Value> & {
|
|
29
|
+
cancel: () => void;
|
|
30
|
+
};
|
|
29
31
|
export default _default;
|
|
30
32
|
export { Separator } from '@inquirer/core';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inquirer/select",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Inquirer select/list prompt",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"typings": "./dist/cjs/types/index.d.ts",
|
|
@@ -54,14 +54,14 @@
|
|
|
54
54
|
"license": "MIT",
|
|
55
55
|
"homepage": "https://github.com/SBoudrias/Inquirer.js/blob/main/packages/select/README.md",
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@inquirer/core": "^9.0
|
|
57
|
+
"@inquirer/core": "^9.2.0",
|
|
58
58
|
"@inquirer/figures": "^1.0.5",
|
|
59
|
-
"@inquirer/type": "^1.5.
|
|
59
|
+
"@inquirer/type": "^1.5.4",
|
|
60
60
|
"ansi-escapes": "^4.3.2",
|
|
61
61
|
"yoctocolors-cjs": "^2.1.2"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@inquirer/testing": "^2.1.
|
|
64
|
+
"@inquirer/testing": "^2.1.33"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"tsc": "yarn run tsc:esm && yarn run tsc:cjs",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
90
|
"sideEffects": false,
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "5fe03a4686d349d0d6cf281f86f12a4f7c992ad4"
|
|
92
92
|
}
|