onClick: getOnClickWithOverrideTarget()

in packages/react/src/components/ContextualMenu/ContextualMenu.base.tsx [86:768]


          onClick: getOnClickWithOverrideTarget(onClick, target),
        });
      } else {
        overrideItems.push(subItem);
      }
    }

    return overrideItems;
  }
}

/**
 * Returns true if a list of menu items can contain a checkbox
 */
export function canAnyMenuItemsCheck(items: IContextualMenuItem[]): boolean {
  return items.some(item => {
    if (item.canCheck) {
      return true;
    }

    // If the item is a section, check if any of the items in the section can check.
    if (item.sectionProps && item.sectionProps.items.some(submenuItem => submenuItem.canCheck === true)) {
      return true;
    }

    return false;
  });
}

const NavigationIdleDelay = 250; /* ms */

const COMPONENT_NAME = 'ContextualMenu';

const _getMenuItemStylesFunction = memoizeFunction(
  (
    ...styles: (IStyleFunctionOrObject<IContextualMenuItemStyleProps, IContextualMenuItemStyles> | undefined)[]
  ): IStyleFunctionOrObject<IContextualMenuItemStyleProps, IContextualMenuItemStyles> => {
    return (styleProps: IContextualMenuItemStyleProps) =>
      concatStyleSetsWithProps(styleProps, getItemStyles, ...styles);
  },
);

//#region Custom hooks
function useVisibility(props: IContextualMenuProps, targetWindow: Window | undefined) {
  const { hidden = false, onMenuDismissed, onMenuOpened } = props;
  const previousHidden = usePrevious(hidden);

  const onMenuOpenedRef = React.useRef(onMenuOpened);
  const onMenuClosedRef = React.useRef(onMenuDismissed);
  const propsRef = React.useRef(props);

  onMenuOpenedRef.current = onMenuOpened;
  onMenuClosedRef.current = onMenuDismissed;
  propsRef.current = props;

  React.useEffect(() => {
    // Don't issue dismissed callbacks on initial mount
    if (hidden && previousHidden === false) {
      onMenuClosedRef.current?.(propsRef.current);
    } else if (!hidden && previousHidden !== false) {
      onMenuOpenedRef.current?.(propsRef.current);
    }
  }, [hidden, previousHidden]);

  // Issue onDismissedCallback on unmount
  React.useEffect(() => () => onMenuClosedRef.current?.(propsRef.current), []);
}

function useSubMenuState(
  { hidden, items, theme, className, id, target: menuTarget }: IContextualMenuProps,
  dismiss: () => void,
) {
  const [expandedMenuItemKey, setExpandedMenuItemKey] = React.useState<string>();
  const [submenuTarget, setSubmenuTarget] = React.useState<HTMLElement>();
  /** True if the menu was expanded by mouse click OR hover (as opposed to by keyboard) */
  const [expandedByMouseClick, setExpandedByMouseClick] = React.useState<boolean>();
  const subMenuId = useId(COMPONENT_NAME, id);

  const closeSubMenu = React.useCallback(() => {
    setExpandedByMouseClick(undefined);
    setExpandedMenuItemKey(undefined);
    setSubmenuTarget(undefined);
  }, []);

  const openSubMenu = React.useCallback(
    ({ key: submenuItemKey }: IContextualMenuItem, target: HTMLElement, openedByMouseClick?: boolean) => {
      if (expandedMenuItemKey === submenuItemKey) {
        return;
      }

      target.focus();

      setExpandedByMouseClick(openedByMouseClick);
      setExpandedMenuItemKey(submenuItemKey);
      setSubmenuTarget(target);
    },
    [expandedMenuItemKey],
  );

  React.useEffect(() => {
    if (hidden) {
      closeSubMenu();
    }
  }, [hidden, closeSubMenu]);

  const onSubMenuDismiss = useOnSubmenuDismiss(dismiss, closeSubMenu);

  const getSubmenuProps = (): IContextualMenuProps | null => {
    const item = findItemByKeyFromItems(expandedMenuItemKey!, items);
    let submenuProps: IContextualMenuProps | null = null;

    if (item) {
      submenuProps = {
        items: getSubmenuItems(item, { target: menuTarget })!,
        target: submenuTarget,
        onDismiss: onSubMenuDismiss,
        isSubMenu: true,
        id: subMenuId,
        shouldFocusOnMount: true,
        shouldFocusOnContainer: expandedByMouseClick,
        directionalHint: getRTL(theme) ? DirectionalHint.leftTopEdge : DirectionalHint.rightTopEdge,
        className,
        gapSpace: 0,
        isBeakVisible: false,
      };

      if (item.subMenuProps) {
        assign(submenuProps, item.subMenuProps);
      }

      if (item.preferMenuTargetAsEventTarget) {
        const { onItemClick } = item;

        submenuProps.onItemClick = getOnClickWithOverrideTarget(onItemClick, menuTarget);
      }
    }
    return submenuProps;
  };

  return [expandedMenuItemKey, openSubMenu, getSubmenuProps, onSubMenuDismiss] as const;
}

