/**
 * External dependencies
 */
import * as Ariakit from '@ariakit/react';
import { useStoreState } from '@ariakit/react';

/**
 * WordPress dependencies
 */
import { useContext, useMemo, cloneElement, isValidElement, useCallback } from '@wordpress/element';
import { isRTL } from '@wordpress/i18n';
import { chevronRightSmall } from '@wordpress/icons';

/**
 * Internal dependencies
 */
import { useContextSystem, contextConnect } from '../context';
import * as Styled from './styles';
import { MenuContext } from './context';
import { MenuItem } from './item';
import { MenuCheckboxItem } from './checkbox-item';
import { MenuRadioItem } from './radio-item';
import { MenuGroup } from './group';
import { MenuGroupLabel } from './group-label';
import { MenuSeparator } from './separator';
import { MenuItemLabel } from './item-label';
import { MenuItemHelpText } from './item-help-text';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
const UnconnectedMenu = (props, ref) => {
  var _props$placement;
  const {
    // Store props
    open,
    defaultOpen = false,
    onOpenChange,
    placement,
    // Menu trigger props
    trigger,
    // Menu props
    gutter,
    children,
    shift,
    modal = true,
    // From internal components context
    variant,
    // Rest
    ...otherProps
  } = useContextSystem(props, 'Menu');
  const parentContext = useContext(MenuContext);
  const computedDirection = isRTL() ? 'rtl' : 'ltr';

  // If an explicit value for the `placement` prop is not passed,
  // apply a default placement of `bottom-start` for the root menu popover,
  // and of `right-start` for nested menu popovers.
  let computedPlacement = (_props$placement = props.placement) !== null && _props$placement !== void 0 ? _props$placement : parentContext?.store ? 'right-start' : 'bottom-start';
  // Swap left/right in case of RTL direction
  if (computedDirection === 'rtl') {
    if (/right/.test(computedPlacement)) {
      computedPlacement = computedPlacement.replace('right', 'left');
    } else if (/left/.test(computedPlacement)) {
      computedPlacement = computedPlacement.replace('left', 'right');
    }
  }
  const menuStore = Ariakit.useMenuStore({
    parent: parentContext?.store,
    open,
    defaultOpen,
    placement: computedPlacement,
    focusLoop: true,
    setOpen(willBeOpen) {
      onOpenChange?.(willBeOpen);
    },
    rtl: computedDirection === 'rtl'
  });
  const contextValue = useMemo(() => ({
    store: menuStore,
    variant
  }), [menuStore, variant]);

  // Extract the side from the applied placement — useful for animations.
  // Using `currentPlacement` instead of `placement` to make sure that we
  // use the final computed placement (including "flips" etc).
  const appliedPlacementSide = useStoreState(menuStore, 'currentPlacement').split('-')[0];
  if (menuStore.parent && !(isValidElement(trigger) && MenuItem === trigger.type)) {
    // eslint-disable-next-line no-console
    console.warn('For nested Menus, the `trigger` should always be a `MenuItem`.');
  }
  const hideOnEscape = useCallback(event => {
    // Pressing Escape can cause unexpected consequences (ie. exiting
    // full screen mode on MacOs, close parent modals...).
    event.preventDefault();
    // Returning `true` causes the menu to hide.
    return true;
  }, []);
  const wrapperProps = useMemo(() => ({
    dir: computedDirection,
    style: {
      direction: computedDirection
    }
  }), [computedDirection]);
  return /*#__PURE__*/_jsxs(_Fragment, {
    children: [/*#__PURE__*/_jsx(Ariakit.MenuButton, {
      ref: ref,
      store: menuStore,
      render: menuStore.parent ? cloneElement(trigger, {
        // Add submenu arrow, unless a `suffix` is explicitly specified
        suffix: /*#__PURE__*/_jsxs(_Fragment, {
          children: [trigger.props.suffix, /*#__PURE__*/_jsx(Styled.SubmenuChevronIcon, {
            "aria-hidden": "true",
            icon: chevronRightSmall,
            size: 24,
            preserveAspectRatio: "xMidYMid slice"
          })]
        })
      }) : trigger
    }), /*#__PURE__*/_jsx(Ariakit.Menu, {
      ...otherProps,
      modal: modal,
      store: menuStore
      // Root menu has an 8px distance from its trigger,
      // otherwise 0 (which causes the submenu to slightly overlap)
      ,
      gutter: gutter !== null && gutter !== void 0 ? gutter : menuStore.parent ? 0 : 8
      // Align nested menu by the same (but opposite) amount
      // as the menu container's padding.
      ,
      shift: shift !== null && shift !== void 0 ? shift : menuStore.parent ? -4 : 0,
      hideOnHoverOutside: false,
      "data-side": appliedPlacementSide,
      wrapperProps: wrapperProps,
      hideOnEscape: hideOnEscape,
      unmountOnHide: true,
      render: renderProps =>
      /*#__PURE__*/
      // Two wrappers are needed for the entry animation, where the menu
      // container scales with a different factor than its contents.
      // The {...renderProps} are passed to the inner wrapper, so that the
      // menu element is the direct parent of the menu item elements.
      _jsx(Styled.MenuPopoverOuterWrapper, {
        variant: variant,
        children: /*#__PURE__*/_jsx(Styled.MenuPopoverInnerWrapper, {
          ...renderProps
        })
      }),
      children: /*#__PURE__*/_jsx(MenuContext.Provider, {
        value: contextValue,
        children: children
      })
    })]
  });
};
export const Menu = Object.assign(contextConnect(UnconnectedMenu, 'Menu'), {
  Context: Object.assign(MenuContext, {
    displayName: 'Menu.Context'
  }),
  Item: Object.assign(MenuItem, {
    displayName: 'Menu.Item'
  }),
  RadioItem: Object.assign(MenuRadioItem, {
    displayName: 'Menu.RadioItem'
  }),
  CheckboxItem: Object.assign(MenuCheckboxItem, {
    displayName: 'Menu.CheckboxItem'
  }),
  Group: Object.assign(MenuGroup, {
    displayName: 'Menu.Group'
  }),
  GroupLabel: Object.assign(MenuGroupLabel, {
    displayName: 'Menu.GroupLabel'
  }),
  Separator: Object.assign(MenuSeparator, {
    displayName: 'Menu.Separator'
  }),
  ItemLabel: Object.assign(MenuItemLabel, {
    displayName: 'Menu.ItemLabel'
  }),
  ItemHelpText: Object.assign(MenuItemHelpText, {
    displayName: 'Menu.ItemHelpText'
  })
});
export default Menu;
//# sourceMappingURL=index.js.map