All files / components/Accordion Accordion.jsx

100% Statements 11/11
75% Branches 3/4
100% Functions 2/2
100% Lines 11/11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110                  120x               120x             120x                                                                                   120x           2x   2x                       18x   18x   18x           32x       2x                  
import _ from 'lodash';
import React from 'react';
import { lucidClassNames } from '../../util/style-helpers';
import { createClass, findTypes, omitProps }  from '../../util/component-types';
 
import ExpanderPanel from '../ExpanderPanel/ExpanderPanel';
 
import * as reducers from '../Accordion/Accordion.reducers';
 
const cx = lucidClassNames.bind('&-Accordion');
 
const {
	any,
	func,
	object,
	number,
	string,
} = React.PropTypes;
 
/**
* {"categories": ["layout"], "madeFrom": ["ExpanderPanel"]}
*
* This is a container that renders panels and controls its expansion/retraction.
*/
const Accordion = createClass({
	displayName: 'Accordion',
 
	components: {
		Item: ExpanderPanel,
		Header: ExpanderPanel.Header,
	},
 
	reducers,
 
	propTypes: {
		/**
		* Appended to the component-specific class names set on the root
		* element.
		*/
		className: string,
 
		/**
		* Indicates which item is expanded.
		*/
		selectedIndex: number,
 
		/**
		* Called when the user clicks on the component's header of an item.
		*
		* Signature: `(itemIndex, { event, props }) => {}`
		*/
		onSelect: func,
 
		/**
		* Passed through to the root element.
		*/
		style: object,
 
		/**
		 * prop alternative to Header child component
		 * passed through to the underlying ExpanderPanel
		 */
		Header: any,
	},
 
	getDefaultProps() {
		return {
			onSelect: _.noop,
		};
	},
 
	handleToggle(isExpanded, index, event) {
		const selectedIndex = isExpanded ? index : null;
 
		this.props.onSelect(selectedIndex, {
			event,
			props: this.props,
		});
	},
 
	render() {
		const {
			style,
			className,
			selectedIndex,
			...passThroughs,
		} = this.props;
 
		const itemChildProps = _.map(findTypes(this.props, Accordion.Item), 'props');
 
		return (
			<div
				{...omitProps(passThroughs, Accordion)}
				className={cx('&', className)}
				style={style}>
				{_.map(itemChildProps, (itemChildProp, index) => {
					return <ExpanderPanel
							key={index}
							{...itemChildProp}
							className={cx('&-Item', itemChildProp.className)}
							onToggle={(isExpanded, { event }) => this.handleToggle(isExpanded, index, event)}
							isExpanded={!itemChildProp.isDisabled && selectedIndex === index}/>;
				})}
			</div>
		);
	},
});
 
export default Accordion;