import { ArrowDropDown } from '@mui/icons-material' import clsx from 'clsx' import { useEffect, useRef, useState } from 'react' import { createPortal } from 'react-dom' import { useTranslation } from 'react-i18next' import { TypedOption } from '@dao-dao/types' import { useTrackDropdown } from '../../hooks/useTrackDropdown' import { Button } from '../buttons' export interface DropdownProps { options: TypedOption[] placeholder?: string selected?: T | T[] onSelect: (option: T, index: number) => void containerClassName?: string labelContainerClassName?: string labelClassName?: string iconClassName?: string keepOpenOnSelect?: boolean } export const Dropdown = ({ options, placeholder, selected, onSelect, containerClassName, labelContainerClassName, labelClassName, iconClassName, keepOpenOnSelect, }: DropdownProps) => { const { t } = useTranslation() const containerRef = useRef(null) const [open, setOpen] = useState(false) const selectedOptions = selected && Array.isArray(selected) ? options.filter(({ value }) => selected.includes(value)) : options.filter(({ value }) => selected === value) // Listen for click not in dropdown bounds, and close if so. Adds listener // only when the dropdown is open. useEffect(() => { // Don't do anything if not on browser or dropdown is not open. // If open is switched off, the useEffect will remove the listener and then // not-readd it. if (typeof window === 'undefined' || !open) { return } const closeIfClickOutside = (event: MouseEvent) => { // If clicked on an element that is not a descendant of this Dropdown's // outermost container, close the dropdown. if ( event.target instanceof Node && !containerRef.current?.contains(event.target) ) { setOpen(false) } } window.addEventListener('click', closeIfClickOutside) return () => window.removeEventListener('click', closeIfClickOutside) }, [open]) // Track button to position the dropdown. const { onDropdownRef, onTrackRef } = useTrackDropdown() return ( <>
{ containerRef.current = ref onTrackRef(ref) }} >
{/* Dropdown */} {createPortal(
{options.map((option, index) => ( ))}
, document.body )} ) }