function useShouldUpdateFocusOnMouseMove({ delayUpdateFocusOnHover, hidden }: IContextualMenuProps) {
  const shouldUpdateFocusOnMouseEvent = React.useRef<boolean>(!delayUpdateFocusOnHover);
  const gotMouseMove = React.useRef<boolean>(false);

  React.useEffect(() => {
    shouldUpdateFocusOnMouseEvent.current = !delayUpdateFocusOnHover;
    gotMouseMove.current = hidden ? false : !delayUpdateFocusOnHover && gotMouseMove.current;
  }, [delayUpdateFocusOnHover, hidden]);

  const onMenuFocusCapture = React.useCallback(() => {
    if (delayUpdateFocusOnHover) {
      shouldUpdateFocusOnMouseEvent.current = true;
    }
  }, [delayUpdateFocusOnHover]);

  return [shouldUpdateFocusOnMouseEvent, gotMouseMove, onMenuFocusCapture] as const;
}

function usePreviousActiveElement({ hidden, onRestoreFocus }: IContextualMenuProps, targetWindow: Window | undefined) {
  const previousActiveElement = React.useRef<undefined | HTMLElement>();

  const tryFocusPreviousActiveElement = React.useCallback(
    (options: IPopupRestoreFocusParams) => {
      if (onRestoreFocus) {
        onRestoreFocus(options);
      } else if (options?.documentContainsFocus) {
        // Make sure that the focus method actually exists
        // In some cases the object might exist but not be a real element.
        // This is primarily for IE 11 and should be removed once IE 11 is no longer in use.
        previousActiveElement.current?.focus?.();
      }
    },
    [onRestoreFocus],
  );

  // eslint-disable-next-line no-restricted-properties
  React.useLayoutEffect(() => {
    if (!hidden) {
      previousActiveElement.current = targetWindow?.document.activeElement as HTMLElement;
    } else if (previousActiveElement.current) {
      tryFocusPreviousActiveElement({
        originalElement: previousActiveElement.current,
        containsFocus: true,
        documentContainsFocus: getDocument()?.hasFocus() || false,
      });

      previousActiveElement.current = undefined;
    }
  }, [hidden, targetWindow?.document.activeElement, tryFocusPreviousActiveElement]);

  return [tryFocusPreviousActiveElement] as const;
}

