melt
Version:
The next generation of Melt UI. Built for Svelte 5.
37 lines (36 loc) • 1.44 kB
JavaScript
import { useDebounce } from "runed";
import { extract } from "./extract";
export const letterRegex = /^[a-zA-Z]$/;
export function createTypeahead(args) {
let value = $state("");
const timeout = $derived(extract(args.timeout, 500));
const debounceClear = useDebounce(() => {
value = "";
}, () => timeout);
function typeahead(letter) {
if (!letterRegex.test(letter))
return;
debounceClear();
value += letter.toLowerCase();
const isStartingTypeahead = value.length === 1;
const items = args.getItems();
const index = items.findIndex((item) => item.current);
const itemsForTypeahead = items
.filter((item) => {
const searchValue = item.typeahead ?? item.value;
return searchValue.toLowerCase().startsWith(value);
})
.map((item) => ({ item, index: items.indexOf(item) }));
if (!itemsForTypeahead.length)
return;
// In case you're starting the typeahead, a different element than the first one should be focused.
// Otherwise, if the current element matches the typed string, don't change.
const next = itemsForTypeahead.find((item) => {
if (isStartingTypeahead)
return item.index > index;
return item.index >= index;
}) ?? itemsForTypeahead[0];
return next?.item;
}
return typeahead;
}