'use strict';

var _extends = require('@babel/runtime/helpers/extends');
var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
var _createClass = require('@babel/runtime/helpers/createClass');
var _possibleConstructorReturn = require('@babel/runtime/helpers/possibleConstructorReturn');
var _getPrototypeOf = require('@babel/runtime/helpers/getPrototypeOf');
var _inherits = require('@babel/runtime/helpers/inherits');
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
require('core-js/modules/es.array.map.js');
require('core-js/modules/es.reflect.construct.js');
var classnames = require('classnames');
var React = require('react');
var PropTypes = require('prop-types');
var react = require('@carbon/react');
var HeaderPropTypes = require('../HeaderPropTypes.js');
var componentUtilityFunctions = require('../../../utils/componentUtilityFunctions.js');
var Button = require('../../Button/Button.js');
var suiteHeaderUtils = require('../../SuiteHeader/suiteHeaderUtils.js');
var iconsReact = require('@carbon/icons-react');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var _extends__default = /*#__PURE__*/_interopDefault(_extends);
var _classCallCheck__default = /*#__PURE__*/_interopDefault(_classCallCheck);
var _createClass__default = /*#__PURE__*/_interopDefault(_createClass);
var _possibleConstructorReturn__default = /*#__PURE__*/_interopDefault(_possibleConstructorReturn);
var _getPrototypeOf__default = /*#__PURE__*/_interopDefault(_getPrototypeOf);
var _inherits__default = /*#__PURE__*/_interopDefault(_inherits);
var _defineProperty__default = /*#__PURE__*/_interopDefault(_defineProperty);
var classnames__default = /*#__PURE__*/_interopDefault(classnames);
var React__default = /*#__PURE__*/_interopDefault(React);
var PropTypes__default = /*#__PURE__*/_interopDefault(PropTypes);

