<template> <ComboBox v-model="modelValue" v-bind="props" :choices="filteredChoices" :close-on-select="props.closeOnSelect ?? !Array.isArray(modelValue)" input-container-class="tw-flex tw-flex-wrap tw-p-2 tw-gap-2 tw-items-baseline tw-w-full form-control tw-h-auto tw-min-h-[46px]" input-class="tw-border-none tw-px-1 tw-w-[100px] focus:tw-shadow-none focus:tw-outline-none focus:tw-ring-0" @search="searchQuery = $event" > <template #default="{ choice, ...attributes }"> <slot :choice="choice" v-bind="attributes"> <li v-bind="attributes"> {{ choice.name }} </li> </slot> </template> <template #selected="{ value, deselect, isOpen }"> <slot name="selected" :value="value" :deselect="deselect" :is-open="isOpen"> <template v-if="Array.isArray(value)"> <Tag v-for="(item, index) in value" :key="index" :label="item.name" removable @remove="deselect(item)" /> </template> <template v-else> <p v-if="value">{{ value.name }}</p> </template> </slot> </template> </ComboBox> </template> <script setup lang="ts" generic="T extends { id: ID, name: string }"> import { ID } from '@/api' import Tag from './generic/Tag.vue' import ComboBox from './ComboBox.vue' import type { ComboBoxProps } from '@/components/ComboBox.vue' import { computed, ref } from 'vue' import { matchesSearch } from '@/util' defineOptions({ compatConfig: { MODE: 3 }, }) defineSlots<{ default( props: Record<string, unknown> & { id: string choice: T index: number activeIndex: number }, ): unknown selected(props: { value: null | T | T[] deselect: (choice: null | T) => void isOpen: boolean }): unknown }>() const modelValue = defineModel<null | T | T[]>({ required: true }) const props = defineProps<ComboBoxProps<T>>() const searchQuery = ref('') const selectedIds = computed(() => { if (Array.isArray(modelValue.value)) { return modelValue.value.map((item) => item.id) } else if (modelValue.value !== null) { return [modelValue.value.id] } else { return [] } }) const filteredChoices = computed(() => props.choices.filter( ({ id, name }) => !selectedIds.value.includes(id) && matchesSearch(name, searchQuery.value), ), ) </script>