UNPKG

react-accordion-with-header

Version:
164 lines (131 loc) 6.14 kB
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } import React, { PureComponent, Children, cloneElement } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; var defaultProps = { speed: 250 }; var defaultStyle = { overflow: 'hidden', padding: 0 }; var AccordionPanel = function (_PureComponent) { _inherits(AccordionPanel, _PureComponent); function AccordionPanel() { var _temp, _this, _ret; _classCallCheck(this, AccordionPanel); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, _PureComponent.call.apply(_PureComponent, [this].concat(args))), _this), _this.state = { panelHeight: 0 }, _this.preloadImages = function () { var images = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var imagesLoaded = 0; var imgLoaded = function imgLoaded(data) { imagesLoaded++; if (imagesLoaded === images.length) _this.calcHeight(); }; images.forEach(function (element) { var img = new Image(); img.src = element.src; img.onload = img.onerror = imgLoaded; }); }, _this.calcHeight = function () { if (_this.componentRef) { var _panelHeight = _this.componentRef.current.clientHeight; _this.setState({ panelHeight: _panelHeight }); return; } var panelHeight = Children.map(_this.props.children, function (child, i) { return _this.refs['item-' + child.props.key]; }).reduce(function (previousValue, child) { return previousValue + child.clientHeight; }, _this.state.panelHeight); _this.setState({ panelHeight: panelHeight }); }, _this.renderChildren = function () { if (!_this.props.template && !_this.props.children) { throw new Error('AccordionPanel must have at least one child!'); } /*************************************************************** create a ref so we calculate its height on componentDidMount() this way we know how high to expand the panel ***************************************************************/ var wrapComponent = function wrapComponent(components) { return Children.map(components, function (child, index) { var WrappedComponent = React.forwardRef(function (props, ref) { _this.componentRef = ref; return React.createElement( 'div', { ref: ref }, child ); }); var ref = React.createRef(); return React.createElement(WrappedComponent, { ref: ref }); }); }; if (_this.props.template) { // for template prop that contains a class component console.warn('The template prop will be deprecated in the future. \n Prefer passing in your component directly as children: https://reactjs.org/docs/composition-vs-inheritance.html'); return wrapComponent(cloneElement(_this.props.template)); } if (typeof _this.props.children.type === 'function') { // for children that are class components return wrapComponent(_this.props.children); } return Children.map(_this.props.children, function (child) { return cloneElement(child, { ref: 'item-' + child.props.key }); }); }, _temp), _possibleConstructorReturn(_this, _ret); } AccordionPanel.prototype.componentDidMount = function componentDidMount() { var bodyNode = this.accordionPanelRef; if (!bodyNode) return; // tests only? var images = bodyNode.querySelectorAll('img'); if (images.length > 0) { this.preloadImages(images); } else { this.calcHeight(); } }; // Wait for images to load before calculating height of element AccordionPanel.prototype.render = function render() { var _this2 = this; var _props = this.props, className = _props.className, isExpanded = _props.isExpanded, style = _props.style, speed = _props.speed; var styles = { transition: 'all ' + (speed || defaultProps.speed) + 'ms ease-in-out', maxHeight: isExpanded ? this.state.panelHeight : 0, opacity: isExpanded ? 1 : 0 }; return React.createElement( 'div', { ref: function ref(inst) { return _this2.accordionPanelRef = inst; }, className: classNames(className, { 'is-expanded': isExpanded }), style: _extends({}, style, defaultStyle, styles) }, this.renderChildren() ); }; return AccordionPanel; }(PureComponent); export { AccordionPanel as default }; AccordionPanel.propTypes = process.env.NODE_ENV !== "production" ? { className: PropTypes.string, style: PropTypes.object, speed: PropTypes.number, isExpanded: PropTypes.bool } : {}; AccordionPanel.defaultProps = defaultProps;