import cns from 'classnames' import React, { createContext, CSSProperties, HTMLAttributes, PropsWithChildren, ReactNode, useCallback, useContext, useMemo } from 'react' import { usePrefix, ComponentSize } from '../ConfigProvider' import { useDropdownCtx } from '../Dropdown' import { concat } from '../utils' import { WithRef } from '../utils/type' export interface MenuProps { /** 内容(`MenuItem` / `MenuItemGroup`) */ children?: ReactNode /** 尺寸 */ size?: ComponentSize /** 是否在菜单项被点击后收起所在 `Dropdown` */ hideDropdownOnItemClick?: boolean /** 自定义样式名 */ className?: string /** 自定义样式 */ style?: CSSProperties /** 根元素的 html 属性 */ rootHtmlProps?: WithRef, HTMLDivElement> } interface MenuCtxValue { hideDropdownOnItemClick: boolean } const menuCtx = createContext({ hideDropdownOnItemClick: true }) export function Menu({ children, size = 'default', hideDropdownOnItemClick = true, className: classNameFromProps, style, rootHtmlProps }: MenuProps) { const prefix = usePrefix('menu') const className = cns( prefix, concat(prefix, 'size', size), classNameFromProps, rootHtmlProps?.className ) const ctxValue = useMemo(() => ({ hideDropdownOnItemClick }), [hideDropdownOnItemClick]) return (
{children}
) } export interface MenuItemProps { /** 内容 */ children?: ReactNode /** 是否激活 */ active?: boolean /** 是否禁用 */ disabled?: boolean /** 点击事件的回调函数 */ onClick?: () => void /** 自定义样式名 */ className?: string /** 自定义样式 */ style?: CSSProperties /** 根元素的 html 属性 */ rootHtmlProps?: WithRef, HTMLLIElement> } export function MenuItem({ children, active = false, disabled = false, onClick, className: classNameFromProps, style, rootHtmlProps }: MenuItemProps) { const prefix = concat(usePrefix('menu'), 'item') const className = cns( prefix, active && concat(prefix, 'active'), disabled && concat(prefix, 'disabled'), classNameFromProps, rootHtmlProps?.className ) const { hideDropdownOnItemClick } = useContext(menuCtx) const dropdownCtx = useDropdownCtx() const handleClick = useCallback((e: React.MouseEvent) => { if (disabled) return rootHtmlProps?.onClick?.(e) if (e.defaultPrevented) return onClick?.() if (dropdownCtx && hideDropdownOnItemClick) { dropdownCtx.setVisible(false) } }, [disabled, onClick, rootHtmlProps, hideDropdownOnItemClick, dropdownCtx]) return (
  • {children}
  • ) } export interface MenuItemGroupProps { /** 标题 */ title: string /** 内容(`MenuItem`) */ children?: ReactNode /** 自定义样式名 */ className?: string /** 自定义样式 */ style?: CSSProperties /** 根元素的 html 属性 */ rootHtmlProps?: WithRef, HTMLLIElement> } export function MenuItemGroup({ title, children, className: classNameFromProps, style, rootHtmlProps }: MenuItemGroupProps) { const prefix = concat(usePrefix('menu'), 'item', 'group') const className = cns(prefix, classNameFromProps, rootHtmlProps?.className) return (
  • {title}
    {children}
  • ) } function MenuList({ children }: PropsWithChildren<{}>) { const prefix = usePrefix('menu') return (
      {children}
    ) }