"use client"; import { SidebarContent, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarProvider } from "@/components/ui/sidebar"; import { cn } from "@/utils/cn"; import * as Collapsible from "@radix-ui/react-collapsible"; import type { Folder, Item, Node, Root } from "fumadocs-core/page-tree"; import { ChevronDown } from "lucide-react"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { type ReactNode, useState } from "react"; function SplitName({ children }: { children: ReactNode; }) { let name: string | undefined; if (Array.isArray(children)) { name = children.find((child): child is string => typeof child === "string"); } else if (typeof children === "string") { name = children; } if (name === undefined) return children; const icon = name.split(" ").shift() || ""; const label = name.replace(icon, "").trim(); return ( <> {icon} {label} ); } function isActive(url: string, pathname: string) { const href = url.length > 1 && url.endsWith("/") ? url.slice(0, -1) : url; const path = pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname; return href === path; } function folderActive(folder: Folder, pathname: string): boolean { if (folder.index && isActive(folder.index.url, pathname)) return true; return folder.children.some((child) => nodeActive(child, pathname)); } function nodeActive(node: Node, pathname: string): boolean { if (node.type === "page") return isActive(node.url, pathname); if (node.type === "folder") return folderActive(node, pathname); return false; } function ItemNode({ item }: { item: Item; }) { const pathname = usePathname(); return ( {item.name} ); } function FolderNode({ item, children }: { item: Folder; children: ReactNode; }) { const pathname = usePathname(); const indexActive = item.index ? isActive(item.index.url, pathname) : false; const active = folderActive(item, pathname); const [open, setOpen] = useState(active); const [prevPathname, setPrevPathname] = useState(pathname); if (prevPathname !== pathname) { setPrevPathname(pathname); setOpen(active); } return (
{item.index ? ( {item.name} ) : ( setOpen((value) => !value)} > {item.name} )}
{children}
); } function renderNodes(nodes: Node[]): ReactNode { return nodes.map((node) => { if (node.type === "folder") { return ( {renderNodes(node.children)} ); } if (node.type === "separator") { return null; } return ; }); } export function DocsNav({ tree }: { tree: Root; }) { return ( {renderNodes(tree.children)} ); }