"use client"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { cn } from "@/lib/utils"; import { useSidebar } from "fumadocs-ui/provider"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; import { type HTMLAttributes, type ReactNode, useCallback, useMemo, useRef, } from "react"; import { PiGraph } from "react-icons/pi"; export function isActive( url: string, pathname: string, nested = true, root = false ): boolean { const isActive = url === pathname || (nested && pathname.startsWith(root ? url : `${url}/`)); return isActive; } export interface Option { /** * Redirect URL of the folder, usually the index page */ url: string; icon?: ReactNode; title: ReactNode; description?: ReactNode; bgGradient: string; selectedStyle?: string; props?: HTMLAttributes; } export interface OptionDropdown { title: ReactNode; options: Option[]; } function isOptionDropdown( item: Option | OptionDropdown ): item is OptionDropdown { return "options" in item; } function isOption(item: Option | OptionDropdown): item is Option { return !isOptionDropdown(item); } export function SubdocsMenu({ options, ...props }: { options: (Option | OptionDropdown)[]; } & HTMLAttributes): React.ReactElement { const { closeOnRedirect } = useSidebar(); const pathname = usePathname(); const selected: Option | undefined = useMemo(() => { // First, try all non-root options let nonRootOptions = options.filter( (item) => isOption(item) && item.url !== "/" ); const dropDowns = options.filter((item) => isOptionDropdown(item)); if (dropDowns.length > 0) { const dropDown = dropDowns[0]; nonRootOptions = nonRootOptions.concat(dropDown.options); } const activeNonRootOption = nonRootOptions.find( (item) => isOption(item) && isActive(item.url, pathname, true) ); if (activeNonRootOption) { return activeNonRootOption as Option; } // If no non-root options are active, try the root options ("/*") return options.find( (item) => isOption(item) && isActive(item.url, pathname, true, true) ) as Option | undefined; }, [options, pathname]); const onClick = useCallback(() => { closeOnRedirect.current = false; }, [closeOnRedirect]); return (
{options.map((item) => ( ))}
); } function SubdocsMenuItem({ item, selected, onClick, }: { item: Option | OptionDropdown; selected?: Option; onClick?: () => void; }) { if (isOption(item)) { return (
{item.icon}
{item.title}
); } else if (isOptionDropdown(item)) { return ( ); } } function SubdocsMenuItemAgentFramework({ item, selected, onClick, }: { item: OptionDropdown; selected?: Option; onClick?: () => void; }) { const defaultOption = item.options.find( (option) => option.url === "/coagents" )!; const isSelected = item.options.find( (option) => option.url === selected?.url ); const showOption = item.options.find((option) => option.url === selected?.url) || defaultOption; return (
{showOption.icon}
{showOption.title}
); } function SubdocsMenuItemDropdown({ item, selected, onClick, }: { item: OptionDropdown; selected?: Option; onClick?: () => void; }) { const router = useRouter(); const selectRef = useRef(null); const selectedOption = item.options.find( (option) => option.url === selected?.url ); const isSelected = selectedOption !== undefined; return (
); }