chatbot-ui/components/sidebar/items/folders/folder-item.tsx

115 lines
3.1 KiB
TypeScript

import { cn } from "@/lib/utils"
import { Tables } from "@/supabase/types"
import { ContentType } from "@/types"
import { IconChevronDown, IconChevronRight } from "@tabler/icons-react"
import { FC, useRef, useState } from "react"
import { DeleteFolder } from "./delete-folder"
import { UpdateFolder } from "./update-folder"
interface FolderProps {
folder: Tables<"folders">
contentType: ContentType
children: React.ReactNode
onUpdateFolder: (itemId: string, folderId: string | null) => void
}
export const Folder: FC<FolderProps> = ({
folder,
contentType,
children,
onUpdateFolder
}) => {
const itemRef = useRef<HTMLDivElement>(null)
const [isDragOver, setIsDragOver] = useState(false)
const [isExpanded, setIsExpanded] = useState(false)
const [isHovering, setIsHovering] = useState(false)
const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault()
setIsDragOver(true)
}
const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault()
setIsDragOver(false)
}
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault()
setIsDragOver(true)
}
const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault()
setIsDragOver(false)
const itemId = e.dataTransfer.getData("text/plain")
onUpdateFolder(itemId, folder.id)
}
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
if (e.key === "Enter") {
e.stopPropagation()
itemRef.current?.click()
}
}
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
setIsExpanded(!isExpanded)
}
return (
<div
ref={itemRef}
id="folder"
className={cn("rounded focus:outline-none", isDragOver && "bg-accent")}
onDragEnter={handleDragEnter}
onDragLeave={handleDragLeave}
onDragOver={handleDragOver}
onDrop={handleDrop}
onKeyDown={handleKeyDown}
onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)}
>
<div
tabIndex={0}
className={cn(
"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center justify-between rounded p-2 hover:opacity-50 focus:outline-none"
)}
onClick={handleClick}
>
<div className="flex w-full items-center justify-between">
<div className="flex items-center space-x-2">
{isExpanded ? (
<IconChevronDown stroke={3} />
) : (
<IconChevronRight stroke={3} />
)}
<div>{folder.name}</div>
</div>
{isHovering && (
<div
onClick={e => {
e.stopPropagation()
e.preventDefault()
}}
className="ml-2 flex space-x-2"
>
<UpdateFolder folder={folder} />
<DeleteFolder folder={folder} contentType={contentType} />
</div>
)}
</div>
</div>
{isExpanded && (
<div className="ml-5 mt-2 space-y-2 border-l-2 pl-4">{children}</div>
)}
</div>
)
}