import classNames from "classnames" ; import { Modifiers } from "popper.js" ; import * as React from "react" ; import { polyfill } from "react-lifecycles-compat" ; import { AbstractPureComponent2 , Classes , Position } from "../../common" ; import { DISPLAYNAME_PREFIX , ActionProps , LinkProps } from "../../common/props" ; import { Icon } from "../icon/icon" ; import { IPopoverProps , Popover , PopoverInteractionKind } from "../popover/popover" ; import { Text } from "../text/text" ; import { Menu } from "./menu" ; export type MenuItemProps = IMenuItemProps ; deprecated export interface IMenuItemProps extends ActionProps , LinkProps { /** Item text, required for usability. */ text : React . ReactNode ; /** Whether this menu item should appear with an active state. */ active ? : boolean ; /**
     * Children of this component will be rendered in a __submenu__ that appears when hovering or
     * clicking on this menu item.
     *
     * Use `text` prop for the content of the menu item itself.
     */ children ? : React . ReactNode ; /**
     * Whether this menu item is non-interactive. Enabling this prop will ignore `href`, `tabIndex`,
     * and mouse event handlers (in particular click, down, enter, leave).
     */ disabled ? : boolean ; /**
     * Right-aligned label text content, useful for displaying hotkeys.
     *
     * This prop actually supports JSX elements, but TypeScript will throw an error because
     * `HTMLAttributes` only allows strings. Use `labelElement` to supply a JSX element in TypeScript.
     */ label ? : string ; /**
     * A space-delimited list of class names to pass along to the right-aligned label wrapper element.
     */ labelClassName ? : string ; /**
     * Right-aligned label content, useful for displaying hotkeys.
     */ labelElement ? : React . ReactNode ; default multiline ? : boolean ; /**
     * Props to spread to `Popover`. Note that `content` and `minimal` cannot be
     * changed and `usePortal` defaults to `false` so all submenus will live in
     * the same container.
     */ popoverProps ? : Partial < IPopoverProps > ; default shouldDismissPopover ? : boolean ; default tagName ? : keyof JSX . IntrinsicElements ; /**
     * A space-delimited list of class names to pass along to the text wrapper element.
     */ textClassName ? : string ; /**
     * HTML title to be passed to the <Text> component
     */ htmlTitle ? : string ; } @ polyfill export class MenuItem extends AbstractPureComponent2 < MenuItemProps & React . AnchorHTMLAttributes < HTMLAnchorElement > > { public static defaultProps : MenuItemProps = { disabled : false , multiline : false , popoverProps : { } , shouldDismissPopover : true , text : "" , } ; public static displayName = `${ DISPLAYNAME_PREFIX }.MenuItem` ; public render ( ) { const { active , className , children , disabled , icon , intent , labelClassName , labelElement , multiline , popoverProps , shouldDismissPopover , text , textClassName , tagName = "a" , htmlTitle , ... htmlProps } = this . props ; const hasSubmenu = children != null ; const intentClass = Classes . intentClass ( intent ) ; const anchorClasses = classNames ( Classes . MENU_ITEM , intentClass , { [ Classes . ACTIVE ] : active , [ Classes . INTENT_PRIMARY ] : active && intentClass == null , [ Classes . DISABLED ] : disabled , [ Classes . POPOVER_DISMISS ] : shouldDismissPopover && ! disabled && ! hasSubmenu , } , className ) ; const target = React . createElement ( tagName , { tabIndex : 0 , ... htmlProps , ... ( disabled ? DISABLED_PROPS : { } ) , className : anchorClasses , } , < Icon icon = { icon } / > , < Text className = { classNames ( Classes . FILL , textClassName ) } ellipsize = { ! multiline } title = { htmlTitle } > { text } < /Text>, this.maybeRenderLabel(labelElement), hasSubmenu ? <Icon title="Open sub menu" icon="caret-right"/ > : undefined ) ; const liClasses = classNames ( { [ Classes . MENU_SUBMENU ] : hasSubmenu } ) ; return < li className = { liClasses } > { this . maybeRenderPopover ( target , children ) } < /li>; } private maybeRenderLabel ( labelElement ? ) { const { label , labelClassName } = this . props ; if ( label == null && labelElement == null ) { return null ; } return ( < span className = { classNames ( Classes . MENU_ITEM_LABEL , labelClassName ) } > { label } { labelElement } < /span>); } private maybeRenderPopover ( target , children ? ) { if ( children == null ) { return target ; } const { disabled , popoverProps } = this . props ; return ( < Popover autoFocus = { false } captureDismiss = { false } disabled = { disabled } enforceFocus = { false } hoverCloseDelay = { 0 } interactionKind = { PopoverInteractionKind . HOVER } modifiers = { SUBMENU_POPOVER_MODIFIERS } position = { Position . RIGHT_TOP } usePortal = { false } { ... popoverProps } content = { < Menu > { children } < /Menu>} minimal={true} popoverClassName={classNames(Classes.MENU_SUBMENU, popoverProps?.popoverClassName)} target={target}/ > ) ; } } const SUBMENU_POPOVER_MODIFIERS = { flip : { boundariesElement : "viewport" , padding : 20 } , offset : { offset : - 5 } , preventOverflow : { boundariesElement : "viewport" , padding : 20 } , } ; const DISABLED_PROPS = { href : undefined , onClick : undefined , onMouseDown : undefined , onMouseEnter : undefined , onMouseLeave : undefined , tabIndex : - 1 , } ;