import { IconBook2 as BookOpen, IconChevronRight as ChevronRight, IconMenu2 as Menu, IconSearch as Search, IconX as X, } from '@tabler/icons-react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Link, Navigate, useNavigate, useParams } from 'react-router'; import { Nav } from '@/components/Nav'; import { SEO } from '@/components/SEO'; import FooterSection from '@/components/sections/footer'; import { Button } from '@/components/ui/button'; import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'; import { type PackageManager, replacePackageManager, SHOW_PACKAGE_MANAGER_SWITCHER, usePackageManager, } from '@/hooks/usePackageManager'; import { getPage, pages } from '@/lib/docs'; import { type SearchResult, searchDocs } from '@/lib/docs-search'; import { cn } from '@/lib/utils'; function DocsSearch({ onNavigate }: { onNavigate?: () => void }) { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [isOpen, setIsOpen] = useState(false); const inputRef = useRef(null); const navigate = useNavigate(); const handleSearch = useCallback((value: string) => { setQuery(value); if (value.length >= 2) { setResults(searchDocs(value)); setIsOpen(true); } else { setResults([]); setIsOpen(false); } }, []); const handleSelect = useCallback( (slug: string) => { navigate(`/docs/${slug}`); setQuery(''); setIsOpen(false); onNavigate?.(); }, [navigate, onNavigate] ); // Cmd+K / Ctrl+K keyboard shortcut useEffect(() => { const handler = (e: KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); inputRef.current?.focus(); } if (e.key === 'Escape') { setIsOpen(false); inputRef.current?.blur(); } }; document.addEventListener('keydown', handler); return () => document.removeEventListener('keydown', handler); }, []); return (
handleSearch(e.target.value)} onFocus={() => query.length >= 2 && setIsOpen(true)} onBlur={() => setTimeout(() => setIsOpen(false), 200)} placeholder="Search docs..." className="w-full rounded-md border border-border bg-muted/50 pl-8 pr-12 py-1.5 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary" /> ⌘K
{/* Results dropdown */} {isOpen && results.length > 0 && (
{results.map((result) => ( ))}
)} {isOpen && query.length >= 2 && results.length === 0 && (

No results found.

)}
); } function DocsSidebar({ currentSlug, onNavigate, }: { currentSlug: string; onNavigate?: () => void; }) { return ( ); } export function DocsIndex() { // Redirect to the first doc page if (pages.length > 0) { return ; } return (
); } const PM_OPTIONS: PackageManager[] = ['npm', 'pnpm', 'bun']; // Docs are authored against npm; only rewrite snippets that actually invoke // it. Word-boundary matched so `npm_config_*` and the like are left alone. const NPM_INVOCATION = /\bnpm\b/; function PackageManagerSwitcher({ pm, onChange, }: { pm: PackageManager; onChange: (pm: PackageManager) => void; }) { return ( { const next = values[0] as PackageManager | undefined; if (next) onChange(next); }} variant="outline" size="sm" className="shrink-0" > {PM_OPTIONS.map((option) => ( {option} ))} ); } export function DocsPage() { const { slug } = useParams<{ slug: string }>(); const page = slug ? getPage(slug) : undefined; const [sidebarOpen, setSidebarOpen] = useState(false); const [pm, setPm] = usePackageManager(); const mdxComponents = useMemo( () => ({ code: ((rawProps: unknown) => { const { children, ...props } = rawProps as Record & { children?: React.ReactNode; }; const content = typeof children === 'string' && NPM_INVOCATION.test(children) ? replacePackageManager(children, pm) : children; return {content}; }) as React.ComponentType, }), [pm] ); if (!page) { return (
); } // Find prev/next pages const currentIndex = pages.findIndex((p) => p.slug === slug); const prevPage = currentIndex > 0 ? pages[currentIndex - 1] : null; const nextPage = currentIndex < pages.length - 1 ? pages[currentIndex + 1] : null; return (
); } /** Default export for React.lazy() route-level code splitting */ export default function DocsRoute() { const { slug } = useParams<{ slug: string }>(); return slug ? : ; }