function useKeyHandlers(
  {
    theme,
    isSubMenu,
    focusZoneProps: { checkForNoWrap, direction: focusZoneDirection = FocusZoneDirection.vertical } = {},
  }: IContextualMenuProps,
  dismiss: (ev?: any, dismissAll?: boolean | undefined) => void | undefined,
  hostElement: React.RefObject<HTMLDivElement>,
  openSubMenu: (submenuItemKey: IContextualMenuItem, target: HTMLElement, openedByMouseClick?: boolean) => void,
) {
  /** True if the most recent keydown event was for alt (option) or meta (command). */
  const lastKeyDownWasAltOrMeta = React.useRef<boolean | undefined>();

  /**
   * Calls `shouldHandleKey` to determine whether the keyboard event should be handled;
   * if so, stops event propagation and dismisses menu(s).
   * @param ev - The keyboard event.
   * @param shouldHandleKey - Returns whether we should handle this keyboard event.
   * @param dismissAllMenus - If true, dismiss all menus. Otherwise, dismiss only the current menu.
   * Only does anything if `shouldHandleKey` returns true.
   * @returns Whether the event was handled.
   */
  const keyHandler = (
    ev: React.KeyboardEvent<HTMLElement>,
    shouldHandleKey: (ev: React.KeyboardEvent<HTMLElement>) => boolean,
    dismissAllMenus?: boolean,
  ): boolean => {
    let handled = false;

    if (shouldHandleKey(ev)) {
      dismiss(ev, dismissAllMenus);
      ev.preventDefault();
      ev.stopPropagation();
      handled = true;
    }

    return handled;
  };

  /**
   * Checks if the submenu should be closed
   */
  const shouldCloseSubMenu = (ev: React.KeyboardEvent<HTMLElement>): boolean => {
    const submenuCloseKey = getRTL(theme) ? KeyCodes.right : KeyCodes.left;

    // eslint-disable-next-line deprecation/deprecation
    if (ev.which !== submenuCloseKey || !isSubMenu) {
      return false;
    }

    return !!(
      focusZoneDirection === FocusZoneDirection.vertical ||
      (checkForNoWrap && !shouldWrapFocus(ev.target as HTMLElement, 'data-no-horizontal-wrap'))
    );
  };

  const shouldHandleKeyDown = (ev: React.KeyboardEvent<HTMLElement>) => {
    return (
      // eslint-disable-next-line deprecation/deprecation
      ev.which === KeyCodes.escape ||
      shouldCloseSubMenu(ev) ||
      // eslint-disable-next-line deprecation/deprecation
      (ev.which === KeyCodes.up && (ev.altKey || ev.metaKey))
    );
  };

  const onKeyDown = (ev: React.KeyboardEvent<HTMLElement>): boolean => {
    // Take note if we are processing an alt (option) or meta (command) keydown.
    // See comment in shouldHandleKeyUp for reasoning.
    lastKeyDownWasAltOrMeta.current = isAltOrMeta(ev);

    // On Mac, pressing escape dismisses all levels of native context menus
    // eslint-disable-next-line deprecation/deprecation
    const dismissAllMenus = ev.which === KeyCodes.escape && (isMac() || isIOS());

    return keyHandler(ev, shouldHandleKeyDown, dismissAllMenus);
  };

  /**
   * We close the menu on key up only if ALL of the following are true:
   * - Most recent key down was alt or meta (command)
   * - The alt/meta key down was NOT followed by some other key (such as down/up arrow to
   *   expand/collapse the menu)
   * - We're not on a Mac (or iOS)
   *
   * This is because on Windows, pressing alt moves focus to the application menu bar or similar,
   * closing any open context menus. There is not a similar behavior on Macs.
   */
  const shouldHandleKeyUp = (ev: React.KeyboardEvent<HTMLElement>) => {
    const keyPressIsAltOrMetaAlone = lastKeyDownWasAltOrMeta.current && isAltOrMeta(ev);
    lastKeyDownWasAltOrMeta.current = false;
    return !!keyPressIsAltOrMetaAlone && !(isIOS() || isMac());
  };

  const onKeyUp = (ev: React.KeyboardEvent<HTMLElement>): boolean => {
    return keyHandler(ev, shouldHandleKeyUp, true /* dismissAllMenus */);
  };

  const onMenuKeyDown = (ev: React.KeyboardEvent<HTMLElement>) => {
    // Mark as handled if onKeyDown returns true (for handling collapse cases)
    // or if we are attempting to expand a submenu
    const handled = onKeyDown(ev);

    if (handled || !hostElement.current) {
      return;
    }

    // If we have a modifier key being pressed, we do not want to move focus.
    // Otherwise, handle up and down keys.
    const hasModifier = !!(ev.altKey || ev.metaKey);
    // eslint-disable-next-line deprecation/deprecation
    const isUp = ev.which === KeyCodes.up;
    // eslint-disable-next-line deprecation/deprecation
    const isDown = ev.which === KeyCodes.down;
    if (!hasModifier && (isUp || isDown)) {
      const elementToFocus = isUp
        ? getLastFocusable(hostElement.current, hostElement.current.lastChild as HTMLElement, true)
        : getFirstFocusable(hostElement.current, hostElement.current.firstChild as HTMLElement, true);

      if (elementToFocus) {
        elementToFocus.focus();
        ev.preventDefault();
        ev.stopPropagation();
      }
    }
  };

  const onItemKeyDown = (item: any, ev: React.KeyboardEvent<HTMLElement>): void => {
    const openKey = getRTL(theme) ? KeyCodes.left : KeyCodes.right;

    if (
      !item.disabled &&
      // eslint-disable-next-line deprecation/deprecation
      (ev.which === openKey || ev.which === KeyCodes.enter || (ev.which === KeyCodes.down && (ev.altKey || ev.metaKey)))
    ) {
      openSubMenu(item, ev.currentTarget as HTMLElement, false);
      ev.preventDefault();
    }
  };

  return [onKeyDown, onKeyUp, onMenuKeyDown, onItemKeyDown] as const;
}

