import { useT } from "@agent-native/core/client/i18n"; import { CreativeContextShareSheet } from "@agent-native/creative-context/client"; import { SortableContext, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import type { Document, DocumentTreeNode } from "@shared/api"; import { IconChevronRight, IconDatabase, IconFolder, IconFileText, IconPlus, IconStar, IconTrash, IconDots, } from "@tabler/icons-react"; import { useState } from "react"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; interface DocumentTreeItemProps { node: DocumentTreeNode; depth: number; sidebarWidth?: number; activeId: string | null; expandedIds: Set; onToggleExpanded: (id: string) => void; onSelect: (id: string) => void; onCreateChildPage: (parentId: string) => void; onCreateChildDatabase: (parentId: string) => void; onDelete: (id: string) => void; onToggleFavorite: (id: string, isFavorite: boolean) => void; } export function getDocumentSidebarIconKind( document: Pick, ) { if ( document.source?.mode === "local-files" && document.source.kind === "folder" ) { return "folder"; } if (document.icon?.trim()) return "custom"; if (document.database) return "database"; return "page"; } export function DocumentSidebarIcon({ document, }: { document: Pick; }) { const iconKind = getDocumentSidebarIconKind(document); if (iconKind === "custom") return <>{document.icon}; if (iconKind === "database") { return ; } if (iconKind === "folder") { return ; } return ; } export function FavoriteDocumentItem({ document, active, sidebarWidth, onSelect, onCreateChildPage, onCreateChildDatabase, onRemoveFavorite, onDelete, }: { document: Document; active: boolean; sidebarWidth?: number; onSelect: () => void; onCreateChildPage: () => void; onCreateChildDatabase: () => void; onRemoveFavorite: () => void; onDelete: () => void; }) { const t = useT(); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const canEdit = document.canEdit !== false; const canManage = document.canManage === true || document.accessRole === "owner" || document.accessRole === "admin"; const canCreateChild = canEdit && document.source?.mode !== "local-files"; const title = document.title || t("sidebar.untitled"); return (
{canEdit && ( { event.stopPropagation(); onRemoveFavorite(); }} > {t("sidebar.removeFromFavorites")} )} {canEdit && canManage && } {canManage && ( { event.stopPropagation(); setDeleteDialogOpen(true); }} > {t("database.delete")} )} )} {canCreateChild && ( {t("sidebar.addChild")} { event.stopPropagation(); onCreateChildPage(); }} > {t("sidebar.page")} { event.stopPropagation(); onCreateChildDatabase(); }} > {t("sidebar.database")} )}
{t("sidebar.deletePageQuestion")} {t("sidebar.deletePageDescription", { title })} {t("comments.cancel")} {t("database.delete")} ); } export function DocumentTreeItem({ node, depth, sidebarWidth, activeId, expandedIds, onToggleExpanded, onSelect, onCreateChildPage, onCreateChildDatabase, onDelete, onToggleFavorite, }: DocumentTreeItemProps) { const t = useT(); const expanded = expandedIds.has(node.id); const hasChildren = node.children.length > 0; const isActive = node.id === activeId; const isLocalFileNode = node.source?.mode === "local-files"; const isLocalFolder = isLocalFileNode && node.source?.kind === "folder"; const canEdit = node.canEdit !== false; const canManage = node.canManage === true || node.accessRole === "owner" || node.accessRole === "admin"; const hasMenuActions = canEdit || canManage; const canCreateChild = canEdit && !isLocalFileNode; const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [contextSheetOpen, setContextSheetOpen] = useState(false); const indent = depth * 12 + 12; const rowWidth = sidebarWidth === undefined ? undefined : Math.max(0, sidebarWidth - 8); const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: node.id, disabled: !canEdit || isLocalFileNode, }); return (
{ if (isLocalFolder && hasChildren) { onToggleExpanded(node.id); return; } onSelect(node.id); }} aria-expanded={hasChildren ? expanded : undefined} > {hasChildren && ( )} {node.title || "Untitled"}
e.stopPropagation()} > {hasMenuActions && ( {canEdit && ( { e.stopPropagation(); onToggleFavorite(node.id, !node.isFavorite); }} > {node.isFavorite ? "Remove from favorites" : "Add to favorites"} )} {canEdit && canManage && } {canEdit && !isLocalFileNode && ( { event.preventDefault(); event.stopPropagation(); setContextSheetOpen(true); }} > {t("creativeContext.addToContext" /* i18n-key-ignore */)} )} {canManage && ( { e.stopPropagation(); setDeleteDialogOpen(true); }} > {t("database.delete")} )} )} {canCreateChild && ( {t("sidebar.addChild")} { e.stopPropagation(); onCreateChildPage(node.id); }} > {t("sidebar.page")} { e.stopPropagation(); onCreateChildDatabase(node.id); }} > {t("sidebar.database")} )}
{hasChildren && expanded && ( child.id)} strategy={verticalListSortingStrategy} > {node.children.map((child) => ( ))} )} {t("sidebar.deletePageQuestion")} {t("sidebar.deletePageDescription", { title: node.title || t("sidebar.untitled"), })} {t("comments.cancel")} onDelete(node.id)} > {t("database.delete")}
); }