59 lines
1.5 KiB
Svelte
59 lines
1.5 KiB
Svelte
<script>
|
|
import Fuse from "fuse.js";
|
|
import {createEventDispatcher} from "svelte";
|
|
|
|
export let field;
|
|
export let value;
|
|
export let search = "";
|
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
|
|
function select(e, option) {
|
|
e.preventDefault();
|
|
value = option.value;
|
|
search = "";
|
|
dispatch("selected", {option: option})
|
|
}
|
|
|
|
|
|
function formatOptionsForSearch(listOptions) {
|
|
if (Array.isArray(listOptions)) {
|
|
return listOptions.map(value => {
|
|
return {
|
|
value: value,
|
|
label: value,
|
|
}
|
|
})
|
|
}
|
|
|
|
return Object.entries(listOptions).map(([k, v]) => {
|
|
return {
|
|
value: k,
|
|
label: v,
|
|
}
|
|
})
|
|
}
|
|
|
|
let formattedOptions = formatOptionsForSearch(field.selectOptions);
|
|
const fuse = new Fuse(formattedOptions, {
|
|
includeScore: false,
|
|
keys: ['value', 'label']
|
|
})
|
|
$: result = search === "" ? formattedOptions : fuse.search(search).map(resItem => resItem.item)
|
|
</script>
|
|
|
|
{#if result}
|
|
{#each result as suggestion (suggestion.value)}
|
|
<div
|
|
class="autocomplete-option"
|
|
role="button"
|
|
tabindex="0"
|
|
on:click={(e) => select(e, suggestion)}
|
|
on:keypress={(e) => select(e, suggestion)}
|
|
>
|
|
{suggestion.label}
|
|
</div>
|
|
{/each}
|
|
{/if}
|