import { CSSProperties, ReactNode, useEffect, useRef, useState } from 'react' import classNames from 'classnames' import { CommonComponentProps } from '../../utils/types' import { Popup } from '../popup/Popup' import { DropdownOption } from './DropdownOption' import { Icon } from '../icon/Icon' import './Dropdown.scss' import { DropdownOptionProps } from './DropdownOption' import { useEvent } from '../../use' export interface DropdownItemProps extends CommonComponentProps { className?: string style?: CSSProperties children?: ReactNode label?: ReactNode placeholder?: ReactNode options?: DropdownOptionProps[] disabled?: boolean value?: any defaultValue?: any onChange?: (value: any) => void } export function DropdownItem(props: DropdownItemProps) { const { className, style, children, placeholder, options = [], disabled, value, defaultValue, onChange, ...restProps } = props const [innerValue, setInnerValue] = useState(value ?? defaultValue ?? null) // 受控 useEffect(() => { if (value != null) { setInnerValue(value) } }, [value]) const [visible, setVisible] = useState(false) const optionsRef = useRef(null) const itemRef = useRef(null) const handleItemClick = () => { setVisible(!visible) } const handleDocumentClick = useEvent((event: MouseEvent) => { if ( visible && !optionsRef.current?.contains(event.target as Node) && !itemRef.current?.contains(event.target as Node) ) { setVisible(false) } }) useEffect(() => { document.addEventListener('click', handleDocumentClick) return () => { document.removeEventListener('click', handleDocumentClick) } }, []) const handleOptionClick = (option: DropdownOptionProps) => { if (option.value !== innerValue) { // 非受控 if (value == null) { setInnerValue(option.value) } onChange?.(option.value) } setVisible(false) } const itemClass = classNames( 's-dropdown-item', { 's-dropdown-item-show': visible, 's-dropdown-item-disabled': disabled, }, className ) return ( <>
{children &&
{children}
} {(innerValue && (
{options.find((option) => option.value === innerValue)?.label}
)) || (placeholder && (
{placeholder}
))}
{options.map((option, index) => ( handleOptionClick(option)} > ))}
) } export default DropdownItem