import _extends from '@babel/runtime/helpers/extends';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import 'core-js/modules/es.symbol.js';
import 'core-js/modules/es.array.concat.js';
import 'core-js/modules/es.array.filter.js';
import 'core-js/modules/es.array.map.js';
import 'core-js/modules/es.object.assign.js';
import 'core-js/modules/es.object.get-own-property-descriptor.js';
import 'core-js/modules/es.object.get-own-property-descriptors.js';
import 'core-js/modules/es.object.keys.js';
import 'core-js/modules/es.object.to-string.js';
import 'core-js/modules/web.dom-collections.for-each.js';
import React__default, { useState, useRef, useCallback, useEffect, useLayoutEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { Menu } from '@carbon/react';
import classnames from 'classnames';
import { useLangDirection } from '../../utils/useLangDirection.js';
import { settings } from '../../constants/Settings.js';
import deprecate from '../../internal/deprecate.js';
import { SplitMenuButton } from './SplitMenuButton.js';
import { SingleMenuButton } from './SingleMenuButton.js';
import { getMenuPosition, getShadowBlockerConfig } from './utils.js';
import { ChevronDown, ChevronUp } from '@carbon/icons-react';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var iotPrefix = settings.iotPrefix;
var GHOST = 'ghost';
var propTypes = {
  // eslint-disable-next-line react/require-default-props
  testID: deprecate(PropTypes.string, "The 'testID' prop has been deprecated. Please use 'testId' instead."),
  testId: PropTypes.string,
  /**
   * Use by a split menu button to fire the event for clicking on the main button,
   * not the chevron to open the additional menu actions
   */
  onPrimaryActionClick: PropTypes.func,
  /**
   * The label on the primary button in a split button, or the whole button on a single menu button
   */
  label: PropTypes.string,
  /**
   * Optional prop to change the open icon on the button
   * Can be a React component class
   */
  renderOpenIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
  /**
   * Optional prop to change the closed state icon on the button
   * Can be a React component class
   */
  renderCloseIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
  /**
   * If specifying the `renderIcon` prop, provide a description for that icon that can
   * be read by screen readers
   */
  closeIconDescription: function closeIconDescription(props) {
    if (props.renderCloseIcon && !props.closeIconDescription) {
      return new Error('renderCloseIcon property specified without also providing an closeIconDescription property.');
    }
    return undefined;
  },
  /**
   * If specifying the `renderIcon` prop, provide a description for that icon that can
   * be read by screen readers
   */
  openIconDescription: function openIconDescription(props) {
    if (props.renderOpenIcon && !props.openIconDescription) {
      return new Error('renderOpenIcon property specified without also providing an openIconDescription property.');
    }
    return undefined;
  },
  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
  /**
   * The size of the button and the dropdown items
   */
  size: PropTypes.oneOf(['sm', 'md', 'default']),
  /**
   * The kind of button.
   */
  kind: PropTypes.oneOf(['primary', 'secondary', 'tertiary', 'ghost'])
};
var defaultProps = {
  testId: 'menu-button',
  onPrimaryActionClick: null,
  label: null,
  openIconDescription: 'open menu button',
  closeIconDescription: 'close menu button',
  renderOpenIcon: ChevronDown,
  renderCloseIcon: ChevronUp,
  size: 'default',
  kind: 'primary'
};
var MenuButton = function MenuButton(_ref) {
  var testID = _ref.testID,
    testId = _ref.testId,
    onPrimaryActionClick = _ref.onPrimaryActionClick,
    label = _ref.label,
    openIconDescription = _ref.openIconDescription,
    closeIconDescription = _ref.closeIconDescription,
    renderOpenIcon = _ref.renderOpenIcon,
    renderCloseIcon = _ref.renderCloseIcon,
    children = _ref.children,
    buttonSize = _ref.size,
    kind = _ref.kind;
  var _useState = useState(false),
    _useState2 = _slicedToArray(_useState, 2),
    isMenuOpen = _useState2[0],
    setIsMenuOpen = _useState2[1];
  var _useState3 = useState({
      x: 0,
      y: 0
    }),
    _useState4 = _slicedToArray(_useState3, 2),
    position = _useState4[0],
    setPosition = _useState4[1];
  var _useState5 = useState({}),
    _useState6 = _slicedToArray(_useState5, 2),
    shadowBlockerConf = _useState6[0],
    setShadowBlockerConf = _useState6[1];
  var buttonRef = useRef(null);
  var langDir = useLangDirection();
  var handleResize = useCallback(function () {
    /* istanbul ignore else */
    if (buttonRef.current) {
      var _getMenuPosition = getMenuPosition({
          label: label,
          buttonRef: buttonRef,
          onPrimaryActionClick: onPrimaryActionClick,
          langDir: langDir
        }),
        x = _getMenuPosition.x,
        y = _getMenuPosition.y;
      setPosition({
        x: x,
        y: y
      });
      setShadowBlockerConf(getShadowBlockerConfig(buttonRef));
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [label, langDir, onPrimaryActionClick, isMenuOpen, buttonSize]);

  /**
   * This is a hacky work-around, because the current Menu (7.42.1) won't allow us
   * to set classNames or a target for where the menu should be placed via the portal
   * So, to fix the autopositioning, I have to open it, hide it with a property, check
   * the positioning, reposition it, and then show it. ugh. They are adding these other
   * features. Hopefully they'll be released soon, and we can use the `target` prop to open
   * the menu in this container div where it used to be...
   */
  useEffect(function () {
    document.querySelector(':root').style.setProperty('--iot-menu-button-menu-opacity', isMenuOpen ? 0 : 1);
    setTimeout(function () {
      document.querySelector(':root').style.setProperty('--iot-menu-button-menu-opacity', 1);
    }, 0);
  }, [isMenuOpen]);
  useLayoutEffect(function () {
    window.addEventListener('resize', handleResize);
    return function () {
      return window.removeEventListener('resize', handleResize);
    };
  }, [handleResize]);
  useEffect(function () {
    window.addEventListener('scroll', handleResize);
    return function () {
      return window.removeEventListener('scroll', handleResize);
    };
  }, [handleResize]);
  useLayoutEffect(function () {
    handleResize();
  }, [handleResize]);
  var handlePrimaryClick = useCallback(function (e) {
    if (typeof onPrimaryActionClick === 'function') {
      onPrimaryActionClick(e);
    } else {
      setIsMenuOpen(function (prev) {
        handleResize();
        return !prev;
      });
    }
  }, [handleResize, onPrimaryActionClick]);
  var handleSecondaryClick = useCallback(function () {
    setIsMenuOpen(function (prev) {
      handleResize();
      return !prev;
    });
  }, [handleResize]);
  var handleChildClick = useCallback(function (onClick) {
    return function (e) {
      /* istanbul ignore else */
      if (typeof onClick === 'function') {
        setIsMenuOpen(function (prev) {
          handleResize();
          return !prev;
        });
        onClick(e);
      }
    };
  }, [handleResize]);

  /**
   * Wrap the children onClick handlers to also close the menu when an
   * action is triggered.
   */
  var contextMenuItems = useMemo(function () {
    return React__default.Children.map(children, function (child) {
      var _child$props;
      return /*#__PURE__*/React__default.cloneElement(child, Object.assign({}, child.props, {
        onClick: typeof ((_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.onClick) === 'function' ? handleChildClick(child.props.onClick) : undefined
      }));
    });
  }, [children, handleChildClick]);
  var menuSize = buttonSize === 'default' ? 'lg' : buttonSize;
  var buttonKind = !label ? GHOST : kind;

  /**
   * This shadow-blocker is needed to remove the menu shadow covering the button.
   * We can't use a pure CSS solution (like ::after) for this since the shadow-blocker styling
   * needs to get the position and dimensions of the menu and it is not possible to
   * pass that info as css attributes (vars) to the menu since the component internally use
   * the style attribute to set the x & y attributes.
   */
  var menuHeight = shadowBlockerConf.menuHeight,
    flippedX = shadowBlockerConf.flippedX,
    flippedY = shadowBlockerConf.flippedY,
    opensHorizontally = shadowBlockerConf.opensHorizontally;
  var shadowBlockerButtonClasses = _defineProperty(_defineProperty(_defineProperty({}, "".concat(iotPrefix, "--menu-button--flip-y"), flippedY), "".concat(iotPrefix, "--menu-button--flip-x"), flippedX), "".concat(iotPrefix, "--menu-button--opens-horizontally"), opensHorizontally);
  var showShadowBlocker = buttonKind === GHOST && isMenuOpen && !label;
  var shadowBlocker = showShadowBlocker ? /*#__PURE__*/React__default.createElement("div", {
    style: _defineProperty({}, "--menu-height", "".concat(menuHeight, "px")),
    className: classnames(_defineProperty(_defineProperty(_defineProperty({}, "".concat(iotPrefix, "--menu__shadow-blocker--flip-y"), flippedY), "".concat(iotPrefix, "--menu__shadow-blocker--flip-x"), flippedX), "".concat(iotPrefix, "--menu__shadow-blocker--opens-horizontally"), opensHorizontally), "".concat(iotPrefix, "--menu__shadow-blocker"), "".concat(iotPrefix, "--menu__shadow-blocker--").concat(menuSize))
  }) : null;
  var ButtonComponent = typeof onPrimaryActionClick === 'function' && label ? SplitMenuButton : SingleMenuButton;
  return /*#__PURE__*/React__default.createElement("div", {
    // TODO: remove deprecated 'testID' in v3.
    "data-testid": "".concat(testID || testId, "-wrapper"),
    className: classnames("".concat(iotPrefix, "--menu-button"), _objectSpread(_defineProperty({}, "".concat(iotPrefix, "--menu-button--open"), isMenuOpen), shadowBlockerButtonClasses))
  }, /*#__PURE__*/React__default.createElement(ButtonComponent, {
    ref: buttonRef,
    onPrimaryActionClick: handlePrimaryClick,
    onSecondaryActionClick: handleSecondaryClick,
    iconDescription: isMenuOpen ? closeIconDescription : openIconDescription,
    renderIcon: isMenuOpen ? renderCloseIcon : renderOpenIcon,
    label: label
    // TODO: remove deprecated 'testID' in v3.
    ,
    testId: testID || testId,
    size: buttonSize,
    kind: buttonKind
  }), /*#__PURE__*/React__default.createElement(Menu, _extends({
    className: classnames(_defineProperty({}, "".concat(iotPrefix, "--menu-button--icon-only"), buttonKind === GHOST), "".concat(iotPrefix, "--menu-button__menu")),
    size: menuSize,
    open: isMenuOpen
  }, position), contextMenuItems, shadowBlocker));
};
MenuButton.propTypes = propTypes;
MenuButton.defaultProps = defaultProps;
MenuButton.__docgenInfo = {
  "description": "",
  "methods": [],
  "displayName": "MenuButton",
  "props": {
    "testId": {
      "defaultValue": {
        "value": "'menu-button'",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "onPrimaryActionClick": {
      "defaultValue": {
        "value": "null",
        "computed": false
      },
      "description": "Use by a split menu button to fire the event for clicking on the main button,\nnot the chevron to open the additional menu actions",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "label": {
      "defaultValue": {
        "value": "null",
        "computed": false
      },
      "description": "The label on the primary button in a split button, or the whole button on a single menu button",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "openIconDescription": {
      "defaultValue": {
        "value": "'open menu button'",
        "computed": false
      },
      "description": "If specifying the `renderIcon` prop, provide a description for that icon that can\nbe read by screen readers",
      "type": {
        "name": "custom",
        "raw": "(props) => {\n  if (props.renderOpenIcon && !props.openIconDescription) {\n    return new Error(\n      'renderOpenIcon property specified without also providing an openIconDescription property.'\n    );\n  }\n  return undefined;\n}"
      },
      "required": false
    },
    "closeIconDescription": {
      "defaultValue": {
        "value": "'close menu button'",
        "computed": false
      },
      "description": "If specifying the `renderIcon` prop, provide a description for that icon that can\nbe read by screen readers",
      "type": {
        "name": "custom",
        "raw": "(props) => {\n  if (props.renderCloseIcon && !props.closeIconDescription) {\n    return new Error(\n      'renderCloseIcon property specified without also providing an closeIconDescription property.'\n    );\n  }\n  return undefined;\n}"
      },
      "required": false
    },
    "renderOpenIcon": {
      "defaultValue": {
        "value": "ChevronDown",
        "computed": true
      },
      "description": "Optional prop to change the open icon on the button\nCan be a React component class",
      "type": {
        "name": "union",
        "value": [{
          "name": "func"
        }, {
          "name": "object"
        }]
      },
      "required": false
    },
    "renderCloseIcon": {
      "defaultValue": {
        "value": "ChevronUp",
        "computed": true
      },
      "description": "Optional prop to change the closed state icon on the button\nCan be a React component class",
      "type": {
        "name": "union",
        "value": [{
          "name": "func"
        }, {
          "name": "object"
        }]
      },
      "required": false
    },
    "size": {
      "defaultValue": {
        "value": "'default'",
        "computed": false
      },
      "description": "The size of the button and the dropdown items",
      "type": {
        "name": "enum",
        "value": [{
          "value": "'sm'",
          "computed": false
        }, {
          "value": "'md'",
          "computed": false
        }, {
          "value": "'default'",
          "computed": false
        }]
      },
      "required": false
    },
    "kind": {
      "defaultValue": {
        "value": "'primary'",
        "computed": false
      },
      "description": "The kind of button.",
      "type": {
        "name": "enum",
        "value": [{
          "value": "'primary'",
          "computed": false
        }, {
          "value": "'secondary'",
          "computed": false
        }, {
          "value": "'tertiary'",
          "computed": false
        }, {
          "value": "'ghost'",
          "computed": false
        }]
      },
      "required": false
    },
    "testID": {
      "description": "",
      "type": {
        "name": "custom",
        "raw": "deprecate(\n  PropTypes.string,\n  `The 'testID' prop has been deprecated. Please use 'testId' instead.`\n)"
      },
      "required": false
    },
    "children": {
      "description": "",
      "type": {
        "name": "union",
        "value": [{
          "name": "arrayOf",
          "value": {
            "name": "node"
          }
        }, {
          "name": "node"
        }]
      },
      "required": true
    }
  }
};
var MenuButton$1 = MenuButton;

export { MenuButton$1 as default };
