"use client"; import { useQuery } from "@tanstack/react-query"; import { useEffect, useRef, useState } from "react"; import { get } from "../../lib/api"; interface Directory { name: string; path: string; } interface PathAutocompleteProps { value: string; onChange: (value: string) => void; placeholder?: string; className?: string; defaultPath?: string; } export default function PathAutocomplete({ value, onChange, placeholder = "/path/to/destination", className = "", defaultPath = "", }: PathAutocompleteProps) { const [showSuggestions, setShowSuggestions] = useState(false); const [selectedIndex, setSelectedIndex] = useState(-1); const inputRef = useRef(null); const suggestionsRef = useRef(null); // Get the parent directory to search for subdirectories const searchPath = value || defaultPath; const parentPath = searchPath.endsWith("/") ? searchPath.slice(0, -1) : searchPath; // Fetch directories for autocomplete const { data: dirData } = useQuery<{ directories: Directory[] }>({ queryKey: ["directories", parentPath], queryFn: async () => { if (!parentPath) return { directories: [] }; return get("/directories", { path: parentPath }); }, enabled: !!parentPath && showSuggestions, staleTime: 30000, // Cache for 30 seconds }); const directories = dirData?.directories || []; // Close suggestions when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( suggestionsRef.current && !suggestionsRef.current.contains(event.target as Node) && !inputRef.current?.contains(event.target as Node) ) { setShowSuggestions(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); const handleInputChange = (e: React.ChangeEvent) => { const newValue = e.target.value; onChange(newValue); setShowSuggestions(true); setSelectedIndex(-1); }; const handleSuggestionClick = (dirPath: string) => { onChange(dirPath); setShowSuggestions(false); setSelectedIndex(-1); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (!showSuggestions || directories.length === 0) { if (e.key === "ArrowDown") { e.preventDefault(); setShowSuggestions(true); } return; } switch (e.key) { case "ArrowDown": e.preventDefault(); setSelectedIndex((prev) => prev < directories.length - 1 ? prev + 1 : prev ); break; case "ArrowUp": e.preventDefault(); setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1)); break; case "Enter": e.preventDefault(); if (selectedIndex >= 0 && selectedIndex < directories.length) { handleSuggestionClick(directories[selectedIndex].path); } break; case "Escape": setShowSuggestions(false); setSelectedIndex(-1); break; } }; const handleFocus = () => { if (directories.length > 0) { setShowSuggestions(true); } }; return (
{showSuggestions && directories.length > 0 && (
{directories.map((dir, index) => ( ))}
)} {defaultPath && value !== defaultPath && (

Default: {defaultPath}

)}
); }