import { useEffect, useRef, useState } from "react"; import { isTauri } from "@tauri-apps/api/core"; import { open } from "@tauri-apps/plugin-shell"; interface DropdownListProps { selected: (item: any) => void; suggests: any[]; isSearchComplete: boolean; } function DropdownList({ selected, suggests }: DropdownListProps) { const [selectedItem, setSelectedItem] = useState(null); const [showIndex, setShowIndex] = useState(false); const containerRef = useRef(null); const itemRefs = useRef<(HTMLDivElement | null)[]>([]); const handleOpenURL = async (url: string) => { if (!url) return; try { if (isTauri()) { await open(url); // console.log("URL opened in default browser"); } } catch (error) { console.error("Failed to open URL:", error); } }; const handleKeyDown = (e: KeyboardEvent) => { // console.log( // "handleKeyDown", // e.key, // showIndex, // e.key >= "0" && e.key <= "9" && showIndex // ); if (!suggests.length) return; if (e.key === "ArrowUp") { e.preventDefault(); setSelectedItem((prev) => prev === null || prev === 0 ? suggests.length - 1 : prev - 1 ); } else if (e.key === "ArrowDown") { e.preventDefault(); setSelectedItem((prev) => prev === null || prev === suggests.length - 1 ? 0 : prev + 1 ); } else if (e.key === "Meta") { e.preventDefault(); setShowIndex(true); } if (e.key === "Enter" && selectedItem !== null) { // console.log("Enter key pressed", selectedItem); const item = suggests[selectedItem]; if (item?._source?.url) { handleOpenURL(item?._source?.url); } else { selected(item); } } if (e.key >= "0" && e.key <= "9" && showIndex) { // console.log(`number ${e.key}`); const item = suggests[parseInt(e.key, 10)]; if (item?._source?.url) { handleOpenURL(item?._source?.url); } else { selected(item); } } }; const handleKeyUp = (e: KeyboardEvent) => { // console.log("handleKeyUp", e.key); if (!suggests.length) return; if (!e.metaKey) { setShowIndex(false); } }; useEffect(() => { window.addEventListener("keydown", handleKeyDown); window.addEventListener("keyup", handleKeyUp); return () => { window.removeEventListener("keydown", handleKeyDown); window.removeEventListener("keyup", handleKeyUp); }; }, [showIndex, selectedItem, suggests]); // useEffect(() => { // if (suggests.length > 0) { // setSelectedItem(0); // } // }, [JSON.stringify(suggests)]); useEffect(() => { if (selectedItem !== null && itemRefs.current[selectedItem]) { itemRefs.current[selectedItem]?.scrollIntoView({ behavior: "smooth", block: "nearest", }); } }, [selectedItem]); return (
Results
{suggests?.map((item, index) => { const isSelected = selectedItem === index; return (
(itemRefs.current[index] = el)} onMouseEnter={() => setSelectedItem(index)} onClick={() => { if (item?._source?.url) { handleOpenURL(item?._source?.url); } else { selected(item); } }} className={`w-full px-2 py-2.5 text-sm flex items-center justify-between rounded-lg transition-colors ${ isSelected ? "bg-[rgba(0,0,0,0.1)] dark:bg-[rgba(255,255,255,0.1)] hover:bg-[rgba(0,0,0,0.1)] dark:hover:bg-[rgba(255,255,255,0.1)]" : "" }`} >
icon {item?._source?.title}
{item?._source?.source} {showIndex && index < 10 ? (
{index}
) : null}
); })}
); } export default DropdownList;