'use client' import type { FC } from 'react' import React, { Fragment, useEffect, useState } from 'react' import { Combobox, Listbox, Transition } from '@headlessui/react' import classNames from 'classnames' import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/20/solid' import { useTranslation } from 'react-i18next' const defaultItems = [ { value: 1, name: 'option1' }, { value: 2, name: 'option2' }, { value: 3, name: 'option3' }, { value: 4, name: 'option4' }, { value: 5, name: 'option5' }, { value: 6, name: 'option6' }, { value: 7, name: 'option7' }, ] export type Item = { value: number | string name: string } export type ISelectProps = { className?: string wrapperClassName?: string items?: Item[] defaultValue?: number | string disabled?: boolean onSelect: (value: Item) => void allowSearch?: boolean bgClassName?: string placeholder?: string } const Select: FC = ({ className, items = defaultItems, defaultValue = 1, disabled = false, onSelect, allowSearch = true, bgClassName = 'bg-gray-100', }) => { const [query, setQuery] = useState('') const [open, setOpen] = useState(false) const [selectedItem, setSelectedItem] = useState(null) useEffect(() => { let defaultSelect = null const existed = items.find((item: Item) => item.value === defaultValue) if (existed) { defaultSelect = existed } setSelectedItem(defaultSelect) }, [defaultValue]) const filteredItems: Item[] = query === '' ? items : items.filter((item) => { return item.name.toLowerCase().includes(query.toLowerCase()) }) return ( { if (!disabled) { setSelectedItem(value) setOpen(false) onSelect(value) } }}>
{allowSearch ? { if (!disabled) setQuery(event.target.value) }} displayValue={(item: Item) => item?.name} /> : { if (!disabled) setOpen(!open) } } className={`flex items-center h-9 w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200`}> {selectedItem?.name} } { if (!disabled) setOpen(!open) } }> {open ? : }
{filteredItems.length > 0 && ( {filteredItems.map((item: Item) => ( classNames( 'relative cursor-default select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700', active ? 'bg-gray-100' : '', ) } > {({ /* active, */ selected }) => ( <> {item.name} {selected && ( )} )} ))} )}
) } const SimpleSelect: FC = ({ className, wrapperClassName, items = defaultItems, defaultValue = 1, disabled = false, onSelect, placeholder, }) => { const { t } = useTranslation() const localPlaceholder = placeholder || t('common.placeholder.select') const [selectedItem, setSelectedItem] = useState(null) useEffect(() => { let defaultSelect = null const existed = items.find((item: Item) => item.value === defaultValue) if (existed) { defaultSelect = existed } setSelectedItem(defaultSelect) }, [defaultValue]) return ( { if (!disabled) { setSelectedItem(value) onSelect(value) } }} >
{selectedItem?.name ?? localPlaceholder} {items.map((item: Item) => ( `relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700 ${active ? 'bg-gray-100' : '' }` } value={item} disabled={disabled} > {({ /* active, */ selected }) => ( <> {item.name} {selected && ( )} )} ))}
) } export { SimpleSelect } export default React.memo(Select)