Skip to content

Commit 417b451

Browse files
authored
feat(autocomplete): do not set default filter for options getters (#496)
1 parent 001351e commit 417b451

3 files changed

Lines changed: 54 additions & 5 deletions

File tree

.changeset/silent-sides-call.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+
Only apply autocomplete default filter if it has been explicitly set or if options is not a getter.

packages/core/src/prompts/autocomplete.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt<
7171
focusedValue: T['value'] | undefined;
7272
#cursor = 0;
7373
#lastUserInput = '';
74-
#filterFn: FilterFunction<T>;
74+
#filterFn: FilterFunction<T> | undefined;
7575
#options: T[] | (() => T[]);
7676
#placeholder: string | undefined;
7777

@@ -106,7 +106,8 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt<
106106
const options = this.options;
107107
this.filteredOptions = [...options];
108108
this.multiple = opts.multiple === true;
109-
this.#filterFn = opts.filter ?? defaultFilter;
109+
this.#filterFn =
110+
typeof opts.options === 'function' ? opts.filter : (opts.filter ?? defaultFilter);
110111
let initialValues: unknown[] | undefined;
111112
if (opts.initialValue && Array.isArray(opts.initialValue)) {
112113
if (this.multiple) {
@@ -160,7 +161,9 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt<
160161
const placeholderMatchesOption =
161162
placeholder !== undefined &&
162163
placeholder !== '' &&
163-
options.some((opt) => !opt.disabled && this.#filterFn(placeholder, opt));
164+
options.some(
165+
(opt) => !opt.disabled && (this.#filterFn ? this.#filterFn(placeholder, opt) : true)
166+
);
164167
if (key.name === 'tab' && isEmptyOrOnlyTab && placeholderMatchesOption) {
165168
if (this.userInput === '\t') {
166169
this._clearUserInput();
@@ -225,8 +228,8 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt<
225228

226229
const options = this.options;
227230

228-
if (value) {
229-
this.filteredOptions = options.filter((opt) => this.#filterFn(value, opt));
231+
if (value && this.#filterFn) {
232+
this.filteredOptions = options.filter((opt) => this.#filterFn?.(value, opt));
230233
} else {
231234
this.filteredOptions = [...options];
232235
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,47 @@ describe('AutocompletePrompt', () => {
216216
expect(result).to.equal('apple');
217217
});
218218

219+
test('options as function skips default filter', () => {
220+
const dynamicOptions = [
221+
{ value: 'apple', label: 'Apple' },
222+
{ value: 'banana', label: 'Banana' },
223+
];
224+
const instance = new AutocompletePrompt({
225+
input,
226+
output,
227+
render: () => 'foo',
228+
options: () => dynamicOptions,
229+
});
230+
231+
instance.prompt();
232+
233+
input.emit('keypress', 'z', { name: 'z' });
234+
235+
expect(instance.filteredOptions).toEqual(dynamicOptions);
236+
});
237+
238+
test('options as function applies user-provided filter', () => {
239+
const dynamicOptions = [
240+
{ value: 'apple', label: 'Apple' },
241+
{ value: 'banana', label: 'Banana' },
242+
{ value: 'cherry', label: 'Cherry' },
243+
];
244+
const instance = new AutocompletePrompt({
245+
input,
246+
output,
247+
render: () => 'foo',
248+
options: () => dynamicOptions,
249+
filter: (search, opt) => (opt.label ?? '').toLowerCase().endsWith(search.toLowerCase()),
250+
});
251+
252+
instance.prompt();
253+
254+
input.emit('keypress', 'a', { name: 'a' });
255+
256+
// 'endsWith' matches Banana but not Apple or Cherry
257+
expect(instance.filteredOptions).toEqual([{ value: 'banana', label: 'Banana' }]);
258+
});
259+
219260
test('Tab with non-matching placeholder does not fill input', async () => {
220261
const instance = new AutocompletePrompt({
221262
input,

0 commit comments

Comments
 (0)