import { Children, cloneElement, Component } from 'react'; import cx from 'classnames'; import kindOf from '../utils/kindOf'; import Panel from './Panel'; import { isElement } from 'react-is'; export interface ICollapsePropsAccordion extends ICollapsePropsBase { accordion: true; activeKey?: string; onChange: (value: string | null) => void; } export interface ICollapsePropsMultiple extends ICollapsePropsBase { accordion?: false; activeKey?: string[]; onChange: (value: string[]) => void; } interface ICollapsePropsBase { bordered?: boolean; panelTitleBackground?: string; className?: string; showContentBackground?: boolean; } // The I prefix is for backward compatibility export type ICollapseProps = ICollapsePropsAccordion | ICollapsePropsMultiple; export class Collapse extends Component { static defaultProps = { bordered: true, panelTitleBackground: 'default', accordion: false, }; static Panel = Panel; render() { const { className, bordered, panelTitleBackground, showContentBackground, children, activeKey, } = this.props; return (
{Children.map(children, (c, idx) => { if (!isElement(c) || !kindOf(c.type, Panel)) { throw new Error( `Invalid children supplied to Collapse. Each child should be a Panel.` ); } const key = c.key?.toString(); return cloneElement(c, { onChange: this.onChange, active: isPanelActive(activeKey, key), panelKey: key, panelTitleBackground, showContentBackground, isLast: idx === Children.count(children) - 1, bordered, }); })}
); } onChange = (key: string, active: boolean) => { if (this.props.accordion) { const { onChange, activeKey } = this.props; if (activeKey !== key && active) { onChange(key); } else if (activeKey === key && !active) { onChange(null); } } else { const { activeKey, onChange } = this.props as ICollapsePropsMultiple; const activeKeyArray = ([] as string[]).concat(activeKey ?? []); const keyIndex = activeKeyArray.indexOf(key); if (active) { keyIndex === -1 && activeKeyArray.push(key); } else { keyIndex !== -1 && activeKeyArray.splice(keyIndex, 1); } onChange(activeKeyArray); } }; } function isPanelActive( activeKey: string | string[] | undefined, key: string | undefined ) { if (typeof activeKey === 'string') { return activeKey === key; } if (Array.isArray(activeKey)) { return key !== undefined && activeKey.indexOf(key) !== -1; } return false; } export default Collapse;