'use client'; import { useRef, type CSSProperties, type ReactNode } from 'react'; import { useDrop } from 'react-dnd'; import type { Folder, SidebarFilter } from '@/types/documents'; import { PDFIcon, EPUBIcon, FileIcon } from '@/components/icons/Icons'; import { FolderIcon, HomeIcon, ClockIcon } from './finderIcons'; import { DND_DOCUMENT, type DocumentDragItem } from '../dnd/dndTypes'; interface FinderSidebarProps { filter: SidebarFilter; onFilterChange: (filter: SidebarFilter) => void; folders: Folder[]; counts: { all: number; pdf: number; epub: number; html: number }; /** When dragging onto a folder row, move dropped docs into that folder. */ onDropOnFolder: (folderId: string, item: DocumentDragItem) => void; /** Width controls (desktop only). */ width: number; onWidthChange: (px: number) => void; topSlot?: ReactNode; } const MIN_WIDTH = 168; const MAX_WIDTH = 320; interface SidebarRowProps { active: boolean; onClick: () => void; icon: ReactNode; label: string; count?: number; trailing?: ReactNode; isDropTarget?: boolean; } function SidebarRow({ active, onClick, icon, label, count, trailing, isDropTarget, }: SidebarRowProps) { return ( ); } function FolderRow({ folder, active, onClick, onDropOnFolder, }: { folder: Folder; active: boolean; onClick: () => void; onDropOnFolder: (folderId: string, item: DocumentDragItem) => void; }) { const [{ isOver, canDrop }, dropRef] = useDrop< DocumentDragItem, void, { isOver: boolean; canDrop: boolean } >(() => ({ accept: DND_DOCUMENT, drop: (item) => { onDropOnFolder(folder.id, item); }, canDrop: (item) => { // Don't accept if all items are already in this folder. return item.docs.some((d) => d.folderId !== folder.id); }, collect: (monitor) => ({ isOver: monitor.isOver({ shallow: true }), canDrop: monitor.canDrop(), }), }), [folder.id, onDropOnFolder]); const isDropTarget = isOver && canDrop; return (
{children}
); } export function FinderSidebar({ filter, onFilterChange, folders, counts, onDropOnFolder, width, onWidthChange, topSlot, }: FinderSidebarProps) { const startRef = useRef<{ x: number; w: number } | null>(null); const onResizeStart = (e: React.PointerEvent) => { (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId); startRef.current = { x: e.clientX, w: width }; }; const onResizeMove = (e: React.PointerEvent) => { if (!startRef.current) return; const delta = e.clientX - startRef.current.x; const next = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, startRef.current.w + delta)); onWidthChange(next); }; const onResizeEnd = (e: React.PointerEvent) => { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); startRef.current = null; }; return ( ); }