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);
});
}
}