Skip to content

Commit

Permalink
feat(@clack/prompts): add validate option for select and multiselect
Browse files Browse the repository at this point in the history
  • Loading branch information
await-ovo committed Sep 20, 2023
1 parent 90f8e3d commit a406701
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/young-mice-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clack/prompts': patch
---

feat(@clack/prompts): Add validate option for select and multiselect
21 changes: 21 additions & 0 deletions packages/prompts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ export interface SelectOptions<Value> {
options: Option<Value>[];
initialValue?: Value;
maxItems?: number;
validate?: (value: string) => string | void;
}

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

return new SelectPrompt({
validate: opts.validate,
options: opts.options,
initialValue: opts.initialValue,
render() {
Expand All @@ -247,6 +249,20 @@ export const select = <Value>(opts: SelectOptions<Value>) => {
this.options[this.cursor],
'cancelled'
)}\n${color.gray(S_BAR)}`;
case 'error': {
const footer = this.error
.split('\n')
.map((ln, i) =>
i === 0 ? `${color.yellow(S_BAR_END)} ${color.yellow(ln)}` : ` ${ln}`
)
.join('\n');
return `${title}${color.yellow(S_BAR)} ${limitOptions({
cursor: this.cursor,
options: this.options,
maxItems: opts.maxItems,
style: (item, active) => opt(item, active ? 'active' : 'inactive'),
}).join(`\n${color.yellow(S_BAR)} `)}\n${footer}`;
}
default: {
return `${title}${color.cyan(S_BAR)} ${limitOptions({
cursor: this.cursor,
Expand Down Expand Up @@ -313,6 +329,7 @@ export interface MultiSelectOptions<Value> {
maxItems?: number;
required?: boolean;
cursorAt?: Value;
validate?: (value: Value[]) => string | void;
}
export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
const opt = (
Expand Down Expand Up @@ -344,6 +361,10 @@ export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
required: opts.required ?? true,
cursorAt: opts.cursorAt,
validate(selected: Value[]) {
if (opts.validate) {
const error = opts.validate(selected);
if (error) return error;
}
if (this.required && selected.length === 0)
return `Please select at least one option.\n${color.reset(
color.dim(
Expand Down

0 comments on commit a406701

Please sign in to comment.