UNPKG

semantic-ui-react

Version:
215 lines (171 loc) 7.5 kB
import _extends from 'babel-runtime/helpers/extends'; import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _createClass from 'babel-runtime/helpers/createClass'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; import _keys from 'lodash/keys'; import _omit from 'lodash/omit'; import _isFunction from 'lodash/isFunction'; import _each from 'lodash/each'; import _has from 'lodash/has'; import _without from 'lodash/without'; import _includes from 'lodash/includes'; import cx from 'classnames'; import React, { Children, cloneElement, PropTypes } from 'react'; import { AutoControlledComponent as Component, customPropTypes, getElementType, META, useKeyOnly } from '../../lib'; import AccordionContent from './AccordionContent'; import AccordionTitle from './AccordionTitle'; /** * An accordion allows users to toggle the display of sections of content. */ var Accordion = function (_Component) { _inherits(Accordion, _Component); function Accordion() { var _ref; _classCallCheck(this, Accordion); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var _this = _possibleConstructorReturn(this, (_ref = Accordion.__proto__ || Object.getPrototypeOf(Accordion)).call.apply(_ref, [this].concat(args))); _this.state = {}; _this.handleTitleClick = function (e, index) { var _this$props = _this.props, onTitleClick = _this$props.onTitleClick, exclusive = _this$props.exclusive; var activeIndex = _this.state.activeIndex; var newIndex = void 0; if (exclusive) { newIndex = index === activeIndex ? -1 : index; } else { // check to see if index is in array, and remove it, if not then add it newIndex = _includes(activeIndex, index) ? _without(activeIndex, index) : [].concat(_toConsumableArray(activeIndex), [index]); } _this.trySetState({ activeIndex: newIndex }); if (onTitleClick) onTitleClick(e, index); }; _this.isIndexActive = function (index) { var exclusive = _this.props.exclusive; var activeIndex = _this.state.activeIndex; return exclusive ? activeIndex === index : _includes(activeIndex, index); }; _this.renderChildren = function () { var children = _this.props.children; var titleIndex = 0; var contentIndex = 0; return Children.map(children, function (child) { var isTitle = child.type === AccordionTitle; var isContent = child.type === AccordionContent; if (isTitle) { var currentIndex = titleIndex; var isActive = _has(child, 'props.active') ? child.props.active : _this.isIndexActive(titleIndex); var onClick = function onClick(e) { _this.handleTitleClick(e, currentIndex); if (child.props.onClick) child.props.onClick(e, currentIndex); }; titleIndex++; return cloneElement(child, _extends({}, child.props, { active: isActive, onClick: onClick })); } if (isContent) { var _isActive = _has(child, 'props.active') ? child.props.active : _this.isIndexActive(contentIndex); contentIndex++; return cloneElement(child, _extends({}, child.props, { active: _isActive })); } return child; }); }; _this.renderPanels = function () { var panels = _this.props.panels; var children = []; _each(panels, function (panel, i) { var isActive = _has(panel, 'active') ? panel.active : _this.isIndexActive(i); var onClick = function onClick(e) { _this.handleTitleClick(e, i); if (panel.onClick) panel.onClick(e, i); }; // implement all methods of creating a key that are supported in factories var key = panel.key || _isFunction(panel.childKey) && panel.childKey(panel) || panel.childKey && panel.childKey || panel.title; children.push(AccordionTitle.create({ active: isActive, onClick: onClick, key: key + '-title', content: panel.title })); children.push(AccordionContent.create({ active: isActive, key: key + '-content', content: panel.content })); }); return children; }; _this.state = { activeIndex: _this.props.exclusive ? -1 : [-1] }; return _this; } _createClass(Accordion, [{ key: 'render', value: function render() { var _props = this.props, className = _props.className, fluid = _props.fluid, inverted = _props.inverted, panels = _props.panels, styled = _props.styled; var classes = cx('ui', useKeyOnly(fluid, 'fluid'), useKeyOnly(inverted, 'inverted'), useKeyOnly(styled, 'styled'), 'accordion', className); var rest = _omit(this.props, _keys(Accordion.propTypes)); var ElementType = getElementType(Accordion, this.props); return React.createElement( ElementType, _extends({}, rest, { className: classes }), panels ? this.renderPanels() : this.renderChildren() ); } }]); return Accordion; }(Component); Accordion.defaultProps = { exclusive: true }; Accordion.autoControlledProps = ['activeIndex']; Accordion._meta = { name: 'Accordion', type: META.TYPES.MODULE }; Accordion.Content = AccordionContent; Accordion.Title = AccordionTitle; export default Accordion; process.env.NODE_ENV !== "production" ? Accordion.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, /** Index of the currently active panel. */ activeIndex: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), /** Primary content. */ children: PropTypes.node, /** Additional classes. */ className: PropTypes.string, /** Initial activeIndex value. */ defaultActiveIndex: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), /** Only allow one panel open at a time. */ exclusive: PropTypes.bool, /** Format to take up the width of it's container. */ fluid: PropTypes.bool, /** Format for dark backgrounds. */ inverted: PropTypes.bool, /** * Called when a panel title is clicked. * * @param {SyntheticEvent} event - React's original SyntheticEvent. * @param {number} index - The index of the clicked panel. */ onTitleClick: PropTypes.func, /** * Create simple accordion panels from an array of { text: <string>, content: <custom> } objects. * Object can optionally define an `active` key to open/close the panel. * Object can opitonally define a `key` key used for title and content nodes' keys. * Mutually exclusive with children. * TODO: AccordionPanel should be a sub-component */ panels: customPropTypes.every([customPropTypes.disallow(['children']), PropTypes.arrayOf(PropTypes.shape({ key: PropTypes.string, active: PropTypes.bool, title: customPropTypes.contentShorthand, content: customPropTypes.contentShorthand, onClick: PropTypes.func }))]), /** Adds some basic styling to accordion panels. */ styled: PropTypes.bool } : void 0; Accordion.handledProps = ['activeIndex', 'as', 'children', 'className', 'defaultActiveIndex', 'exclusive', 'fluid', 'inverted', 'onTitleClick', 'panels', 'styled'];