function useScrollHandler(asyncTracker: Async) {
  const isScrollIdle = React.useRef<boolean>(true);
  const scrollIdleTimeoutId = React.useRef<number | undefined>();

  /**
   * Scroll handler for the callout to make sure the mouse events
   * for updating focus are not interacting during scroll
   */
  const onScroll = (): void => {
    if (!isScrollIdle.current && scrollIdleTimeoutId.current !== undefined) {
      asyncTracker.clearTimeout(scrollIdleTimeoutId.current);
      scrollIdleTimeoutId.current = undefined;
    } else {
      isScrollIdle.current = false;
    }

    scrollIdleTimeoutId.current = asyncTracker.setTimeout(() => {
      isScrollIdle.current = true;
    }, NavigationIdleDelay);
  };

  return [onScroll, isScrollIdle] as const;
}

function useOnSubmenuDismiss(dismiss: (ev?: any, dismissAll?: boolean) => void, closeSubMenu: () => void) {
  const isMountedRef = React.useRef(false);
  React.useEffect(() => {
    isMountedRef.current = true;
    return () => {
      isMountedRef.current = false;
    };
  }, []);

  /**
   * This function is called ASYNCHRONOUSLY, and so there is a chance it is called
   * after the component is unmounted. The isMountedRef is added to prevent
   * from calling setState() after unmount. Do NOT copy this pattern in synchronous
   * code.
   */
  const onSubMenuDismiss = (ev?: any, dismissAll?: boolean): void => {
    if (dismissAll) {
      dismiss(ev, dismissAll);
    } else if (isMountedRef.current) {
      closeSubMenu();
    }
  };

  return onSubMenuDismiss;
}

function useSubmenuEnterTimer({ subMenuHoverDelay = NavigationIdleDelay }: IContextualMenuProps, asyncTracker: Async) {
  const enterTimerRef = React.useRef<number | undefined>(undefined);

  const cancelSubMenuTimer = () => {
    if (enterTimerRef.current !== undefined) {
      asyncTracker.clearTimeout(enterTimerRef.current);
      enterTimerRef.current = undefined;
    }
  };

  const startSubmenuTimer = (onTimerExpired: () => void) => {
    enterTimerRef.current = asyncTracker.setTimeout(() => {
      onTimerExpired();
      cancelSubMenuTimer();
    }, subMenuHoverDelay);
  };

  return [cancelSubMenuTimer, startSubmenuTimer, enterTimerRef as React.RefObject<number | undefined>] as const;
}

