|
4 | 4 | isCancel,
|
5 | 5 | MultiSelectPrompt,
|
6 | 6 | PasswordPrompt,
|
| 7 | + SelectKeyPrompt, |
7 | 8 | SelectPrompt,
|
8 | 9 | State,
|
9 | 10 | TextPrompt,
|
@@ -216,6 +217,54 @@ export const select = <Options extends Option<Value>[], Value extends Primitive>
|
216 | 217 | }).prompt() as Promise<Options[number]['value'] | symbol>;
|
217 | 218 | };
|
218 | 219 |
|
| 220 | +export const selectKey = <Options extends Option<Value>[], Value extends string>( |
| 221 | + opts: SelectOptions<Options, Value> |
| 222 | +) => { |
| 223 | + const opt = ( |
| 224 | + option: Options[number], |
| 225 | + state: 'inactive' | 'active' | 'selected' | 'cancelled' = 'inactive' |
| 226 | + ) => { |
| 227 | + const label = option.label ?? String(option.value); |
| 228 | + if (state === 'selected') { |
| 229 | + return `${color.dim(label)}`; |
| 230 | + } else if (state === 'cancelled') { |
| 231 | + return `${color.strikethrough(color.dim(label))}`; |
| 232 | + } else if (state === 'active') { |
| 233 | + return `${color.bgCyan(color.gray(` ${option.value} `))} ${label} ${ |
| 234 | + option.hint ? color.dim(`(${option.hint})`) : '' |
| 235 | + }`; |
| 236 | + } |
| 237 | + return `${color.gray(color.bgWhite(color.inverse(` ${option.value} `)))} ${label} ${ |
| 238 | + option.hint ? color.dim(`(${option.hint})`) : '' |
| 239 | + }`; |
| 240 | + }; |
| 241 | + |
| 242 | + return new SelectKeyPrompt({ |
| 243 | + options: opts.options, |
| 244 | + initialValue: opts.initialValue, |
| 245 | + render() { |
| 246 | + const title = `${color.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; |
| 247 | + |
| 248 | + switch (this.state) { |
| 249 | + case 'submit': |
| 250 | + return `${title}${color.gray(S_BAR)} ${opt( |
| 251 | + this.options.find((opt) => opt.value === this.value)!, |
| 252 | + 'selected' |
| 253 | + )}`; |
| 254 | + case 'cancel': |
| 255 | + return `${title}${color.gray(S_BAR)} ${opt(this.options[0], 'cancelled')}\n${color.gray( |
| 256 | + S_BAR |
| 257 | + )}`; |
| 258 | + default: { |
| 259 | + return `${title}${color.cyan(S_BAR)} ${this.options |
| 260 | + .map((option, i) => opt(option, i === this.cursor ? 'active' : 'inactive')) |
| 261 | + .join(`\n${color.cyan(S_BAR)} `)}\n${color.cyan(S_BAR_END)}\n`; |
| 262 | + } |
| 263 | + } |
| 264 | + }, |
| 265 | + }).prompt() as Promise<Options[number]['value'] | symbol>; |
| 266 | +}; |
| 267 | + |
219 | 268 | export interface MultiSelectOptions<Options extends Option<Value>[], Value extends Primitive> {
|
220 | 269 | message: string;
|
221 | 270 | options: Options;
|
|
0 commit comments