'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.ContentPadding = exports.Container = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _lodash = require('lodash');

var _styledComponents = require('styled-components');

var _styledComponents2 = _interopRequireDefault(_styledComponents);

var _animationTimer = require('animation-timer');

var _functionalEasing = require('functional-easing');

var _Icon = require('./Icon');

var _Icon2 = _interopRequireDefault(_Icon);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

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; }

var Container = exports.Container = _styledComponents2.default.div.withConfig({
  displayName: 'Accordion__Container'
})(['border: 1px solid ', ';'], function (_ref) {
  var theme = _ref.theme;
  return theme.colors.border;
});

var Label = _styledComponents2.default.div.withConfig({
  displayName: 'Accordion__Label'
})(['padding: ', ';color: ', ';font-family: ', ';font-size: ', ';text-transform: ', ';font-weight: ', ';cursor: pointer;display: flex;flex-direction: row;user-select: none;'], function (_ref2) {
  var theme = _ref2.theme;
  return theme.accordion.padding;
}, function (_ref3) {
  var theme = _ref3.theme;
  return theme.accordion.labelFG;
}, function (_ref4) {
  var theme = _ref4.theme;
  return theme.accordion.labelFontFamily;
}, function (_ref5) {
  var theme = _ref5.theme;
  return theme.accordion.labelFontSize;
}, function (_ref6) {
  var theme = _ref6.theme;
  return theme.accordion.textTransform;
}, function (_ref7) {
  var theme = _ref7.theme;
  return theme.accordion.labelFontWeight;
});

var Content = _styledComponents2.default.div.withConfig({
  displayName: 'Accordion__Content'
})(['overflow: hidden;']);

var ContentHolder = _styledComponents2.default.div.withConfig({
  displayName: 'Accordion__ContentHolder'
})(['padding: 0;padding-top: 0;']);

var ModdedIcon = (0, _styledComponents2.default)(_Icon2.default).withConfig({
  displayName: 'Accordion__ModdedIcon'
})(['color: #666;margin: auto 1em auto auto;transform: ', ';transition: 0.2s all ease;font-weight: 100;&:after {padding-top: 0;padding-bottom: 0;font-size: ', ';}'], function (_ref8) {
  var isCollapsed = _ref8.isCollapsed;
  return isCollapsed ? 'rotate(0)' : 'rotate(90deg)';
}, function (_ref9) {
  var theme = _ref9.theme;
  return theme.accordion.iconFontSize;
});

var LabelText = _styledComponents2.default.span.withConfig({
  displayName: 'Accordion__LabelText'
})(['margin: auto;flex: 1;']);

var ContentPadding = exports.ContentPadding = _styledComponents2.default.div.withConfig({
  displayName: 'Accordion__ContentPadding'
})(['padding: ', ';padding-top: 0;display: flex;flex-direction: column;'], function (_ref10) {
  var theme = _ref10.theme;
  return theme.accordion.padding;
});

/**
 * Accordion works like a controllable component. Provide the
 * isCollapsed prop to control it, or don't to let it control itself.
 */

var Accordion = function (_React$Component) {
  _inherits(Accordion, _React$Component);

  function Accordion(props) {
    _classCallCheck(this, Accordion);

    var _this = _possibleConstructorReturn(this, (Accordion.__proto__ || Object.getPrototypeOf(Accordion)).call(this, props));

    _this.setContentCollapseState = function () {
      var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;

      var isCollapsed = _this.calcIsCollapsed();
      var content = _this._content;
      if (!content) {
        return;
      }
      var naturalHeight = content.scrollHeight;
      if (animate) {
        var easer = new _functionalEasing.Easer().using('cubic');
        new _animationTimer.AnimationTimer().duration(200).on('tick', easer(function (percent) {
          var directionalPercent = isCollapsed ? 1.0 - percent : percent;
          content.style.height = naturalHeight * directionalPercent + 'px';
        })).play();
      } else {
        content.style.height = isCollapsed ? 0 : naturalHeight;
      }
    };

    _this.handleToggle = function () {
      if (_this.props.onToggle) {
        _this.props.onToggle(_this.calcIsCollapsed());
      }
      _this.setState({ internalIsCollapsed: !_this.state.internalIsCollapsed });
    };

    _this.calcIsCollapsed = function () {
      var isCollapsed = _this.props.isCollapsed;
      var internalIsCollapsed = _this.state.internalIsCollapsed;

      if (isCollapsed === null) {
        return internalIsCollapsed;
      }

      return isCollapsed;
    };

    _this.renderContent = function () {
      return _react2.default.createElement(
        Content,
        {
          innerRef: function innerRef(el) {
            _this._content = el;
          },
          isCollapsed: _this.calcIsCollapsed()
        },
        _react2.default.createElement(
          ContentHolder,
          null,
          _this.props.children
        )
      );
    };

    _this.state = { internalIsCollapsed: true };
    return _this;
  }

  _createClass(Accordion, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      // on first mount, recalculate the natural size and setup without animation
      this.setContentCollapseState(false);
      // any time the window resizes, recalculate the natural size
      window.addEventListener('resize', (0, _lodash.debounce)(this.setContentCollapseState.bind(this, false), 300));
    }
  }, {
    key: 'componentDidUpdate',
    value: function componentDidUpdate(prevProps, prevState) {
      // only animate if the collapsed state has changed.
      this.setContentCollapseState(prevProps.isCollapsed !== this.props.isCollapsed || prevState.internalIsCollapsed !== this.state.internalIsCollapsed);
    }
  }, {
    key: 'render',
    value: function render() {
      var isCollapsed = this.calcIsCollapsed();
      return _react2.default.createElement(
        Container,
        null,
        _react2.default.createElement(
          Label,
          { onClick: this.handleToggle },
          _react2.default.createElement(ModdedIcon, { isCollapsed: isCollapsed, name: 'forward', size: 21 }),
          _react2.default.createElement(
            LabelText,
            null,
            this.props.label
          )
        ),
        this.renderContent()
      );
    }
  }]);

  return Accordion;
}(_react2.default.Component);

Accordion.propTypes = {
  label: _propTypes2.default.node.isRequired,
  children: _propTypes2.default.node.isRequired,
  isCollapsed: _propTypes2.default.bool,
  onToggle: _propTypes2.default.func
};
Accordion.defaultProps = {
  isCollapsed: null,
  onToggle: function onToggle() {} // no-op
};


Accordion.usage = '\n# Accordion\n\nExpands and collapses when the label is clicked. Or, you can provide the `isCollapsed` prop to force open/closed state. You can also provide a hook to `onToggle`. Your `onToggle` function will be called with one parameter, a boolean representing whether the component is currently collapsed at the time it was clicked.\n\nAccepts `label` to define what\'s rendered in the label.\n\nAlso exports `ContentPadding`, which you can use on any content contained inside the accordion to achieve consistent padding.\n\n```\n<Accordion label="Hello">\n  Some content\n</Accordion>\n```\n';

exports.default = Accordion;