'use strict';

exports.__esModule = true;
exports.Context = undefined;

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

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');

var _reactDom2 = _interopRequireDefault(_reactDom);

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

var _propTypes2 = _interopRequireDefault(_propTypes);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _helper = require('./Shared/helper.js');

var _reactPopper = require('react-popper');

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

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } 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; }

var Context = exports.Context = _react2.default.createContext({});

//component - CoreUI / CPopperContentWrapper

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

  function CPopperContentWrapper() {
    _classCallCheck(this, CPopperContentWrapper);

    return _possibleConstructorReturn(this, _React$Component.apply(this, arguments));
  }

  CPopperContentWrapper.prototype.getChildContext = function getChildContext() {
    return this.context;
  };

  CPopperContentWrapper.prototype.render = function render() {
    return this.props.children;
  };

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

CPopperContentWrapper.contextType = Context;

CPopperContentWrapper.childContextTypes = {
  toggle: _propTypes2.default.func.isRequired,
  isOpen: _propTypes2.default.bool.isRequired,
  direction: _propTypes2.default.oneOf(['up', 'down', 'left', 'right']).isRequired,
  inNavbar: _propTypes2.default.bool.isRequired
};

//component - CoreUI / CDropdownCustom

var CDropdownCustom = function CDropdownCustom(props) {
  var _classNames;

  var _omit = (0, _helper.omit)(props, ['toggle', 'disabled', 'inNavbar', 'direction']),
      className = _omit.className,
      cssModule = _omit.cssModule,
      innerRef = _omit.innerRef,
      show = _omit.show,
      group = _omit.group,
      size = _omit.size,
      inNav = _omit.inNav,
      setActiveFromChild = _omit.setActiveFromChild,
      active = _omit.active,
      addonType = _omit.addonType,
      attributes = _objectWithoutProperties(_omit, ['className', 'cssModule', 'innerRef', 'show', 'group', 'size', 'inNav', 'setActiveFromChild', 'active', 'addonType']);

  var fields = (0, _react.useRef)({
    firstRender: true,
    ref: { current: null }
  }).current;

  var reference = function reference(r) {
    fields.ref.current = r;
    innerRef && innerRef(r);
  };

  var getContainer = function getContainer() {
    if (fields._$container) return fields._$container;
    fields._$container = _reactDom2.default.findDOMNode(fields.ref.current);
    return fields._$container;
  };

  var getMenuCtrl = function getMenuCtrl() {
    if (fields._$menuCtrl) return fields._$menuCtrl;
    fields._$menuCtrl = getContainer().querySelector('[aria-expanded]');
    return fields._$menuCtrl;
  };

  var getMenuItems = function getMenuItems() {
    return [].slice.call(getContainer().querySelectorAll('[role="menuitem"]'));
  };

  var addEvents = function addEvents() {
    ['click', 'touchstart', 'keyup'].forEach(function (event) {
      return document.addEventListener(event, handleDocumentClick, true);
    });
    fields.handleDocumentClick = handleDocumentClick;
  };

  var removeEvents = function removeEvents() {
    ['click', 'touchstart', 'keyup'].forEach(function (event) {
      return document.removeEventListener(event, fields.handleDocumentClick, true);
    });
  };

  var handleDocumentClick = function handleDocumentClick(e) {
    if (e && (e.which === 3 || e.type === 'keyup' && e.which !== _helper.keyCodes.tab)) return;
    var container = getContainer();
    if (container.contains(e.target) && container !== e.target && (e.type !== 'keyup' || e.which === _helper.keyCodes.tab)) {
      return;
    }
    toggle(e);
  };

  var handleKeyDown = function handleKeyDown(e) {
    if (/input|textarea/i.test(e.target.tagName) || _helper.keyCodes.tab === e.which && e.target.getAttribute('role') !== 'menuitem') {
      return;
    }
    e.preventDefault();
    if (fields.disabled) return;
    if (getMenuCtrl() === e.target) {
      if (!fields.isOpen && [_helper.keyCodes.space, _helper.keyCodes.enter, _helper.keyCodes.up, _helper.keyCodes.down].indexOf(e.which) > -1) {
        toggle(e);
        setTimeout(function () {
          return getMenuItems()[0].focus();
        });
      }
    }
    if (fields.isOpen && e.target.getAttribute('role') === 'menuitem') {
      if ([_helper.keyCodes.tab, _helper.keyCodes.esc].indexOf(e.which) > -1) {
        toggle(e);
        getMenuCtrl().focus();
      } else if ([_helper.keyCodes.space, _helper.keyCodes.enter].indexOf(e.which) > -1) {
        e.target.click();
        getMenuCtrl().focus();
      } else if ([_helper.keyCodes.down, _helper.keyCodes.up].indexOf(e.which) > -1 || [_helper.keyCodes.n, _helper.keyCodes.p].indexOf(e.which) > -1 && e.ctrlKey) {
        var $menuitems = getMenuItems();
        var index = $menuitems.indexOf(e.target);
        if (_helper.keyCodes.up === e.which || _helper.keyCodes.p === e.which && e.ctrlKey) {
          index = index !== 0 ? index - 1 : $menuitems.length - 1;
        } else if (_helper.keyCodes.down === e.which || _helper.keyCodes.n === e.which && e.ctrlKey) {
          index = index === $menuitems.length - 1 ? 0 : index + 1;
        }
        $menuitems[index].focus();
      } else if (_helper.keyCodes.end === e.which) {
        var _$menuitems = getMenuItems();
        _$menuitems[_$menuitems.length - 1].focus();
      } else if (_helper.keyCodes.home === e.which) {
        var _$menuitems2 = getMenuItems();
        _$menuitems2[0].focus();
      } else if (e.which >= 48 && e.which <= 90) {
        var _$menuitems3 = getMenuItems();
        var charPressed = String.fromCharCode(e.which).toLowerCase();
        for (var i = 0; i < _$menuitems3.length; i += 1) {
          var firstLetter = _$menuitems3[i].textContent && _$menuitems3[i].textContent[0].toLowerCase();
          if (firstLetter === charPressed) {
            _$menuitems3[i].focus();
            break;
          }
        }
      }
    }
  };

  var handleProps = function handleProps() {
    if (props.show) {
      addEvents();
    } else {
      removeEvents();
    }
  };

  var toggle = function toggle(e) {
    if (fields.disabled) {
      return e && e.preventDefault();
    }
    return props.toggle(e);
  };

  //effect

  (0, _react.useEffect)(function () {
    if (fields.firstRender) {
      return;
    };
    handleProps();
  }, [props.show]);

  (0, _react.useEffect)(function () {
    fields.firstRender = false;
    handleProps();
    return function cleanup() {
      removeEvents();
    };
  }, []);

  //render

  fields.disabled = props.disabled;
  fields.isOpen = props.show;

  var direction = props.direction === 'down' ? 'up' : props.direction;

  attributes.tag = attributes.tag || (inNav ? 'li' : 'div');

  var subItemIsActive = false;

  if (setActiveFromChild) {
    _react2.default.Children.map(props.children[1].props.children, function (dropdownItem) {
      if (dropdownItem && dropdownItem.props.active) subItemIsActive = true;
    });
  }

  var classes = (0, _helper.mapToCssModules)((0, _classnames2.default)(className, direction !== 'down' && 'drop' + direction, inNav && active ? 'active' : false, setActiveFromChild && subItemIsActive ? 'active' : false, (_classNames = {}, _classNames['input-group-' + addonType] = addonType, _classNames['btn-group'] = group, _classNames['btn-group-' + size] = !!size, _classNames['dropdown'] = !group && !addonType, _classNames['show'] = show, _classNames['nav-item'] = inNav, _classNames)), cssModule);

  return _react2.default.createElement(
    Context.Provider,
    { value: {
        toggle: props.toggle,
        isOpen: props.show,
        direction: props.direction === 'down' ? 'up' : props.direction,
        inNavbar: props.inNavbar
      } },
    _react2.default.createElement(
      CPopperContentWrapper,
      null,
      _react2.default.createElement(_reactPopper.Manager, _extends({}, attributes, { className: classes, onKeyDown: handleKeyDown, ref: reference }))
    )
  );
};

CDropdownCustom.propTypes = process.env.NODE_ENV !== "production" ? {
  tag: _helper.tagPropType,
  children: _propTypes2.default.node,
  className: _propTypes2.default.string,
  cssModule: _propTypes2.default.object,
  //
  innerRef: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func, _propTypes2.default.string]),
  direction: _propTypes2.default.oneOf(['up', 'down', 'left', 'right']),
  group: _propTypes2.default.bool,
  show: _propTypes2.default.bool,
  disabled: _propTypes2.default.bool,
  active: _propTypes2.default.bool,
  addonType: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.oneOf(['prepend', 'append'])]),
  size: _propTypes2.default.string,
  toggle: _propTypes2.default.func,
  inNav: _propTypes2.default.bool,
  inNavbar: _propTypes2.default.bool,
  setActiveFromChild: _propTypes2.default.bool
} : {};

CDropdownCustom.defaultProps = {
  show: false,
  direction: 'down',
  active: false,
  addonType: false,
  inNav: false,
  inNavbar: false,
  setActiveFromChild: false,
  group: true
};

exports.default = CDropdownCustom;