Selection functionality for single and multiple choice scenarios from lists of options.
Single selection from a list of options with keyboard navigation.
/**
* Prompt for selecting a single option from a list
* @template T - Type of option objects, must have a 'value' property
*/
class SelectPrompt<T extends { value: any }> extends Prompt<T['value']> {
constructor(opts: SelectOptions<T>);
/** Array of available options */
options: T[];
/** Current cursor position (index of highlighted option) */
cursor: number;
}
/**
* Configuration options for SelectPrompt
* @template T - Type of option objects
*/
interface SelectOptions<T> extends PromptOptions<SelectPrompt<T>> {
/** Array of options to choose from */
options: T[];
/** Initial value to select (matches option.value) */
initialValue?: T['value'];
}Usage Examples:
import { SelectPrompt, isCancel } from '@clack/core';
// Basic single selection
const colorPrompt = new SelectPrompt({
render() {
return `Choose a color:\n${this.options
.map((option, i) => {
const isSelected = i === this.cursor;
const prefix = isSelected ? '→' : ' ';
return `${prefix} ${option.label}`;
})
.join('\n')}`;
},
options: [
{ value: 'red', label: 'Red' },
{ value: 'green', label: 'Green' },
{ value: 'blue', label: 'Blue' }
]
});
const selectedColor = await colorPrompt.prompt();
if (isCancel(selectedColor)) {
process.exit(0);
}
// Selection with initial value
const frameworkPrompt = new SelectPrompt({
render() {
return `Choose framework:\n${this.options
.map((option, i) => {
const isSelected = i === this.cursor;
const prefix = isSelected ? '●' : '○';
return `${prefix} ${option.label} - ${option.description}`;
})
.join('\n')}`;
},
options: [
{ value: 'react', label: 'React', description: 'A JavaScript library for building user interfaces' },
{ value: 'vue', label: 'Vue', description: 'The Progressive JavaScript Framework' },
{ value: 'svelte', label: 'Svelte', description: 'Cybernetically enhanced web apps' }
],
initialValue: 'react'
});
const framework = await frameworkPrompt.prompt();Multiple selection from a list of options with individual item toggling.
/**
* Prompt for selecting multiple options from a list
* @template T - Type of option objects, must have a 'value' property
*/
class MultiSelectPrompt<T extends { value: any }> extends Prompt<T['value'][]> {
constructor(opts: MultiSelectOptions<T>);
/** Array of available options */
options: T[];
/** Current cursor position (index of highlighted option) */
cursor: number;
}
/**
* Configuration options for MultiSelectPrompt
* @template T - Type of option objects
*/
interface MultiSelectOptions<T> extends PromptOptions<MultiSelectPrompt<T>> {
/** Array of options to choose from */
options: T[];
/** Initial values to select (array of option.value) */
initialValues?: T['value'][];
/** Whether at least one selection is required */
required?: boolean;
/** Initial cursor position (option.value to start at) */
cursorAt?: T['value'];
}Usage Examples:
import { MultiSelectPrompt, isCancel } from '@clack/core';
// Basic multi-selection
const featuresPrompt = new MultiSelectPrompt({
render() {
return `Select features to install:\n${this.options
.map((option, i) => {
const isSelected = i === this.cursor;
const isChecked = this.value?.includes(option.value);
const cursor = isSelected ? '→' : ' ';
const checkbox = isChecked ? '☑' : '☐';
return `${cursor} ${checkbox} ${option.label}`;
})
.join('\n')}`;
},
options: [
{ value: 'typescript', label: 'TypeScript support' },
{ value: 'eslint', label: 'ESLint configuration' },
{ value: 'prettier', label: 'Prettier formatting' },
{ value: 'tests', label: 'Test setup' }
]
});
const selectedFeatures = await featuresPrompt.prompt();
if (isCancel(selectedFeatures)) {
process.exit(0);
}
// Multi-selection with initial values and required selection
const toolsPrompt = new MultiSelectPrompt({
render() {
const selectedCount = this.value?.length || 0;
return `Select development tools (${selectedCount} selected):\n${this.options
.map((option, i) => {
const isSelected = i === this.cursor;
const isChecked = this.value?.includes(option.value);
const cursor = isSelected ? '▶' : ' ';
const checkbox = isChecked ? '✓' : ' ';
return `${cursor} [${checkbox}] ${option.label}`;
})
.join('\n')}`;
},
options: [
{ value: 'webpack', label: 'Webpack bundler' },
{ value: 'vite', label: 'Vite build tool' },
{ value: 'rollup', label: 'Rollup bundler' }
],
initialValues: ['vite'],
required: true,
cursorAt: 'vite'
});
const tools = await toolsPrompt.prompt();Selection by pressing specific keys assigned to each option.
/**
* Prompt for selecting options by pressing assigned keys
* @template T - Type of option objects, must have a 'value' property
*/
class SelectKeyPrompt<T extends { value: any }> extends Prompt<T['value']> {
constructor(opts: SelectKeyOptions<T>);
/** Array of available options */
options: T[];
/** Current cursor position (index of highlighted option) */
cursor: number;
}
/**
* Configuration options for SelectKeyPrompt
* @template T - Type of option objects
*/
interface SelectKeyOptions<T> extends PromptOptions<SelectKeyPrompt<T>> {
/** Array of options to choose from */
options: T[];
}Usage Examples:
import { SelectKeyPrompt, isCancel } from '@clack/core';
// Key-based selection
const actionPrompt = new SelectKeyPrompt({
render() {
return `Choose an action:\n${this.options
.map((option) => ` [${option.key}] ${option.label}`)
.join('\n')}\n\nPress a key...`;
},
options: [
{ value: 'create', label: 'Create new project', key: 'c' },
{ value: 'update', label: 'Update existing project', key: 'u' },
{ value: 'delete', label: 'Delete project', key: 'd' },
{ value: 'exit', label: 'Exit', key: 'x' }
]
});
const action = await actionPrompt.prompt();
if (isCancel(action)) {
process.exit(0);
}