import React from "react"; // headless ui import { Listbox, Transition } from "@headlessui/react"; // icons import { CheckIcon } from "@heroicons/react/20/solid"; import { Props } from "./types"; const CustomListbox: React.FC<Props> = ({ title = "", options, value, onChange, multiple, icon, width, footerOption, optionsFontsize, className, label, }) => { return ( <Listbox value={value} onChange={onChange} multiple={multiple}> {({ open }) => ( <> {label && ( <Listbox.Label> <div className="text-gray-500 mb-2">{label}</div> </Listbox.Label> )} <div className="relative"> <Listbox.Button className={`flex items-center gap-1 hover:bg-gray-100 relative border rounded-md shadow-sm cursor-pointer focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm duration-300 ${ width === "sm" ? "w-32" : width === "md" ? "w-48" : width === "lg" ? "w-64" : width === "xl" ? "w-80" : width === "2xl" ? "w-96" : width === "w-full" ? "w-full" : "" } ${className || "px-2 py-1"}`} > {icon ?? null} <span className="block truncate"> {Array.isArray(value) ? value.map((v) => options?.find((o) => o.value === v)?.display).join(", ") || `${title}` : options?.find((o) => o.value === value)?.display || `${title}`} </span> </Listbox.Button> <Transition show={open} as={React.Fragment} leave="transition ease-in duration-100" leaveFrom="opacity-100" leaveTo="opacity-0" > <Listbox.Options className={`absolute mt-1 bg-white shadow-lg max-h-32 overflow-auto ${ width === "sm" ? "w-32" : width === "md" ? "w-48" : width === "lg" ? "w-64" : width === "xl" ? "w-80" : width === "2xl" ? "w-96" : width === "w-full" ? "w-full" : "" } ${ optionsFontsize === "sm" ? "text-xs" : optionsFontsize === "md" ? "text-base" : optionsFontsize === "lg" ? "text-lg" : optionsFontsize === "xl" ? "text-xl" : optionsFontsize === "2xl" ? "text-2xl" : "" } rounded-md py-1 ring-1 ring-black ring-opacity-5 focus:outline-none z-10`} > <div className="p-1"> {options ? ( options.length > 0 ? ( options.map((option) => ( <Listbox.Option key={option.value} className={({ active }) => `${ active ? "text-white bg-theme" : "text-gray-900" } cursor-pointer select-none relative p-2 rounded-md` } value={option.value} > {({ selected, active }) => ( <> <span className={`${ selected || (Array.isArray(value) ? value.includes(option.value) : value === option.value) ? "font-semibold" : "font-normal" } block truncate`} > {option.display} </span> {selected || (Array.isArray(value) ? value.includes(option.value) : value === option.value) ? ( <span className={`absolute inset-y-0 right-0 flex items-center pr-4 ${ active || (Array.isArray(value) ? value.includes(option.value) : value === option.value) ? "text-white" : "text-indigo-600" }`} > <CheckIcon className="h-5 w-5" aria-hidden="true" /> </span> ) : null} </> )} </Listbox.Option> )) ) : ( <p className="text-sm text-gray-500 text-center">No options</p> ) ) : ( <p className="text-sm text-gray-500 text-center">Loading...</p> )} </div> {footerOption ?? null} </Listbox.Options> </Transition> </div> </> )} </Listbox> ); }; export default CustomListbox;