101 lines
2.4 KiB
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>
|