import * as React from 'react' import * as cx from 'classnames' import { connect } from 'react-redux' import { forceArray } from '../../utils' import { StylableComponent } from '../theme' import { Column } from '../flex' import { accordionExpand, accordionCollapse, accordionDestroy, } from './actions' import { AccordionProps, AccordionComponentProps } from './interfaces' import { getAccordionById } from './selectors' const styles = require('../../../src/components/accordion/styles.scss') class Component extends StylableComponent { public componentWillMount() { if (this.props.firstOpen) { const firstChild: JSX.Element = (forceArray(this.props.children)[0] as JSX.Element) this.props.accordionExpand(this.props.id, (firstChild.key as string)) } else { this.props.accordionCollapse(this.props.id) } } public componentWillUnmount() { this.props.accordionDestroy(this.props.id) } public render(): JSX.Element | null { if (!this.props.accordion) return null return ( {this.getChildNodes()} ) } private getChildNodes(): JSX.Element[] { return forceArray(this.props.children) .map((child: JSX.Element) => this.getChildNode(child)) } private getChildNode(child: JSX.Element): JSX.Element { if (!child || child.key === null || child.key === undefined || typeof child.key === 'number') { throw new Error('Accordion children MUST be a JSX element with a string key') } return React.cloneElement(child, { expanded: this.props.accordion.key === child.key, onToggle: this.mkHandleClick(child.key), }) } private mkHandleClick = (key: string) => (e: React.SyntheticEvent): void => { e.preventDefault() if (key === this.props.accordion.key) { this.props.accordionCollapse(this.props.id) } else { this.props.accordionExpand(this.props.id, key) } } } const mapStateToProps = (state: any, ownProps: AccordionProps) => ({ ...ownProps, accordion: getAccordionById(state, ownProps.id), }) const mapDispatchToProps = { accordionExpand, accordionCollapse, accordionDestroy } export const Accordion = connect(mapStateToProps, mapDispatchToProps)(Component)