import { CSSProperties, ReactNode, ReactElement, Children, useState, useEffect, cloneElement, } from 'react' import classNames from 'classnames' import { CommonComponentProps } from '../../utils/types' import './Accordion.scss' import { AccordionItem, AccordionItemProps } from './AccordionItem' export * from './AccordionItem' interface AccordionBaseProps extends CommonComponentProps { className?: string style?: CSSProperties children?: ReactNode duration?: number onChange?: (name: any) => void } interface AccordionSingleProps extends AccordionBaseProps { multiple?: false defaultActiveName?: any activeName?: any } interface AccordionMultipleProps extends AccordionBaseProps { multiple?: true defaultActiveName?: any[] activeName?: any[] } export type AccordionProps = AccordionSingleProps | AccordionMultipleProps export function Accordion(props: AccordionProps) { const { className, style, children, defaultActiveName, activeName, multiple = false, duration, onChange, ...restProps } = props const [innerName, setInnerName] = useState(() => { return activeName ?? defaultActiveName ?? (multiple ? [] : '') }) // 受控 useEffect(() => { if (activeName != null) { setInnerName(activeName) } }, [activeName]) const handleItemClick = (name: any) => { if (multiple) { name = innerName.includes(name) ? innerName.filter((item: any) => item !== name) : [...innerName, name] } else { name = name !== innerName ? name : '' } // 非受控 if (activeName == null) { setInnerName(name) } onChange?.(name) } const accordionClass = classNames('s-accordion', className) return (
{Children.map( children as ReactElement, (item: ReactElement, index: number) => { const name = item.props.name ?? index return cloneElement(item, { name, multiple, activeName: innerName, duration: item.props.duration ?? duration, onClick: () => handleItemClick(name), }) } )}
) } Accordion.Item = AccordionItem export default Accordion