import React, { useEffect, useRef, useState } from "react"; import styled from "styled-components"; import useDebounce from "../hooks/useDebounce"; import useOnClickOutside from "../hooks/useClickoutside"; const DropdownContainer = styled.div` position: relative; width: 400px; z-index: 100; margin-bottom: 5px; `; const SearchInput = styled.input` width: 100%; padding: 8px; box-sizing: border-box; background-color: ${({ theme }) => theme.background}; color: ${({ theme }) => theme.text}; `; const DropdownList = styled.ul` position: absolute; width: 100%; max-height: 200px; overflow-y: auto; background: white; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); margin: 0; padding: 0; list-style: none; background-color: ${({ theme }) => theme.background2}; color: ${({ theme }) => theme.text2}; `; const DropdownListItem = styled.li` padding: 8px; cursor: pointer; &:hover { background-color: ${({ theme }) => theme.background}; } `; interface DropdownProps { items: T[]; handleItemClick: (opt: T) => void; handleSearchChange: (val: string) => void; renderItem: ( item: T, searchTerm: string ) => { label: string; key: number | string; renderComp: () => React.JSX.Element; }; } const Dropdown = ({ items, handleItemClick, handleSearchChange, renderItem, }: DropdownProps) => { const [searchTerm, setSearchTerm] = useState(""); const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); const handleSearch = (e: React.ChangeEvent) => { setSearchTerm(e.target.value); }; const debouncedSearchVal = useDebounce(searchTerm, 1000); useEffect(() => { handleSearchChange(debouncedSearchVal); }, [debouncedSearchVal]); const handleSearchItemClick = (item: T) => { setIsOpen(false); handleItemClick(item); setSearchTerm(""); }; const handleClickOutside = () => { setIsOpen(false); }; useOnClickOutside(dropdownRef, handleClickOutside); return ( setIsOpen(true)} /> {isOpen && ( {searchTerm && !items.length && No Results} {items.map((item: T) => { const { key, label, renderComp } = renderItem(item, searchTerm); return ( handleSearchItemClick(item)} > {renderComp ? renderComp() : label} ); })} )} ); }; export default Dropdown;