"use client"; import { useRouter } from "next/navigation"; import { useEffect, useMemo, useState, useRef } from "react"; import { ArrowUpIcon, ArrowDownIcon, CommandIcon, FileTextIcon, SearchIcon, CornerDownLeftIcon } from "lucide-react"; import { Input } from "@/components/ui/input"; import { Dialog, DialogContent, DialogHeader, DialogFooter, DialogTrigger, DialogClose, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import Anchor from "./anchor"; import { advanceSearch, cn } from "@/lib/utils"; import { ScrollArea } from "@/components/ui/scroll-area"; export default function Search() { const router = useRouter(); const [searchedInput, setSearchedInput] = useState(""); const [isOpen, setIsOpen] = useState(false); const [selectedIndex, setSelectedIndex] = useState(0); const itemRefs = useRef<(HTMLDivElement | null)[]>([]); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if ((event.ctrlKey || event.metaKey) && event.key === "k") { event.preventDefault(); setIsOpen(true); } }; window.addEventListener("keydown", handleKeyDown); return () => { window.removeEventListener("keydown", handleKeyDown); }; }, []); const filteredResults = useMemo( () => advanceSearch(searchedInput.trim()), [searchedInput] ); useEffect(() => { setSelectedIndex(0); }, [filteredResults]); useEffect(() => { const handleNavigation = (event: KeyboardEvent) => { if (!isOpen || filteredResults.length === 0) return; if (event.key === "ArrowDown") { event.preventDefault(); setSelectedIndex((prev) => (prev + 1) % filteredResults.length); } if (event.key === "ArrowUp") { event.preventDefault(); setSelectedIndex((prev) => (prev - 1 + filteredResults.length) % filteredResults.length); } if (event.key === "Enter") { event.preventDefault(); const selectedItem = filteredResults[selectedIndex]; if (selectedItem) { router.push(`/docs${selectedItem.href}`); setIsOpen(false); } } }; window.addEventListener("keydown", handleNavigation); return () => { window.removeEventListener("keydown", handleNavigation); }; }, [isOpen, filteredResults, selectedIndex, router]); useEffect(() => { if (itemRefs.current[selectedIndex]) { itemRefs.current[selectedIndex]?.scrollIntoView({ behavior: "smooth", block: "nearest", }); } }, [selectedIndex]); return (
{ if (!open) setSearchedInput(""); setIsOpen(open); }} >
K
Search Documentation Search through the documentation setSearchedInput(e.target.value)} placeholder="Type something to search..." autoFocus className="h-14 px-6 bg-transparent border-b text-[14px] outline-none w-full" aria-label="Search documentation" /> {filteredResults.length == 0 && searchedInput && (

No results found for{" "} {`"${searchedInput}"`}

)}
{filteredResults.map((item, index) => { const level = (item.href.split("/").slice(1).length - 1) as keyof typeof paddingMap; const paddingClass = paddingMap[level]; const isActive = index === selectedIndex; return ( { itemRefs.current[index] = el as HTMLDivElement | null; }} className={cn( "dark:hover:bg-accent/15 hover:bg-accent/10 w-full px-3 rounded-sm text-sm flex items-center gap-2.5", isActive && "bg-primary/20 dark:bg-primary/30", paddingClass )} href={`/docs${item.href}`} tabIndex={0} >
1 && "border-l pl-4" )} >
{item.title}
{isActive && (
Return
)}
); })}

to navigate

to select

esc

to close

); } const paddingMap = { 1: "pl-2", 2: "pl-4", 3: "pl-10", } as const;