import React, { useState, useEffect } from "react"; import classNames from "classnames"; import { StyledProps } from "../_type"; import { Icon } from "../icon"; import { MenuGroup } from "./MenuGroup"; import { SubMenu } from "./SubMenu"; import { MenuItem } from "./MenuItem"; import { useDefault } from "../_util/use-default"; import { Tooltip } from "../tooltip"; import { useConfig } from "../_util/config-context"; import { Badge } from "../badge"; import { MenuContext } from "./MenuContext"; import { forwardRefWithStatics } from "../_util/forward-ref-with-statics"; export interface MenuBackOptions { /** * 返回区域标题 */ title?: React.ReactNode; /** * 返回区域描述 */ description?: React.ReactNode; /** * 为该区域文字添加 Tooltip 说明 */ tooltip?: React.ReactNode; /** * 返回按钮点击回调 */ onClick?: (event: React.MouseEvent) => void; } export interface MenuProps extends StyledProps { /** * 标题 */ title?: React.ReactNode; /** * 标题旁标签内容 */ tag?: React.ReactNode; /** * 导航折叠后标题处显示的图标 URL 或自定义节点内容 * * **传入 `string` 类型将作为 URL 解析** * * @docType [React.ReactNode, React.ReactNode] | React.ReactNode */ icon?: React.ReactNode | [React.ReactNode, React.ReactNode]; /** * 顶部返回区域相关配置 */ back?: MenuBackOptions; /** * 主题样式 * * @default "light" */ theme?: "light" | "dark"; /** * 导航内容(Menu.Group 或 Menu.SubMenu 或 Menu.Item) */ children?: React.ReactNode; /** * 导航是否支持折叠(展示底部折叠/展示操作区) * * 如开启支持请为菜单项配置图标 * * @default false */ collapsable?: boolean; /** * 导航是否默认被折叠 * * @default false */ defaultCollapsed?: boolean; /** * 导航是否被折叠 * * @default false */ collapsed?: boolean; /** * 导航折叠变化时回调 */ onCollapsedChange?: (collapsed: boolean) => void; } export const Menu = forwardRefWithStatics( function Menu( { theme, title, tag, icon, back, children, className, collapsable, defaultCollapsed = false, collapsed, onCollapsedChange, ...props }: MenuProps, ref: React.Ref ) { const { classPrefix } = useConfig(); // eslint-disable-next-line no-param-reassign [collapsed, onCollapsedChange] = useDefault( collapsed, defaultCollapsed, onCollapsedChange ); const [hover, setHover] = useState(false); const [mobileCollapsed, setMobileCollapsed] = useState(false); useEffect(() => { if (!collapsed) { setHover(false); } }, [collapsed]); if (Array.isArray(icon)) { // eslint-disable-next-line icon = icon[0]; } const renderBack = typeof back === "object" ? () => { const { title, description, onClick = () => null, tooltip } = back; const titleList = (
{title}
{description}
); return (
{tooltip ? ( {titleList} ) : ( titleList )}
); } : () => null; return (
collapsed && setHover(true)} onMouseLeave={() => collapsed && setHover(false)} onClick={() => setMobileCollapsed(collapsed => !collapsed)} > {!!title && (
{!!icon && (typeof icon === "string" ? ( icon ) : ( icon ))}

{title} {!!tag && {tag}}

)} {renderBack()}
collapsed && setHover(true)} onMouseLeave={() => collapsed && setHover(false)} >
    {children}
{!!collapsable && (
onCollapsedChange(!collapsed)} >
)}
); }, { Group: MenuGroup, SubMenu, Item: MenuItem, } ); Menu.displayName = "Menu"; export { MenuGroupProps } from "./MenuGroup"; export { MenuItemProps } from "./MenuItem"; export { SubMenuProps } from "./SubMenu";