import React, { useState, useEffect, useRef } from "react"; import { useFormContext } from "react-hook-form"; import { createPortal } from "react-dom"; import "./MultiSelectDropdown.css"; const SelectMultiple = ({ name, options = [], label = "Select options", labelKey = "name", // Can now be a function or a string valueKey = "id", placeholder = "Please select...", IsLoading = false, }) => { const { setValue, watch } = useFormContext(); const selectedValues = watch(name) || []; const [isOpen, setIsOpen] = useState(false); const [searchText, setSearchText] = useState(""); const containerRef = useRef(null); const dropdownRef = useRef(null); const [dropdownStyles, setDropdownStyles] = useState({ top: 0, left: 0, width: 0 }); useEffect(() => { const handleClickOutside = (e) => { if ( containerRef.current && !containerRef.current.contains(e.target) && (!dropdownRef.current || !dropdownRef.current.contains(e.target)) ) { setIsOpen(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); useEffect(() => { if (isOpen && containerRef.current) { const rect = containerRef.current.getBoundingClientRect(); setDropdownStyles({ top: rect.bottom + window.scrollY, left: rect.left + window.scrollX, width: rect.width, }); } }, [isOpen]); const getLabel = (item) => { return typeof labelKey === "function" ? labelKey(item) : item[labelKey]; }; const handleCheckboxChange = (value) => { const updated = selectedValues.includes(value) ? selectedValues.filter((v) => v !== value) : [...selectedValues, value]; setValue(name, updated, { shouldValidate: true }); }; const filteredOptions = options.filter((item) => { const label = getLabel(item); return label?.toLowerCase().includes(searchText.toLowerCase()); }); const dropdownElement = (
setSearchText(e.target.value)} className="multi-select-dropdown-search-input" style={{ width: "100%", padding: 4 }} />
{filteredOptions.map((item) => { const labelVal = getLabel(item); const valueVal = item[valueKey]; const isChecked = selectedValues.includes(valueVal); return (
handleCheckboxChange(valueVal)} style={{ marginRight: 8 }} />
); })} {!IsLoading && filteredOptions.length === 0 && (
)} {IsLoading && filteredOptions.length === 0 && (
)}
); return ( <>
setIsOpen((prev) => !prev)} style={{ cursor: "pointer" }} > 0 ? "placeholder-style-selected" : "placeholder-style" } >
{selectedValues.length > 0 ? ( selectedValues.map((val) => { const found = options.find((opt) => opt[valueKey] === val); const label = found ? getLabel(found) : ""; return ( {label} ); }) ) : ( {placeholder} )}
{isOpen && createPortal(dropdownElement, document.body)} ); }; export default SelectMultiple;