text: import * as React from 'react';
  import { isFragment } from 'react-is';
  import PropTypes from 'prop-types';
  import clsx from 'clsx';
  import { HTMLElementType } from '@material-ui/utils';
  import withStyles from '../styles/withStyles';
  import Popover from '../Popover';
  import MenuList from '../MenuList';
  import setRef from '../utils/setRef';
  import useTheme from '../styles/useTheme';
  
  const RTL_ORIGIN = {
    vertical: 'top',
    horizontal: 'right',
  };
  
  const LTR_ORIGIN = {
    vertical: 'top',
    horizontal: 'left',
  };
  
  export const styles = {
    /* Styles applied to the `Paper` component. */
    paper: {
      // specZ: The maximum height of a simple menu should be one or more rows less than the view
      // height. This ensures a tapable area outside of the simple menu with which to dismiss
      // the menu.
      maxHeight: 'calc(100% - 96px)',
      // Add iOS momentum scrolling.
      WebkitOverflowScrolling: 'touch',
    },
    /* Styles applied to the `List` component via `MenuList`. */
    list: {
      // We disable the focus ring for mouse, touch and keyboard users.
      outline: 0,
    },
  };
  
  const Menu = React.forwardRef(function Menu(props, ref) {
    const {
      autoFocus = true,
      children,
      classes,
      disableAutoFocusItem = false,
      MenuListProps = {},
      onClose,
      open,
      PaperProps = {},
      PopoverClasses,
      transitionDuration = 'auto',
      variant = 'selectedMenu',
      TransitionProps: { onEntering, ...TransitionProps } = {},
      ...other
    } = props;
    const theme = useTheme();
  
    const autoFocusItem = autoFocus && !disableAutoFocusItem && open;
  
    const menuListActionsRef = React.useRef(null);
    const contentAnchorRef = React.useRef(null);
  
    const getContentAnchorEl = () => contentAnchorRef.current;
  
    const handleEntering = (element, isAppearing) => {
      if (menuListActionsRef.current) {
        menuListActionsRef.current.adjustStyleForScrollbar(element, theme);
      }
  
      if (onEntering) {
        onEntering(element, isAppearing);
      }
    };
  
    const handleListKeyDown = (event) => {
      if (event.key === 'Tab') {
        event.preventDefault();
  
        if (onClose) {
          onClose(event, 'tabKeyDown');
        }
      }
    };
  
    /**
     * the index of the item should receive focus
     * in a `variant="selectedMenu"` it's the first `selected` item
     * otherwise it's the very first item.
     */
    let activeItemIndex = -1;
    // since we inject focus related props into children we have to do a lookahead
    // to check if there is a `selected` item. We're looking for the last `selected`
    // item and use the first valid item as a fallback
    React.Children.map(children, (child, index) => {
      if (!React.isValidElement(child)) {
        return;
      }
  
      if (process.env.NODE_ENV !== 'production') {
        if (isFragment(child)) {
          console.error(
            [
              "Material-UI: The Menu component doesn't accept a Fragment as a child.",
              'Consider providing an array instead.',
            ].join('\n'),
          );
        }
      }
  
      if (!child.props.disabled) {
        if (variant === 'selectedMenu' && child.props.selected) {
          activeItemIndex = index;
        } else if (activeItemIndex === -1) {
          activeItemIndex = index;
        }
      }
    });
  
    const items = React.Children.map(children, (child, index) => {
      if (index === activeItemIndex) {
        return React.cloneElement(child, {
          ref: (instance) => {
            contentAnchorRef.current = instance;
            setRef(child.ref, instance);
          },
        });
      }
  
      return child;
    });
  
    return (
      <Popover
        getContentAnchorEl={getContentAnchorEl}
        classes={PopoverClasses}
        onClose={onClose}
        anchorOrigin={theme.direction === 'rtl' ? RTL_ORIGIN : LTR_ORIGIN}
        transformOrigin={theme.direction === 'rtl' ? RTL_ORIGIN : LTR_ORIGIN}
        PaperProps={{
          ...PaperProps,
          classes: {
            ...PaperProps.classes,
            root: classes.paper,
          },
        }}
        open={open}
        ref={ref}
        transitionDuration={transitionDuration}
        TransitionProps={{ onEntering: handleEntering, ...TransitionProps }}
        {...other}
      >
        <MenuList
          data-mui-test="Menu"
          onKeyDown={handleListKeyDown}
          actions={menuListActionsRef}
          autoFocus={autoFocus && (activeItemIndex === -1 || disableAutoFocusItem)}
          autoFocusItem={autoFocusItem}
          variant={variant}
          {...MenuListProps}
          className={clsx(classes.list, MenuListProps.className)}
        >
          {items}
        </MenuList>
      </Popover>
    );
  });
  
  Menu.propTypes = {
    // ----------------------------- Warning --------------------------------
    // | These PropTypes are generated from the TypeScript type definitions |
    // |     To update them edit the d.ts file and run "yarn proptypes"     |
    // ----------------------------------------------------------------------
    /**
     * A HTML element, or a function that returns it.
     * It's used to set the position of the menu.
     */
    anchorEl: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
      HTMLElementType,
      PropTypes.func,
    ]),
    /**
     * If `true` (Default) will focus the `[role="menu"]` if no focusable child is found. Disabled
     * children are not focusable. If you set this prop to `false` focus will be placed
     * on the parent modal container. This has severe accessibility implications
     * and should only be considered if you manage focus otherwise.
     */
    autoFocus: PropTypes.bool,
    /**
     * Menu contents, normally `MenuItem`s.
     */
    children: PropTypes.node,
    /**
     * Override or extend the styles applied to the component.
     */
    classes: PropTypes.object,
    /**
     * When opening the menu will not focus the active item but the `[role="menu"]`
     * unless `autoFocus` is also set to `false`. Not using the default means not
     * following WAI-ARIA authoring practices. Please be considerate about possible
     * accessibility implications.
     */
    disableAutoFocusItem: PropTypes.bool,
    /**
     * Props applied to the [`MenuList`](/api/menu-list/) element.
     */
    MenuListProps: PropTypes.object,
    /**
     * Callback fired when the component requests to be closed.
     *
     * @param {object} event The event source of the callback.
     * @param {string} reason Can be: `"escapeKeyDown"`, `"backdropClick"`, `"tabKeyDown"`.
     */
    onClose: PropTypes.func,
    /**
     * If `true`, the menu is visible.
     */
    open: PropTypes.bool.isRequired,
    /**
     * @ignore
     */
    PaperProps: PropTypes.object,
    /**
     * `classes` prop applied to the [`Popover`](/api/popover/) element.
     */
    PopoverClasses: PropTypes.object,
    /**
     * The length of the transition in `ms`, or 'auto'
     */
    transitionDuration: PropTypes.oneOfType([
      PropTypes.oneOf(['auto']),
      PropTypes.number,
      PropTypes.shape({
        appear: PropTypes.number,
        enter: PropTypes.number,
        exit: PropTypes.number,
      }),
    ]),
    /**
     * Props applied to the transition element.
     * By default, the element is based on this [`Transition`](http://reactcommunity.org/react-transition-group/transition) component.
     */
    TransitionProps: PropTypes.object,
    /**
     * The variant to use. Use `menu` to prevent selected items from impacting the initial focus
     * and the vertical alignment relative to the anchor element.
     */
    variant: PropTypes.oneOf(['menu', 'selectedMenu']),
  };
  
  export default withStyles(styles, { name: 'MuiMenu' })(Menu);
  