import { useRef, useState } from 'react'; import { motion, AnimatePresence } from 'motion/react'; import { Eraser, History, Minimize2, PencilLine, RotateCcw } from 'lucide-react'; import { WhiteboardCanvas } from './whiteboard-canvas'; import type { WhiteboardCanvasHandle } from './whiteboard-canvas'; import { WhiteboardHistory } from './whiteboard-history'; import { useStageStore } from '@/lib/store'; import { useCanvasStore } from '@/lib/store/canvas'; import { useWhiteboardHistoryStore } from '@/lib/store/whiteboard-history'; import { createStageAPI } from '@/lib/api/stage-api'; import { toast } from 'sonner'; import { useI18n } from '@/lib/hooks/use-i18n'; interface WhiteboardProps { readonly isOpen: boolean; readonly onClose: () => void; } /** * Whiteboard component */ export function Whiteboard({ isOpen, onClose }: WhiteboardProps) { const { t } = useI18n(); const stage = useStageStore.use.stage(); const isClearing = useCanvasStore.use.whiteboardClearing(); const clearingRef = useRef(false); const [historyOpen, setHistoryOpen] = useState(false); const [viewModified, setViewModified] = useState(false); const canvasRef = useRef(null); const snapshotCount = useWhiteboardHistoryStore((s) => s.snapshots.length); // Get element count for indicator const whiteboard = stage?.whiteboard?.[0]; const elementCount = whiteboard?.elements?.length || 0; const stageAPI = createStageAPI(useStageStore); const handleClear = async () => { if (!whiteboard || elementCount === 0 || clearingRef.current) return; clearingRef.current = true; // Save snapshot before clearing if (whiteboard.elements && whiteboard.elements.length > 0) { useWhiteboardHistoryStore.getState().pushSnapshot(whiteboard.elements); } // Trigger cascade exit animation useCanvasStore.getState().setWhiteboardClearing(true); // Wait for cascade: base 380ms + 55ms per element, capped at 1400ms const animMs = Math.min(380 + elementCount * 55, 1400); await new Promise((resolve) => setTimeout(resolve, animMs)); // Actually remove elements const result = stageAPI.whiteboard.delete(whiteboard.id); useCanvasStore.getState().setWhiteboardClearing(false); clearingRef.current = false; if (result.success) { toast.success(t('whiteboard.clearSuccess')); } else { toast.error(t('whiteboard.clearError') + result.error); } }; return ( <> {/* Main Whiteboard Overlay */} {isOpen && ( {/* Header */}
{t('whiteboard.title')}
{viewModified && ( canvasRef.current?.resetView()} whileTap={{ scale: 0.9 }} className="p-2 text-gray-400 dark:text-gray-500 hover:text-purple-500 dark:hover:text-purple-400 hover:bg-purple-50 dark:hover:bg-purple-900/20 rounded-lg transition-colors" title={t('whiteboard.resetView')} > )} {/* History button + popover wrapper */}
setHistoryOpen(!historyOpen)} whileTap={{ scale: 0.9 }} className="relative p-2 text-gray-400 dark:text-gray-500 hover:text-purple-500 dark:hover:text-purple-400 hover:bg-purple-50 dark:hover:bg-purple-900/20 rounded-lg transition-colors" title={t('whiteboard.history')} > {snapshotCount > 0 && ( {snapshotCount} )} setHistoryOpen(false)} />
{/* Whiteboard Content Area */}
)} ); }