reka-ui
Version:
Vue port for Radix UI Primitives.
55 lines (51 loc) • 2.06 kB
JavaScript
;
const shared = require('@vueuse/shared');
const shared_getActiveElement = require('./getActiveElement.cjs');
function useTypeahead(callback) {
const search = shared.refAutoReset("", 1e3);
const handleTypeaheadSearch = (key, items) => {
search.value = search.value + key;
{
const currentItem = shared_getActiveElement.getActiveElement();
const itemsWithTextValue = items.map((item) => ({
...item,
textValue: item.value?.textValue ?? item.ref.textContent?.trim() ?? ""
}));
const currentMatch = itemsWithTextValue.find((item) => item.ref === currentItem);
const values = itemsWithTextValue.map((item) => item.textValue);
const nextMatch = getNextMatch(values, search.value, currentMatch?.textValue);
const newItem = itemsWithTextValue.find((item) => item.textValue === nextMatch);
if (newItem)
newItem.ref.focus();
return newItem?.ref;
}
};
const resetTypeahead = () => {
search.value = "";
};
return {
search,
handleTypeaheadSearch,
resetTypeahead
};
}
function wrapArray(array, startIndex) {
return array.map((_, index) => array[(startIndex + index) % array.length]);
}
function getNextMatch(values, search, currentMatch) {
const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
const normalizedSearch = isRepeated ? search[0] : search;
const currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
let wrappedValues = wrapArray(values, Math.max(currentMatchIndex, 0));
const excludeCurrentMatch = normalizedSearch.length === 1;
if (excludeCurrentMatch)
wrappedValues = wrappedValues.filter((v) => v !== currentMatch);
const nextMatch = wrappedValues.find(
(value) => value.toLowerCase().startsWith(normalizedSearch.toLowerCase())
);
return nextMatch !== currentMatch ? nextMatch : void 0;
}
exports.getNextMatch = getNextMatch;
exports.useTypeahead = useTypeahead;
exports.wrapArray = wrapArray;
//# sourceMappingURL=useTypeahead.cjs.map