import React, { useState, useRef, useEffect, useCallback, memo } from 'react'; import { useRecentSnapsStore, formatRelativeTime, type RecentSnapEntry } from '../store/recentSnapsStore'; import { useCanvasStore } from '../store/canvasStore'; interface RecentSnapsDropdownProps { isOpen: boolean; onClose: () => void; anchorRef: React.RefObject; } const RecentSnapItem = memo(({ entry, onOpen, onDelete }: { entry: RecentSnapEntry; onOpen: (snap: RecentSnapEntry) => void; onDelete: (id: string) => void; }) => { const [isHovered, setIsHovered] = useState(false); return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} onClick={() => onOpen(entry)} > {/* Thumbnail Preview */}
{entry.snap.elements.length} el
{/* Info */}
{entry.title}
{formatRelativeTime(entry.savedAt)}
{/* Actions */} {isHovered && ( )}
); }); RecentSnapItem.displayName = 'RecentSnapItem'; const RecentSnapsDropdown: React.FC = ({ isOpen, onClose, anchorRef }) => { const dropdownRef = useRef(null); const { recentSnaps, removeRecentSnap, clearRecentSnaps } = useRecentSnapsStore(); const { setSnap, saveToHistory } = useCanvasStore(); // Close on outside click useEffect(() => { const handleClickOutside = (e: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(e.target as Node) && anchorRef.current && !anchorRef.current.contains(e.target as Node) ) { onClose(); } }; if (isOpen) { document.addEventListener('mousedown', handleClickOutside); } return () => document.removeEventListener('mousedown', handleClickOutside); }, [isOpen, onClose, anchorRef]); // Close on escape useEffect(() => { const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; if (isOpen) { document.addEventListener('keydown', handleEscape); } return () => document.removeEventListener('keydown', handleEscape); }, [isOpen, onClose]); const handleOpenSnap = useCallback((entry: RecentSnapEntry) => { saveToHistory(); setSnap(entry.snap); onClose(); }, [setSnap, saveToHistory, onClose]); const handleDeleteSnap = useCallback((id: string) => { removeRecentSnap(id); }, [removeRecentSnap]); if (!isOpen) return null; return (
Recent Projects {recentSnaps.length > 0 && ( )}
{recentSnaps.length === 0 ? (

No recent projects

Projects you save will appear here

) : (
{recentSnaps.map((entry) => ( ))}
)}
); }; export default memo(RecentSnapsDropdown);