/** * Debug Docked Panel Component * * Expandable panel that appears above the status bar when expanded. * Contains the full debug interface with tabs. */ import { useRef, useCallback, useEffect } from 'react'; import { HardDrive, Cpu, Bot, RefreshCw, Trash2, Play, Pause, GripHorizontal } from 'lucide-react'; import { cn } from '@/lib/utils'; import { useDebugStore, MIN_DOCKED_HEIGHT, MAX_DOCKED_HEIGHT_RATIO, type DebugTab, } from '@/store/debug-store'; import { useDebugMetrics } from '@/hooks/use-debug-metrics'; import { useRenderTracking } from '@/hooks/use-render-tracking'; import { MemoryMonitor } from './memory-monitor'; import { CPUMonitor } from './cpu-monitor'; import { ProcessKanban } from './process-kanban'; import { RenderTracker } from './render-tracker'; import { LeakIndicator } from './leak-indicator'; import { useRenderTrackingContext } from './render-profiler'; const TAB_CONFIG: { id: DebugTab; label: string; icon: React.ReactNode }[] = [ { id: 'memory', label: 'Memory', icon: }, { id: 'cpu', label: 'CPU', icon: }, { id: 'processes', label: 'Processes', icon: }, { id: 'renders', label: 'Renders', icon: }, ]; interface DebugDockedPanelProps { className?: string; } export function DebugDockedPanel({ className }: DebugDockedPanelProps) { const { isOpen, isDockedExpanded, panelMode, dockedHeight, activeTab, setActiveTab, setDockedHeight, isResizing, setIsResizing, } = useDebugStore(); const metrics = useDebugMetrics(); const renderTrackingFromContext = useRenderTrackingContext(); const localRenderTracking = useRenderTracking(); const renderTracking = renderTrackingFromContext ?? localRenderTracking; // Ref for resize handling const panelRef = useRef(null); const resizeStartRef = useRef<{ y: number; height: number } | null>(null); // Handle resize start (drag from top edge) const handleResizeStart = useCallback( (e: React.MouseEvent) => { e.preventDefault(); setIsResizing(true); resizeStartRef.current = { y: e.clientY, height: dockedHeight, }; }, [setIsResizing, dockedHeight] ); // Handle resize move useEffect(() => { if (!isResizing) return; const handleMouseMove = (e: MouseEvent) => { if (!resizeStartRef.current) return; // Dragging up increases height, dragging down decreases const deltaY = resizeStartRef.current.y - e.clientY; const newHeight = resizeStartRef.current.height + deltaY; // Clamp to min/max bounds const maxHeight = window.innerHeight * MAX_DOCKED_HEIGHT_RATIO; const clampedHeight = Math.max(MIN_DOCKED_HEIGHT, Math.min(maxHeight, newHeight)); setDockedHeight(clampedHeight); }; const handleMouseUp = () => { setIsResizing(false); resizeStartRef.current = null; }; window.addEventListener('mousemove', handleMouseMove); window.addEventListener('mouseup', handleMouseUp); return () => { window.removeEventListener('mousemove', handleMouseMove); window.removeEventListener('mouseup', handleMouseUp); }; }, [isResizing, setIsResizing, setDockedHeight]); // Only show in docked mode when expanded if (panelMode !== 'docked' || !isDockedExpanded || !isOpen) { return null; } return (
{/* Resize handle - top edge */}
{/* Tabs */}
{TAB_CONFIG.map((tab) => ( ))}
{/* Right side controls */}
{/* Content */}
{activeTab === 'memory' && (
)} {activeTab === 'cpu' && ( )} {activeTab === 'processes' && ( )} {activeTab === 'renders' && ( )}
); } /** * Debug Docked Panel Wrapper - Only renders in development mode */ export function DebugDockedPanelWrapper({ className }: DebugDockedPanelProps) { const isDev = import.meta.env.DEV || import.meta.env.VITE_ENABLE_DEBUG_PANEL === 'true'; if (!isDev) { return null; } return ; }