import {
ChevronDownIcon,
ChevronRightIcon,
FileIcon,
FolderIcon,
} from 'lucide-react';
import { useMemo, useState } from 'react';
import { Link } from '#/components/atoms/link.jsx';
import { buildFileTree, filterFiles } from '#/lib/file-tree.js';
import { cn } from '#/lib/utils.js';
/** Whether a directory holds, or is, the path in view. */
const onPath = (dir, path) =>
dir === path || path.startsWith(`${dir}/`) || dir.startsWith(`${path}/`);
/**
* One row per node, indented by depth. A directory opens on its own state;
* one on the way to the path in view opens by itself, so the branch a reader
* is standing on is the one they see. A filter opens everything it matched.
*/
function Node({ node, depth, base, refName, path, selected, filter }) {
const [manual, setManual] = useState(/** @type {boolean|null} */ (null));
const pad = { paddingLeft: `${depth * 12 + 10}px` };
if (node.type === 'file') {
const current = node.path === selected;
return (
{node.name}
);
}
const open = filter ? true : (manual ?? onPath(node.path, path));
const current = node.path === selected;
const Chevron = open ? ChevronDownIcon : ChevronRightIcon;
return (
{node.name}
{open &&
node.children.map((child) => (
))}
);
}
/**
* The whole repository as a tree, down the rail beside whatever is open:
* every directory from the root, closed but for the ones on the way to the
* path in view, the way a forge's file rail reads.
*
* `path` is the directory in view, which opens the branch leading to it.
* `selected` is the row a reader is standing on, a file or the directory
* itself. `filter` narrows the tree to the paths holding the text.
* @param {{repo: string, refName: string, files: Array<{path: string}>, path: string, selected?: string, filter?: string}} props
*/
export function RepoTree({
repo,
refName,
files,
path,
selected = '',
filter = '',
}) {
const base = `/${encodeURIComponent(repo)}`;
const ref = encodeURI(refName);
const roots = useMemo(
() => buildFileTree(filterFiles(files, filter)),
[files, filter],
);
if (roots.length === 0) {
return (