Skip to content

Commit 4f6b3c2

Browse files
authored
fix(autocomplete): use first option as initial value in non-multiple (#332)
1 parent 9bd8072 commit 4f6b3c2

File tree

3 files changed

+79
-7
lines changed

3 files changed

+79
-7
lines changed

.changeset/moody-baboons-greet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clack/core": patch
3+
---
4+
5+
Set initial values of auto complete prompt to first option when multiple is false.

packages/core/src/prompts/autocomplete.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt {
9696
} else {
9797
initialValues = opts.initialValue.slice(0, 1);
9898
}
99+
} else {
100+
if (!this.multiple && this.options.length > 0) {
101+
initialValues = [this.options[0].value];
102+
}
99103
}
100104

101105
if (initialValues) {
@@ -151,14 +155,19 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt {
151155
}
152156
this.isNavigating = true;
153157
} else {
154-
if (
155-
this.multiple &&
156-
this.focusedValue !== undefined &&
157-
(key.name === 'tab' || (this.isNavigating && key.name === 'space'))
158-
) {
159-
this.toggleSelected(this.focusedValue);
158+
if (this.multiple) {
159+
if (
160+
this.focusedValue !== undefined &&
161+
(key.name === 'tab' || (this.isNavigating && key.name === 'space'))
162+
) {
163+
this.toggleSelected(this.focusedValue);
164+
} else {
165+
this.isNavigating = false;
166+
}
160167
} else {
161-
this.isNavigating = false;
168+
if (this.focusedValue) {
169+
this.selectedValues = [this.focusedValue];
170+
}
162171
}
163172
}
164173
}

packages/core/test/prompts/autocomplete.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,31 @@ describe('AutocompletePrompt', () => {
9393
expect(instance.selectedValues).to.deep.equal(['cherry']);
9494
});
9595

96+
test('initialValue defaults to first option when non-multiple', () => {
97+
const instance = new AutocompletePrompt({
98+
input,
99+
output,
100+
render: () => 'foo',
101+
options: testOptions,
102+
});
103+
104+
expect(instance.cursor).to.equal(0);
105+
expect(instance.selectedValues).to.deep.equal(['apple']);
106+
});
107+
108+
test('initialValue is empty when multiple', () => {
109+
const instance = new AutocompletePrompt({
110+
input,
111+
output,
112+
render: () => 'foo',
113+
options: testOptions,
114+
multiple: true,
115+
});
116+
117+
expect(instance.cursor).to.equal(0);
118+
expect(instance.selectedValues).to.deep.equal([]);
119+
});
120+
96121
test('filtering through value event', () => {
97122
const instance = new AutocompletePrompt({
98123
input,
@@ -136,4 +161,37 @@ describe('AutocompletePrompt', () => {
136161

137162
expect(instance.filteredOptions).toEqual([]);
138163
});
164+
165+
test('submit without nav resolves to first option in non-multiple', async () => {
166+
const instance = new AutocompletePrompt({
167+
input,
168+
output,
169+
render: () => 'foo',
170+
options: testOptions,
171+
});
172+
173+
const promise = instance.prompt();
174+
input.emit('keypress', '', { name: 'return' });
175+
const result = await promise;
176+
177+
expect(instance.selectedValues).to.deep.equal(['apple']);
178+
expect(result).to.equal('apple');
179+
});
180+
181+
test('submit without nav resolves to [] in multiple', async () => {
182+
const instance = new AutocompletePrompt({
183+
input,
184+
output,
185+
render: () => 'foo',
186+
options: testOptions,
187+
multiple: true,
188+
});
189+
190+
const promise = instance.prompt();
191+
input.emit('keypress', '', { name: 'return' });
192+
const result = await promise;
193+
194+
expect(instance.selectedValues).to.deep.equal([]);
195+
expect(result).to.deep.equal([]);
196+
});
139197
});

0 commit comments

Comments
 (0)