import React, { type ComponentPropsWithoutRef, type ComponentPropsWithRef, type FC, type ReactElement, type ReactNode, } from 'react'; import { clsx } from 'clsx'; import { Icon, LeftContentRightLayout } from '../../components'; import { cn } from '../../utils/cn'; import { NavLink } from '../links'; import { Tooltip } from '../Tooltip'; import { IconMenuSidebarLayout } from './IconMenuSidebarLayout'; type GroupItem = { type: 'group'; // name?: string; title?: ReactNode; items: NavItem[]; }; type NavItem = | (ComponentPropsWithoutRef<'a'> & { title: string; href: string; icon: ReactElement; iconActive?: ReactElement; }) | (ComponentPropsWithoutRef<'button'> & { title: string; href?: string; type?: string; icon: ReactElement; iconActive?: ReactElement; }); type ItemProp = GroupItem | NavItem; const MenuBarItem: FC<{ item: NavItem }> = ({ item: { title, href, icon, iconActive, className, ...props } }) => { // NavLink 使用 useLocation 会每次 rerender return ( {href ? ( clsx( 'btn btn-square btn-ghost btn-sm h-10 w-10 p-0', isActive ? 'text-base-content/90' : 'opacity-70', className, ) } {...(props as ComponentPropsWithoutRef<'a'>)} > {({ isActive }: { isActive: boolean }) => ( )} ) : ( )} ); }; export namespace IconSidebarLayout { export type LayoutProps = ComponentPropsWithRef<'div'> & { top?: ReactNode | ItemProp[]; bottom?: ReactNode | ItemProp[]; center?: ReactNode | ItemProp[]; }; export const Layout: FC = ({ className, top, bottom, center, children, ...props }) => { // bp 为 md // 小设备使用行显示 /* 48+8+1 - 外层无 padding,因为可能中间会有滚动,外层 padding 后非常窄 */ return ( } className={cn('h-full flex-col md:flex-row', className)} {...props} > {children} ); }; export const Item = MenuBarItem; const Divider = ({ children, ...props }: ComponentPropsWithRef<'div'>) => { return (
{children}
); }; function renderItems(items: ReactNode | ItemProp[]): ReactNode { if (!Array.isArray(items)) { return items; } let n = 0; const renderItem = (item: ItemProp): ReactNode[] => { let key = n++; if (React.isValidElement(item)) { return [item]; } if ('type' in item && item.type === 'group') { let o: ReactNode[] = []; if (item.title) { o.push({item.title}); } if ('items' in item && Array.isArray(item.items)) { return o.concat(items.flatMap((v) => renderItem(v))); } return o; } return []; }; return items.flatMap((item, i) => { return renderItem(item); }); } }