import React from 'react' import type { MenuProps } from 'antd' import { Link } from 'react-router-dom' import type { PathPattern } from 'react-router-dom' import { CaretDownOutlined } from '@ant-design/icons' type ItemTypes = NonNullable export const renderMenuHelper = (isTopNav: boolean) => function renderMenu( menuConfig: ReadonlyArray, isFirstLevel: boolean = false, collectMenuKeys: string[] = [] ): ItemTypes { function getIcon(item: MenuConfig, defaultIcon?: React.ReactNode) { const actualIcon = 'icon' in item ? item.icon : defaultIcon if (isTopNav) { return { leftIcon: undefined, rightIcon: actualIcon, } } return { leftIcon: actualIcon, rightIcon: undefined, } } return menuConfig.map((item) => { if ('href' in item) { const { leftIcon, rightIcon } = getIcon( item, isFirstLevel && typeof item.label === 'string' ? ( ) : undefined ) return { key: item.href, icon: leftIcon, label: ( {item.label} {rightIcon} ), } } if ('path' in item) { const { leftIcon, rightIcon } = getIcon(item) return { key: item.path, icon: leftIcon, label: ( {item.label} {rightIcon} ), } } if ('subMenu' in item) { const { leftIcon, rightIcon } = getIcon( item, isTopNav ? : undefined ) collectMenuKeys.push(item.subMenu) return { key: item.subMenu, icon: leftIcon, label: ( <> {item.subMenu} {rightIcon} ), children: renderMenu(item.children), } } if ('group' in item) { return { type: 'group', key: item.group, label: item.group, children: renderMenu(item.children), } } throw new Error(`invalid menu config`) }) } export type MenuConfig = | { readonly label: string /** * The url. * @example 'https://www.google.com/' */ readonly href: string readonly icon?: React.ReactNode } | { readonly label: string /** * The path in the current webapp. * @example '/posts/hello-world' */ readonly path: string readonly icon?: React.ReactNode /** * The menu item will show an "active" state * if it matches with current browsing path. */ readonly activeIfMatch?: | string | string[] | PathPattern | PathPattern[] } | { /** * The label of the subnav */ readonly subMenu: string readonly children: ReadonlyArray readonly icon?: React.ReactNode readonly activeIfMatch?: | string | string[] | PathPattern | PathPattern[] } | { /** * The label of the nav group */ readonly group: string readonly children: ReadonlyArray } function ExternalLinkIcon() { return ( ) } function SubMenuIcon() { return }