function _callSuper(t, o, e) { return o = _getPrototypeOf__default.default(o), _possibleConstructorReturn__default.default(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf__default.default(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }

// const { prefix } = settings; carbon 11
var prefix = 'cds';
// eslint-disable-next-line react/prop-types
var defaultRenderMenuContent = function defaultRenderMenuContent(_ref) {
  var ariaLabel = _ref.ariaLabel;
  return /*#__PURE__*/React__default.default.createElement(React__default.default.Fragment, null, ariaLabel, /*#__PURE__*/React__default.default.createElement(iconsReact.ChevronDown, {
    size: 32,
    className: "".concat(prefix, "--header__menu-arrow")
  }));
};

/**
 * `HeaderActionMenu` is used to render submenu's in the `Header`. Most often children
 * will be a `HeaderActionMenuItem`. It handles certain keyboard events to help
 * with managing focus. It also passes along refs to each child so that it can
 * help manage focus state of its children.
 */
var HeaderActionMenu = /*#__PURE__*/function (_React$Component) {
  function HeaderActionMenu(props) {
    var _this;
    _classCallCheck__default.default(this, HeaderActionMenu);
    _this = _callSuper(this, HeaderActionMenu, [props]);
    _defineProperty__default.default(_this, "state", {
      isOverflowing: []
    });
    _this.menuItemRefs = props.childContent.map(function () {
      return /*#__PURE__*/React__default.default.createRef(null);
    });
    _this.menuRef = /*#__PURE__*/React__default.default.createRef(null);
    _this.handleOutsideMenuClick = _this.handleOutsideMenuClick.bind(_this);
    return _this;
  }
  _inherits__default.default(HeaderActionMenu, _React$Component);
  return _createClass__default.default(HeaderActionMenu, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      var isExpanded = this.props.isExpanded;
      if (isExpanded) {
        this.checkForOverflows();
      }
      document.addEventListener('click', this.handleOutsideMenuClick, {
        capture: true
      });
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps) {
      var isExpanded = this.props.isExpanded;
      if (isExpanded && !prevProps.isExpanded) {
        this.checkForOverflows();
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      document.removeEventListener('click', this.handleOutsideMenuClick, {
        capture: true
      });
    }
  }, {
    key: "handleOutsideMenuClick",
    value: function handleOutsideMenuClick(evt) {
      if (!suiteHeaderUtils.isSafari()) {
        return;
      }
      var _this$props = this.props,
        isExpanded = _this$props.isExpanded,
        onToggleExpansion = _this$props.onToggleExpansion;
      if (this.menuRef.current && this.menuRef.current.contains(evt.target)) {
        return;
      }
      if (isExpanded) {
        onToggleExpansion();
      }
    }
  }, {
    key: "checkForOverflows",
    value: function checkForOverflows() {
      this.setState({
        isOverflowing: this.menuItemRefs.map(function (ref) {
          var element = ref.current.firstChild;
          return element.offsetHeight < element.scrollHeight || element.offsetWidth < element.scrollWidth;
        })
      });
    }
  }, {
    key: "render",
    value: function render() {
      var _this2 = this;
      var _this$props2 = this.props,
        ariaLabel = _this$props2['aria-label'],
        ariaLabelledBy = _this$props2['aria-labelledby'],
        customClassName = _this$props2.className,
        MenuContent = _this$props2.renderMenuContent,
        childContent = _this$props2.childContent,
        onToggleExpansion = _this$props2.onToggleExpansion,
        label = _this$props2.label,
        focusRef = _this$props2.focusRef,
        isExpanded = _this$props2.isExpanded,
        id = _this$props2.id;
      var accessibilityLabel = {
        'aria-label': ariaLabel,
        'aria-labelledby': ariaLabelledBy
      };
      var className = classnames__default.default("".concat(prefix, "--header__submenu"), customClassName);

      // Notes on eslint comments and based on the examples in:
      // https://www.w3.org/TR/wai-aria-practices/examples/menubar/menubar-1/menubar-1.html#
      // - The focus is handled by the <a> menuitem, onMouseOver is for mouse
      // users
      // - aria-haspopup can definitely have the value "menu"
      // - aria-expanded is on their example node with role="menuitem"

      return (
        /*#__PURE__*/
        // TODO: CAN WE REMOVE THIS DIV WRAPPER AND ATTACH THE CLASS DIRECTLY
        React__default.default.createElement("div", {
          "aria-expanded": isExpanded,
          className: className
        }, /*#__PURE__*/React__default.default.createElement(Button, {
          hasIconOnly: true,
          iconDescription: ariaLabel,
          tooltipPosition: "bottom",
          "aria-haspopup": "menu",
          "aria-expanded": isExpanded,
          className: classnames__default.default("".concat(prefix, "--header__menu-item"), "".concat(prefix, "--header__menu-title")),
          onClick: onToggleExpansion,
          ref: focusRef,
          testId: "menuitem",
          "aria-label": ariaLabel,
          id: id
        }, /*#__PURE__*/React__default.default.createElement(MenuContent, {
          ariaLabel: ariaLabel
        })), /*#__PURE__*/React__default.default.createElement("ul", _extends__default.default({}, accessibilityLabel, {
          ref: this.menuRef,
          className: "".concat(prefix, "--header__menu"),
          role: "menu"
        }), childContent.map(function (childItem, index) {
          var _this2$menuItemRefs$i, _this2$menuItemRefs, _childItem$metaData$t, _childItem$metaData, _childItem$metaData2, _childItem$metaData3, _childItem$metaData4, _childItem$metaData5;
          var isOverflowing = _this2.state.isOverflowing;
          var childIsOverflowing = isOverflowing[index];
          var fallbackTitle = (_this2$menuItemRefs$i = (_this2$menuItemRefs = _this2.menuItemRefs) === null || _this2$menuItemRefs === void 0 || (_this2$menuItemRefs = _this2$menuItemRefs[index]) === null || _this2$menuItemRefs === void 0 || (_this2$menuItemRefs = _this2$menuItemRefs.current) === null || _this2$menuItemRefs === void 0 ? void 0 : _this2$menuItemRefs.textContent) !== null && _this2$menuItemRefs$i !== void 0 ? _this2$menuItemRefs$i : '';
          var title = (_childItem$metaData$t = (_childItem$metaData = childItem.metaData) === null || _childItem$metaData === void 0 ? void 0 : _childItem$metaData.title) !== null && _childItem$metaData$t !== void 0 ? _childItem$metaData$t : childIsOverflowing ? fallbackTitle : undefined;
          var onKeyDownClick = function onKeyDownClick(e) {
            return e.target.click();
          };

          // if the item is an A and doesn't have an onClick event
          // do nothing. An A tag doesn't need an onClick handler.
          var onClick = ((_childItem$metaData2 = childItem.metaData) === null || _childItem$metaData2 === void 0 ? void 0 : _childItem$metaData2.element) === 'a' && !((_childItem$metaData3 = childItem.metaData) !== null && _childItem$metaData3 !== void 0 && _childItem$metaData3.onClick) ? undefined :
          // otherwise, if an onClick exists use that, or fallback to a noop.
          ((_childItem$metaData4 = childItem.metaData) === null || _childItem$metaData4 === void 0 ? void 0 : _childItem$metaData4.onClick) || function () {};

          // if item has onKeyDown use that otherwise, fallback to onClick if it exists
          // or create a custom handler to trigger the click
          var onKeyDown = childItem !== null && childItem !== void 0 && (_childItem$metaData5 = childItem.metaData) !== null && _childItem$metaData5 !== void 0 && _childItem$metaData5.onKeyDown ? childItem.metaData.onKeyDown : onClick || onKeyDownClick;
          return /*#__PURE__*/React__default.default.createElement(react.HeaderMenuItem, _extends__default.default({
            ref: _this2.menuItemRefs[index],
            key: "menu-item-".concat(label + index, "-child")
          }, childItem.metaData, {
            title: title,
            onClick: onClick,
            onKeyDown: componentUtilityFunctions.handleSpecificKeyDown(['Enter', ' '], onKeyDown)
          }), childItem.content);
        })))
      );
    }
  }]);
}(React__default.default.Component); // eslint-disable-next-line react/no-multi-comp
_defineProperty__default.default(HeaderActionMenu, "propTypes", {
  /** Ref object to be attached to the parent that should receive focus when a menu is closed */
  focusRef: PropTypes__default.default.oneOfType([
  // Either a function
  PropTypes__default.default.func,
  // Or the instance of a DOM native element (see the note about SSR)
  PropTypes__default.default.shape({
    current: typeof Element === 'undefined' ? PropTypes__default.default.any : PropTypes__default.default.instanceOf(Element)
  })]).isRequired,
  /** Optionally provide a tabIndex for the underlying menu button */
  tabIndex: PropTypes__default.default.number,
  /** Optional component to render instead of string */
  renderMenuContent: PropTypes__default.default.func,
  /** Determines if the header panel should be rendered which is decided by Header */
  isExpanded: PropTypes__default.default.bool,
  /** Hides/unhides the header panel logic */
  onToggleExpansion: PropTypes__default.default.func.isRequired,
  /** Unique name used by handleExpandedState */
  label: PropTypes__default.default.string.isRequired,
  /** MenuItem's to be rendered as children */
  childContent: PropTypes__default.default.arrayOf(PropTypes__default.default.shape(HeaderPropTypes.ChildContentPropTypes)).isRequired,
  /** Unique id for action menu */
  id: PropTypes__default.default.string.isRequired
});
_defineProperty__default.default(HeaderActionMenu, "defaultProps", {
  renderMenuContent: defaultRenderMenuContent,
  isExpanded: false,
  tabIndex: null
});
var HeaderActionMenu$1 = /*#__PURE__*/React__default.default.forwardRef(function (props, ref) {
  return /*#__PURE__*/React__default.default.createElement(HeaderActionMenu, _extends__default.default({}, props, {
    focusRef: ref
  }));
});

module.exports = HeaderActionMenu$1;
