import * as React from 'react' ; import classNames from 'classnames' ; import Overflow from 'rc-overflow' ; import warning from 'rc-util/lib/warning' ; import KeyCode from 'rc-util/lib/KeyCode' ; import omit from 'rc-util/lib/omit' ; import type { MenuClickEventHandler , MenuInfo , MenuHoverEventHandler , RenderIconType , } from './interface' ; import { MenuContext } from './context/MenuContext' ; import useActive from './hooks/useActive' ; import { warnItemProp } from './utils/warnUtil' ; import Icon from './Icon' ; import useDirectionStyle from './hooks/useDirectionStyle' ; import { useFullPath , useMeasure } from './context/PathContext' ; import { useMenuId } from './context/IdContext' ; import PrivateContext from './context/PrivateContext' ; export interface MenuItemProps extends Omit < React . HTMLAttributes < HTMLLIElement > , 'onClick' | 'onMouseEnter' | 'onMouseLeave' | 'onSelect' > { children ? : React . ReactNode ; private eventKey ? : string ; private warnKey ? : boolean ; disabled ? : boolean ; itemIcon ? : RenderIconType ; deprecated attribute ? : Record < string , string > ; onMouseEnter ? : MenuHoverEventHandler ; onMouseLeave ? : MenuHoverEventHandler ; onClick ? : MenuClickEventHandler ; } class LegacyMenuItem extends React . Component < any > { render ( ) { const { title , attribute , elementRef , ... restProps } = this . props ; const passedProps = omit ( restProps , [ 'eventKey' ] ) ; warning ( ! attribute , '`attribute` of Menu.Item is deprecated. Please pass attribute directly.' ) ; return ( < Overflow . Item { ... attribute } title = { typeof title === 'string' ? title : undefined } { ... passedProps } ref = { elementRef } / > ) ; } } /**
 * Real Menu Item component
 */ const InternalMenuItem = ( props ) => { const { style , className , eventKey , warnKey , disabled , itemIcon , children , role , onMouseEnter , onMouseLeave , onClick , onKeyDown , onFocus , ... restProps } = props ; const domDataId = useMenuId ( eventKey ) ; const { prefixCls , onItemClick , disabled : contextDisabled , overflowDisabled , itemIcon : contextItemIcon , selectedKeys , onActive , } = React . useContext ( MenuContext ) ; const { _internalRenderMenuItem } = React . useContext ( PrivateContext ) ; const itemCls = `${ prefixCls }-item` ; const legacyMenuItemRef = React . useRef < any > ( ) ; const elementRef = React . useRef < HTMLLIElement > ( ) ; const mergedDisabled = contextDisabled || disabled ; const connectedKeys = useFullPath ( eventKey ) ; if ( process . env . NODE_ENV !== 'production' && warnKey ) { warning ( false , 'MenuItem should not leave undefined `key`.' ) ; } const getEventInfo = ( e ) : MenuInfo => { return { key : eventKey , keyPath : [ ... connectedKeys ] . reverse ( ) , item : legacyMenuItemRef . current , domEvent : e , } ; } ; const mergedItemIcon = itemIcon || contextItemIcon ; const { active , ... activeProps } = useActive ( eventKey , mergedDisabled , onMouseEnter , onMouseLeave ) ; const selected = selectedKeys . includes ( eventKey ) ; const directionStyle = useDirectionStyle ( connectedKeys . length ) ; const onInternalClick = e => { if ( mergedDisabled ) { return ; } const info = getEventInfo ( e ) ; onClick ?. ( warnItemProp ( info ) ) ; onItemClick ( info ) ; } ; const onInternalKeyDown = e => { onKeyDown ?. ( e ) ; if ( e . which === KeyCode . ENTER ) { const info = getEventInfo ( e ) ; onClick ?. ( warnItemProp ( info ) ) ; onItemClick ( info ) ; } } ; /**
     * Used for accessibility. Helper will focus element without key board.
     * We should manually trigger an active
     */ const onInternalFocus = e => { onActive ( eventKey ) ; onFocus ?. ( e ) ; } ; const optionRoleProps = { } ; if ( props . role === 'option' ) { optionRoleProps [ 'aria-selected' ] = selected ; } let renderNode = ( < LegacyMenuItem ref = { legacyMenuItemRef } elementRef = { elementRef } role = { role === null ? 'none' : role || 'menuitem' } tabIndex = { disabled ? null : - 1 } data - menu - id = { overflowDisabled && domDataId ? null : domDataId } { ... restProps } { ... activeProps } { ... optionRoleProps } component = "li" aria - disabled = { disabled } style = { { ... directionStyle , ... style , } } className = { classNames ( itemCls , { [ `${ itemCls }-active` ] : active , [ `${ itemCls }-selected` ] : selected , [ `${ itemCls }-disabled` ] : mergedDisabled , } , className ) } onClick = { onInternalClick } onKeyDown = { onInternalKeyDown } onFocus = { onInternalFocus } > { children } < Icon props = { { ... props , isSelected : selected , } } icon = { mergedItemIcon } / > < /LegacyMenuItem>); if ( _internalRenderMenuItem ) { renderNode = _internalRenderMenuItem ( renderNode , props , { selected } ) ; } return renderNode ; } ; function MenuItem ( props ) { const { eventKey } = props ; const measure = useMeasure ( ) ; const connectedKeyPath = useFullPath ( eventKey ) ; React . useEffect ( ( ) => { if ( measure ) { measure . registerPath ( eventKey , connectedKeyPath ) ; return ( ) => { measure . unregisterPath ( eventKey , connectedKeyPath ) ; } ; } } , [ connectedKeyPath ] ) ; if ( measure ) { return null ; } return < InternalMenuItem { ... props } / > ; } export default MenuItem ;