Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/dull-tools-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@clack/core": patch
"@clack/prompts": patch
---

Multiselect: return `Value[]` instead of `Option[]`.
8 changes: 4 additions & 4 deletions packages/core/src/prompts/multi-select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ export default class MultiSelectPrompt<T extends { value: any }> extends Prompt
cursor: number = 0;

private get _value() {
return this.options[this.cursor];
return this.options[this.cursor].value;
}

private toggleValue() {
const selected = this.value.some(({ value }: T) => value === this._value.value);
const selected = this.value.includes(this._value);
this.value = selected
? this.value.filter(({ value }: T) => value !== this._value.value)
? this.value.filter((value: T['value']) => value !== this._value)
: [...this.value, this._value];
}

constructor(opts: MultiSelectOptions<T>) {
super(opts, false);

this.options = opts.options;
this.value = this.options.filter(({ value }) => opts.initialValue?.includes(value));
this.value = [...(opts.initialValue ?? [])];
this.cursor = Math.max(
this.options.findIndex(({ value }) => value === opts.cursorAt),
0
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/prompts/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export interface PromptOptions<Self extends Prompt> {
render(this: Omit<Self, 'prompt'>): string | void;
placeholder?: string;
initialValue?: any;
validate?: ((value: string) => string | void) | undefined;
validate?: ((value: any) => string | void) | undefined;
input?: Readable;
output?: Writable;
debug?: boolean;
Expand Down
22 changes: 10 additions & 12 deletions packages/prompts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ export const multiselect = <Options extends Option<Value>[], Value extends Primi
initialValue: opts.initialValue,
required: opts.required ?? true,
cursorAt: opts.cursorAt,
validate(value) {
if (this.required && value.length === 0)
validate(selected: Value[]) {
if (this.required && selected.length === 0)
return `Please select at least one option.\n${color.reset(
color.dim(
`Press ${color.gray(color.bgWhite(color.inverse(' space ')))} to select, ${color.gray(
Expand All @@ -236,13 +236,15 @@ export const multiselect = <Options extends Option<Value>[], Value extends Primi

switch (this.state) {
case 'submit': {
return `${title}${color.gray(S_BAR)} ${this.value
.map((option: Option<Value>) => opt(option, 'submitted'))
return `${title}${color.gray(S_BAR)} ${this.options
.filter(({ value }) => this.value.includes(value))
.map((option) => opt(option, 'submitted'))
.join(color.dim(', '))}`;
}
case 'cancel': {
const label = this.value
.map((option: Option<Value>) => opt(option, 'cancelled'))
const label = this.options
.filter(({ value }) => this.value.includes(value))
.map((option) => opt(option, 'cancelled'))
.join(color.dim(', '));
return `${title}${color.gray(S_BAR)} ${
label.trim() ? `${label}\n${color.gray(S_BAR)}` : ''
Expand All @@ -257,9 +259,7 @@ export const multiselect = <Options extends Option<Value>[], Value extends Primi
.join('\n');
return `${title}${color.yellow(S_BAR)} ${this.options
.map((option, i) => {
const selected = this.value.some(
({ value }: Option<Value>) => value === option.value
);
const selected = this.value.includes(option.value);
const active = i === this.cursor;
if (active && selected) {
return opt(option, 'active-selected');
Expand All @@ -274,9 +274,7 @@ export const multiselect = <Options extends Option<Value>[], Value extends Primi
default: {
return `${title}${color.cyan(S_BAR)} ${this.options
.map((option, i) => {
const selected = this.value.some(
({ value }: Option<Value>) => value === option.value
);
const selected = this.value.includes(option.value);
const active = i === this.cursor;
if (active && selected) {
return opt(option, 'active-selected');
Expand Down