function useMouseHandlers(
  props: IContextualMenuProps,
  isScrollIdle: React.MutableRefObject<boolean>,
  subMenuEntryTimer: React.RefObject<number | undefined>,
  targetWindow: Window | undefined,
  shouldUpdateFocusOnMouseEvent: React.MutableRefObject<boolean>,
  gotMouseMove: React.MutableRefObject<boolean>,
  expandedMenuItemKey: string | undefined,
  hostElement: React.RefObject<HTMLDivElement>,
  startSubmenuTimer: (onTimerExpired: () => void) => void,
  cancelSubMenuTimer: () => void,
  openSubMenu: (submenuItemKey: IContextualMenuItem, target: HTMLElement, openedByMouseClick?: boolean) => void,
  onSubMenuDismiss: (ev?: any, dismissAll?: boolean) => void,
  dismiss: (ev?: any, dismissAll?: boolean) => void,
) {
  const { target: menuTarget } = props;

  const onItemMouseEnterBase = (item: any, ev: React.MouseEvent<HTMLElement>, target?: HTMLElement): void => {
    if (shouldIgnoreMouseEvent()) {
      return;
    }

    updateFocusOnMouseEvent(item, ev, target);
  };

  const onItemMouseMoveBase = (item: any, ev: React.MouseEvent<HTMLElement>, target: HTMLElement): void => {
    const targetElement = ev.currentTarget as HTMLElement;

    // Always do this check to make sure we record a mouseMove if needed (even if we are timed out)
    if (shouldUpdateFocusOnMouseEvent.current) {
      gotMouseMove.current = true;
    } else {
      return;
    }

    if (
      !isScrollIdle.current ||
      subMenuEntryTimer.current !== undefined ||
      targetElement === (targetWindow?.document.activeElement as HTMLElement)
    ) {
      return;
    }

    updateFocusOnMouseEvent(item, ev, target);
  };

  const shouldIgnoreMouseEvent = (): boolean => {
    return !isScrollIdle.current || !gotMouseMove.current;
  };

  const onMouseItemLeave = (item: any, ev: React.MouseEvent<HTMLElement>): void => {
    if (shouldIgnoreMouseEvent()) {
      return;
    }

    cancelSubMenuTimer();

    if (expandedMenuItemKey !== undefined) {
      return;
    }

    /**
     * IE11 focus() method forces parents to scroll to top of element.
     * Edge and IE expose a setActive() function for focusable divs that
     * sets the page focus but does not scroll the parent element.
     */
    if ((hostElement.current as any).setActive) {
      try {
        (hostElement.current as any).setActive();
      } catch (e) {
        /* no-op */
      }
    } else {
      hostElement.current?.focus();
    }
  };

  /**
   * Handles updating focus when mouseEnter or mouseMove fire.
   * As part of updating focus, This function will also update
   * the expand/collapse state accordingly.
   */
  const updateFocusOnMouseEvent = (
    item: IContextualMenuItem,
    ev: React.MouseEvent<HTMLElement>,
    target?: HTMLElement,
  ) => {
    const targetElement = target ? target : (ev.currentTarget as HTMLElement);

    if (item.key === expandedMenuItemKey) {
      return;
    }

    cancelSubMenuTimer();

    // If the menu is not expanded we can update focus without any delay
    if (expandedMenuItemKey === undefined) {
      targetElement.focus();
    }

    // Delay updating expanding/dismissing the submenu
    // and only set focus if we have not already done so
    if (hasSubmenu(item)) {
      ev.stopPropagation();
      startSubmenuTimer(() => {
        targetElement.focus();
        openSubMenu(item, targetElement, true);
      });
    } else {
      startSubmenuTimer(() => {
        onSubMenuDismiss(ev);
        targetElement.focus();
      });
    }
  };

  const onItemClick = (
    item: IContextualMenuItem,
    ev: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
  ): void => {
    onItemClickBase(item, ev, ev.currentTarget as HTMLElement);
  };

  const onItemClickBase = (
    item: IContextualMenuItem,
    ev: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
    target: HTMLElement,
  ): void => {
    const items = getSubmenuItems(item, { target: menuTarget });

    // Cancel an async menu item hover timeout action from being taken and instead
    // just trigger the click event instead.
    cancelSubMenuTimer();

    if (!hasSubmenu(item) && (!items || !items.length)) {
      // This is an item without a menu. Click it.
      executeItemClick(item, ev);
    } else {
      if (item.key !== expandedMenuItemKey) {
        // This has a collapsed sub menu. Expand it.
        openSubMenu(
          item,
          target,
          // When Edge + Narrator are used together (regardless of if the button is in a form or not), pressing
          // "Enter" fires this method and not _onMenuKeyDown. Checking ev.nativeEvent.detail differentiates
          // between a real click event and a keypress event (detail should be the number of mouse clicks).
          // ...Plot twist! For a real click event in IE 11, detail is always 0 (Edge sets it properly to 1).
          // So we also check the pointerType property, which both Edge and IE set to "mouse" for real clicks
          // and "" for pressing "Enter" with Narrator on.
          ev.nativeEvent.detail !== 0 || (ev.nativeEvent as PointerEvent).pointerType === 'mouse',
        );
      }
    }

    ev.stopPropagation();
    ev.preventDefault();
  };

  const onAnchorClick = (item: IContextualMenuItem, ev: React.MouseEvent<HTMLElement>) => {
    executeItemClick(item, ev);
    ev.stopPropagation();
  };

  const executeItemClick = (
    item: IContextualMenuItem,
    ev: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
  ): void => {
    if (item.disabled || item.isDisabled) {
      return;
    }

    if (item.preferMenuTargetAsEventTarget) {
      overrideTarget(ev, menuTarget);
    }

    let shouldDismiss = false;
    if (item.onClick) {
      shouldDismiss = !!item.onClick(ev, item);
    } else if (props.onItemClick) {
      shouldDismiss = !!props.onItemClick(ev, item);
    }

    if (shouldDismiss || !ev.defaultPrevented) {
      dismiss(ev, true);
    }
  };

  return [
    onItemMouseEnterBase,
    onItemMouseMoveBase,
    onMouseItemLeave,
    onItemClick,
    onAnchorClick,
    executeItemClick,
    onItemClickBase,
  ] as const;
}
//#endregion

