1
0
Fork 0
mirror of synced 2024-06-11 23:15:07 +12:00
budibase/packages/bbui/src/Form/Core/Multiselect.svelte

100 lines
2.5 KiB
Svelte

<script>
import Picker from "./Picker.svelte"
import { createEventDispatcher } from "svelte"
export let value = []
export let id = null
export let placeholder = null
export let disabled = false
export let error = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
export let readonly = false
export let autocomplete = false
export let sort = false
export let autoWidth = false
export let fetchTerm = null
export let useFetch = false
export let customPopoverHeight
const dispatch = createEventDispatcher()
$: arrayValue = Array.isArray(value) ? value : [value].filter(x => !!x)
$: selectedLookupMap = getSelectedLookupMap(arrayValue)
$: optionLookupMap = getOptionLookupMap(options)
$: fieldText = getFieldText(arrayValue, optionLookupMap, placeholder)
$: isOptionSelected = optionValue => selectedLookupMap[optionValue] === true
$: toggleOption = makeToggleOption(selectedLookupMap, arrayValue)
const getFieldText = (value, map, placeholder) => {
if (Array.isArray(value) && value.length > 0) {
if (!map) {
return ""
}
const vals = value.map(option => map[option] || option).join(", ")
return `(${value.length}) ${vals}`
} else {
return placeholder || "Choose some options"
}
}
const getSelectedLookupMap = value => {
let map = {}
if (Array.isArray(value) && value.length > 0) {
value.forEach(option => {
if (option) {
map[option] = true
}
})
}
return map
}
const getOptionLookupMap = options => {
let map = null
if (options?.length) {
map = {}
options.forEach((option, idx) => {
const optionValue = getOptionValue(option, idx)
if (optionValue != null) {
map[optionValue] = getOptionLabel(option, idx) || ""
}
})
}
return map
}
const makeToggleOption = (map, value) => {
return optionValue => {
if (map[optionValue]) {
const filtered = value.filter(option => option !== optionValue)
dispatch("change", filtered)
} else {
dispatch("change", [...value, optionValue])
}
}
}
</script>
<Picker
{id}
{error}
{disabled}
{readonly}
{fieldText}
{options}
isPlaceholder={!arrayValue.length}
{autocomplete}
bind:fetchTerm
{useFetch}
{isOptionSelected}
{getOptionLabel}
{getOptionValue}
onSelectOption={toggleOption}
{sort}
{autoWidth}
{customPopoverHeight}
/>