"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _typeof = require("@babel/runtime/helpers/typeof");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _react = _interopRequireWildcard(require("react"));

var _classnames = _interopRequireDefault(require("classnames"));

var _utils = require("../utils");

var _utils2 = require("../utils/utils");

var _box = _interopRequireWildcard(require("../box"));

var _MenuItem = _interopRequireDefault(require("./MenuItem"));

var _theme = _interopRequireDefault(require("./theme.css"));

var _uiUtilities = _interopRequireDefault(require("@teamleader/ui-utilities"));

var _excluded = ["active", "children", "className", "onHide", "onSelect", "onShow", "outline", "position", "selectable", "selected"];

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

var POSITION = {
  AUTO: 'auto',
  STATIC: 'static',
  TOP_LEFT: 'top-left',
  TOP_RIGHT: 'top-right',
  BOTTOM_LEFT: 'bottom-left',
  BOTTOM_RIGHT: 'bottom-right'
};

var Menu = function Menu(_ref) {
  var _menuNode$current2;

  var _ref$active = _ref.active,
      active = _ref$active === void 0 ? false : _ref$active,
      children = _ref.children,
      className = _ref.className,
      onHide = _ref.onHide,
      onSelect = _ref.onSelect,
      onShow = _ref.onShow,
      _ref$outline = _ref.outline,
      outline = _ref$outline === void 0 ? true : _ref$outline,
      _ref$position = _ref.position,
      position = _ref$position === void 0 ? 'static' : _ref$position,
      _ref$selectable = _ref.selectable,
      selectable = _ref$selectable === void 0 ? true : _ref$selectable,
      selected = _ref.selected,
      others = (0, _objectWithoutProperties2.default)(_ref, _excluded);

  var _useState = (0, _react.useState)(0),
      _useState2 = (0, _slicedToArray2.default)(_useState, 2),
      stateWidth = _useState2[0],
      setStateWidth = _useState2[1];

  var _useState3 = (0, _react.useState)(0),
      _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
      stateHeight = _useState4[0],
      setStateHeight = _useState4[1];

  var _useState5 = (0, _react.useState)(position),
      _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
      statePosition = _useState6[0],
      setPosition = _useState6[1];

  var menuNode = (0, _react.useRef)(null);
  var menuWrapper = (0, _react.useRef)(null);
  var boxProps = (0, _box.pickBoxProps)(others);
  var classNames = (0, _classnames.default)(_theme.default['menu'], _theme.default[position], (0, _defineProperty2.default)({}, _theme.default['active'], active), className);
  var outlineClassNames = (0, _classnames.default)(_theme.default['outline'], (0, _defineProperty2.default)({}, _uiUtilities.default['box-shadow-200'], position !== POSITION.STATIC));

  var handleDocumentClick = function handleDocumentClick(event) {
    if (active && !_utils.events.targetIsDescendant(event, menuWrapper.current)) {
      // eslint-disable-next-line @typescript-eslint/no-use-before-define
      hide();
    }
  };

  var handleSelect = function handleSelect(item, event) {
    var _item$props = item.props,
        value = _item$props.value,
        onClick = _item$props.onClick;

    if (onSelect) {
      onSelect(value);
    }

    if (onClick) {
      event.persist();
      onClick(event);
    } // eslint-disable-next-line @typescript-eslint/no-use-before-define


    hide();
  };

  var addEvents = function addEvents() {
    window.setTimeout(function () {
      return _utils.events.addEventsToDocument({
        click: handleDocumentClick,
        touchstart: handleDocumentClick
      });
    }, 0);
  };

  var removeEvents = function removeEvents() {
    _utils.events.removeEventsFromDocument({
      click: handleDocumentClick,
      touchstart: handleDocumentClick
    });
  };

  var calculatePosition = function calculatePosition() {
    var _menuWrapper$current;

    var parentNode = menuWrapper === null || menuWrapper === void 0 ? void 0 : (_menuWrapper$current = menuWrapper.current) === null || _menuWrapper$current === void 0 ? void 0 : _menuWrapper$current.parentNode;

    if (!parentNode) {
      return;
    }

    var _parentNode$getBoundi = parentNode.getBoundingClientRect(),
        top = _parentNode$getBoundi.top,
        left = _parentNode$getBoundi.left,
        height = _parentNode$getBoundi.height,
        width = _parentNode$getBoundi.width;

    var _getViewport = (0, _utils2.getViewport)(),
        vh = _getViewport.height,
        vw = _getViewport.width;

    var toTop = top < vh / 2 - height / 2;
    var toLeft = left < vw / 2 - width / 2;
    return "".concat(toTop ? 'top' : 'bottom').concat(toLeft ? 'Left' : 'Right');
  };

  var getRootStyle = function getRootStyle() {
    if (statePosition !== POSITION.STATIC) {
      return {
        width: stateWidth,
        height: stateHeight
      };
    }
  };

  var getActiveMenuStyle = function getActiveMenuStyle() {
    return {
      clip: "rect(0 ".concat(stateWidth, "px ").concat(stateHeight, "px 0)")
    };
  };

  var getMenuStyleByPosition = function getMenuStyleByPosition() {
    switch (statePosition) {
      case POSITION.TOP_RIGHT:
        return {
          clip: "rect(0 ".concat(stateWidth, "px 0 ").concat(stateWidth, "px)")
        };

      case POSITION.BOTTOM_RIGHT:
        return {
          clip: "rect(".concat(stateHeight, "px ").concat(stateWidth, "px ").concat(stateHeight, "px ").concat(stateWidth, "px)")
        };

      case POSITION.BOTTOM_LEFT:
        return {
          clip: "rect(".concat(stateHeight, "px 0 ").concat(stateHeight, "px 0)")
        };

      case POSITION.TOP_LEFT:
        return {
          clip: 'rect(0 0 0 0)'
        };

      default:
        return {};
    }
  };

  var getMenuStyle = function getMenuStyle() {
    return active ? getActiveMenuStyle() : getMenuStyleByPosition();
  };

  var getItems = (0, _react.useCallback)(function () {
    // Because React Hot Loader creates proxied versions of your components,
    // comparing reference types of elements won't work
    // https://github.com/gaearon/react-hot-loader/blob/master/docs/Known%20Limitations.md#checking-element-types
    var MenuItemType = /*#__PURE__*/_react.default.createElement(_MenuItem.default, null).type;

    return _react.default.Children.map(children, function (item) {
      if (!item) {
        return item;
      }

      if ( /*#__PURE__*/_react.default.isValidElement(item)) {
        if (item.type === MenuItemType) {
          return /*#__PURE__*/_react.default.cloneElement(item, {
            selected: typeof item.props.value !== 'undefined' && selectable && item.props.value === selected,
            onClick: function onClick(event) {
              return handleSelect(item, event);
            }
          });
        } else {
          return /*#__PURE__*/_react.default.cloneElement(item);
        }
      }
    });
  }, [children]);

  var show = function show() {
    onShow && onShow();
    addEvents();
  };

  var hide = function hide() {
    onHide && onHide();
    removeEvents();
  };

  (0, _react.useLayoutEffect)(function () {
    var _menuNode$current;

    var _ref2 = ((_menuNode$current = menuNode.current) === null || _menuNode$current === void 0 ? void 0 : _menuNode$current.getBoundingClientRect()) || {},
        width = _ref2.width,
        height = _ref2.height;

    setStateWidth(width);
    setStateHeight(height);
  }, [(_menuNode$current2 = menuNode.current) === null || _menuNode$current2 === void 0 ? void 0 : _menuNode$current2.getBoundingClientRect()]);
  (0, _react.useEffect)(function () {
    active ? show() : hide();
    return function () {
      active && removeEvents();
    };
  }, [active]);
  (0, _react.useEffect)(function () {
    if (position === POSITION.AUTO) {
      setPosition(calculatePosition());
    }
  }, [position]);
  return /*#__PURE__*/_react.default.createElement(_box.default, (0, _extends2.default)({
    "data-teamleader-ui": "menu",
    className: classNames,
    ref: menuWrapper,
    style: getRootStyle()
  }, boxProps), outline && /*#__PURE__*/_react.default.createElement("div", {
    className: outlineClassNames,
    style: _objectSpread(_objectSpread({}, stateWidth && {
      width: Math.ceil(stateWidth)
    }), {}, {
      height: stateHeight
    })
  }), /*#__PURE__*/_react.default.createElement("ul", {
    ref: menuNode,
    className: _theme.default['menu-inner'],
    style: getMenuStyle()
  }, getItems()));
};

var _default = Menu;
exports.default = _default;