toby/resources/js/Shared/Forms/MultipleCombobox.vue
2022-05-11 10:34:11 +02:00

93 lines
2.6 KiB
Vue

<template>
<Combobox
v-model="selectedItems"
as="div"
nullable
multiple
>
<div class="flex flex-wrap gap-3">
<button
v-for="(item, index) in selectedItems"
:key="index"
type="button"
class="py-1 px-2 bg-gray-200 rounded-md"
@click="selectedItems.splice(index, 1)"
>
{{ item }}
</button>
</div>
<div class="relative mt-2">
<ComboboxInput
:id="id"
class="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-blumilk-500 focus:outline-none focus:ring-1 focus:ring-blumilk-500 sm:text-sm"
@change="query = $event.target.value"
/>
<ComboboxButton class="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none">
<SelectorIcon class="h-5 w-5 text-gray-400" />
</ComboboxButton>
<ComboboxOptions
v-if="filteredItems.length"
class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
>
<ComboboxOption
v-for="item in filteredItems"
:key="item.id"
v-slot="{ active, selected }"
:value="item"
as="template"
>
<li :class="['relative cursor-default select-none py-2 pl-3 pr-9', active ? 'bg-blumilk-600 text-white' : 'text-gray-900']">
<span :class="['block truncate', selected && 'font-semibold']">
{{ item }}
</span>
<span
v-if="selected"
:class="['absolute inset-y-0 right-0 flex items-center pr-4', active ? 'text-white' : 'text-blumilk-600']"
>
<CheckIcon class="h-5 w-5" />
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</div>
</Combobox>
</template>
<script setup>
import { computed, ref } from 'vue'
import { CheckIcon, SelectorIcon } from '@heroicons/vue/solid'
import {
Combobox,
ComboboxButton,
ComboboxInput,
ComboboxOption,
ComboboxOptions,
} from '@headlessui/vue'
const props = defineProps({
items: Array,
modelValue: Array,
id: String,
})
const emit = defineEmits(['update:modelValue'])
const query = ref('')
const selectedItems = computed({
get: () => props.modelValue,
set: (value) => {
query.value = ''
emit('update:modelValue', value)
},
})
const filteredItems = computed(() =>
query.value === ''
? props.items
: props.items.filter((item) => item.toLowerCase().includes(query.value.toLowerCase())),
)
</script>