Skip to content
64 changes: 51 additions & 13 deletions src/Typeahead.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

/** @type {(item: Item) => Item} */
export let extract = (item) => item;

/** @type {(item: Item) => Item} */
export let selection = (item) => false;

/** @type {(item: Item) => Item} */
export let disable = (item) => false;
Expand Down Expand Up @@ -48,6 +51,38 @@
let hideDropdown = false;
let selectedIndex = -1;
let prevResults = "";

function setNextSelectedIndex(i = 0) {
i += 1;

selectedIndex += 1;
if (selectedIndex === results.length) {
selectedIndex = 0;
}

if(results.lenght == 0 || !(selectedIndex in results) || i > results.lenght) {
selectedIndex = -1;
} else if(results[selectedIndex].disabled) {
setNextSelectedIndex(i);
}

};

function setPreviousSelectedIndex(i = 0) {
i += 1;

selectedIndex -= 1;
if (selectedIndex < 0) {
selectedIndex = results.length - 1;
}

if(results.lenght == 0 || i > results.lenght) {
selectedIndex = -1;
} else if(results[selectedIndex].disabled) {
setPreviousSelectedIndex(i);
}

};

afterUpdate(() => {
if (prevResults !== resultsId && autoselect) {
Expand Down Expand Up @@ -89,7 +124,11 @@
.filter(value, data, options)
.filter(({ score }) => score > 0)
.filter((result) => !filter(result.original))
.map((result) => ({ ...result, disabled: disable(result.original) }));
.map((result)=> ({
...result,
disabled: disable(result.original),
selected: selection(result.original)
}));
$: resultsId = results.map((result) => extract(result.original)).join("");
</script>

Expand Down Expand Up @@ -139,17 +178,11 @@
break;
case 'ArrowDown':
e.preventDefault();
selectedIndex += 1;
if (selectedIndex === results.length) {
selectedIndex = 0;
}
setNextSelectedIndex();
break;
case 'ArrowUp':
e.preventDefault();
selectedIndex -= 1;
if (selectedIndex < 0) {
selectedIndex = results.length - 1;
}
setPreviousSelectedIndex();
break;
case 'Escape':
e.preventDefault();
Expand All @@ -171,7 +204,8 @@
<li
role="option"
id="{id}-result"
class:selected={selectedIndex === i}
class:active={selectedIndex === i}
class:selected={result.selected}
class:disabled={result.disabled}
aria-selected={selectedIndex === i}
on:click={() => {
Expand Down Expand Up @@ -228,18 +262,22 @@
background-color: #cacaca;
}

.active {
background-color: #d8e9f3;
}

.disabled {
opacity: 0.4;
cursor: not-allowed;
}

:global([data-svelte-search] label) {
[data-svelte-typeahead] :global([data-svelte-search] label) {
margin-bottom: 0.25rem;
display: inline-flex;
font-size: 0.875rem;
}

:global([data-svelte-search] input) {
[data-svelte-typeahead] :global([data-svelte-search] input) {
width: 100%;
padding: 0.5rem 0.75rem;
background: none;
Expand All @@ -249,7 +287,7 @@
border: 1px solid #e5e5e5;
}

:global([data-svelte-search] input:focus) {
[data-svelte-typeahead] :global([data-svelte-search] input:focus) {
outline-color: #0f62fe;
outline-offset: 2px;
outline-width: 1px;
Expand Down
5 changes: 5 additions & 0 deletions types/Typeahead.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export interface TypeaheadProps extends SearchProps {
* @default (item) => item
*/
extract?: (item: Item) => Item;

/**
* @default (item) => item
*/
selection?: (item: Item) => Item;

/**
* @default (item) => false
Expand Down