Teren-app/resources/js/Components/app/ui/AppCombobox.vue

101 lines
2.4 KiB
Vue

<script setup>
import { CheckIcon, ChevronsUpDownIcon } from "lucide-vue-next";
import { computed, ref } from "vue";
import { cn } from "@/lib/utils";
import { Button } from "@/Components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/Components/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@/Components/ui/popover";
const props = defineProps({
modelValue: {
type: [String, Number],
default: "",
},
items: {
type: Array,
default: () => [],
},
placeholder: {
type: String,
default: "Select item...",
},
searchPlaceholder: {
type: String,
default: "Search...",
},
emptyText: {
type: String,
default: "No item found.",
},
disabled: {
type: Boolean,
default: false,
},
buttonClass: {
type: String,
default: "w-[200px]",
},
});
const emit = defineEmits(["update:modelValue"]);
const open = ref(false);
const selectedItem = computed(() =>
props.items.find((item) => item.value === props.modelValue)
);
function selectItem(selectedValue) {
const newValue = selectedValue === props.modelValue ? "" : selectedValue;
emit("update:modelValue", newValue);
open.value = false;
}
</script>
<template>
<Popover v-model:open="open">
<PopoverTrigger as-child>
<Button
variant="outline"
role="combobox"
:aria-expanded="open"
:disabled="disabled"
:class="cn('justify-between', buttonClass)"
>
{{ selectedItem?.label || placeholder }}
<ChevronsUpDownIcon class="opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent class="p-0" :class="buttonClass">
<Command>
<CommandInput class="h-9" :placeholder="searchPlaceholder" />
<CommandList>
<CommandEmpty>{{ emptyText }}</CommandEmpty>
<CommandGroup>
<CommandItem
v-for="item in items"
:key="item.value"
:value="item.value"
@select="selectItem"
>
{{ item.label }}
<CheckIcon
:class="
cn('ml-auto', modelValue === item.value ? 'opacity-100' : 'opacity-0')
"
/>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</template>