Skip to content

Commit a406701

Browse files
committed
feat(@clack/prompts): add validate option for select and multiselect
1 parent 90f8e3d commit a406701

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

.changeset/young-mice-vanish.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clack/prompts': patch
3+
---
4+
5+
feat(@clack/prompts): Add validate option for select and multiselect

packages/prompts/src/index.ts

+21
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ export interface SelectOptions<Value> {
214214
options: Option<Value>[];
215215
initialValue?: Value;
216216
maxItems?: number;
217+
validate?: (value: string) => string | void;
217218
}
218219

219220
export const select = <Value>(opts: SelectOptions<Value>) => {
@@ -234,6 +235,7 @@ export const select = <Value>(opts: SelectOptions<Value>) => {
234235
};
235236

236237
return new SelectPrompt({
238+
validate: opts.validate,
237239
options: opts.options,
238240
initialValue: opts.initialValue,
239241
render() {
@@ -247,6 +249,20 @@ export const select = <Value>(opts: SelectOptions<Value>) => {
247249
this.options[this.cursor],
248250
'cancelled'
249251
)}\n${color.gray(S_BAR)}`;
252+
case 'error': {
253+
const footer = this.error
254+
.split('\n')
255+
.map((ln, i) =>
256+
i === 0 ? `${color.yellow(S_BAR_END)} ${color.yellow(ln)}` : ` ${ln}`
257+
)
258+
.join('\n');
259+
return `${title}${color.yellow(S_BAR)} ${limitOptions({
260+
cursor: this.cursor,
261+
options: this.options,
262+
maxItems: opts.maxItems,
263+
style: (item, active) => opt(item, active ? 'active' : 'inactive'),
264+
}).join(`\n${color.yellow(S_BAR)} `)}\n${footer}`;
265+
}
250266
default: {
251267
return `${title}${color.cyan(S_BAR)} ${limitOptions({
252268
cursor: this.cursor,
@@ -313,6 +329,7 @@ export interface MultiSelectOptions<Value> {
313329
maxItems?: number;
314330
required?: boolean;
315331
cursorAt?: Value;
332+
validate?: (value: Value[]) => string | void;
316333
}
317334
export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
318335
const opt = (
@@ -344,6 +361,10 @@ export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
344361
required: opts.required ?? true,
345362
cursorAt: opts.cursorAt,
346363
validate(selected: Value[]) {
364+
if (opts.validate) {
365+
const error = opts.validate(selected);
366+
if (error) return error;
367+
}
347368
if (this.required && selected.length === 0)
348369
return `Please select at least one option.\n${color.reset(
349370
color.dim(

0 commit comments

Comments
 (0)