'use client'; import { useContext, useId, useState } from 'react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { cva } from 'class-variance-authority'; import { ChevronDown } from 'lucide-react'; import { z } from 'zod'; import { Button } from '../shadcn/button'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '../shadcn/tooltip'; import { cn, isRouteActive } from '../utils'; import { SidebarContext } from './context/sidebar.context'; import { If } from './if'; import { SidebarConfigSchema } from './sidebar-schema'; import { Trans } from './trans'; export type SidebarConfig = z.infer; export function Sidebar(props: { collapsed?: boolean; children: | React.ReactNode | ((props: { collapsed: boolean; setCollapsed: (collapsed: boolean) => void; }) => React.ReactNode); }) { const [collapsed, setCollapsed] = useState(props.collapsed ?? false); const className = getClassNameBuilder()({ collapsed, }); const ctx = { collapsed, setCollapsed }; return (
{typeof props.children === 'function' ? props.children(ctx) : props.children}
); } export function SidebarContent({ children, className, }: React.PropsWithChildren<{ className?: string; }>) { return (
{children}
); } export function SidebarGroup({ label, collapsed = false, collapsible = true, children, }: React.PropsWithChildren<{ label: string | React.ReactNode; collapsible?: boolean; collapsed?: boolean; }>) { const { collapsed: sidebarCollapsed } = useContext(SidebarContext); const [isGroupCollapsed, setIsGroupCollapsed] = useState(collapsed); const id = useId(); const Title = (props: React.PropsWithChildren) => { if (sidebarCollapsed) { return null; } return ( {props.children} ); }; const Wrapper = () => { const className = cn( 'group flex items-center justify-between px-container space-x-2.5', { 'py-2.5': !sidebarCollapsed, }, ); if (collapsible) { return ( ); } return (
{label}
); }; return (
{children}
); } export function SidebarDivider() { return (
); } export function SidebarItem({ end, path, children, Icon, }: React.PropsWithChildren<{ path: string; Icon: React.ReactNode; end?: boolean; }>) { const { collapsed } = useContext(SidebarContext); const currentPath = usePathname() ?? ''; const active = isRouteActive(path, currentPath, end ? 0 : 3); const variant = active ? 'secondary' : 'ghost'; const size = collapsed ? 'icon' : 'sm'; return ( ); } function getClassNameBuilder() { return cva( ['flex box-content h-screen flex-col border-r border-border relative'], { variants: { collapsed: { true: `w-[6rem]`, false: `w-2/12 lg:w-[17rem]`, }, }, }, ); } export function SidebarNavigation({ config, }: React.PropsWithChildren<{ config: SidebarConfig; }>) { return ( <> {config.routes.map((item, index) => { if ('divider' in item) { return ; } if ('children' in item) { return ( } collapsible={item.collapsible} collapsed={item.collapsed} > {item.children.map((child) => { return ( ); })} ); } return ( ); })} ); }