import { useState, useRef, useEffect } from 'react';
import type { FileNode } from '../../lib/types/api';
interface FileTreeProps {
files: FileNode[];
selectedFile: string | null;
onSelectFile: (path: string) => void;
owner: string;
repo: string;
onCreateFile?: (parentPath: string) => void;
onCreateFolder?: (parentPath: string) => void;
onRename?: (oldPath: string, newName: string) => void;
}
export function FileTree({
files,
selectedFile,
onSelectFile,
owner,
repo,
onCreateFile,
onCreateFolder,
onRename,
}: FileTreeProps) {
return (
{files.length === 0 ? (
No markdown files found in this repository
) : (
files.map((file) => (
))
)}
);
}
interface FileTreeNodeProps {
node: FileNode;
selectedFile: string | null;
onSelectFile: (path: string) => void;
level: number;
owner: string;
repo: string;
onCreateFile?: (parentPath: string) => void;
onCreateFolder?: (parentPath: string) => void;
onRename?: (oldPath: string, newName: string) => void;
}
function FileTreeNode({
node,
selectedFile,
onSelectFile,
level,
owner,
repo,
onCreateFile,
onCreateFolder,
onRename,
}: FileTreeNodeProps) {
const [isExpanded, setIsExpanded] = useState(true);
const [showActions, setShowActions] = useState(false);
const [isRenaming, setIsRenaming] = useState(false);
const [renameValue, setRenameValue] = useState(node.name);
const renameInputRef = useRef(null);
const isSelected = selectedFile === node.path;
useEffect(() => {
if (isRenaming && renameInputRef.current) {
renameInputRef.current.focus();
renameInputRef.current.select();
}
}, [isRenaming]);
const handleRenameSubmit = () => {
if (renameValue.trim() && renameValue !== node.name && onRename) {
// Replace spaces with hyphens
let sanitizedName = renameValue.trim().replace(/\s+/g, '-');
// For files, ensure .md extension if not present
if (node.type === 'file' && !sanitizedName.endsWith('.md') && !sanitizedName.endsWith('.mdx')) {
sanitizedName += '.md';
}
onRename(node.path, sanitizedName);
}
setIsRenaming(false);
setRenameValue(node.name);
};
const handleRenameCancel = () => {
setIsRenaming(false);
setRenameValue(node.name);
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
handleRenameSubmit();
} else if (e.key === 'Escape') {
handleRenameCancel();
}
};
if (node.type === 'file') {
return (
setShowActions(true)}
onMouseLeave={() => setShowActions(false)}
>
{isRenaming ? (
) : (
)}
{/* Actions menu for files */}
{showActions && !isRenaming && (
)}
);
}
return (
setShowActions(true)}
onMouseLeave={() => setShowActions(false)}
>
{isRenaming ? (
) : (
)}
{/* Actions menu for folders */}
{showActions && !isRenaming && (
)}
{isExpanded && node.children && (
{node.children.map((child) => (
))}
)}
);
}