export const ContextualMenuBase: React.FunctionComponent<IContextualMenuProps> = React.memo(
  React.forwardRef<HTMLDivElement, IContextualMenuProps>((propsWithoutDefaults, forwardedRef) => {
    const { ref, ...props } = getPropsWithDefaults(DEFAULT_PROPS, propsWithoutDefaults);
    const hostElement = React.useRef<HTMLDivElement>(null);
    const asyncTracker = useAsync();
    const menuId = useId(COMPONENT_NAME, props.id);

    useWarnings({
      name: COMPONENT_NAME,
      props,
      deprecations: {
        getMenuClassNames: 'styles',
      },
    });

    const dismiss = (ev?: any, dismissAll?: boolean) => props.onDismiss?.(ev, dismissAll);
    const [targetRef, targetWindow] = useTarget(props.target, hostElement);
    const [tryFocusPreviousActiveElement] = usePreviousActiveElement(props, targetWindow);
    const [expandedMenuItemKey, openSubMenu, getSubmenuProps, onSubMenuDismiss] = useSubMenuState(props, dismiss);
    const [shouldUpdateFocusOnMouseEvent, gotMouseMove, onMenuFocusCapture] = useShouldUpdateFocusOnMouseMove(props);
    const [onScroll, isScrollIdle] = useScrollHandler(asyncTracker);
    const [cancelSubMenuTimer, startSubmenuTimer, subMenuEntryTimer] = useSubmenuEnterTimer(props, asyncTracker);

    const responsiveMode = useResponsiveMode(hostElement, props.responsiveMode);

    useVisibility(props, targetWindow);

    const [onKeyDown, onKeyUp, onMenuKeyDown, onItemKeyDown] = useKeyHandlers(props, dismiss, hostElement, openSubMenu);
    const [
      onItemMouseEnterBase,
      onItemMouseMoveBase,
      onMouseItemLeave,
      onItemClick,
      onAnchorClick,
      executeItemClick,
      onItemClickBase,
    ] = useMouseHandlers(
      props,
      isScrollIdle,
      subMenuEntryTimer,
      targetWindow,
      shouldUpdateFocusOnMouseEvent,
      gotMouseMove,
      expandedMenuItemKey,
      hostElement,
      startSubmenuTimer,
      cancelSubMenuTimer,
      openSubMenu,
      onSubMenuDismiss,
      dismiss,
    );

    //#region Render helpers

    const onDefaultRenderMenuList = (
      menuListProps: IContextualMenuListProps,
      // eslint-disable-next-line deprecation/deprecation
      menuClassNames: IProcessedStyleSet<IContextualMenuStyles> | IContextualMenuClassNames,
      defaultRender?: IRenderFunction<IContextualMenuListProps>,
    ): JSX.Element => {
      let indexCorrection = 0;
      const { items, totalItemCount, hasCheckmarks, hasIcons } = menuListProps;

      return (
        <ul className={menuClassNames.list} onKeyDown={onKeyDown} onKeyUp={onKeyUp} role={'presentation'}>
          {items.map((item, index) => {
            const menuItem = renderMenuItem(
              item,
              index,
              indexCorrection,
              totalItemCount,
              hasCheckmarks,
              hasIcons,
              menuClassNames,
            );
            if (item.itemType !== ContextualMenuItemType.Divider && item.itemType !== ContextualMenuItemType.Header) {