Fix typeahead search logic when repeating a letter
Fixes #35
This ports 186a4cfcef
This commit is contained in:
@@ -139,14 +139,22 @@
|
||||
|
||||
searchQuery += value.toLowerCase();
|
||||
|
||||
let match = options.findIndex(
|
||||
let reorderedOptions =
|
||||
activeOptionIndex !== null
|
||||
? options
|
||||
.slice(activeOptionIndex + 1)
|
||||
.concat(options.slice(0, activeOptionIndex + 1))
|
||||
: options;
|
||||
|
||||
let matchingOption = reorderedOptions.find(
|
||||
(option) =>
|
||||
!option.dataRef.disabled &&
|
||||
option.dataRef.textValue.startsWith(searchQuery)
|
||||
);
|
||||
|
||||
if (match === -1 || match === activeOptionIndex) return;
|
||||
activeOptionIndex = match;
|
||||
let matchIdx = matchingOption ? options.indexOf(matchingOption) : -1;
|
||||
if (matchIdx === -1 || matchIdx === activeOptionIndex) return;
|
||||
activeOptionIndex = matchIdx;
|
||||
},
|
||||
clearSearch() {
|
||||
if (disabled) return;
|
||||
|
||||
40
src/lib/components/listbox/listbox.test.ts
vendored
40
src/lib/components/listbox/listbox.test.ts
vendored
@@ -3125,6 +3125,46 @@ describe('Keyboard interactions', () => {
|
||||
assertActiveListboxOption(options[1])
|
||||
})
|
||||
)
|
||||
|
||||
it(
|
||||
'should be possible to search for the next occurence',
|
||||
suppressConsoleLogs(async () => {
|
||||
render(svelte`
|
||||
<Listbox value={undefined} onChange={console.log}>
|
||||
<ListboxButton>Trigger</ListboxButton>
|
||||
<ListboxOptions>
|
||||
<ListboxOption value="a">alice</ListboxOption>
|
||||
<ListboxOption value="b">bob</ListboxOption>
|
||||
<ListboxOption value="c">charlie</ListboxOption>
|
||||
<ListboxOption value="d">bob</ListboxOption>
|
||||
</ListboxOptions>
|
||||
</Listbox>
|
||||
`)
|
||||
|
||||
// Open listbox
|
||||
await click(getListboxButton())
|
||||
|
||||
let options = getListboxOptions()
|
||||
|
||||
// Search for bob
|
||||
await type(word('b'))
|
||||
|
||||
// We should be on the first `bob`
|
||||
assertActiveListboxOption(options[1])
|
||||
|
||||
// Search for bob again
|
||||
await type(word('b'))
|
||||
|
||||
// We should be on the second `bob`
|
||||
assertActiveListboxOption(options[3])
|
||||
|
||||
// Search for bob once again
|
||||
await type(word('b'))
|
||||
|
||||
// We should be back on the first `bob`
|
||||
assertActiveListboxOption(options[1])
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -99,14 +99,22 @@
|
||||
search(value: string) {
|
||||
searchQuery += value.toLowerCase();
|
||||
|
||||
let match = items.findIndex(
|
||||
let reorderedItems =
|
||||
activeItemIndex !== null
|
||||
? items
|
||||
.slice(activeItemIndex + 1)
|
||||
.concat(items.slice(0, activeItemIndex + 1))
|
||||
: items;
|
||||
|
||||
let matchingItem = reorderedItems.find(
|
||||
(item) =>
|
||||
item.data.textValue.startsWith(searchQuery) && !item.data.disabled
|
||||
);
|
||||
|
||||
if (match === -1 || match === activeItemIndex) return;
|
||||
let matchIdx = matchingItem ? items.indexOf(matchingItem) : -1;
|
||||
if (matchIdx === -1 || matchIdx === activeItemIndex) return;
|
||||
|
||||
activeItemIndex = match;
|
||||
activeItemIndex = matchIdx;
|
||||
},
|
||||
clearSearch() {
|
||||
searchQuery = "";
|
||||
|
||||
40
src/lib/components/menu/menu.test.ts
vendored
40
src/lib/components/menu/menu.test.ts
vendored
@@ -2682,6 +2682,46 @@ describe('Keyboard interactions', () => {
|
||||
assertMenuLinkedWithMenuItem(items[1])
|
||||
})
|
||||
)
|
||||
|
||||
it(
|
||||
'should be possible to search for the next occurence',
|
||||
suppressConsoleLogs(async () => {
|
||||
render(svelte`
|
||||
<Menu>
|
||||
<MenuButton>Trigger</MenuButton>
|
||||
<MenuItems>
|
||||
<MenuItem as="a">alice</MenuItem>
|
||||
<MenuItem as="a">bob</MenuItem>
|
||||
<MenuItem as="a">charlie</MenuItem>
|
||||
<MenuItem as="a">bob</MenuItem>
|
||||
</MenuItems>
|
||||
</Menu>
|
||||
`)
|
||||
|
||||
// Open menu
|
||||
await click(getMenuButton())
|
||||
|
||||
let items = getMenuItems()
|
||||
|
||||
// Search for bob
|
||||
await type(word('b'))
|
||||
|
||||
// We should be on the first `bob`
|
||||
assertMenuLinkedWithMenuItem(items[1])
|
||||
|
||||
// Search for bob again
|
||||
await type(word('b'))
|
||||
|
||||
// We should be on the second `bob`
|
||||
assertMenuLinkedWithMenuItem(items[3])
|
||||
|
||||
// Search for bob once again
|
||||
await type(word('b'))
|
||||
|
||||
// We should be back on the first `bob`
|
||||
assertMenuLinkedWithMenuItem(items[1])
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user