import { useTranslation } from "react-i18next"; import { useEffect, useState, useRef, useCallback } from "react"; import classNames from "classnames"; import { resolveIcon } from "./services/item"; export default function QuickLaunch({servicesAndBookmarks, searchString, setSearchString, isOpen, close}) { const { t } = useTranslation(); const searchField = useRef(); const [results, setResults] = useState([]); const [currentItemIndex, setCurrentItemIndex] = useState(null); function openCurrentItem() { const result = results[currentItemIndex]; window.open(result.href, '_blank'); } const closeAndReset = useCallback(() => { close(false); setTimeout(() => { setSearchString(""); }, 200); // delay a little for animations }, [close, setSearchString]); function handleSearchChange(event) { setSearchString(event.target.value.toLowerCase()) } function handleSearchKeyDown(event) { if (event.key === "Escape") { closeAndReset(); } else if (event.key === "Enter" && results.length) { closeAndReset(); openCurrentItem(); } else if (event.key === "ArrowDown" && results[currentItemIndex + 1]) { setCurrentItemIndex(currentItemIndex + 1); event.preventDefault(); } else if (event.key === "ArrowUp" && currentItemIndex > 0) { setCurrentItemIndex(currentItemIndex - 1); event.preventDefault(); } } function handleItemHover(event) { setCurrentItemIndex(parseInt(event.target?.dataset?.index, 10)); } function handleItemClick() { closeAndReset(); openCurrentItem(); } useEffect(() => { if (searchString.length === 0) setResults([]); else { const newResults = servicesAndBookmarks.filter(r => r.name.toLowerCase().includes(searchString)); setResults(newResults); if (newResults.length) { setCurrentItemIndex(0); } } }, [searchString, servicesAndBookmarks]); const [hidden, setHidden] = useState(true); useEffect(() => { function handleBackdropClick(event) { if (event.target?.tagName === "DIV") closeAndReset(); } if (isOpen) { searchField.current.focus(); document.body.addEventListener('click', handleBackdropClick); setHidden(false); } else { document.body.removeEventListener('click', handleBackdropClick); setTimeout(() => { setHidden(true); }, 300); // disable on close } }, [isOpen, closeAndReset]); return (