84 lines
2.5 KiB
TypeScript
Executable File
84 lines
2.5 KiB
TypeScript
Executable File
import { Fragment, ReactNode } from 'react';
|
|
import { Link, useLocation } from 'react-router-dom';
|
|
import { cn } from '@crux-kit/utils';
|
|
import { MenuItem } from '#app/config/types';
|
|
import { useMenuConfig } from '#app/menu';
|
|
import { useMenu } from '#shared/hooks/useMenu';
|
|
import { Container } from '#shared/widgets/common/Container';
|
|
|
|
export interface ToolbarHeadingProps {
|
|
title?: string | ReactNode;
|
|
description?: string | ReactNode;
|
|
}
|
|
|
|
function Toolbar({ children }: { children?: ReactNode }) {
|
|
return (
|
|
<div className="mb-5 lg:mb-7.5">
|
|
<Container className="flex flex-wrap items-center justify-between gap-5">
|
|
{children}
|
|
</Container>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function ToolbarActions({ children }: { children?: ReactNode }) {
|
|
return <div className="flex items-center gap-2.5">{children}</div>;
|
|
}
|
|
|
|
function ToolbarBreadcrumbs() {
|
|
const menuConfig = useMenuConfig();
|
|
const { pathname } = useLocation();
|
|
const { getBreadcrumb, isActive } = useMenu(pathname);
|
|
const items: MenuItem[] = getBreadcrumb(menuConfig);
|
|
|
|
if (items.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className="breadcrumb flex items-center gap-1 text-sm">
|
|
{items.map((item, index) => {
|
|
const isLast = index === items.length - 1;
|
|
const active = item.path ? isActive(item.path) : false;
|
|
|
|
return (
|
|
<Fragment key={index}>
|
|
{item.path ? (
|
|
<Link
|
|
to={item.path}
|
|
className={cn(
|
|
'flex items-center gap-1',
|
|
active ? 'text-mono' : 'text-secondary-foreground hover:text-primary'
|
|
)}
|
|
>
|
|
{item.title}
|
|
</Link>
|
|
) : (
|
|
<span className={cn(isLast ? 'text-mono' : 'text-secondary-foreground')}>
|
|
{item.title}
|
|
</span>
|
|
)}
|
|
{!isLast && <span className="text-muted-foreground">/</span>}
|
|
</Fragment>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => {
|
|
const { pathname } = useLocation();
|
|
const { getCurrentItem } = useMenu(pathname);
|
|
const menuConfig = useMenuConfig();
|
|
const item = getCurrentItem(menuConfig);
|
|
|
|
return (
|
|
<div className="flex flex-col flex-wrap gap-1 md:flex-row md:items-center lg:gap-5">
|
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
|
<ToolbarBreadcrumbs />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { Toolbar, ToolbarActions, ToolbarBreadcrumbs, ToolbarHeading };
|