import React, { useEffect, useRef, useState } from "react"; import { Arrow } from "./Arrow"; import "./MultiSelect.css"; import { IProps, Item } from "./Types"; import useKeyPress from "./UseKeyPress"; function MultiSelect({ placeholder = "select", list = [], selectedItems, setSelectedItems: setselectedItems, enableSearch = true, colorSelectedItem = { border: "green", background: "#cecec" }, selectBoxcss = {}, }: IProps) { const searchInputRef = useRef(); const [showDropDownBox, setshowDropDownBox] = useState(false); const [filtertext, setFiltertext] = useState(""); const [allItem, setAllItem] = useState(list); const [isFocused, setisFocused] = useState(false); const [currentFocusedLabelIndex, setCurrentFocusedLabel] = useState(0); const handleAddItem = (itemToBeAdded: Item) => { const doesItemAlreadyExist = selectedItems.find( (item) => item.key === itemToBeAdded.key ); if (doesItemAlreadyExist) return; setselectedItems([...selectedItems, itemToBeAdded]); }; const handleRemoveItem = (itemToBeRemoved: Item) => { setselectedItems( selectedItems.filter((item) => item.key !== itemToBeRemoved.key) ); }; useEffect(() => { window.addEventListener("click", () => { isFocused ? setshowDropDownBox(true) : setshowDropDownBox(false); }); return () => { window.removeEventListener("click", () => {}); }; }, [isFocused]); const arrowUpPressed = useKeyPress("ArrowUp"); const arrowDownPressed = useKeyPress("ArrowDown"); const enterPressed = useKeyPress("Enter"); const escPressed = useKeyPress("Escape"); useEffect(() => { if (arrowUpPressed) { currentFocusedLabelIndex === 0 ? setCurrentFocusedLabel(allItem.length - 1) : setCurrentFocusedLabel(currentFocusedLabelIndex - 1); } }, [arrowUpPressed]); useEffect(() => { if (arrowDownPressed) { currentFocusedLabelIndex === allItem.length - 1 ? setCurrentFocusedLabel(0) : setCurrentFocusedLabel(currentFocusedLabelIndex + 1); } }, [arrowDownPressed]); useEffect(() => { if (enterPressed) { if (!showDropDownBox) { setshowDropDownBox(true); return; } const itemTobeAdded = allItem[currentFocusedLabelIndex]; handleAddItem(itemTobeAdded); } }, [enterPressed]); useEffect(() => { if (escPressed) { setshowDropDownBox(false); } }, [escPressed]); function searchHighLightedResult(label: string): React.ReactNode { if (filtertext.length === 0) return label; if (label.toLowerCase().startsWith(filtertext)) return ( <> {filtertext} {label.split(filtertext).at(1)} ); return ( <> {label.split(filtertext).at(0)} {filtertext} {label.split(filtertext).at(1)} ); } return (
{ setisFocused(false); }} onMouseEnter={() => { setisFocused(true); searchInputRef?.current?.focus(); }} >
{selectedItems.length === 0 && (
{ setshowDropDownBox(!showDropDownBox); setisFocused(true); }} > {placeholder} ...
)} {selectedItems.map((item) => (
handleRemoveItem(item)} > {item.label} x
))}
{ showDropDownBox ? setisFocused(false) : setisFocused(true); setshowDropDownBox(!showDropDownBox); }} >
{enableSearch && ( { setFiltertext(e.target.value.toLowerCase()); setAllItem( list.filter((item) => item.label .toLowerCase() .includes(e.target.value.toLowerCase()) ) ); }} /> )}
{allItem.map((s, index) => (
handleAddItem(s)} > {searchHighLightedResult(s.label.toLowerCase())}
))}
); } export { MultiSelect };