// components/utilities/files/FileBrowserPanel.tsx "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import { ChevronRight, Home, Loader2 } from "lucide-react"; import FilesTable from "./FilesTable"; import FilePreview from "./FilePreview"; import { FsEntry, list, parentDir, download, SortDir, SortKey } from "./api"; export default function FileBrowserPanel() { const [cwd, setCwd] = useState("/"); const [entries, setEntries] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selected, setSelected] = useState(null); const [sortKey, setSortKey] = useState("name"); const [sortDir, setSortDir] = useState("asc"); const refresh = useCallback(async (path: string) => { setLoading(true); setError(null); try { const res = await list(path); setCwd(res.cwd || path || "/"); setEntries(res.entries || []); // Clear selection if it no longer exists if (selected && !res.entries.find(e => e.path === selected.path)) setSelected(null); } catch (e: any) { setError(e?.message || String(e)); } finally { setLoading(false); } }, [selected]); useEffect(() => { refresh(cwd); /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, []); const crumbs = useMemo(() => { const norm = cwd.replace(/\\/g, "/"); const segs = norm.split("/").filter(Boolean); const out: { label: string; path: string }[] = [{ label: "root", path: "/" }]; let acc = ""; for (const s of segs) { acc += "/" + s; out.push({ label: s, path: acc || "/" }); } return out; }, [cwd]); function openEntry(e: FsEntry) { if (e.isDir) { setSelected(null); refresh(e.path); } else { setSelected(e); } } function onSort(k: SortKey) { if (k === sortKey) { setSortDir(d => (d === "asc" ? "desc" : "asc")); } else { setSortKey(k); setSortDir("asc"); } } async function goUp() { const p = parentDir(cwd); setSelected(null); await refresh(p); } return (
{/* Top bar */}
{/* Breadcrumbs */}
{/* Error */} {error && (
{error}
)} {/* Two-column layout */}
{loading ? (
Loading…
) : ( download(e.path)} /> )}
Preview
{selected ? ( ) : (
Select a file to preview.
)}
); }