import React, { FC, useMemo, useRef, useState } from "react"; import sortBy from "lodash/sortBy"; // headless ui import { Combobox } from "@headlessui/react"; // popper-js import { usePopper } from "react-popper"; // plane helpers import { useOutsideClickDetector } from "@plane/hooks"; // components import { DropdownButton } from "./common"; import { DropdownOptions } from "./common/options"; // hooks import { useDropdownKeyPressed } from "../hooks/use-dropdown-key-pressed"; // helper import { cn } from "../../helpers"; // types import { ISingleSelectDropdown } from "./dropdown"; export const Dropdown: FC = (props) => { const { value, onChange, options, onOpen, onClose, containerClassName, tabIndex, placement, disabled, buttonContent, buttonContainerClassName, buttonClassName, disableSearch, inputPlaceholder, inputClassName, inputIcon, inputContainerClassName, keyExtractor, optionsContainerClassName, queryArray, sortByKey, firstItem, renderItem, loader = false, disableSorting, } = props; // states const [isOpen, setIsOpen] = useState(false); const [query, setQuery] = useState(""); const [popperElement, setPopperElement] = useState(null); // refs const dropdownRef = useRef(null); // popper-js refs const [referenceElement, setReferenceElement] = useState(null); // popper-js init const { styles, attributes } = usePopper(referenceElement, popperElement, { placement: placement ?? "bottom-start", modifiers: [ { name: "preventOverflow", options: { padding: 12, }, }, ], }); // handlers const toggleDropdown = () => { if (!isOpen) onOpen?.(); setIsOpen((prevIsOpen) => !prevIsOpen); if (isOpen) onClose?.(); }; const handleOnClick = (e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); toggleDropdown(); }; const handleClose = () => { if (!isOpen) return; setIsOpen(false); onClose?.(); setQuery?.(""); }; // options const sortedOptions = useMemo(() => { if (!options) return undefined; const filteredOptions = queryArray ? (options || []).filter((options) => { const queryString = queryArray.map((query) => options.data[query]).join(" "); return queryString.toLowerCase().includes(query.toLowerCase()); }) : options; if (disableSorting || !sortByKey) return filteredOptions; return sortBy(filteredOptions, [ (option) => firstItem && firstItem(option.data[option.value]), (option) => !(value ?? []).includes(option.data[option.value]), () => sortByKey && sortByKey.toLowerCase(), ]); }, [query, options]); // hooks const handleKeyDown = useDropdownKeyPressed(toggleDropdown, handleClose); useOutsideClickDetector(dropdownRef, handleClose, true); return ( {isOpen && (
)}
); };