import { Search, X } from "lucide-react"; import { useId, useMemo, useRef, useState } from "react"; import { useNavigate } from "react-router"; import { Input } from "~/components/ui/input.tsx"; import { cn } from "~/lib/utils.ts"; import { type SettingsSearchHit, searchSettings } from "./search-index.ts"; import { settingsHash } from "./sections.tsx"; /** 设置页搜索框:按设置名、节名找位置;选中后跳到该节,字段会被聚焦 */ export function SettingsSearch({ className }: { className?: string }) { const navigate = useNavigate(); const listId = useId(); const [q, setQ] = useState(""); const [open, setOpen] = useState(false); const [active, setActive] = useState(0); const inputRef = useRef(null); const hits = useMemo(() => searchSettings(q), [q]); const show = open && q.trim() !== ""; const pick = (h: SettingsSearchHit) => { setOpen(false); setQ(""); navigate({ hash: settingsHash(h.section, h.anchor) }, { state: h.field ? { field: h.field } : null }); }; return (
{ setQ(e.target.value); setActive(0); setOpen(true); }} onFocus={() => setOpen(true)} onBlur={() => window.setTimeout(() => setOpen(false), 120)} onKeyDown={(e) => { if (e.key === "ArrowDown") { e.preventDefault(); setActive((i) => Math.min(i + 1, hits.length - 1)); } else if (e.key === "ArrowUp") { e.preventDefault(); setActive((i) => Math.max(i - 1, 0)); } else if (e.key === "Enter") { const h = hits[active]; if (h) { e.preventDefault(); pick(h); } } else if (e.key === "Escape") { setQ(""); setOpen(false); } }} /> {q ? ( ) : null} {show ? (
{hits.length === 0 ? (

没有匹配的设置

) : ( hits.map((h, i) => ( )) )}
) : null}
); }