r3f-frame-profiler 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +1 -61
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +7 -12890
- package/dist/esm/index.js.map +1 -1
- package/dist/index-D_LaF0YP.cjs +2 -0
- package/dist/index-D_LaF0YP.cjs.map +1 -0
- package/dist/index-o5zvhDta.js +4406 -0
- package/dist/index-o5zvhDta.js.map +1 -0
- package/dist/report-generator-BCq_enQo.js +283 -0
- package/dist/report-generator-BCq_enQo.js.map +1 -0
- package/dist/report-generator-BsoP53qp.cjs +61 -0
- package/dist/report-generator-BsoP53qp.cjs.map +1 -0
- package/dist/types/FrameProfiler.d.ts +2 -0
- package/dist/types/FrameProfiler.d.ts.map +1 -0
- package/dist/types/collectors/frame-time-collector.d.ts +41 -0
- package/dist/types/collectors/frame-time-collector.d.ts.map +1 -0
- package/dist/types/collectors/gpu-collector.d.ts +32 -0
- package/dist/types/collectors/gpu-collector.d.ts.map +1 -0
- package/dist/types/collectors/hot-path-detector.d.ts +42 -0
- package/dist/types/collectors/hot-path-detector.d.ts.map +1 -0
- package/dist/types/collectors/index.d.ts +7 -0
- package/dist/types/collectors/index.d.ts.map +1 -0
- package/dist/types/collectors/memory-collector.d.ts +49 -0
- package/dist/types/collectors/memory-collector.d.ts.map +1 -0
- package/dist/types/collectors/scene-collector.d.ts +47 -0
- package/dist/types/collectors/scene-collector.d.ts.map +1 -0
- package/dist/types/components/ReactProfiler.d.ts +12 -0
- package/dist/types/components/ReactProfiler.d.ts.map +1 -0
- package/dist/types/core/alert-system.d.ts +37 -0
- package/dist/types/core/alert-system.d.ts.map +1 -0
- package/dist/types/core/auto-instrumentation.d.ts +33 -0
- package/dist/types/core/auto-instrumentation.d.ts.map +1 -0
- package/dist/types/core/budget-manager.d.ts +78 -0
- package/dist/types/core/budget-manager.d.ts.map +1 -0
- package/dist/types/core/data-export.d.ts +24 -0
- package/dist/types/core/data-export.d.ts.map +1 -0
- package/dist/types/core/index.d.ts +4 -0
- package/dist/types/core/index.d.ts.map +1 -0
- package/dist/types/core/monitor-state.d.ts +21 -0
- package/dist/types/core/monitor-state.d.ts.map +1 -0
- package/dist/types/core/profiler.d.ts +83 -0
- package/dist/types/core/profiler.d.ts.map +1 -0
- package/dist/types/core/react-monitor.d.ts +51 -0
- package/dist/types/core/react-monitor.d.ts.map +1 -0
- package/dist/types/core/report-generator.d.ts +83 -0
- package/dist/types/core/report-generator.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +17 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/useAlerts.d.ts +11 -0
- package/dist/types/hooks/useAlerts.d.ts.map +1 -0
- package/dist/types/hooks/useBudgetChecker.d.ts +6 -0
- package/dist/types/hooks/useBudgetChecker.d.ts.map +1 -0
- package/dist/types/hooks/useFrameHistory.d.ts +2 -0
- package/dist/types/hooks/useFrameHistory.d.ts.map +1 -0
- package/dist/types/hooks/useFrameTime.d.ts +3 -0
- package/dist/types/hooks/useFrameTime.d.ts.map +1 -0
- package/dist/types/hooks/useGPUStats.d.ts +3 -0
- package/dist/types/hooks/useGPUStats.d.ts.map +1 -0
- package/dist/types/hooks/useHotPath.d.ts +3 -0
- package/dist/types/hooks/useHotPath.d.ts.map +1 -0
- package/dist/types/hooks/useMemoryHistory.d.ts +5 -0
- package/dist/types/hooks/useMemoryHistory.d.ts.map +1 -0
- package/dist/types/hooks/useMemoryStats.d.ts +3 -0
- package/dist/types/hooks/useMemoryStats.d.ts.map +1 -0
- package/dist/types/hooks/useMetricsCollector.d.ts +31 -0
- package/dist/types/hooks/useMetricsCollector.d.ts.map +1 -0
- package/dist/types/hooks/usePerformanceBudget.d.ts +20 -0
- package/dist/types/hooks/usePerformanceBudget.d.ts.map +1 -0
- package/dist/types/hooks/useProfiler.d.ts +5 -0
- package/dist/types/hooks/useProfiler.d.ts.map +1 -0
- package/dist/types/hooks/useR3FProfiler.d.ts +2 -0
- package/dist/types/hooks/useR3FProfiler.d.ts.map +1 -0
- package/dist/types/hooks/useR3FProfilerCollector.d.ts +2 -0
- package/dist/types/hooks/useR3FProfilerCollector.d.ts.map +1 -0
- package/dist/types/hooks/useR3FStatsCollector.d.ts +2 -0
- package/dist/types/hooks/useR3FStatsCollector.d.ts.map +1 -0
- package/dist/types/hooks/useReactProfiler.d.ts +3 -0
- package/dist/types/hooks/useReactProfiler.d.ts.map +1 -0
- package/dist/types/hooks/useReportMetric.d.ts +19 -0
- package/dist/types/hooks/useReportMetric.d.ts.map +1 -0
- package/dist/types/hooks/useSceneStats.d.ts +3 -0
- package/dist/types/hooks/useSceneStats.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/ui/PerformanceMonitor.d.ts +7 -0
- package/dist/types/ui/PerformanceMonitor.d.ts.map +1 -0
- package/dist/types/ui/components/AlertBadge.d.ts +9 -0
- package/dist/types/ui/components/AlertBadge.d.ts.map +1 -0
- package/dist/types/ui/components/MetricCard.d.ts +14 -0
- package/dist/types/ui/components/MetricCard.d.ts.map +1 -0
- package/dist/types/ui/components/SimpleChart.d.ts +13 -0
- package/dist/types/ui/components/SimpleChart.d.ts.map +1 -0
- package/dist/types/ui/components/Tabs.d.ts +15 -0
- package/dist/types/ui/components/Tabs.d.ts.map +1 -0
- package/dist/types/ui/components/index.d.ts +5 -0
- package/dist/types/ui/components/index.d.ts.map +1 -0
- package/dist/types/ui/panels/BudgetPanel.d.ts +2 -0
- package/dist/types/ui/panels/BudgetPanel.d.ts.map +1 -0
- package/dist/types/ui/panels/FramePanel.d.ts +2 -0
- package/dist/types/ui/panels/FramePanel.d.ts.map +1 -0
- package/dist/types/ui/panels/FrameTimePanel.d.ts +2 -0
- package/dist/types/ui/panels/FrameTimePanel.d.ts.map +1 -0
- package/dist/types/ui/panels/GPUPanel.d.ts +2 -0
- package/dist/types/ui/panels/GPUPanel.d.ts.map +1 -0
- package/dist/types/ui/panels/HotPathPanel.d.ts +2 -0
- package/dist/types/ui/panels/HotPathPanel.d.ts.map +1 -0
- package/dist/types/ui/panels/MemoryPanel.d.ts +2 -0
- package/dist/types/ui/panels/MemoryPanel.d.ts.map +1 -0
- package/dist/types/ui/panels/ReactPanel.d.ts +2 -0
- package/dist/types/ui/panels/ReactPanel.d.ts.map +1 -0
- package/dist/types/ui/panels/ScenePanel.d.ts +2 -0
- package/dist/types/ui/panels/ScenePanel.d.ts.map +1 -0
- package/dist/types/ui/panels/index.d.ts +9 -0
- package/dist/types/ui/panels/index.d.ts.map +1 -0
- package/dist/types/ui/styles/theme.d.ts +76 -0
- package/dist/types/ui/styles/theme.d.ts.map +1 -0
- package/dist/types/ui/visualizations/FrameGraph.d.ts +10 -0
- package/dist/types/ui/visualizations/FrameGraph.d.ts.map +1 -0
- package/dist/types/ui/visualizations/MemoryChart.d.ts +10 -0
- package/dist/types/ui/visualizations/MemoryChart.d.ts.map +1 -0
- package/dist/types/ui/visualizations/PerformanceChart.d.ts +16 -0
- package/dist/types/ui/visualizations/PerformanceChart.d.ts.map +1 -0
- package/dist/types/ui/visualizations/TimelineView.d.ts +7 -0
- package/dist/types/ui/visualizations/TimelineView.d.ts.map +1 -0
- package/dist/types/ui/visualizations/index.d.ts +5 -0
- package/dist/types/ui/visualizations/index.d.ts.map +1 -0
- package/package.json +12 -7
- package/README.md +0 -60
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-o5zvhDta.js","sources":["../src/core/profiler.ts","../src/hooks/useR3FProfilerCollector.tsx","../src/collectors/gpu-collector.ts","../src/collectors/scene-collector.ts","../src/collectors/memory-collector.ts","../src/collectors/frame-time-collector.ts","../src/core/auto-instrumentation.ts","../src/core/monitor-state.ts","../src/hooks/useR3FStatsCollector.tsx","../src/ui/styles/theme.ts","../src/ui/components/MetricCard.tsx","../src/ui/components/Tabs.tsx","../src/ui/components/AlertBadge.tsx","../src/hooks/useProfiler.ts","../src/hooks/useFrameHistory.ts","../src/hooks/useFrameTime.ts","../src/ui/visualizations/FrameGraph.tsx","../src/ui/visualizations/TimelineView.tsx","../src/hooks/useMemoryHistory.ts","../src/ui/visualizations/MemoryChart.tsx","../src/ui/panels/FramePanel.tsx","../src/hooks/useGPUStats.ts","../src/ui/panels/GPUPanel.tsx","../src/hooks/useSceneStats.ts","../src/ui/panels/ScenePanel.tsx","../src/hooks/useMemoryStats.ts","../src/ui/panels/MemoryPanel.tsx","../src/ui/panels/FrameTimePanel.tsx","../src/core/budget-manager.ts","../src/hooks/usePerformanceBudget.ts","../src/core/alert-system.ts","../src/hooks/useBudgetChecker.ts","../src/ui/panels/BudgetPanel.tsx","../src/core/react-monitor.ts","../src/hooks/useReactProfiler.ts","../src/ui/panels/ReactPanel.tsx","../src/collectors/hot-path-detector.ts","../src/hooks/useHotPath.ts","../src/ui/panels/HotPathPanel.tsx","../src/ui/PerformanceMonitor.tsx"],"sourcesContent":["export interface ProfilerEntry {\r\n name: string;\r\n total: number;\r\n avg: number;\r\n max: number;\r\n calls: number;\r\n percentage: number;\r\n}\r\n\r\nexport interface ProfilerData {\r\n entries: ProfilerEntry[];\r\n totalTime: number;\r\n calls: number;\r\n frames: number;\r\n}\r\n\r\ninterface ProfilerDataInternal {\r\n total: number;\r\n calls: number;\r\n max: number;\r\n times: number[];\r\n}\r\n\r\nclass Profiler {\r\n private data = new Map<string, ProfilerDataInternal>();\r\n private frameCount = 0;\r\n private enabled = false;\r\n private maxHistorySize = 240;\r\n private listeners: Set<(data: ProfilerData | null) => void> = new Set();\r\n private reportGenerator: any = null;\r\n\r\n constructor() {\r\n this.updateEnabledState();\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('storage', () => {\r\n this.updateEnabledState();\r\n });\r\n // Preload report generator\r\n import('./report-generator').then(({ reportGenerator }) => {\r\n this.reportGenerator = reportGenerator;\r\n });\r\n }\r\n }\r\n\r\n private updateEnabledState(): void {\r\n if (typeof window === 'undefined') {\r\n this.enabled = false;\r\n return;\r\n }\r\n\r\n const urlParams = new URLSearchParams(window.location.search);\r\n this.enabled =\r\n urlParams.get('debug') === '1' ||\r\n localStorage.getItem('debug') === 'true';\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this.enabled;\r\n }\r\n\r\n profile<T>(name: string, fn: () => T): T {\r\n if (!this.enabled) {\r\n return fn();\r\n }\r\n\r\n const start = performance.now();\r\n const result = fn();\r\n const end = performance.now();\r\n const duration = end - start;\r\n\r\n this.record(name, duration);\r\n return result;\r\n }\r\n\r\n async profileAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {\r\n if (!this.enabled) {\r\n return fn();\r\n }\r\n\r\n const start = performance.now();\r\n const result = await fn();\r\n const end = performance.now();\r\n const duration = end - start;\r\n\r\n this.record(name, duration);\r\n return result;\r\n }\r\n\r\n record(name: string, duration: number): void {\r\n if (!this.enabled) return;\r\n\r\n if (!this.data.has(name)) {\r\n this.data.set(name, {\r\n total: 0,\r\n calls: 0,\r\n max: 0,\r\n times: []\r\n });\r\n }\r\n\r\n const entry = this.data.get(name)!;\r\n entry.total += duration;\r\n entry.calls += 1;\r\n entry.max = Math.max(entry.max, duration);\r\n entry.times.push(duration);\r\n\r\n // Record in hot path detector if available\r\n if (typeof window !== 'undefined' && (window as any).__hotPathDetector) {\r\n try {\r\n (window as any).__hotPathDetector.recordCall(name, duration);\r\n } catch (e) {\r\n // Silently fail if hot path detector is not available\r\n }\r\n }\r\n\r\n // Limiter l'historique\r\n if (entry.times.length > this.maxHistorySize) {\r\n const removed = entry.times.shift()!;\r\n entry.total -= removed;\r\n entry.calls -= 1;\r\n }\r\n\r\n this.frameCount += 1;\r\n if (this.frameCount > this.maxHistorySize) {\r\n this.frameCount = this.maxHistorySize;\r\n }\r\n }\r\n\r\n wrap<T extends (...args: any[]) => any>(\r\n name: string,\r\n fn: T\r\n ): T {\r\n if (!this.enabled) {\r\n return fn;\r\n }\r\n\r\n const profiler = this;\r\n return ((...args: Parameters<T>) => {\r\n return profiler.profile(name, () => fn(...args));\r\n }) as T;\r\n }\r\n\r\n wrapAsync<T extends (...args: any[]) => Promise<any>>(\r\n name: string,\r\n fn: T\r\n ): T {\r\n if (!this.enabled) {\r\n return fn;\r\n }\r\n\r\n const profiler = this;\r\n return (async (...args: Parameters<T>) => {\r\n return profiler.profileAsync(name, () => fn(...args));\r\n }) as T;\r\n }\r\n\r\n getData(): ProfilerData | null {\r\n if (!this.enabled) return null;\r\n\r\n const entries = Array.from(this.data.entries()).map(([name, data]) => ({\r\n name,\r\n total: data.total,\r\n avg: data.calls > 0 ? data.total / data.calls : 0,\r\n max: data.max,\r\n calls: data.calls\r\n }));\r\n\r\n const totalTime = entries.reduce((sum, entry) => sum + entry.total, 0);\r\n\r\n const result: ProfilerData = {\r\n entries: entries.map(entry => ({\r\n ...entry,\r\n percentage: totalTime > 0 ? (entry.total / totalTime) * 100 : 0,\r\n avg: isFinite(entry.avg) ? entry.avg : 0 // Ensure safe number\r\n })),\r\n totalTime,\r\n calls: Math.max(...entries.map(e => e.calls), 0),\r\n frames: this.frameCount\r\n };\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Get raw profiler data including individual timing samples for percentile analysis\r\n */\r\n getRawData(): Map<string, { total: number; calls: number; max: number; times: number[] }> | null {\r\n if (!this.enabled) return null;\r\n return this.data;\r\n }\r\n\r\n reset(): void {\r\n this.data.clear();\r\n this.frameCount = 0;\r\n this.notifyListeners();\r\n }\r\n\r\n subscribe(listener: (data: ProfilerData | null) => void): () => void {\r\n this.listeners.add(listener);\r\n return () => {\r\n this.listeners.delete(listener);\r\n };\r\n }\r\n\r\n /**\r\n * Notifie tous les listeners\r\n */\r\n private notifyListeners(): void {\r\n const data = this.getData();\r\n this.listeners.forEach(listener => listener(data));\r\n }\r\n\r\n /**\r\n * Force une notification aux listeners\r\n */\r\n notify(): void {\r\n this.notifyListeners();\r\n }\r\n\r\n /**\r\n * Configure la taille maximale de l'historique\r\n */\r\n setMaxHistorySize(size: number): void {\r\n this.maxHistorySize = size;\r\n }\r\n\r\n /**\r\n * Génère un rapport de performance markdown\r\n * Optimisé pour être analysé par une IA\r\n */\r\n async generateReport(): Promise<string> {\r\n const { reportGenerator } = await import('./report-generator');\r\n return reportGenerator.generateMarkdownReport();\r\n }\r\n\r\n /**\r\n * Copie le rapport dans le clipboard\r\n */\r\n async copyReportToClipboard(): Promise<void> {\r\n const { reportGenerator } = await import('./report-generator');\r\n await reportGenerator.copyReportToClipboard();\r\n }\r\n\r\n /**\r\n * Enregistre une frame pour les statistiques du rapport\r\n */\r\n recordFrameStats(fps: number, frameTime: number, memoryMB?: number): void {\r\n // Validate inputs to prevent bad data\r\n if (!isFinite(fps) || !isFinite(frameTime)) return;\r\n\r\n // Ignore absurd values (first frame spikes)\r\n if (fps > 1000 || frameTime <= 0) return;\r\n\r\n if (this.reportGenerator) {\r\n this.reportGenerator.recordFrame(fps, frameTime, memoryMB);\r\n } else {\r\n import('./report-generator').then(({ reportGenerator }) => {\r\n this.reportGenerator = reportGenerator;\r\n this.reportGenerator.recordFrame(fps, frameTime, memoryMB);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Enregistre une métrique custom pour le rapport\r\n */\r\n recordMetricForReport(name: string, value: number): void {\r\n import('./report-generator').then(({ reportGenerator }) => {\r\n reportGenerator.recordMetric(name, value);\r\n });\r\n }\r\n}\r\n\r\n// Instance singleton globale\r\nexport const profiler = new Profiler();\r\n\r\n// Expose hot path detector globally for integration\r\nif (typeof window !== 'undefined') {\r\n // Lazy load to avoid circular dependencies\r\n Promise.resolve().then(async () => {\r\n try {\r\n const { hotPathDetector } = await import('../collectors/hot-path-detector');\r\n (window as any).__hotPathDetector = hotPathDetector;\r\n } catch (e) {\r\n // Silently fail if module is not available\r\n }\r\n });\r\n}\r\n\r\n// Export des fonctions utilitaires\r\nexport const profile = <T>(name: string, fn: () => T): T => {\r\n return profiler.profile(name, fn);\r\n};\r\n\r\nexport const profileAsync = <T>(name: string, fn: () => Promise<T>): Promise<T> => {\r\n return profiler.profileAsync(name, fn);\r\n};\r\n\r\nexport const record = (name: string, duration: number): void => {\r\n profiler.record(name, duration);\r\n};\r\n\r\nexport const wrap = <T extends (...args: any[]) => any>(\r\n name: string,\r\n fn: T\r\n): T => {\r\n return profiler.wrap(name, fn);\r\n};\r\n\r\nexport const wrapAsync = <T extends (...args: any[]) => Promise<any>>(\r\n name: string,\r\n fn: T\r\n): T => {\r\n return profiler.wrapAsync(name, fn);\r\n};\r\n\r\nexport const getProfilerData = (): ProfilerData | null => {\r\n return profiler.getData();\r\n};\r\n\r\nexport const resetProfiler = (): void => {\r\n profiler.reset();\r\n};\r\n\r\nexport const isProfilerEnabled = (): boolean => {\r\n return profiler.isEnabled();\r\n};\r\n\r\nexport const reportMetric = (name: string, value: number): void => {\r\n profiler.recordMetricForReport(name, value);\r\n};\r\n","import { useRef } from 'react';\r\nimport { useFrame } from '@react-three/fiber';\r\nimport { profiler } from '../core/profiler';\r\n\r\nexport const ProfilerDataCollector = () => {\r\n const lastFrameTime = useRef<number>(performance.now());\r\n \r\n useFrame(() => {\r\n \r\n if (profiler.isEnabled()) {\r\n const now = performance.now();\r\n const frameTime = now - lastFrameTime.current;\r\n lastFrameTime.current = now;\r\n \r\n // Enregistrer le temps de frame (temps entre deux frames)\r\n profiler.record('Frame', frameTime);\r\n profiler.notify();\r\n } else {\r\n lastFrameTime.current = performance.now();\r\n }\r\n });\r\n return null;\r\n};\r\n","import type { WebGLRenderer } from 'three';\r\n\r\nexport interface GPUStats {\r\n drawCalls: number;\r\n triangles: number;\r\n points: number;\r\n lines: number;\r\n textures: number;\r\n geometries: number;\r\n programs: number;\r\n memory: {\r\n textures: number;\r\n geometries: number;\r\n programs: number;\r\n total: number;\r\n };\r\n frameTime: number;\r\n timestamp: number;\r\n}\r\n\r\nclass GPUCollector {\r\n private renderer: WebGLRenderer | null = null;\r\n private lastStats: GPUStats | null = null;\r\n private frameStartTime: number = 0;\r\n\r\n setRenderer(renderer: WebGLRenderer): void {\r\n this.renderer = renderer;\r\n }\r\n\r\n getStats(): GPUStats | null {\r\n if (!this.renderer) {\r\n return null;\r\n }\r\n\r\n const info = this.renderer.info;\r\n const memory = info.memory;\r\n const render = info.render;\r\n\r\n // Points and lines may not always be available or may be 0\r\n // Check if they exist in the render object\r\n const points = 'points' in render ? render.points : 0;\r\n const lines = 'lines' in render ? render.lines : 0;\r\n\r\n // Calculate actual memory usage by accessing real texture and geometry data\r\n let texturesMemory = 0;\r\n let geometriesMemory = 0;\r\n\r\n // Calculate texture memory with improved estimation\r\n if (memory.textures && this.renderer) {\r\n try {\r\n // We can't directly query texture sizes from WebGL without storing references\r\n // So we'll use a more accurate estimation based on typical usage\r\n \r\n // Better estimation: assume textures are typically power-of-2 sizes\r\n // Common sizes: 256x256 (256KB), 512x512 (1MB), 1024x1024 (4MB), 2048x2048 (16MB)\r\n // Average: ~2MB per texture for modern applications\r\n texturesMemory = memory.textures * 2 * 1024 * 1024; // 2MB per texture (improved estimate)\r\n } catch (e) {\r\n // Fallback to simple estimation\r\n texturesMemory = memory.textures * 1024 * 1024; // 1MB per texture\r\n }\r\n }\r\n\r\n // Calculate geometry memory by accessing actual geometry data\r\n if (memory.geometries && this.renderer) {\r\n try {\r\n // Access scene to calculate actual geometry sizes\r\n // We can estimate based on vertices and indices\r\n const render = this.renderer.info.render;\r\n const triangles = render.triangles || 0;\r\n \r\n // Better estimation: each triangle has 3 vertices, each vertex has position (12 bytes), \r\n // normal (12 bytes), uv (8 bytes) = ~32 bytes per vertex\r\n // Plus indices: 2 bytes per index (Uint16Array)\r\n // Average: ~100 bytes per triangle\r\n const estimatedBytesPerTriangle = 100;\r\n geometriesMemory = triangles * estimatedBytesPerTriangle;\r\n \r\n // Add base overhead for geometry objects (~10KB per geometry)\r\n geometriesMemory += memory.geometries * 10 * 1024;\r\n } catch (e) {\r\n // Fallback to simple estimation\r\n geometriesMemory = memory.geometries * 100 * 1024; // 100KB per geometry\r\n }\r\n }\r\n\r\n const stats: GPUStats = {\r\n drawCalls: render.calls || 0,\r\n triangles: render.triangles || 0,\r\n points: points || 0,\r\n lines: lines || 0,\r\n textures: memory.textures || 0,\r\n geometries: memory.geometries || 0,\r\n programs: info.programs?.length || 0,\r\n memory: {\r\n textures: texturesMemory,\r\n geometries: geometriesMemory,\r\n programs: 0, // Not available in memory object\r\n total: texturesMemory + geometriesMemory,\r\n },\r\n frameTime: performance.now() - this.frameStartTime,\r\n timestamp: performance.now(),\r\n };\r\n\r\n this.lastStats = stats;\r\n return stats;\r\n }\r\n\r\n startFrame(): void {\r\n this.frameStartTime = performance.now();\r\n }\r\n\r\n endFrame(): void {\r\n // Frame time is calculated in getStats\r\n }\r\n\r\n getLastStats(): GPUStats | null {\r\n return this.lastStats;\r\n }\r\n\r\n reset(): void {\r\n this.lastStats = null;\r\n }\r\n}\r\n\r\nexport const gpuCollector = new GPUCollector();\r\n","import type { Scene, Object3D, Material } from 'three';\r\nimport { Mesh, Light, Camera, Texture } from 'three';\r\n\r\nexport interface SceneStats {\r\n objects: {\r\n total: number;\r\n meshes: number;\r\n lights: number;\r\n cameras: number;\r\n groups: number;\r\n other: number;\r\n };\r\n materials: {\r\n total: number;\r\n byType: Record<string, number>;\r\n };\r\n textures: {\r\n total: number;\r\n totalSize: number;\r\n byFormat: Record<string, number>;\r\n environment: number; // Count of environment textures\r\n system: number; // Count of system textures (lightmaps, etc.)\r\n };\r\n geometries: {\r\n total: number;\r\n vertices: number;\r\n faces: number;\r\n };\r\n visible: {\r\n meshes: number;\r\n total: number;\r\n };\r\n complexity: {\r\n averageVerticesPerMesh: number;\r\n averageFacesPerMesh: number;\r\n totalDrawCalls: number;\r\n };\r\n timestamp: number;\r\n}\r\n\r\nclass SceneCollector {\r\n private scene: Scene | null = null;\r\n\r\n setScene(scene: Scene): void {\r\n this.scene = scene;\r\n }\r\n\r\n getStats(): SceneStats | null {\r\n if (!this.scene) {\r\n return null;\r\n }\r\n\r\n const objects = {\r\n total: 0,\r\n meshes: 0,\r\n lights: 0,\r\n cameras: 0,\r\n groups: 0,\r\n other: 0,\r\n };\r\n\r\n const materials = {\r\n total: 0,\r\n byType: {} as Record<string, number>,\r\n };\r\n\r\n const textures = {\r\n total: 0,\r\n totalSize: 0,\r\n byFormat: {} as Record<string, number>,\r\n environment: 0,\r\n system: 0,\r\n };\r\n\r\n const geometries = {\r\n total: 0,\r\n vertices: 0,\r\n faces: 0,\r\n };\r\n\r\n const visible = {\r\n meshes: 0,\r\n total: 0,\r\n };\r\n\r\n const materialSet = new Set<Material>();\r\n const textureSet = new Set<Texture>();\r\n const geometrySet = new Set();\r\n const countedMeshes = new Set<Mesh>(); // Track which meshes we've already counted\r\n\r\n // Helper to check if object is an internal/helper object we should skip\r\n const isInternalObject = (obj: Object3D): boolean => {\r\n if (!obj) return true;\r\n \r\n // Skip Rapier internal objects\r\n if (obj.userData) {\r\n if (obj.userData.rapier || obj.userData.physics || obj.userData.type === 'RigidBody') {\r\n return true;\r\n }\r\n // Skip R3F internal objects\r\n if (obj.userData.__r3f || obj.userData.__reactInternalInstance) {\r\n return true;\r\n }\r\n // Skip objects marked as internal\r\n if (obj.userData.internal === true || obj.userData.helper === true) {\r\n return true;\r\n }\r\n }\r\n \r\n // Skip objects with names that suggest they're internal\r\n if (obj.name) {\r\n const name = obj.name.toLowerCase();\r\n if (\r\n name.includes('__rapier') ||\r\n name.includes('__physics') ||\r\n name.includes('__r3f') ||\r\n name.includes('__internal') ||\r\n name.startsWith('_helper') ||\r\n name.startsWith('_internal') ||\r\n name.includes('__internal') ||\r\n name.startsWith('_') ||\r\n name.includes('collider') ||\r\n name.includes('rigidbody') ||\r\n name.includes('helper') ||\r\n name.includes('debug')\r\n ) {\r\n return true;\r\n }\r\n }\r\n \r\n // Skip objects that are part of physics systems\r\n if ((obj as any).type === 'RigidBody' || (obj as any).isRigidBody) {\r\n return true;\r\n }\r\n \r\n // Skip helper objects\r\n if (obj.type && obj.type.includes('Helper')) {\r\n return true;\r\n }\r\n \r\n return false;\r\n };\r\n\r\n // Only count \"real\" meshes (those with geometry and material)\r\n const isRealMesh = (obj: Object3D): boolean => {\r\n if (!(obj instanceof Mesh || (obj as any).isMesh)) return false;\r\n const mesh = obj as Mesh;\r\n \r\n // Must have both geometry and material\r\n if (!mesh.geometry || !mesh.material) return false;\r\n \r\n // Skip if it's an internal object\r\n if (isInternalObject(obj)) return false;\r\n \r\n // Skip meshes that are children of internal objects (but still count the mesh itself)\r\n // We'll check parent in the traversal\r\n \r\n return true;\r\n };\r\n\r\n // Only count real lights (not helpers)\r\n const isRealLight = (obj: Object3D): boolean => {\r\n if (!(obj instanceof Light || (obj as any).isLight)) return false;\r\n \r\n // Skip if it's an internal object\r\n if (isInternalObject(obj)) return false;\r\n \r\n // Skip light helpers\r\n if (obj.type && obj.type.includes('Helper')) return false;\r\n \r\n return true;\r\n };\r\n\r\n const traverse = (object: Object3D, depth: number = 0, parentIsInternal: boolean = false): void => {\r\n // Skip if object is null or undefined\r\n if (!object) return;\r\n\r\n // Skip internal objects from physics engines at root level\r\n // But still traverse their children to find real meshes\r\n const isInternal = isInternalObject(object) || parentIsInternal;\r\n \r\n // Check for Mesh first (before checking if internal)\r\n // This will catch meshes even if they're nested inside wrappers like RigidBody\r\n if (object instanceof Mesh || (object as any).isMesh) {\r\n const mesh = object as Mesh;\r\n // Only count \"real\" meshes with geometry and material, and only once\r\n // Even if parent is internal, count the mesh if it's a real mesh\r\n if (isRealMesh(object) && !countedMeshes.has(mesh)) {\r\n countedMeshes.add(mesh);\r\n objects.meshes++;\r\n if (object.visible) {\r\n visible.meshes++;\r\n }\r\n \r\n // Count this mesh in total only if it's not internal\r\n if (!isInternal) {\r\n objects.total++;\r\n if (object.visible) {\r\n visible.total++;\r\n }\r\n }\r\n\r\n // Count geometry\r\n if (mesh.geometry && !geometrySet.has(mesh.geometry)) {\r\n geometrySet.add(mesh.geometry);\r\n geometries.total++;\r\n \r\n const geo = mesh.geometry;\r\n // Check for position attribute\r\n if (geo.attributes && geo.attributes.position) {\r\n const count = geo.attributes.position.count || 0;\r\n geometries.vertices += count;\r\n // For indexed geometry, use index count, otherwise estimate from position\r\n if (geo.index) {\r\n geometries.faces += Math.floor(geo.index.count / 3);\r\n } else {\r\n geometries.faces += Math.floor(count / 3);\r\n }\r\n }\r\n }\r\n\r\n // Count materials\r\n if (mesh.material) {\r\n const mats = Array.isArray(mesh.material) ? mesh.material : [mesh.material];\r\n mats.forEach((mat) => {\r\n if (mat && !materialSet.has(mat)) {\r\n materialSet.add(mat);\r\n materials.total++;\r\n const type = (mat as any).type || mat.constructor.name || 'Unknown';\r\n materials.byType[type] = (materials.byType[type] || 0) + 1;\r\n\r\n // Collect textures from material - check common texture properties\r\n const textureKeys = [\r\n 'map', 'normalMap', 'roughnessMap', 'metalnessMap', 'aoMap',\r\n 'emissiveMap', 'bumpMap', 'displacementMap', 'alphaMap',\r\n 'envMap', 'lightMap', 'specularMap', 'clearcoatMap', 'clearcoatNormalMap',\r\n 'clearcoatRoughnessMap', 'sheenColorMap', 'sheenRoughnessMap',\r\n 'transmissionMap', 'thicknessMap', 'iridescenceMap', 'iridescenceThicknessMap'\r\n ];\r\n\r\n textureKeys.forEach((key) => {\r\n const texture = (mat as any)[key];\r\n if (texture && texture instanceof Texture) {\r\n if (!textureSet.has(texture)) {\r\n textureSet.add(texture);\r\n textures.total++;\r\n \r\n const size = this.estimateTextureSize(texture);\r\n textures.totalSize += size;\r\n \r\n const format = texture.format?.toString() || 'unknown';\r\n textures.byFormat[format] = (textures.byFormat[format] || 0) + 1;\r\n \r\n // Detect environment textures\r\n if (key === 'envMap' || texture.name?.toLowerCase().includes('env') || texture.name?.toLowerCase().includes('environment')) {\r\n textures.environment++;\r\n }\r\n \r\n // Detect system textures (lightmaps, etc.)\r\n if (key === 'lightMap' || texture.name?.toLowerCase().includes('lightmap') || texture.name?.toLowerCase().includes('system')) {\r\n textures.system++;\r\n }\r\n }\r\n }\r\n });\r\n\r\n // Also check all properties for textures (fallback)\r\n Object.keys(mat).forEach((key) => {\r\n const value = (mat as any)[key];\r\n if (value && value instanceof Texture && !textureSet.has(value)) {\r\n textureSet.add(value);\r\n textures.total++;\r\n \r\n const size = this.estimateTextureSize(value);\r\n textures.totalSize += size;\r\n \r\n const format = value.format?.toString() || 'unknown';\r\n textures.byFormat[format] = (textures.byFormat[format] || 0) + 1;\r\n \r\n // Detect environment textures\r\n if (key === 'envMap' || value.name?.toLowerCase().includes('env') || value.name?.toLowerCase().includes('environment')) {\r\n textures.environment++;\r\n }\r\n \r\n // Detect system textures\r\n if (key === 'lightMap' || value.name?.toLowerCase().includes('lightmap') || value.name?.toLowerCase().includes('system')) {\r\n textures.system++;\r\n }\r\n }\r\n });\r\n }\r\n });\r\n }\r\n }\r\n // If it's not a real mesh, we still traverse children but don't count it\r\n } else if (object instanceof Light || (object as any).isLight) {\r\n // Only count real lights, not helpers\r\n if (isRealLight(object)) {\r\n objects.lights++;\r\n }\r\n } else if (object instanceof Camera || (object as any).isCamera) {\r\n // Only count cameras that are not helpers\r\n if (!isInternal && !object.type?.includes('Helper')) {\r\n objects.cameras++;\r\n }\r\n } else if (object.type === 'Group' || (object as any).isGroup) {\r\n // Only count groups that are not internal\r\n if (!isInternal) {\r\n objects.groups++;\r\n }\r\n } else if (!isInternal) {\r\n // Count other objects only if they're not internal\r\n objects.other++;\r\n }\r\n\r\n // Traverse children - this will find meshes even if they're nested in wrappers\r\n // Limit depth to avoid infinite recursion and skip very deep internal structures\r\n if (depth < 20 && object.children && object.children.length > 0) {\r\n object.children.forEach((child) => {\r\n if (child) {\r\n traverse(child, depth + 1, isInternal);\r\n }\r\n });\r\n }\r\n };\r\n\r\n // Run the traversal - this will find all objects including those nested in wrappers\r\n // Start from scene children to avoid counting the scene itself\r\n this.scene.children.forEach((child) => {\r\n if (child) traverse(child, 0, false);\r\n });\r\n\r\n const averageVerticesPerMesh = objects.meshes > 0 \r\n ? geometries.vertices / objects.meshes \r\n : 0;\r\n const averageFacesPerMesh = objects.meshes > 0 \r\n ? geometries.faces / objects.meshes \r\n : 0;\r\n\r\n return {\r\n objects,\r\n materials,\r\n textures,\r\n geometries,\r\n visible,\r\n complexity: {\r\n averageVerticesPerMesh,\r\n averageFacesPerMesh,\r\n totalDrawCalls: objects.meshes, // Simplified estimate\r\n },\r\n timestamp: performance.now(),\r\n };\r\n }\r\n\r\n private estimateTextureSize(texture: Texture): number {\r\n if (!texture.image) return 0;\r\n \r\n const image = texture.image as { width?: number; height?: number } | null;\r\n if (!image) return 0;\r\n \r\n const width = image.width || 1;\r\n const height = image.height || 1;\r\n \r\n // Estimate bytes per pixel - default to 4 (RGBA)\r\n // Three.js format is an enum, we'll use a safe default\r\n let bytesPerPixel = 4; // Default RGBA\r\n try {\r\n const formatValue = Number(texture.format);\r\n if (!isNaN(formatValue)) {\r\n // Common Three.js formats\r\n if (formatValue === 1022) bytesPerPixel = 3; // RGBFormat\r\n if (formatValue === 1021) bytesPerPixel = 1; // AlphaFormat\r\n if (formatValue === 1020) bytesPerPixel = 1; // LuminanceFormat\r\n }\r\n } catch {\r\n // Use default if format is not a number\r\n }\r\n \r\n return width * height * bytesPerPixel;\r\n }\r\n\r\n reset(): void {\r\n // Nothing to reset for scene collector\r\n }\r\n}\r\n\r\nexport const sceneCollector = new SceneCollector();\r\n","import type { WebGLRenderer } from 'three';\r\n\r\n// Type for performance.memory (Chrome only)\r\ninterface PerformanceMemory {\r\n usedJSHeapSize: number;\r\n totalJSHeapSize: number;\r\n jsHeapSizeLimit: number;\r\n}\r\n\r\n// Extend Performance interface to include memory\r\ndeclare global {\r\n interface Performance {\r\n memory?: PerformanceMemory;\r\n }\r\n}\r\n\r\nexport interface MemoryStats {\r\n jsHeap: {\r\n used: number; // bytes\r\n total: number; // bytes\r\n limit: number; // bytes\r\n percentage: number; // 0-100\r\n };\r\n gpuMemory: {\r\n textures: number; // bytes (estimated)\r\n geometries: number; // bytes (estimated)\r\n total: number; // bytes (estimated)\r\n };\r\n leaks: {\r\n detected: boolean;\r\n growthRate: number; // bytes per second\r\n trend: 'stable' | 'increasing' | 'decreasing';\r\n };\r\n timestamp: number;\r\n}\r\n\r\nclass MemoryCollector {\r\n private renderer: WebGLRenderer | null = null;\r\n private lastStats: MemoryStats | null = null;\r\n private history: Array<{ timestamp: number; used: number }> = [];\r\n private readonly historySize = 60; // Keep last 60 samples (1 minute at 1 sample/sec)\r\n private startTime: number = 0;\r\n private readonly warmupPeriod = 10000; // 10 seconds warmup before leak detection\r\n\r\n setRenderer(renderer: WebGLRenderer): void {\r\n this.renderer = renderer;\r\n if (this.startTime === 0) {\r\n this.startTime = performance.now();\r\n }\r\n }\r\n\r\n getStats(): MemoryStats | null {\r\n const jsHeap = this.getJSHeapStats();\r\n const gpuMemory = this.getGPUMemoryStats();\r\n const leaks = this.detectLeaks();\r\n\r\n if (!jsHeap && !gpuMemory) {\r\n return null;\r\n }\r\n\r\n const stats: MemoryStats = {\r\n jsHeap: jsHeap || {\r\n used: 0,\r\n total: 0,\r\n limit: 0,\r\n percentage: 0,\r\n },\r\n gpuMemory: gpuMemory || {\r\n textures: 0,\r\n geometries: 0,\r\n total: 0,\r\n },\r\n leaks,\r\n timestamp: performance.now(),\r\n };\r\n\r\n this.lastStats = stats;\r\n return stats;\r\n }\r\n\r\n private getJSHeapStats(): MemoryStats['jsHeap'] | null {\r\n // performance.memory is only available in Chrome\r\n if (typeof performance === 'undefined' || !performance.memory) {\r\n return null;\r\n }\r\n\r\n const memory = performance.memory;\r\n const used = memory.usedJSHeapSize;\r\n const total = memory.totalJSHeapSize;\r\n const limit = memory.jsHeapSizeLimit;\r\n const percentage = limit > 0 ? (used / limit) * 100 : 0;\r\n\r\n // Add to history for leak detection\r\n this.addToHistory(used);\r\n\r\n return {\r\n used,\r\n total,\r\n limit,\r\n percentage: Math.min(100, Math.max(0, percentage)),\r\n };\r\n }\r\n\r\n private getGPUMemoryStats(): MemoryStats['gpuMemory'] | null {\r\n if (!this.renderer) {\r\n return null;\r\n }\r\n\r\n const info = this.renderer.info;\r\n const memory = info.memory;\r\n const render = info.render;\r\n\r\n // Use improved calculation (same as GPU collector)\r\n let texturesMemory = 0;\r\n let geometriesMemory = 0;\r\n\r\n // Calculate texture memory with improved estimation\r\n if (memory.textures && this.renderer) {\r\n try {\r\n // Better estimation: assume textures are typically power-of-2 sizes\r\n // Average: ~2MB per texture for modern applications\r\n texturesMemory = memory.textures * 2 * 1024 * 1024; // 2MB per texture (improved estimate)\r\n } catch (e) {\r\n texturesMemory = memory.textures * 1024 * 1024; // 1MB per texture\r\n }\r\n }\r\n\r\n // Calculate geometry memory with improved estimation\r\n if (memory.geometries && this.renderer) {\r\n try {\r\n const triangles = render.triangles || 0;\r\n // Better estimation: ~100 bytes per triangle\r\n const estimatedBytesPerTriangle = 100;\r\n geometriesMemory = triangles * estimatedBytesPerTriangle;\r\n // Add base overhead for geometry objects (~10KB per geometry)\r\n geometriesMemory += memory.geometries * 10 * 1024;\r\n } catch (e) {\r\n geometriesMemory = memory.geometries * 100 * 1024; // 100KB per geometry\r\n }\r\n }\r\n\r\n return {\r\n textures: texturesMemory,\r\n geometries: geometriesMemory,\r\n total: texturesMemory + geometriesMemory,\r\n };\r\n }\r\n\r\n private addToHistory(used: number): void {\r\n const now = performance.now();\r\n this.history.push({ timestamp: now, used });\r\n\r\n // Keep only last N samples\r\n if (this.history.length > this.historySize) {\r\n this.history.shift();\r\n }\r\n }\r\n\r\n private detectLeaks(): MemoryStats['leaks'] {\r\n // Don't detect leaks during warmup period (initial loading)\r\n const elapsed = performance.now() - this.startTime;\r\n if (elapsed < this.warmupPeriod) {\r\n return {\r\n detected: false,\r\n growthRate: 0,\r\n trend: 'stable',\r\n };\r\n }\r\n\r\n if (this.history.length < 20) {\r\n // Need at least 20 samples (20 seconds) to detect leaks reliably\r\n return {\r\n detected: false,\r\n growthRate: 0,\r\n trend: 'stable',\r\n };\r\n }\r\n\r\n // Calculate growth rate over multiple time windows for more accuracy\r\n const shortTerm = this.history.slice(-10); // Last 10 seconds\r\n const longTerm = this.history.slice(-30); // Last 30 seconds\r\n\r\n // Short-term growth rate\r\n const shortFirst = shortTerm[0];\r\n const shortLast = shortTerm[shortTerm.length - 1];\r\n const shortTimeDiff = (shortLast.timestamp - shortFirst.timestamp) / 1000;\r\n const shortMemoryDiff = shortLast.used - shortFirst.used;\r\n const shortGrowthRate = shortTimeDiff > 0 ? shortMemoryDiff / shortTimeDiff : 0;\r\n\r\n // Long-term growth rate\r\n const longFirst = longTerm[0];\r\n const longLast = longTerm[longTerm.length - 1];\r\n const longTimeDiff = (longLast.timestamp - longFirst.timestamp) / 1000;\r\n const longMemoryDiff = longLast.used - longFirst.used;\r\n const longGrowthRate = longTimeDiff > 0 ? longMemoryDiff / longTimeDiff : 0;\r\n\r\n // Use average of short and long term for more stable detection\r\n const growthRate = (shortGrowthRate + longGrowthRate) / 2;\r\n\r\n // More conservative threshold: > 2MB per minute (> 33KB per second)\r\n // Also require consistent growth in both short and long term\r\n const leakThreshold = 33 * 1024; // 33KB per second\r\n const consistentGrowth = shortGrowthRate > 0 && longGrowthRate > 0;\r\n const detected = growthRate > leakThreshold && consistentGrowth;\r\n\r\n // Determine trend\r\n let trend: 'stable' | 'increasing' | 'decreasing' = 'stable';\r\n if (Math.abs(growthRate) < 2048) {\r\n // Less than 2KB/sec change is considered stable\r\n trend = 'stable';\r\n } else if (growthRate > 0) {\r\n trend = 'increasing';\r\n } else {\r\n trend = 'decreasing';\r\n }\r\n\r\n return {\r\n detected,\r\n growthRate,\r\n trend,\r\n };\r\n }\r\n\r\n getLastStats(): MemoryStats | null {\r\n return this.lastStats;\r\n }\r\n\r\n reset(): void {\r\n this.lastStats = null;\r\n this.history = [];\r\n this.startTime = 0;\r\n }\r\n}\r\n\r\nexport const memoryCollector = new MemoryCollector();\r\n","export interface FramePhase {\r\n name: string;\r\n start: number;\r\n end: number;\r\n duration: number;\r\n}\r\n\r\nexport interface FrameBreakdown {\r\n total: number; // Total processing time in ms (Work Time)\r\n interval: number; // Time since last frame in ms (1/FPS)\r\n phases: {\r\n react: number; // React render phase\r\n update: number; // Three.js update phase\r\n physics: number; // Physics simulation (if present)\r\n render: number; // Rendering phase\r\n postProcess: number; // Post-processing (if present)\r\n other: number; // Other operations\r\n };\r\n timeline: FramePhase[];\r\n timestamp: number;\r\n}\r\n\r\nclass FrameTimeCollector {\r\n private phases: Map<string, { start: number; end?: number }> = new Map();\r\n private timeline: FramePhase[] = [];\r\n private frameStartTime: number = 0;\r\n private lastFrameTime: number = 0;\r\n private currentInterval: number = 0;\r\n private lastBreakdown: FrameBreakdown | null = null;\r\n private readonly maxTimelineEntries = 100;\r\n\r\n startFrame(): void {\r\n const now = performance.now();\r\n\r\n // Calculate interval since last frame\r\n if (this.lastFrameTime > 0) {\r\n this.currentInterval = now - this.lastFrameTime;\r\n }\r\n this.lastFrameTime = now;\r\n\r\n this.frameStartTime = now;\r\n this.phases.clear();\r\n this.timeline = [];\r\n }\r\n\r\n startPhase(name: string): void {\r\n const start = performance.now();\r\n this.phases.set(name, { start });\r\n }\r\n\r\n endPhase(name: string): void {\r\n const phase = this.phases.get(name);\r\n if (!phase) {\r\n return;\r\n }\r\n\r\n const end = performance.now();\r\n phase.end = end;\r\n\r\n const duration = end - phase.start;\r\n this.timeline.push({\r\n name,\r\n start: phase.start,\r\n end,\r\n duration,\r\n });\r\n }\r\n\r\n endFrame(): FrameBreakdown | null {\r\n const frameEndTime = performance.now();\r\n const total = frameEndTime - this.frameStartTime;\r\n // Use internally calculated interval\r\n // Fallback to processing time (total) only if interval is invalid (first frame)\r\n // If currentInterval is 0 (first frame), we prefer returning a safe default or 0 to indicate invalid interval\r\n const interval = this.currentInterval > 0 ? this.currentInterval : (total > 0 ? total : 16.66);\r\n\r\n // Calculate phase durations\r\n const phases = {\r\n react: this.getPhaseDuration('react'),\r\n update: this.getPhaseDuration('update'),\r\n physics: this.getPhaseDuration('physics'),\r\n render: this.getPhaseDuration('render'),\r\n postProcess: this.getPhaseDuration('postProcess'),\r\n other: 0,\r\n };\r\n\r\n // Calculate \"other\" time (time not accounted for by known phases)\r\n const accountedTime = Object.values(phases).reduce((sum, val) => sum + val, 0);\r\n phases.other = Math.max(0, total - accountedTime);\r\n\r\n const breakdown: FrameBreakdown = {\r\n total,\r\n interval,\r\n phases,\r\n timeline: [...this.timeline].slice(-this.maxTimelineEntries), // Keep last N entries\r\n timestamp: this.frameStartTime,\r\n };\r\n\r\n this.lastBreakdown = breakdown;\r\n return breakdown;\r\n }\r\n\r\n private getPhaseDuration(name: string): number {\r\n const phase = this.phases.get(name);\r\n if (!phase || phase.end === undefined) {\r\n return 0;\r\n }\r\n return phase.end - phase.start;\r\n }\r\n\r\n // Helper method to measure a function execution\r\n measure<T>(name: string, fn: () => T): T {\r\n this.startPhase(name);\r\n try {\r\n return fn();\r\n } finally {\r\n this.endPhase(name);\r\n }\r\n }\r\n\r\n // Helper method to measure async function execution\r\n async measureAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {\r\n this.startPhase(name);\r\n try {\r\n return await fn();\r\n } finally {\r\n this.endPhase(name);\r\n }\r\n }\r\n\r\n getLastBreakdown(): FrameBreakdown | null {\r\n return this.lastBreakdown;\r\n }\r\n\r\n reset(): void {\r\n this.phases.clear();\r\n this.timeline = [];\r\n this.lastBreakdown = null;\r\n }\r\n}\r\n\r\nexport const frameTimeCollector = new FrameTimeCollector();\r\n","import { frameTimeCollector } from '../collectors/frame-time-collector';\r\n\r\n/**\r\n * Automatic frame breakdown instrumentation\r\n * This system automatically detects and measures different phases of a frame\r\n */\r\nclass AutoInstrumentation {\r\n private enabled = false;\r\n private reactPhaseStart: number = 0;\r\n private isReactRendering = false;\r\n private isUpdating = false;\r\n private isPhysicsRunning = false;\r\n private isRendering = false;\r\n private mutationObserver: MutationObserver | null = null;\r\n\r\n enable(): void {\r\n if (this.enabled) return;\r\n this.enabled = true;\r\n this.setupReactInstrumentation();\r\n this.setupThreeJSInstrumentation();\r\n this.setupPhysicsInstrumentation();\r\n }\r\n\r\n disable(): void {\r\n if (!this.enabled) return;\r\n this.enabled = false;\r\n this.cleanup();\r\n }\r\n\r\n private setupReactInstrumentation(): void {\r\n // Hook into React's rendering cycle using React Profiler API\r\n // We'll track React renders via the reactMonitor\r\n if (typeof window === 'undefined') return;\r\n\r\n // Use MutationObserver as a fallback to detect DOM changes (React updates)\r\n const root = document.getElementById('root') || document.body;\r\n if (root) {\r\n this.mutationObserver = new MutationObserver(() => {\r\n // React updates cause DOM mutations\r\n // We'll use this as a signal that React is rendering\r\n if (!this.isReactRendering) {\r\n this.startReactPhase();\r\n }\r\n });\r\n\r\n this.mutationObserver.observe(root, {\r\n childList: true,\r\n subtree: true,\r\n attributes: true,\r\n attributeOldValue: false,\r\n });\r\n }\r\n\r\n // Also track via performance marks if available\r\n if (performance.mark) {\r\n // React 18+ uses performance marks for scheduling\r\n const originalMark = performance.mark;\r\n performance.mark = ((name: string, options?: PerformanceMarkOptions) => {\r\n if (name.includes('react') || name.includes('React')) {\r\n if (!this.isReactRendering) {\r\n this.startReactPhase();\r\n }\r\n }\r\n return originalMark.call(performance, name, options);\r\n }) as typeof performance.mark;\r\n }\r\n }\r\n\r\n private setupThreeJSInstrumentation(): void {\r\n // Three.js phases are handled via useFrame hook\r\n // This is already instrumented in R3FStatsCollector\r\n }\r\n\r\n private setupPhysicsInstrumentation(): void {\r\n // Detect Rapier physics engine\r\n if (typeof window !== 'undefined' && (window as any).RAPIER) {\r\n // Try to hook into Rapier's step function\r\n // This is a best-effort approach\r\n }\r\n }\r\n\r\n startFrame(): void {\r\n if (!this.enabled) return;\r\n frameTimeCollector.startFrame();\r\n }\r\n\r\n startReactPhase(): void {\r\n if (!this.enabled || this.isReactRendering) return;\r\n this.isReactRendering = true;\r\n this.reactPhaseStart = performance.now();\r\n frameTimeCollector.startPhase('react');\r\n }\r\n\r\n endReactPhase(): void {\r\n if (!this.enabled || !this.isReactRendering) return;\r\n this.isReactRendering = false;\r\n frameTimeCollector.endPhase('react');\r\n }\r\n\r\n // Called by ReactMonitor when a component renders\r\n onReactRender(actualDuration: number): void {\r\n if (!this.enabled) return;\r\n // Aggregate React render times\r\n // The reactMonitor already tracks individual components\r\n // We use this to know when React rendering is happening\r\n if (!this.isReactRendering) {\r\n this.startReactPhase();\r\n }\r\n // End phase after a short delay to account for batched updates\r\n setTimeout(() => {\r\n if (this.isReactRendering && performance.now() - this.reactPhaseStart > actualDuration) {\r\n this.endReactPhase();\r\n }\r\n }, 0);\r\n }\r\n\r\n startUpdatePhase(): void {\r\n if (!this.enabled || this.isUpdating) return;\r\n this.isUpdating = true;\r\n frameTimeCollector.startPhase('update');\r\n }\r\n\r\n endUpdatePhase(): void {\r\n if (!this.enabled || !this.isUpdating) return;\r\n this.isUpdating = false;\r\n frameTimeCollector.endPhase('update');\r\n }\r\n\r\n startPhysicsPhase(): void {\r\n if (!this.enabled || this.isPhysicsRunning) return;\r\n this.isPhysicsRunning = true;\r\n frameTimeCollector.startPhase('physics');\r\n }\r\n\r\n endPhysicsPhase(): void {\r\n if (!this.enabled || !this.isPhysicsRunning) return;\r\n this.isPhysicsRunning = false;\r\n frameTimeCollector.endPhase('physics');\r\n }\r\n\r\n startRenderPhase(): void {\r\n if (!this.enabled || this.isRendering) return;\r\n this.isRendering = true;\r\n frameTimeCollector.startPhase('render');\r\n }\r\n\r\n endRenderPhase(): void {\r\n if (!this.enabled || !this.isRendering) return;\r\n this.isRendering = false;\r\n frameTimeCollector.endPhase('render');\r\n frameTimeCollector.endFrame();\r\n }\r\n\r\n private cleanup(): void {\r\n this.isReactRendering = false;\r\n this.isUpdating = false;\r\n this.isPhysicsRunning = false;\r\n this.isRendering = false;\r\n \r\n if (this.mutationObserver) {\r\n this.mutationObserver.disconnect();\r\n this.mutationObserver = null;\r\n }\r\n }\r\n\r\n isActive(): boolean {\r\n return this.enabled;\r\n }\r\n}\r\n\r\nexport const autoInstrumentation = new AutoInstrumentation();\r\n","/**\r\n * Global state manager for Performance Monitor\r\n * Handles pause/resume functionality\r\n */\r\nclass MonitorState {\r\n private isPaused = false;\r\n private listeners: Set<(paused: boolean) => void> = new Set();\r\n private readonly STORAGE_KEY = 'r3f-profiler-paused';\r\n\r\n constructor() {\r\n // Load saved pause state from localStorage\r\n this.loadPauseState();\r\n }\r\n\r\n private loadPauseState(): void {\r\n try {\r\n const saved = localStorage.getItem(this.STORAGE_KEY);\r\n if (saved !== null) {\r\n this.isPaused = saved === 'true';\r\n }\r\n } catch (e) {\r\n console.warn('Failed to load pause state:', e);\r\n }\r\n }\r\n\r\n private savePauseState(): void {\r\n try {\r\n localStorage.setItem(this.STORAGE_KEY, String(this.isPaused));\r\n } catch (e) {\r\n console.warn('Failed to save pause state:', e);\r\n }\r\n }\r\n\r\n pause(): void {\r\n if (this.isPaused) return;\r\n this.isPaused = true;\r\n this.savePauseState();\r\n this.notifyListeners();\r\n }\r\n\r\n resume(): void {\r\n if (!this.isPaused) return;\r\n this.isPaused = false;\r\n this.savePauseState();\r\n this.notifyListeners();\r\n }\r\n\r\n toggle(): void {\r\n if (this.isPaused) {\r\n this.resume();\r\n } else {\r\n this.pause();\r\n }\r\n }\r\n\r\n getPaused(): boolean {\r\n return this.isPaused;\r\n }\r\n\r\n subscribe(listener: (paused: boolean) => void): () => void {\r\n this.listeners.add(listener);\r\n return () => {\r\n this.listeners.delete(listener);\r\n };\r\n }\r\n\r\n private notifyListeners(): void {\r\n this.listeners.forEach(listener => {\r\n try {\r\n listener(this.isPaused);\r\n } catch (error) {\r\n console.error('Error in monitor state listener:', error);\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport const monitorState = new MonitorState();\r\n","import { useEffect } from 'react';\r\nimport { useThree, useFrame } from '@react-three/fiber';\r\nimport { gpuCollector } from '../collectors/gpu-collector';\r\nimport { sceneCollector } from '../collectors/scene-collector';\r\nimport { memoryCollector } from '../collectors/memory-collector';\r\nimport { frameTimeCollector } from '../collectors/frame-time-collector';\r\nimport { autoInstrumentation } from '../core/auto-instrumentation';\r\nimport { monitorState } from '../core/monitor-state';\r\nimport { profiler } from '../core/profiler';\r\n\r\n\r\nexport const R3FStatsCollector = () => {\r\n const { gl, scene } = useThree();\r\n\r\n useEffect(() => {\r\n if (gl) {\r\n gpuCollector.setRenderer(gl);\r\n memoryCollector.setRenderer(gl);\r\n }\r\n }, [gl]);\r\n\r\n useEffect(() => {\r\n if (scene) {\r\n sceneCollector.setScene(scene);\r\n }\r\n }, [scene]);\r\n\r\n // Enable auto-instrumentation when component mounts\r\n useEffect(() => {\r\n autoInstrumentation.enable();\r\n return () => {\r\n autoInstrumentation.disable();\r\n };\r\n }, []);\r\n\r\n // Update stats on each frame using useFrame\r\n useFrame((_state, _delta) => {\r\n if (gl && !monitorState.getPaused()) {\r\n // Start frame timing\r\n frameTimeCollector.startFrame();\r\n\r\n // Start update phase (Three.js updates)\r\n autoInstrumentation.startUpdatePhase();\r\n\r\n // Three.js update happens here (state updates, animations, etc.)\r\n // This is measured by the time spent in useFrame before render\r\n\r\n // End update phase and start render phase\r\n autoInstrumentation.endUpdatePhase();\r\n autoInstrumentation.startRenderPhase();\r\n\r\n gpuCollector.startFrame();\r\n\r\n // Stats will be collected after render\r\n requestAnimationFrame(() => {\r\n if (!monitorState.getPaused()) {\r\n autoInstrumentation.endRenderPhase();\r\n const frameBreakdown = frameTimeCollector.endFrame(); // Ensure frame is ended\r\n\r\n gpuCollector.endFrame();\r\n gpuCollector.getStats();\r\n memoryCollector.getStats();\r\n\r\n if (frameBreakdown) {\r\n const frameInterval = frameBreakdown.interval || frameBreakdown.total;\r\n // Ignore very small intervals (potential first frame noise)\r\n const realFrameTime = Math.max(frameInterval, 0.001);\r\n // Cap FPS to reasonable limit (e.g. 1000) to avoid Infinity/Spikes on startup\r\n const calculatedFps = 1000 / realFrameTime;\r\n const fps = calculatedFps > 500 && frameBreakdown.total < 16 ? 0 : calculatedFps; // Ignore initial spikes if processing was fast but interval tiny\r\n\r\n // Get memory if available\r\n let memoryMB = undefined;\r\n if (typeof performance !== 'undefined' && (performance as any).memory) {\r\n memoryMB = (performance as any).memory.usedJSHeapSize / (1024 * 1024);\r\n }\r\n\r\n if (profiler.isEnabled()) {\r\n profiler.recordFrameStats(fps, realFrameTime, memoryMB);\r\n }\r\n }\r\n }\r\n });\r\n }\r\n });\r\n\r\n return null;\r\n};\r\n","export type ThemeMode = 'dark' | 'light';\r\n\r\nexport interface Theme {\r\n mode: ThemeMode;\r\n colors: {\r\n background: string;\r\n surface: string;\r\n surfaceElevated: string;\r\n text: string;\r\n textSecondary: string;\r\n textTertiary: string;\r\n border: string;\r\n borderLight: string;\r\n primary: string;\r\n primaryHover: string;\r\n success: string;\r\n warning: string;\r\n error: string;\r\n info: string;\r\n accent: string;\r\n };\r\n shadows: {\r\n sm: string;\r\n md: string;\r\n lg: string;\r\n xl: string;\r\n };\r\n borderRadius: {\r\n sm: string;\r\n md: string;\r\n lg: string;\r\n };\r\n spacing: {\r\n xs: string;\r\n sm: string;\r\n md: string;\r\n lg: string;\r\n xl: string;\r\n };\r\n typography: {\r\n fontFamily: string;\r\n fontFamilyMono: string;\r\n fontSize: {\r\n xs: string;\r\n sm: string;\r\n md: string;\r\n lg: string;\r\n xl: string;\r\n };\r\n };\r\n transitions: {\r\n fast: string;\r\n normal: string;\r\n slow: string;\r\n };\r\n zIndex: {\r\n base: number;\r\n dropdown: number;\r\n sticky: number;\r\n overlay: number;\r\n modal: number;\r\n popover: number;\r\n tooltip: number;\r\n };\r\n}\r\n\r\nconst darkTheme: Theme = {\r\n mode: 'dark',\r\n colors: {\r\n background: 'rgba(15, 15, 15, 0.95)',\r\n surface: 'rgba(26, 26, 26, 0.98)',\r\n surfaceElevated: 'rgba(35, 35, 35, 0.98)',\r\n text: '#ffffff',\r\n textSecondary: 'rgba(255, 255, 255, 0.7)',\r\n textTertiary: 'rgba(255, 255, 255, 0.5)',\r\n border: 'rgba(255, 255, 255, 0.1)',\r\n borderLight: 'rgba(255, 255, 255, 0.05)',\r\n primary: '#3b82f6',\r\n primaryHover: '#2563eb',\r\n success: '#10b981',\r\n warning: '#f59e0b',\r\n error: '#ef4444',\r\n info: '#06b6d4',\r\n accent: '#8b5cf6',\r\n },\r\n shadows: {\r\n sm: '0 1px 2px rgba(0, 0, 0, 0.3)',\r\n md: '0 4px 6px rgba(0, 0, 0, 0.4)',\r\n lg: '0 10px 15px rgba(0, 0, 0, 0.5)',\r\n xl: '0 20px 25px rgba(0, 0, 0, 0.6)',\r\n },\r\n borderRadius: {\r\n sm: '4px',\r\n md: '8px',\r\n lg: '12px',\r\n },\r\n spacing: {\r\n xs: '4px',\r\n sm: '8px',\r\n md: '16px',\r\n lg: '24px',\r\n xl: '32px',\r\n },\r\n typography: {\r\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\r\n fontFamilyMono: '\"SF Mono\", \"Monaco\", \"Inconsolata\", \"Roboto Mono\", \"Source Code Pro\", monospace',\r\n fontSize: {\r\n xs: '10px',\r\n sm: '12px',\r\n md: '14px',\r\n lg: '16px',\r\n xl: '18px',\r\n },\r\n },\r\n transitions: {\r\n fast: '150ms ease',\r\n normal: '250ms ease',\r\n slow: '350ms ease',\r\n },\r\n zIndex: {\r\n base: 10000,\r\n dropdown: 10010,\r\n sticky: 10020,\r\n overlay: 10030,\r\n modal: 10040,\r\n popover: 10050,\r\n tooltip: 10060,\r\n },\r\n};\r\n\r\nconst lightTheme: Theme = {\r\n ...darkTheme,\r\n mode: 'light',\r\n colors: {\r\n background: 'rgba(255, 255, 255, 0.95)',\r\n surface: 'rgba(250, 250, 250, 0.98)',\r\n surfaceElevated: 'rgba(255, 255, 255, 0.98)',\r\n text: '#1a1a1a',\r\n textSecondary: 'rgba(26, 26, 26, 0.7)',\r\n textTertiary: 'rgba(26, 26, 26, 0.5)',\r\n border: 'rgba(0, 0, 0, 0.1)',\r\n borderLight: 'rgba(0, 0, 0, 0.05)',\r\n primary: '#3b82f6',\r\n primaryHover: '#2563eb',\r\n success: '#10b981',\r\n warning: '#f59e0b',\r\n error: '#ef4444',\r\n info: '#06b6d4',\r\n accent: '#8b5cf6',\r\n },\r\n shadows: {\r\n sm: '0 1px 2px rgba(0, 0, 0, 0.1)',\r\n md: '0 4px 6px rgba(0, 0, 0, 0.15)',\r\n lg: '0 10px 15px rgba(0, 0, 0, 0.2)',\r\n xl: '0 20px 25px rgba(0, 0, 0, 0.25)',\r\n },\r\n};\r\n\r\nexport const themes = {\r\n dark: darkTheme,\r\n light: lightTheme,\r\n};\r\n\r\nexport const defaultTheme = darkTheme;\r\n\r\n// Helper function to get performance color based on value\r\nexport function getPerformanceColor(value: number, thresholds: { good: number; warning: number }): string {\r\n if (value <= thresholds.good) return defaultTheme.colors.success;\r\n if (value <= thresholds.warning) return defaultTheme.colors.warning;\r\n return defaultTheme.colors.error;\r\n}\r\n\r\n// Helper function to format numbers\r\nexport function formatNumber(value: number, decimals: number = 2): string {\r\n return value.toFixed(decimals);\r\n}\r\n\r\n// Helper function to format percentage\r\nexport function formatPercentage(value: number, decimals: number = 1): string {\r\n return `${value.toFixed(decimals)}%`;\r\n}\r\n","import type { ReactNode } from 'react';\r\nimport { defaultTheme } from '../styles/theme';\r\n\r\nexport interface MetricCardProps {\r\n label: string;\r\n value: string | number;\r\n unit?: string;\r\n trend?: 'up' | 'down' | 'neutral';\r\n status?: 'good' | 'warning' | 'error';\r\n color?: string;\r\n icon?: ReactNode;\r\n onClick?: () => void;\r\n className?: string;\r\n}\r\n\r\nexport const MetricCard = ({\r\n label,\r\n value,\r\n unit,\r\n trend,\r\n status,\r\n color,\r\n icon,\r\n onClick,\r\n className = '',\r\n}: MetricCardProps) => {\r\n const theme = defaultTheme;\r\n \r\n let statusColor = color;\r\n if (!statusColor && status) {\r\n statusColor = status === 'good' \r\n ? theme.colors.success \r\n : status === 'warning' \r\n ? theme.colors.warning \r\n : theme.colors.error;\r\n }\r\n\r\n const displayValue = typeof value === 'number' ? value.toLocaleString() : value;\r\n const displayUnit = unit ? ` ${unit}` : '';\r\n\r\n return (\r\n <div\r\n onClick={onClick}\r\n className={className}\r\n style={{\r\n backgroundColor: theme.colors.surface,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n cursor: onClick ? 'pointer' : 'default',\r\n transition: theme.transitions.fast,\r\n position: 'relative',\r\n overflow: 'hidden',\r\n }}\r\n onMouseEnter={(e) => {\r\n if (onClick) {\r\n e.currentTarget.style.backgroundColor = theme.colors.surfaceElevated;\r\n e.currentTarget.style.transform = 'translateY(-2px)';\r\n e.currentTarget.style.boxShadow = theme.shadows.md;\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (onClick) {\r\n e.currentTarget.style.backgroundColor = theme.colors.surface;\r\n e.currentTarget.style.transform = 'translateY(0)';\r\n e.currentTarget.style.boxShadow = 'none';\r\n }\r\n }}\r\n >\r\n {icon && (\r\n <div style={{ \r\n position: 'absolute', \r\n top: theme.spacing.sm, \r\n right: theme.spacing.sm,\r\n opacity: 0.3,\r\n }}>\r\n {icon}\r\n </div>\r\n )}\r\n \r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.xs,\r\n fontWeight: 500,\r\n }}>\r\n {label}\r\n </div>\r\n \r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'baseline',\r\n gap: theme.spacing.xs,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.lg,\r\n fontWeight: 'bold',\r\n color: statusColor || theme.colors.text,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n {displayValue}\r\n </div>\r\n {unit && (\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n color: theme.colors.textTertiary,\r\n }}>\r\n {displayUnit}\r\n </div>\r\n )}\r\n {trend && (\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: trend === 'up' ? theme.colors.error : trend === 'down' ? theme.colors.success : theme.colors.textTertiary,\r\n marginLeft: 'auto',\r\n }}>\r\n {trend === 'up' ? '↑' : trend === 'down' ? '↓' : '→'}\r\n </div>\r\n )}\r\n </div>\r\n \r\n {statusColor && (\r\n <div style={{\r\n position: 'absolute',\r\n bottom: 0,\r\n left: 0,\r\n right: 0,\r\n height: '2px',\r\n backgroundColor: statusColor,\r\n }} />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from 'react';\r\nimport { defaultTheme } from '../styles/theme';\r\n\r\nexport interface Tab {\r\n id: string;\r\n label: string;\r\n icon?: ReactNode;\r\n badge?: number | string;\r\n}\r\n\r\nexport interface TabsProps {\r\n tabs: Tab[];\r\n activeTab: string;\r\n onTabChange: (tabId: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport const Tabs = ({ tabs, activeTab, onTabChange, className = '' }: TabsProps) => {\r\n const theme = defaultTheme;\r\n\r\n return (\r\n <div className={className} style={{ position: 'relative' }}>\r\n <div style={{\r\n display: 'flex',\r\n gap: theme.spacing.xs,\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n paddingBottom: theme.spacing.xs,\r\n }}>\r\n {tabs.map((tab) => {\r\n const isActive = tab.id === activeTab;\r\n return (\r\n <button\r\n key={tab.id}\r\n onClick={() => onTabChange(tab.id)}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.xs,\r\n padding: `${theme.spacing.sm} ${theme.spacing.md}`,\r\n backgroundColor: 'transparent',\r\n border: 'none',\r\n color: isActive ? theme.colors.primary : theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: isActive ? 600 : 400,\r\n cursor: 'pointer',\r\n position: 'relative',\r\n transition: theme.transitions.fast,\r\n borderRadius: `${theme.borderRadius.sm} ${theme.borderRadius.sm} 0 0`,\r\n }}\r\n onMouseEnter={(e) => {\r\n if (!isActive) {\r\n e.currentTarget.style.color = theme.colors.text;\r\n e.currentTarget.style.backgroundColor = theme.colors.surfaceElevated;\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (!isActive) {\r\n e.currentTarget.style.color = theme.colors.textSecondary;\r\n e.currentTarget.style.backgroundColor = 'transparent';\r\n }\r\n }}\r\n >\r\n {tab.icon && (\r\n <span style={{ display: 'flex', alignItems: 'center' }}>\r\n {tab.icon}\r\n </span>\r\n )}\r\n <span>{tab.label}</span>\r\n {tab.badge !== undefined && (\r\n <span style={{\r\n backgroundColor: isActive ? theme.colors.primary : theme.colors.surfaceElevated,\r\n color: isActive ? theme.colors.text : theme.colors.textSecondary,\r\n borderRadius: theme.borderRadius.sm,\r\n padding: `2px ${theme.spacing.xs}`,\r\n fontSize: theme.typography.fontSize.xs,\r\n fontWeight: 600,\r\n minWidth: '18px',\r\n textAlign: 'center',\r\n }}>\r\n {tab.badge}\r\n </span>\r\n )}\r\n {isActive && (\r\n <div style={{\r\n position: 'absolute',\r\n bottom: -1,\r\n left: 0,\r\n right: 0,\r\n height: '2px',\r\n backgroundColor: theme.colors.primary,\r\n }} />\r\n )}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from 'react';\r\nimport { defaultTheme } from '../styles/theme';\r\n\r\nexport interface AlertBadgeProps {\r\n severity: 'info' | 'warning' | 'error';\r\n count?: number;\r\n children?: ReactNode;\r\n onClick?: () => void;\r\n}\r\n\r\nexport const AlertBadge = ({ severity, count, children, onClick }: AlertBadgeProps) => {\r\n const theme = defaultTheme;\r\n\r\n const colors = {\r\n info: theme.colors.info,\r\n warning: theme.colors.warning,\r\n error: theme.colors.error,\r\n };\r\n\r\n const backgroundColor = colors[severity];\r\n\r\n return (\r\n <div\r\n onClick={onClick}\r\n style={{\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.xs,\r\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\r\n backgroundColor: `${backgroundColor}20`,\r\n color: backgroundColor,\r\n borderRadius: theme.borderRadius.md,\r\n fontSize: theme.typography.fontSize.xs,\r\n fontWeight: 600,\r\n cursor: onClick ? 'pointer' : 'default',\r\n border: `1px solid ${backgroundColor}40`,\r\n transition: theme.transitions.fast,\r\n }}\r\n onMouseEnter={(e) => {\r\n if (onClick) {\r\n e.currentTarget.style.backgroundColor = `${backgroundColor}30`;\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (onClick) {\r\n e.currentTarget.style.backgroundColor = `${backgroundColor}20`;\r\n }\r\n }}\r\n >\r\n <div style={{\r\n width: '8px',\r\n height: '8px',\r\n borderRadius: '50%',\r\n backgroundColor: backgroundColor,\r\n }} />\r\n {count !== undefined && count > 0 && (\r\n <span>{count}</span>\r\n )}\r\n {children}\r\n </div>\r\n );\r\n};\r\n","import { useEffect, useCallback, useState } from 'react';\r\nimport { profiler, type ProfilerData } from '../core/profiler';\r\nimport { monitorState } from '../core/monitor-state';\r\n\r\nexport function useProfiled<T extends (...args: any[]) => any>(\r\n name: string,\r\n fn: T\r\n): T {\r\n return useCallback(\r\n profiler.wrap(name, fn),\r\n [name, fn]\r\n );\r\n}\r\n\r\nexport function useProfiledAsync<T extends (...args: any[]) => Promise<any>>(\r\n name: string,\r\n fn: T\r\n): T {\r\n return useCallback(\r\n profiler.wrapAsync(name, fn),\r\n [name, fn]\r\n );\r\n}\r\n\r\n\r\nexport function useProfilerData(): ProfilerData | null {\r\n const [data, setData] = useState<ProfilerData | null>(null);\r\n\r\n useEffect(() => {\r\n const updateData = () => {\r\n if (!monitorState.getPaused()) {\r\n const data = profiler.getData();\r\n setData(data);\r\n }\r\n };\r\n\r\n const unsubscribe = profiler.subscribe((newData) => {\r\n if (!monitorState.getPaused()) {\r\n setData(newData);\r\n }\r\n });\r\n\r\n // Mise à jour initiale\r\n updateData();\r\n\r\n // Mise à jour périodique\r\n const interval = setInterval(() => {\r\n if (profiler.isEnabled() && !monitorState.getPaused()) {\r\n updateData();\r\n }\r\n }, 100);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateData();\r\n }\r\n });\r\n\r\n return () => {\r\n unsubscribe();\r\n unsubscribePause();\r\n clearInterval(interval);\r\n };\r\n }, []);\r\n\r\n return data;\r\n}\r\n","import { useEffect, useRef, useState } from 'react';\r\nimport { useProfilerData } from './useProfiler';\r\nimport { frameTimeCollector } from '../collectors/frame-time-collector';\r\nimport { monitorState } from '../core/monitor-state';\r\n\r\nconst MAX_HISTORY_SIZE = 120; // 2 seconds at 60fps\r\n\r\nexport function useFrameHistory() {\r\n const data = useProfilerData();\r\n const [history, setHistory] = useState<number[]>([]);\r\n const lastFrameCountRef = useRef<number>(0);\r\n const intervalRef = useRef<number | null>(null);\r\n\r\n useEffect(() => {\r\n if (!data || data.frames === 0) {\r\n setHistory([]);\r\n lastFrameCountRef.current = 0;\r\n return;\r\n }\r\n\r\n const updateHistory = () => {\r\n if (monitorState.getPaused()) return;\r\n\r\n // Try to get frame time from frameTimeCollector first (most accurate)\r\n const breakdown = frameTimeCollector.getLastBreakdown();\r\n if (breakdown && breakdown.total > 0) {\r\n // Use actual frame breakdown if available\r\n // Only add if it's a new frame (check if total changed)\r\n setHistory((prev) => {\r\n const lastValue = prev.length > 0 ? prev[prev.length - 1] : null;\r\n // Only add if it's different from the last value (new frame)\r\n if (lastValue === null || Math.abs(breakdown.total - lastValue) > 0.1) {\r\n const newHistory = [...prev, breakdown.total];\r\n // Keep only the last MAX_HISTORY_SIZE frames\r\n if (newHistory.length > MAX_HISTORY_SIZE) {\r\n return newHistory.slice(-MAX_HISTORY_SIZE);\r\n }\r\n return newHistory;\r\n }\r\n return prev;\r\n });\r\n return;\r\n }\r\n\r\n // Fallback: use profiler data\r\n if (data && data.frames > 0) {\r\n const currentAvgFrameTime = data.totalTime / data.frames;\r\n \r\n // Only add if we have new frames\r\n if (data.frames > lastFrameCountRef.current) {\r\n const framesDelta = data.frames - lastFrameCountRef.current;\r\n lastFrameCountRef.current = data.frames;\r\n \r\n // Add frame time for each new frame\r\n setHistory((prev) => {\r\n const newHistory = [...prev];\r\n // Add one entry per frame (or limit to avoid spikes)\r\n const framesToAdd = Math.min(framesDelta, 10);\r\n for (let i = 0; i < framesToAdd; i++) {\r\n newHistory.push(currentAvgFrameTime);\r\n }\r\n // Keep only the last MAX_HISTORY_SIZE frames\r\n if (newHistory.length > MAX_HISTORY_SIZE) {\r\n return newHistory.slice(-MAX_HISTORY_SIZE);\r\n }\r\n return newHistory;\r\n });\r\n }\r\n }\r\n };\r\n\r\n // Update every ~16ms (60fps) to capture frame times in real-time\r\n intervalRef.current = window.setInterval(updateHistory, 16);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused && data && data.frames > 0) {\r\n // Resume: update immediately\r\n updateHistory();\r\n }\r\n });\r\n\r\n return () => {\r\n if (intervalRef.current !== null) {\r\n clearInterval(intervalRef.current);\r\n }\r\n unsubscribePause();\r\n };\r\n }, [data]);\r\n\r\n return history;\r\n}\r\n","import { useEffect, useState, useRef } from 'react';\r\nimport { frameTimeCollector, type FrameBreakdown } from '../collectors/frame-time-collector';\r\nimport { monitorState } from '../core/monitor-state';\r\n\r\nexport function useFrameTime(): FrameBreakdown | null {\r\n const [breakdown, setBreakdown] = useState<FrameBreakdown | null>(null);\r\n const intervalRef = useRef<number | null>(null);\r\n\r\n useEffect(() => {\r\n // Update breakdown periodically\r\n const updateBreakdown = () => {\r\n if (!monitorState.getPaused()) {\r\n const newBreakdown = frameTimeCollector.getLastBreakdown();\r\n if (newBreakdown) {\r\n setBreakdown(newBreakdown);\r\n }\r\n }\r\n };\r\n\r\n // Initial update\r\n updateBreakdown();\r\n\r\n // Update every 100ms (10 times per second) for real-time updates\r\n intervalRef.current = window.setInterval(updateBreakdown, 100);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateBreakdown();\r\n }\r\n });\r\n\r\n return () => {\r\n if (intervalRef.current !== null) {\r\n clearInterval(intervalRef.current);\r\n }\r\n unsubscribePause();\r\n };\r\n }, []);\r\n\r\n return breakdown;\r\n}\r\n","import { useMemo } from 'react';\r\nimport { useFrameHistory } from '../../hooks/useFrameHistory';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport interface FrameGraphProps {\r\n width?: number | string;\r\n height?: number;\r\n showGrid?: boolean;\r\n showLabels?: boolean;\r\n maxValue?: number;\r\n minValue?: number;\r\n}\r\n\r\nexport const FrameGraph = ({\r\n width = 600,\r\n height = 200,\r\n showGrid = true,\r\n showLabels = true,\r\n maxValue,\r\n minValue,\r\n}: FrameGraphProps) => {\r\n const frameHistory = useFrameHistory();\r\n const theme = defaultTheme;\r\n\r\n // Calculate actual width if percentage or use numeric value\r\n const isPercentage = typeof width === 'string' && width.includes('%');\r\n const actualWidth = isPercentage\r\n ? '100%'\r\n : typeof width === 'number'\r\n ? width\r\n : 600;\r\n\r\n const { normalizedData, chartMax, chartMin } = useMemo(() => {\r\n if (frameHistory.length === 0) {\r\n return {\r\n normalizedData: [],\r\n chartMax: 0,\r\n chartMin: 0,\r\n };\r\n }\r\n\r\n const dataMax = maxValue ?? Math.max(...frameHistory);\r\n const dataMin = minValue ?? Math.min(...frameHistory);\r\n const range = dataMax - dataMin || 1;\r\n\r\n const normalized = frameHistory.map(value => {\r\n const normalized = ((value - dataMin) / range) * height;\r\n return Math.max(0, Math.min(height, normalized));\r\n });\r\n\r\n return {\r\n normalizedData: normalized,\r\n chartMax: dataMax,\r\n chartMin: dataMin,\r\n };\r\n }, [frameHistory, maxValue, minValue, height]);\r\n\r\n if (frameHistory.length === 0) {\r\n return (\r\n <div style={{\r\n width: actualWidth,\r\n height,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n color: theme.colors.textTertiary,\r\n fontSize: theme.typography.fontSize.sm,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.md,\r\n }}>\r\n No frame data available\r\n </div>\r\n );\r\n }\r\n\r\n // Use fixed width for calculations, but responsive for display\r\n const svgWidthNum = isPercentage ? 600 : (typeof actualWidth === 'number' ? actualWidth : 600);\r\n const pointSpacing = svgWidthNum / (frameHistory.length - 1 || 1);\r\n const pathData = normalizedData\r\n .map((y, i) => {\r\n const x = i * pointSpacing;\r\n return `${i === 0 ? 'M' : 'L'} ${x} ${height - y}`;\r\n })\r\n .join(' ');\r\n\r\n const areaPath = `${pathData} L ${svgWidthNum} ${height} L 0 ${height} Z`;\r\n\r\n // Target frame time (16.67ms for 60fps)\r\n const targetFrameTime = 16.67;\r\n const targetY = height - ((targetFrameTime - chartMin) / (chartMax - chartMin || 1)) * height;\r\n\r\n const svgWidth = isPercentage ? '100%' : actualWidth;\r\n\r\n return (\r\n <div style={{ position: 'relative', width: actualWidth }}>\r\n <svg \r\n width={svgWidth} \r\n height={height} \r\n style={{ display: 'block' }}\r\n viewBox={isPercentage ? `0 0 600 ${height}` : undefined}\r\n preserveAspectRatio={isPercentage ? 'none' : undefined}\r\n >\r\n {/* Grid */}\r\n {showGrid && (\r\n <g opacity={0.2}>\r\n {[0, 0.25, 0.5, 0.75, 1].map((ratio) => {\r\n const y = height * ratio;\r\n return (\r\n <line\r\n key={ratio}\r\n x1={0}\r\n y1={y}\r\n x2={svgWidthNum}\r\n y2={y}\r\n stroke={theme.colors.border}\r\n strokeWidth={1}\r\n />\r\n );\r\n })}\r\n </g>\r\n )}\r\n\r\n {/* Target line (60 FPS) */}\r\n {targetY >= 0 && targetY <= height && (\r\n <line\r\n x1={0}\r\n y1={targetY}\r\n x2={svgWidthNum}\r\n y2={targetY}\r\n stroke={theme.colors.success}\r\n strokeWidth={2}\r\n strokeDasharray=\"4 4\"\r\n opacity={0.5}\r\n />\r\n )}\r\n\r\n {/* Area fill */}\r\n <path\r\n d={areaPath}\r\n fill={theme.colors.primary}\r\n fillOpacity={0.2}\r\n />\r\n\r\n {/* Line */}\r\n <path\r\n d={pathData}\r\n fill=\"none\"\r\n stroke={theme.colors.primary}\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n />\r\n\r\n {/* Points */}\r\n {normalizedData.map((y, i) => {\r\n const value = frameHistory[i];\r\n const isSlow = value > 16.67;\r\n return (\r\n <circle\r\n key={i}\r\n cx={i * pointSpacing}\r\n cy={height - y}\r\n r={isSlow ? 3 : 2}\r\n fill={isSlow ? theme.colors.error : theme.colors.primary}\r\n />\r\n );\r\n })}\r\n\r\n {/* Labels */}\r\n {showLabels && (\r\n <g>\r\n <text\r\n x={svgWidthNum - 4}\r\n y={12}\r\n fill={theme.colors.textSecondary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatNumber(chartMax, 2)}ms\r\n </text>\r\n <text\r\n x={svgWidthNum - 4}\r\n y={height - 4}\r\n fill={theme.colors.textSecondary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatNumber(chartMin, 2)}ms\r\n </text>\r\n {targetY >= 0 && targetY <= height && (\r\n <text\r\n x={4}\r\n y={targetY - 4}\r\n fill={theme.colors.success}\r\n fontSize={theme.typography.fontSize.xs}\r\n fontWeight={600}\r\n >\r\n 60 FPS\r\n </text>\r\n )}\r\n </g>\r\n )}\r\n </svg>\r\n </div>\r\n );\r\n};\r\n","import { useMemo } from 'react';\r\nimport { useFrameHistory } from '../../hooks/useFrameHistory';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport interface TimelineViewProps {\r\n width?: number | string;\r\n height?: number;\r\n timeWindow?: number; // seconds\r\n}\r\n\r\nexport const TimelineView = ({\r\n width = 800,\r\n height = 300,\r\n timeWindow = 10, // 10 seconds\r\n}: TimelineViewProps) => {\r\n const frameHistory = useFrameHistory();\r\n const theme = defaultTheme;\r\n\r\n // Calculate actual width if percentage or use numeric value\r\n const isPercentage = typeof width === 'string' && width.includes('%');\r\n const actualWidth = isPercentage\r\n ? '100%'\r\n : typeof width === 'number'\r\n ? width\r\n : 800;\r\n\r\n const timelineData = useMemo(() => {\r\n const now = performance.now();\r\n\r\n // Get recent frame times\r\n const recentFrames = frameHistory.slice(-Math.floor(timeWindow * 60)); // Assume 60fps max\r\n\r\n // Normalize data to timeline\r\n const normalized = recentFrames.map((frameTime, index) => {\r\n const timestamp = now - ((recentFrames.length - index) * (1000 / 60)); // Estimate timestamp\r\n return {\r\n timestamp,\r\n frameTime,\r\n fps: frameTime > 0 ? 1000 / frameTime : 0,\r\n };\r\n });\r\n\r\n return normalized;\r\n }, [frameHistory, timeWindow]);\r\n\r\n if (timelineData.length === 0) {\r\n return (\r\n <div style={{\r\n width: actualWidth,\r\n height,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n color: theme.colors.textTertiary,\r\n fontSize: theme.typography.fontSize.sm,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.md,\r\n backgroundColor: theme.colors.surface,\r\n }}>\r\n No timeline data available\r\n </div>\r\n );\r\n }\r\n\r\n // Calculate scales\r\n const frameTimeMax = Math.max(...timelineData.map(d => d.frameTime), 50);\r\n const frameTimeMin = Math.min(...timelineData.map(d => d.frameTime), 0);\r\n const fpsMax = Math.max(...timelineData.map(d => d.fps), 60);\r\n const fpsMin = Math.min(...timelineData.map(d => d.fps), 0);\r\n\r\n const chartHeight = height / 2;\r\n const svgWidthNum = isPercentage ? 800 : (typeof actualWidth === 'number' ? actualWidth : 800); // Use fixed width for calculations\r\n const pointSpacing = svgWidthNum / (timelineData.length - 1 || 1);\r\n\r\n // Frame time path\r\n const frameTimePath = timelineData\r\n .map((d, i) => {\r\n const y = chartHeight - ((d.frameTime - frameTimeMin) / (frameTimeMax - frameTimeMin || 1)) * chartHeight;\r\n const x = i * pointSpacing;\r\n return `${i === 0 ? 'M' : 'L'} ${x} ${y}`;\r\n })\r\n .join(' ');\r\n\r\n // FPS path\r\n const fpsPath = timelineData\r\n .map((d, i) => {\r\n const y = chartHeight - ((d.fps - fpsMin) / (fpsMax - fpsMin || 1)) * chartHeight;\r\n const x = i * pointSpacing;\r\n return `${i === 0 ? 'M' : 'L'} ${x} ${y + chartHeight}`;\r\n })\r\n .join(' ');\r\n\r\n // For percentage width, we need to use a container approach\r\n const svgWidth = isPercentage ? '100%' : actualWidth;\r\n\r\n return (\r\n <div style={{\r\n width: actualWidth,\r\n height,\r\n backgroundColor: 'transparent',\r\n borderRadius: theme.borderRadius.md,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Timeline ({timeWindow}s window)\r\n </div>\r\n <div style={{\r\n width: '100%',\r\n height,\r\n position: 'relative',\r\n overflow: 'hidden',\r\n }}>\r\n <svg width={svgWidth} height={height} style={{ display: 'block' }} viewBox={isPercentage ? `0 0 800 ${height}` : undefined} preserveAspectRatio={isPercentage ? 'none' : undefined}>\r\n {/* Grid */}\r\n <g opacity={0.1}>\r\n {[0, 0.25, 0.5, 0.75, 1].map((ratio) => {\r\n const y = height * ratio;\r\n return (\r\n <line\r\n key={ratio}\r\n x1={0}\r\n y1={y}\r\n x2={svgWidthNum}\r\n y2={y}\r\n stroke={theme.colors.border}\r\n strokeWidth={1}\r\n />\r\n );\r\n })}\r\n </g>\r\n\r\n {/* Divider line */}\r\n <line\r\n x1={0}\r\n y1={chartHeight}\r\n x2={svgWidthNum}\r\n y2={chartHeight}\r\n stroke={theme.colors.border}\r\n strokeWidth={2}\r\n />\r\n\r\n {/* Frame Time Chart */}\r\n <g>\r\n <text\r\n x={4}\r\n y={12}\r\n fill={theme.colors.textSecondary}\r\n fontSize={theme.typography.fontSize.xs}\r\n fontWeight={600}\r\n >\r\n Frame Time (ms)\r\n </text>\r\n <path\r\n d={frameTimePath}\r\n fill=\"none\"\r\n stroke={theme.colors.error}\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n />\r\n {/* Target line (16.67ms) */}\r\n <line\r\n x1={0}\r\n y1={chartHeight - ((16.67 - frameTimeMin) / (frameTimeMax - frameTimeMin || 1)) * chartHeight}\r\n x2={svgWidthNum}\r\n y2={chartHeight - ((16.67 - frameTimeMin) / (frameTimeMax - frameTimeMin || 1)) * chartHeight}\r\n stroke={theme.colors.success}\r\n strokeWidth={1}\r\n strokeDasharray=\"2 2\"\r\n opacity={0.5}\r\n />\r\n </g>\r\n\r\n {/* FPS Chart */}\r\n <g>\r\n <text\r\n x={4}\r\n y={chartHeight + 12}\r\n fill={theme.colors.textSecondary}\r\n fontSize={theme.typography.fontSize.xs}\r\n fontWeight={600}\r\n >\r\n FPS\r\n </text>\r\n <path\r\n d={fpsPath}\r\n fill=\"none\"\r\n stroke={theme.colors.success}\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n />\r\n {/* Target line (60 FPS) */}\r\n <line\r\n x1={0}\r\n y1={chartHeight + chartHeight - ((60 - fpsMin) / (fpsMax - fpsMin || 1)) * chartHeight}\r\n x2={svgWidthNum}\r\n y2={chartHeight + chartHeight - ((60 - fpsMin) / (fpsMax - fpsMin || 1)) * chartHeight}\r\n stroke={theme.colors.success}\r\n strokeWidth={1}\r\n strokeDasharray=\"2 2\"\r\n opacity={0.5}\r\n />\r\n </g>\r\n\r\n {/* Labels */}\r\n <g>\r\n <text\r\n x={svgWidthNum - 4}\r\n y={12}\r\n fill={theme.colors.textTertiary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatNumber(frameTimeMax, 1)}ms\r\n </text>\r\n <text\r\n x={svgWidthNum - 4}\r\n y={chartHeight - 4}\r\n fill={theme.colors.textTertiary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatNumber(frameTimeMin, 1)}ms\r\n </text>\r\n <text\r\n x={svgWidthNum - 4}\r\n y={chartHeight + 12}\r\n fill={theme.colors.textTertiary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatNumber(fpsMax, 0)} FPS\r\n </text>\r\n <text\r\n x={svgWidthNum - 4}\r\n y={height - 4}\r\n fill={theme.colors.textTertiary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatNumber(fpsMin, 0)} FPS\r\n </text>\r\n </g>\r\n </svg>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import { useState, useEffect } from 'react';\r\nimport { memoryCollector } from '../collectors/memory-collector';\r\nimport { monitorState } from '../core/monitor-state';\r\nimport type { MemoryStats } from '../collectors/memory-collector';\r\n\r\nconst MAX_HISTORY_SIZE = 120; // 2 minutes at 1 sample/sec\r\n\r\nexport function useMemoryHistory(): Array<MemoryStats & { time: number }> {\r\n const [history, setHistory] = useState<Array<MemoryStats & { time: number }>>([]);\r\n\r\n useEffect(() => {\r\n const updateHistory = () => {\r\n if (!monitorState.getPaused()) {\r\n const stats = memoryCollector.getStats();\r\n if (stats) {\r\n setHistory(prev => {\r\n const newHistory = [...prev, { ...stats, time: Date.now() }];\r\n // Keep only last MAX_HISTORY_SIZE entries\r\n return newHistory.slice(-MAX_HISTORY_SIZE);\r\n });\r\n }\r\n }\r\n };\r\n\r\n // Initial update\r\n updateHistory();\r\n\r\n // Update every second\r\n const interval = setInterval(updateHistory, 1000);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateHistory();\r\n }\r\n });\r\n\r\n return () => {\r\n clearInterval(interval);\r\n unsubscribePause();\r\n };\r\n }, []);\r\n\r\n return history;\r\n}\r\n","import { useMemo } from 'react';\r\nimport { useMemoryHistory } from '../../hooks/useMemoryHistory';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport interface MemoryChartProps {\r\n width?: number | string;\r\n height?: number;\r\n showGrid?: boolean;\r\n showLabels?: boolean;\r\n timeWindow?: number; // seconds\r\n metric?: 'jsHeap' | 'gpuMemory' | 'both';\r\n}\r\n\r\nexport const MemoryChart = ({\r\n width = '100%',\r\n height = 200,\r\n showGrid = true,\r\n showLabels = true,\r\n timeWindow = 60, // 60 seconds default\r\n metric = 'both',\r\n}: MemoryChartProps) => {\r\n const memoryHistory = useMemoryHistory();\r\n const theme = defaultTheme;\r\n\r\n const chartData = useMemo(() => {\r\n const now = Date.now();\r\n const cutoff = now - timeWindow * 1000;\r\n \r\n // Filter recent data\r\n const recent = memoryHistory.filter(entry => entry.time >= cutoff);\r\n \r\n if (recent.length === 0) {\r\n return {\r\n jsHeapData: [],\r\n gpuMemoryData: [],\r\n maxValue: 0,\r\n minValue: 0,\r\n };\r\n }\r\n\r\n const jsHeapData = recent.map(entry => entry.jsHeap.used);\r\n const gpuMemoryData = recent.map(entry => entry.gpuMemory.total);\r\n \r\n const allValues = [...jsHeapData, ...gpuMemoryData].filter(v => v > 0);\r\n const maxValue = allValues.length > 0 ? Math.max(...allValues) : 0;\r\n const minValue = allValues.length > 0 ? Math.min(...allValues) : 0;\r\n\r\n return {\r\n jsHeapData,\r\n gpuMemoryData,\r\n maxValue: maxValue || 1,\r\n minValue,\r\n };\r\n }, [memoryHistory, timeWindow]);\r\n\r\n if (chartData.jsHeapData.length === 0 && chartData.gpuMemoryData.length === 0) {\r\n return (\r\n <div style={{\r\n width,\r\n height,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n color: theme.colors.textTertiary,\r\n fontSize: theme.typography.fontSize.sm,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.md,\r\n backgroundColor: theme.colors.surface,\r\n }}>\r\n No memory data available\r\n </div>\r\n );\r\n }\r\n\r\n const internalWidth = 800;\r\n const pointSpacing = internalWidth / (Math.max(chartData.jsHeapData.length, chartData.gpuMemoryData.length) - 1 || 1);\r\n const range = chartData.maxValue - chartData.minValue || 1;\r\n\r\n // JS Heap path\r\n const jsHeapPath = chartData.jsHeapData\r\n .map((value, i) => {\r\n const y = height - ((value - chartData.minValue) / range) * height;\r\n const x = i * pointSpacing;\r\n return `${i === 0 ? 'M' : 'L'} ${x} ${y}`;\r\n })\r\n .join(' ');\r\n\r\n // GPU Memory path\r\n const gpuMemoryPath = chartData.gpuMemoryData\r\n .map((value, i) => {\r\n const y = height - ((value - chartData.minValue) / range) * height;\r\n const x = i * pointSpacing;\r\n return `${i === 0 ? 'M' : 'L'} ${x} ${y}`;\r\n })\r\n .join(' ');\r\n\r\n const formatBytes = (bytes: number): string => {\r\n if (bytes < 1024) return `${formatNumber(bytes, 0)} B`;\r\n if (bytes < 1024 * 1024) return `${formatNumber(bytes / 1024, 1)} KB`;\r\n if (bytes < 1024 * 1024 * 1024) return `${formatNumber(bytes / (1024 * 1024), 1)} MB`;\r\n return `${formatNumber(bytes / (1024 * 1024 * 1024), 2)} GB`;\r\n };\r\n\r\n return (\r\n <div style={{ position: 'relative', width, height }}>\r\n <svg width=\"100%\" height={height} viewBox={`0 0 ${internalWidth} ${height}`} preserveAspectRatio=\"none\" style={{ display: 'block' }}>\r\n {showGrid && (\r\n <g opacity={0.2}>\r\n {[0, 0.25, 0.5, 0.75, 1].map((ratio) => {\r\n const y = height * ratio;\r\n return (\r\n <line\r\n key={ratio}\r\n x1={0}\r\n y1={y}\r\n x2={internalWidth}\r\n y2={y}\r\n stroke={theme.colors.border}\r\n strokeWidth={1}\r\n />\r\n );\r\n })}\r\n </g>\r\n )}\r\n\r\n {/* JS Heap Area */}\r\n {metric === 'jsHeap' || metric === 'both' ? (\r\n <>\r\n <path\r\n d={`${jsHeapPath} L ${internalWidth} ${height} L 0 ${height} Z`}\r\n fill={theme.colors.primary}\r\n fillOpacity={0.1}\r\n />\r\n <path\r\n d={jsHeapPath}\r\n fill=\"none\"\r\n stroke={theme.colors.primary}\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n />\r\n </>\r\n ) : null}\r\n\r\n {/* GPU Memory Area */}\r\n {metric === 'gpuMemory' || metric === 'both' ? (\r\n <>\r\n <path\r\n d={`${gpuMemoryPath} L ${internalWidth} ${height} L 0 ${height} Z`}\r\n fill={theme.colors.accent}\r\n fillOpacity={0.1}\r\n />\r\n <path\r\n d={gpuMemoryPath}\r\n fill=\"none\"\r\n stroke={theme.colors.accent}\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n />\r\n </>\r\n ) : null}\r\n\r\n {showLabels && (\r\n <g>\r\n <text\r\n x={internalWidth - 4}\r\n y={12}\r\n fill={theme.colors.textSecondary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatBytes(chartData.maxValue)}\r\n </text>\r\n <text\r\n x={internalWidth - 4}\r\n y={height - 4}\r\n fill={theme.colors.textSecondary}\r\n fontSize={theme.typography.fontSize.xs}\r\n textAnchor=\"end\"\r\n >\r\n {formatBytes(chartData.minValue)}\r\n </text>\r\n {metric === 'both' && (\r\n <>\r\n <text\r\n x={4}\r\n y={12}\r\n fill={theme.colors.primary}\r\n fontSize={theme.typography.fontSize.xs}\r\n >\r\n JS Heap\r\n </text>\r\n <text\r\n x={4}\r\n y={height - 4}\r\n fill={theme.colors.accent}\r\n fontSize={theme.typography.fontSize.xs}\r\n >\r\n GPU Memory\r\n </text>\r\n </>\r\n )}\r\n </g>\r\n )}\r\n </svg>\r\n </div>\r\n );\r\n};\r\n","import { useMemo } from 'react';\r\nimport { useProfilerData } from '../../hooks/useProfiler';\r\nimport { useFrameHistory } from '../../hooks/useFrameHistory';\r\nimport { useFrameTime } from '../../hooks/useFrameTime';\r\nimport { MetricCard } from '../components';\r\nimport { FrameGraph, TimelineView } from '../visualizations';\r\nimport { defaultTheme, getPerformanceColor, formatNumber } from '../styles/theme';\r\n\r\nexport const FramePanel = () => {\r\n const data = useProfilerData();\r\n const frameHistory = useFrameHistory();\r\n const breakdown = useFrameTime();\r\n const theme = defaultTheme;\r\n\r\n // All hooks must be called before any conditional returns\r\n const sortedEntries = useMemo(() => {\r\n if (!data || !data.entries) return [];\r\n return [...data.entries].sort((a, b) => b.total - a.total);\r\n }, [data]);\r\n\r\n // Calculate real FPS and Frame Time\r\n const interval = useMemo(() => {\r\n if (breakdown) return breakdown.interval || breakdown.total;\r\n if (!data || data.totalTime || data.frames === 0) return 0;\r\n return data.totalTime / data.frames;\r\n }, [breakdown, data]);\r\n\r\n const processingTime = useMemo(() => {\r\n if (breakdown) return breakdown.total;\r\n if (!data || data.frames === 0) return 0;\r\n return data.totalTime / data.frames;\r\n }, [breakdown, data]);\r\n\r\n const fps = useMemo(() => {\r\n if (interval > 0) return 1000 / interval;\r\n return 0;\r\n }, [interval]);\r\n\r\n const frameTimeStatus = useMemo(() => {\r\n // Check processing time against budget (16ms)\r\n if (processingTime <= 16.67) return 'good';\r\n if (processingTime <= 33.33) return 'warning';\r\n return 'error';\r\n }, [processingTime]);\r\n\r\n // Use real frame history or fallback to current frame time\r\n const frameTimeHistory = useMemo(() => {\r\n if (frameHistory.length > 0) {\r\n return frameHistory;\r\n }\r\n // Fallback: show current processing time\r\n return processingTime > 0 ? [processingTime] : [];\r\n }, [frameHistory, processingTime]);\r\n\r\n // Max frame time for graph\r\n const maxFrameTime = useMemo(() => {\r\n if (frameTimeHistory.length === 0) return 33; // Default to ~30fps scale\r\n return Math.max(...frameTimeHistory, 20);\r\n }, [frameTimeHistory]);\r\n\r\n // Now we can do conditional rendering\r\n if (!data || data.entries.length === 0) {\r\n return (\r\n <div style={{\r\n padding: theme.spacing.lg,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Aucune donnée profilée pour le moment.\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* Key Metrics */}\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n gap: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n }}>\r\n <MetricCard\r\n label=\"FPS\"\r\n value={formatNumber(fps, 1)}\r\n status={fps >= 60 ? 'good' : fps >= 30 ? 'warning' : 'error'}\r\n />\r\n <MetricCard\r\n label=\"Frame Time\"\r\n value={formatNumber(processingTime, 2)}\r\n unit=\"ms\"\r\n status={frameTimeStatus as 'good' | 'warning' | 'error'}\r\n />\r\n <MetricCard\r\n label=\"Total Time\"\r\n value={formatNumber(data.totalTime, 2)}\r\n unit=\"ms\"\r\n />\r\n <MetricCard\r\n label=\"Frames\"\r\n value={data.frames}\r\n />\r\n </div>\r\n\r\n {/* Frame Time Chart */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n overflow: 'hidden',\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Frame Time History\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n {frameTimeHistory.length} frames\r\n </div>\r\n </div>\r\n <FrameGraph\r\n width=\"100%\"\r\n height={100}\r\n showGrid={true}\r\n showLabels={true}\r\n maxValue={maxFrameTime}\r\n />\r\n <div style={{\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n marginTop: theme.spacing.xs,\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textTertiary,\r\n }}>\r\n <div>Target: <16.67ms (60 FPS)</div>\r\n <div style={{\r\n color: getPerformanceColor(processingTime, { good: 16.67, warning: 33.33 }),\r\n }}>\r\n Current: {formatNumber(processingTime, 2)}ms (work)\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Timeline View */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n overflow: 'hidden',\r\n }}>\r\n <TimelineView width=\"100%\" height={200} timeWindow={10} />\r\n </div>\r\n\r\n {/* Entries Table */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n overflow: 'hidden',\r\n }}>\r\n <table style={{\r\n width: '100%',\r\n borderCollapse: 'collapse',\r\n }}>\r\n <thead>\r\n <tr style={{\r\n backgroundColor: theme.colors.surfaceElevated,\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <th style={{\r\n textAlign: 'left',\r\n padding: theme.spacing.md,\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}>\r\n Hook\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}>\r\n Total (ms)\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}>\r\n Avg (ms)\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}>\r\n Max (ms)\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}>\r\n %\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {sortedEntries.map((entry, index) => {\r\n const entryColor = getPerformanceColor(entry.avg, { good: 5, warning: 10 });\r\n return (\r\n <tr\r\n key={entry.name}\r\n style={{\r\n borderBottom: index < sortedEntries.length - 1 ? `1px solid ${theme.colors.borderLight}` : 'none',\r\n transition: theme.transitions.fast,\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = theme.colors.surfaceElevated;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'transparent';\r\n }}\r\n >\r\n <td style={{\r\n padding: theme.spacing.md,\r\n color: theme.colors.text,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n {entry.name}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: theme.colors.text,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n {formatNumber(entry.total, 2)}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: entryColor,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}>\r\n {formatNumber(entry.avg, 3)}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: theme.colors.text,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n {formatNumber(entry.max, 3)}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.md,\r\n color: theme.colors.textSecondary,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n {formatNumber(entry.percentage, 1)}%\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import { useEffect, useState, useRef } from 'react';\r\nimport { gpuCollector, type GPUStats } from '../collectors/gpu-collector';\r\nimport { monitorState } from '../core/monitor-state';\r\n\r\nexport function useGPUStats(): GPUStats | null {\r\n const [stats, setStats] = useState<GPUStats | null>(null);\r\n const intervalRef = useRef<number | null>(null);\r\n\r\n useEffect(() => {\r\n // Update stats periodically\r\n const updateStats = () => {\r\n if (!monitorState.getPaused()) {\r\n const newStats = gpuCollector.getStats();\r\n if (newStats) {\r\n setStats(newStats);\r\n }\r\n }\r\n };\r\n\r\n // Initial update\r\n updateStats();\r\n\r\n // Update every 100ms (10 times per second)\r\n intervalRef.current = window.setInterval(updateStats, 100);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateStats();\r\n }\r\n });\r\n\r\n return () => {\r\n if (intervalRef.current !== null) {\r\n clearInterval(intervalRef.current);\r\n }\r\n unsubscribePause();\r\n };\r\n }, []);\r\n\r\n return stats;\r\n}\r\n","import { useMemo } from 'react';\r\nimport { useGPUStats } from '../../hooks/useGPUStats';\r\nimport { MetricCard } from '../components';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport const GPUPanel = () => {\r\n const stats = useGPUStats();\r\n const theme = defaultTheme;\r\n\r\n const drawCallsStatus = useMemo(() => {\r\n if (!stats) return 'neutral';\r\n if (stats.drawCalls <= 100) return 'good';\r\n if (stats.drawCalls <= 500) return 'warning';\r\n return 'error';\r\n }, [stats]);\r\n\r\n const trianglesStatus = useMemo(() => {\r\n if (!stats) return 'neutral';\r\n if (stats.triangles <= 100000) return 'good';\r\n if (stats.triangles <= 500000) return 'warning';\r\n return 'error';\r\n }, [stats]);\r\n\r\n if (!stats) {\r\n return (\r\n <div style={{\r\n padding: theme.spacing.lg,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Aucune donnée GPU disponible. Assurez-vous que le composant est à l'intérieur d'un Canvas R3F.\r\n </div>\r\n );\r\n }\r\n\r\n const formatBytes = (bytes: number): string => {\r\n if (bytes === 0) return '0 B';\r\n if (bytes < 1024) return `${formatNumber(bytes, 0)} B`;\r\n if (bytes < 1024 * 1024) return `${formatNumber(bytes / 1024, 2)} KB`;\r\n return `${formatNumber(bytes / (1024 * 1024), 2)} MB`;\r\n };\r\n\r\n // Note: GPU memory values are estimates based on object counts\r\n // Three.js doesn't expose exact memory usage\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* Key Metrics */}\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n gap: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n }}>\r\n <MetricCard\r\n label=\"Draw Calls\"\r\n value={stats.drawCalls.toLocaleString()}\r\n status={drawCallsStatus as 'good' | 'warning' | 'error'}\r\n />\r\n <MetricCard\r\n label=\"Triangles\"\r\n value={stats.triangles.toLocaleString()}\r\n status={trianglesStatus as 'good' | 'warning' | 'error'}\r\n />\r\n <MetricCard\r\n label=\"Points\"\r\n value={stats.points.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Lines\"\r\n value={stats.lines.toLocaleString()}\r\n />\r\n </div>\r\n\r\n {/* Memory Section */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.md,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n GPU Memory\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\r\n gap: theme.spacing.md,\r\n }}>\r\n <MetricCard\r\n label=\"Textures\"\r\n value={formatBytes(stats.memory.textures)}\r\n />\r\n <MetricCard\r\n label=\"Geometries\"\r\n value={formatBytes(stats.memory.geometries)}\r\n />\r\n <MetricCard\r\n label=\"Programs\"\r\n value={formatBytes(stats.memory.programs)}\r\n />\r\n <MetricCard\r\n label=\"Total\"\r\n value={formatBytes(stats.memory.total)}\r\n color={stats.memory.total > 100 * 1024 * 1024 ? theme.colors.warning : theme.colors.success}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Resources Section */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.md,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n Resources\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\r\n gap: theme.spacing.md,\r\n }}>\r\n <MetricCard\r\n label=\"Textures\"\r\n value={stats.textures}\r\n />\r\n <MetricCard\r\n label=\"Geometries\"\r\n value={stats.geometries}\r\n />\r\n <MetricCard\r\n label=\"Programs\"\r\n value={stats.programs}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import { useEffect, useState, useRef } from 'react';\r\nimport { sceneCollector, type SceneStats } from '../collectors/scene-collector';\r\nimport { monitorState } from '../core/monitor-state';\r\n\r\nexport function useSceneStats(): SceneStats | null {\r\n const [stats, setStats] = useState<SceneStats | null>(null);\r\n const intervalRef = useRef<number | null>(null);\r\n\r\n useEffect(() => {\r\n // Update stats periodically\r\n const updateStats = () => {\r\n if (!monitorState.getPaused()) {\r\n const newStats = sceneCollector.getStats();\r\n if (newStats) {\r\n setStats(newStats);\r\n }\r\n }\r\n };\r\n\r\n // Initial update\r\n updateStats();\r\n\r\n // Update every 500ms (2 times per second) - scene stats don't change as frequently\r\n intervalRef.current = window.setInterval(updateStats, 500);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateStats();\r\n }\r\n });\r\n\r\n return () => {\r\n if (intervalRef.current !== null) {\r\n clearInterval(intervalRef.current);\r\n }\r\n unsubscribePause();\r\n };\r\n }, []);\r\n\r\n return stats;\r\n}\r\n","import { useSceneStats } from '../../hooks/useSceneStats';\r\nimport { MetricCard } from '../components';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport const ScenePanel = () => {\r\n const stats = useSceneStats();\r\n const theme = defaultTheme;\r\n\r\n if (!stats) {\r\n return (\r\n <div style={{\r\n padding: theme.spacing.lg,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Aucune donnée de scène disponible. Assurez-vous que le composant est à l'intérieur d'un Canvas R3F.\r\n </div>\r\n );\r\n }\r\n\r\n const formatBytes = (bytes: number): string => {\r\n if (bytes < 1024) return `${formatNumber(bytes, 0)} B`;\r\n if (bytes < 1024 * 1024) return `${formatNumber(bytes / 1024, 2)} KB`;\r\n return `${formatNumber(bytes / (1024 * 1024), 2)} MB`;\r\n };\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* Objects Section */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.md,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n Objects\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\r\n gap: theme.spacing.md,\r\n }}>\r\n <MetricCard\r\n label=\"Total\"\r\n value={stats.objects.total.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Meshes\"\r\n value={stats.objects.meshes.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Lights\"\r\n value={stats.objects.lights.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Cameras\"\r\n value={stats.objects.cameras.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Groups\"\r\n value={stats.objects.groups.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Visible\"\r\n value={stats.visible.total.toLocaleString()}\r\n color={stats.visible.total === stats.objects.total ? theme.colors.success : theme.colors.warning}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Materials Section */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.md,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n Materials ({stats.materials.total})\r\n </div>\r\n <div style={{\r\n display: 'flex',\r\n flexWrap: 'wrap',\r\n gap: theme.spacing.sm,\r\n }}>\r\n {Object.entries(stats.materials.byType).map(([type, count]) => (\r\n <div\r\n key={type}\r\n style={{\r\n backgroundColor: theme.colors.surfaceElevated,\r\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\r\n borderRadius: theme.borderRadius.sm,\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}\r\n >\r\n {type}: {count}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Textures Section */}\r\n {stats.textures.total > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.md,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n Textures\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n gap: theme.spacing.md,\r\n }}>\r\n <MetricCard\r\n label=\"Total\"\r\n value={stats.textures.total.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Total Size\"\r\n value={formatBytes(stats.textures.totalSize)}\r\n />\r\n {stats.textures.environment > 0 && (\r\n <MetricCard\r\n label=\"Environment\"\r\n value={stats.textures.environment.toLocaleString()}\r\n color={theme.colors.info}\r\n />\r\n )}\r\n {stats.textures.system > 0 && (\r\n <MetricCard\r\n label=\"System\"\r\n value={stats.textures.system.toLocaleString()}\r\n color={theme.colors.warning}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Geometries Section */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.md,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n Geometries\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n gap: theme.spacing.md,\r\n }}>\r\n <MetricCard\r\n label=\"Total\"\r\n value={stats.geometries.total.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Vertices\"\r\n value={stats.geometries.vertices.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Faces\"\r\n value={stats.geometries.faces.toLocaleString()}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Complexity Section */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.md,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n Complexity\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n gap: theme.spacing.md,\r\n }}>\r\n <MetricCard\r\n label=\"Avg Vertices/Mesh\"\r\n value={formatNumber(stats.complexity.averageVerticesPerMesh, 0)}\r\n />\r\n <MetricCard\r\n label=\"Avg Faces/Mesh\"\r\n value={formatNumber(stats.complexity.averageFacesPerMesh, 0)}\r\n />\r\n <MetricCard\r\n label=\"Est. Draw Calls\"\r\n value={stats.complexity.totalDrawCalls.toLocaleString()}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import { useEffect, useState, useRef } from 'react';\r\nimport { memoryCollector, type MemoryStats } from '../collectors/memory-collector';\r\nimport { monitorState } from '../core/monitor-state';\r\n\r\nexport function useMemoryStats(): MemoryStats | null {\r\n const [stats, setStats] = useState<MemoryStats | null>(null);\r\n const intervalRef = useRef<number | null>(null);\r\n\r\n useEffect(() => {\r\n // Update stats periodically\r\n const updateStats = () => {\r\n if (!monitorState.getPaused()) {\r\n const newStats = memoryCollector.getStats();\r\n if (newStats) {\r\n setStats(newStats);\r\n }\r\n }\r\n };\r\n\r\n // Initial update\r\n updateStats();\r\n\r\n // Update every second (memory doesn't change as frequently as GPU stats)\r\n intervalRef.current = window.setInterval(updateStats, 1000);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateStats();\r\n }\r\n });\r\n\r\n return () => {\r\n if (intervalRef.current !== null) {\r\n clearInterval(intervalRef.current);\r\n }\r\n unsubscribePause();\r\n };\r\n }, []);\r\n\r\n return stats;\r\n}\r\n","import { useMemo } from 'react';\r\nimport { useMemoryStats } from '../../hooks/useMemoryStats';\r\nimport { MetricCard } from '../components';\r\nimport { MemoryChart } from '../visualizations/MemoryChart';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport const MemoryPanel = () => {\r\n const stats = useMemoryStats();\r\n const theme = defaultTheme;\r\n\r\n const formatBytes = (bytes: number): string => {\r\n if (bytes === 0) return '0 B';\r\n if (bytes < 1024) return `${formatNumber(bytes, 0)} B`;\r\n if (bytes < 1024 * 1024) return `${formatNumber(bytes / 1024, 2)} KB`;\r\n if (bytes < 1024 * 1024 * 1024) return `${formatNumber(bytes / (1024 * 1024), 2)} MB`;\r\n return `${formatNumber(bytes / (1024 * 1024 * 1024), 2)} GB`;\r\n };\r\n\r\n const jsHeapStatus = useMemo(() => {\r\n if (!stats) return 'neutral';\r\n const percentage = stats.jsHeap.percentage;\r\n if (percentage < 50) return 'good';\r\n if (percentage < 80) return 'warning';\r\n return 'error';\r\n }, [stats]);\r\n\r\n const leakStatus = useMemo(() => {\r\n if (!stats) return 'neutral';\r\n if (!stats.leaks.detected) return 'good';\r\n return 'error';\r\n }, [stats]);\r\n\r\n if (!stats) {\r\n return (\r\n <div style={{\r\n padding: theme.spacing.lg,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Aucune donnée de mémoire disponible. Les stats de mémoire JS nécessitent Chrome.\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* JS Heap Memory Section */}\r\n {stats.jsHeap.limit > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n JavaScript Heap Memory\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n gap: theme.spacing.md,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n <MetricCard\r\n label=\"Used\"\r\n value={formatBytes(stats.jsHeap.used)}\r\n status={jsHeapStatus as 'good' | 'warning' | 'error'}\r\n />\r\n <MetricCard\r\n label=\"Total\"\r\n value={formatBytes(stats.jsHeap.total)}\r\n />\r\n <MetricCard\r\n label=\"Limit\"\r\n value={formatBytes(stats.jsHeap.limit)}\r\n />\r\n <MetricCard\r\n label=\"Usage\"\r\n value={`${formatNumber(stats.jsHeap.percentage, 1)}%`}\r\n status={jsHeapStatus as 'good' | 'warning' | 'error'}\r\n />\r\n </div>\r\n {/* Usage Bar */}\r\n <div style={{\r\n width: '100%',\r\n height: '8px',\r\n backgroundColor: theme.colors.border,\r\n borderRadius: theme.borderRadius.sm,\r\n overflow: 'hidden',\r\n marginTop: theme.spacing.sm,\r\n }}>\r\n <div style={{\r\n width: `${Math.min(100, stats.jsHeap.percentage)}%`,\r\n height: '100%',\r\n backgroundColor: (() => {\r\n if (stats.jsHeap.percentage <= 50) return theme.colors.success;\r\n if (stats.jsHeap.percentage <= 80) return theme.colors.warning;\r\n return theme.colors.error;\r\n })(),\r\n transition: theme.transitions.normal,\r\n }} />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* GPU Memory Section */}\r\n {stats.gpuMemory.total > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n GPU Memory (Estimated)\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\r\n gap: theme.spacing.sm,\r\n }}>\r\n <MetricCard\r\n label=\"Textures\"\r\n value={formatBytes(stats.gpuMemory.textures)}\r\n />\r\n <MetricCard\r\n label=\"Geometries\"\r\n value={formatBytes(stats.gpuMemory.geometries)}\r\n />\r\n <MetricCard\r\n label=\"Total\"\r\n value={formatBytes(stats.gpuMemory.total)}\r\n />\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textTertiary,\r\n marginTop: theme.spacing.sm,\r\n }}>\r\n Note: GPU memory is an estimation based on resource counts. Actual usage may vary.\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Memory Evolution Chart */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n overflow: 'hidden',\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Memory Evolution (Last 60s)\r\n </div>\r\n <MemoryChart\r\n width=\"100%\"\r\n height={150}\r\n timeWindow={60}\r\n metric=\"both\"\r\n showGrid={true}\r\n showLabels={true}\r\n />\r\n </div>\r\n\r\n {/* Memory Leak Detection */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Memory Leak Detection\r\n </div>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n <div style={{\r\n width: '12px',\r\n height: '12px',\r\n borderRadius: '50%',\r\n backgroundColor: leakStatus === 'good' ? theme.colors.success : theme.colors.error,\r\n }} />\r\n <div style={{\r\n color: theme.colors.text,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n {stats.leaks.detected ? 'Potential leak detected' : 'No leaks detected'}\r\n </div>\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n <div>Growth Rate: {formatBytes(Math.abs(stats.leaks.growthRate))}/s</div>\r\n <div>Trend: {stats.leaks.trend}</div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import { useMemo } from 'react';\r\nimport { useFrameTime } from '../../hooks/useFrameTime';\r\nimport { MetricCard } from '../components';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport const FrameTimePanel = () => {\r\n const breakdown = useFrameTime();\r\n const theme = defaultTheme;\r\n\r\n const formatTime = (ms: number): string => {\r\n if (ms < 0.1) return `${formatNumber(ms * 1000, 0)} μs`;\r\n if (ms < 1) return `${formatNumber(ms, 2)} ms`;\r\n return `${formatNumber(ms, 2)} ms`;\r\n };\r\n\r\n const formatPercentage = (value: number, total: number): string => {\r\n if (total === 0) return '0%';\r\n return `${formatNumber((value / total) * 100, 1)}%`;\r\n };\r\n\r\n const frameTimeStatus = useMemo(() => {\r\n if (!breakdown) return 'neutral';\r\n // 60 FPS = 16.67ms per frame\r\n if (breakdown.total <= 16.67) return 'good';\r\n if (breakdown.total <= 33.33) return 'warning'; // 30 FPS\r\n return 'error';\r\n }, [breakdown]);\r\n\r\n if (!breakdown) {\r\n return (\r\n <div style={{\r\n padding: theme.spacing.lg,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Aucune donnée de breakdown de frame disponible. Le frame breakdown nécessite une instrumentation du code.\r\n </div>\r\n );\r\n }\r\n\r\n const phases = [\r\n { name: 'React', value: breakdown.phases.react, color: theme.colors.primary },\r\n { name: 'Update', value: breakdown.phases.update, color: theme.colors.info },\r\n { name: 'Physics', value: breakdown.phases.physics, color: theme.colors.warning },\r\n { name: 'Render', value: breakdown.phases.render, color: theme.colors.success },\r\n { name: 'Post-Process', value: breakdown.phases.postProcess, color: theme.colors.accent },\r\n { name: 'Other', value: breakdown.phases.other, color: theme.colors.textSecondary },\r\n ].filter(phase => phase.value > 0);\r\n\r\n const maxPhaseValue = Math.max(...phases.map(p => p.value), breakdown.total);\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* Total Frame Time */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Total Frame Time\r\n </div>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'baseline',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n <MetricCard\r\n label=\"Frame Time\"\r\n value={formatTime(breakdown.total)}\r\n status={frameTimeStatus as 'good' | 'warning' | 'error'}\r\n />\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n ({formatNumber(1000 / breakdown.total, 1)} FPS)\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Phase Breakdown */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Phase Breakdown\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n {phases.map((phase) => (\r\n <MetricCard\r\n key={phase.name}\r\n label={phase.name}\r\n value={formatTime(phase.value)}\r\n />\r\n ))}\r\n </div>\r\n\r\n {/* Waterfall Chart */}\r\n <div style={{\r\n marginTop: theme.spacing.md,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Timeline (Waterfall)\r\n </div>\r\n <div style={{\r\n position: 'relative',\r\n height: '200px',\r\n backgroundColor: theme.colors.background,\r\n borderRadius: theme.borderRadius.sm,\r\n border: `1px solid ${theme.colors.border}`,\r\n padding: theme.spacing.xs,\r\n }}>\r\n {phases.map((phase, index) => {\r\n const width = (phase.value / maxPhaseValue) * 100;\r\n const left = phases.slice(0, index).reduce((sum, p) => sum + (p.value / maxPhaseValue) * 100, 0);\r\n \r\n return (\r\n <div\r\n key={phase.name}\r\n style={{\r\n position: 'absolute',\r\n left: `${left}%`,\r\n width: `${width}%`,\r\n height: '30px',\r\n backgroundColor: phase.color,\r\n borderRadius: theme.borderRadius.sm,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.background,\r\n fontWeight: 600,\r\n marginTop: `${index * 35}px`,\r\n opacity: 0.8,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}\r\n title={`${phase.name}: ${formatTime(phase.value)} (${formatPercentage(phase.value, breakdown.total)})`}\r\n >\r\n {width > 5 && `${phase.name}: ${formatTime(phase.value)}`}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Timeline Details */}\r\n {breakdown.timeline.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Timeline Details\r\n </div>\r\n <div style={{\r\n maxHeight: '200px',\r\n overflowY: 'auto',\r\n fontSize: theme.typography.fontSize.xs,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {breakdown.timeline.slice(-20).reverse().map((phase, index) => (\r\n <div\r\n key={index}\r\n style={{\r\n padding: theme.spacing.xs,\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n }}\r\n >\r\n <span>{phase.name}</span>\r\n <span>{formatTime(phase.duration)}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n","export interface PerformanceBudget {\r\n fps?: {\r\n min: number; // Minimum FPS required\r\n };\r\n frameTime?: {\r\n max: number; // Maximum frame time in ms\r\n };\r\n memory?: {\r\n max: number; // Maximum memory in bytes\r\n jsHeap?: {\r\n maxPercentage: number; // Maximum JS heap usage percentage (0-100)\r\n };\r\n };\r\n gpu?: {\r\n drawCalls?: {\r\n max: number; // Maximum draw calls per frame\r\n };\r\n triangles?: {\r\n max: number; // Maximum triangles per frame\r\n };\r\n };\r\n}\r\n\r\nexport interface BudgetViolation {\r\n id: string;\r\n metric: string;\r\n current: number;\r\n budget: number;\r\n severity: 'warning' | 'error';\r\n timestamp: number;\r\n message: string;\r\n}\r\n\r\nexport type BudgetViolationHistory = BudgetViolation[];\r\n\r\nclass BudgetManager {\r\n private budget: PerformanceBudget | null = null;\r\n private violations: BudgetViolationHistory = [];\r\n private readonly maxHistorySize = 100;\r\n private listeners: Set<(violations: BudgetViolation[]) => void> = new Set();\r\n private readonly STORAGE_KEY = 'r3f-profiler-budget';\r\n\r\n constructor() {\r\n // Load saved budget from localStorage on initialization\r\n this.loadBudget();\r\n }\r\n\r\n private loadBudget(): void {\r\n try {\r\n const savedBudget = localStorage.getItem(this.STORAGE_KEY);\r\n if (savedBudget) {\r\n const parsed = JSON.parse(savedBudget);\r\n // Validate the structure before setting\r\n if (this.isValidBudget(parsed)) {\r\n this.budget = parsed;\r\n }\r\n }\r\n } catch (e) {\r\n console.warn('Failed to load saved budget from localStorage:', e);\r\n }\r\n }\r\n\r\n private saveBudget(): void {\r\n try {\r\n if (this.budget) {\r\n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.budget));\r\n } else {\r\n // Remove from localStorage if budget is cleared\r\n localStorage.removeItem(this.STORAGE_KEY);\r\n }\r\n } catch (e) {\r\n console.warn('Failed to save budget to localStorage:', e);\r\n }\r\n }\r\n\r\n private isValidBudget(obj: any): obj is PerformanceBudget {\r\n // Basic validation - check if it's an object with optional budget properties\r\n if (!obj || typeof obj !== 'object') {\r\n return false;\r\n }\r\n \r\n // Check if it has at least one valid budget property\r\n const hasValidProperty = \r\n (obj.fps && typeof obj.fps.min === 'number') ||\r\n (obj.frameTime && typeof obj.frameTime.max === 'number') ||\r\n (obj.memory && (typeof obj.memory.max === 'number' || obj.memory.jsHeap)) ||\r\n (obj.gpu && (obj.gpu.drawCalls || obj.gpu.triangles));\r\n \r\n return hasValidProperty;\r\n }\r\n\r\n setBudget(budget: PerformanceBudget): void {\r\n // Check if budget is empty (all properties are undefined/null)\r\n const isEmpty = !budget || (\r\n !budget.fps &&\r\n !budget.frameTime &&\r\n !budget.memory &&\r\n !budget.gpu\r\n );\r\n\r\n if (isEmpty) {\r\n this.budget = null;\r\n } else {\r\n this.budget = budget;\r\n }\r\n \r\n // Clear violations when budget changes\r\n this.violations = [];\r\n // Save to localStorage\r\n this.saveBudget();\r\n this.notifyListeners();\r\n }\r\n\r\n getBudget(): PerformanceBudget | null {\r\n return this.budget;\r\n }\r\n\r\n checkBudget(metrics: {\r\n fps?: number;\r\n frameTime?: number;\r\n memory?: {\r\n used: number;\r\n jsHeapPercentage?: number;\r\n };\r\n gpu?: {\r\n drawCalls: number;\r\n triangles: number;\r\n };\r\n }): BudgetViolation[] {\r\n if (!this.budget) {\r\n return [];\r\n }\r\n\r\n const violations: BudgetViolation[] = [];\r\n\r\n // Check FPS\r\n if (this.budget.fps?.min !== undefined && metrics.fps !== undefined) {\r\n if (metrics.fps < this.budget.fps.min) {\r\n violations.push({\r\n id: `fps-${Date.now()}-${Math.random()}`,\r\n metric: 'fps',\r\n current: metrics.fps,\r\n budget: this.budget.fps.min,\r\n severity: metrics.fps < this.budget.fps.min * 0.7 ? 'error' : 'warning',\r\n timestamp: performance.now(),\r\n message: `FPS is ${metrics.fps.toFixed(1)} (budget: ${this.budget.fps.min} FPS)`,\r\n });\r\n }\r\n }\r\n\r\n // Check Frame Time\r\n if (this.budget.frameTime?.max !== undefined && metrics.frameTime !== undefined) {\r\n if (metrics.frameTime > this.budget.frameTime.max) {\r\n violations.push({\r\n id: `frameTime-${Date.now()}-${Math.random()}`,\r\n metric: 'frameTime',\r\n current: metrics.frameTime,\r\n budget: this.budget.frameTime.max,\r\n severity: metrics.frameTime > this.budget.frameTime.max * 1.5 ? 'error' : 'warning',\r\n timestamp: performance.now(),\r\n message: `Frame time is ${metrics.frameTime.toFixed(2)}ms (budget: ${this.budget.frameTime.max}ms)`,\r\n });\r\n }\r\n }\r\n\r\n // Check Memory\r\n if (this.budget.memory) {\r\n if (this.budget.memory.max !== undefined && metrics.memory?.used !== undefined) {\r\n if (metrics.memory.used > this.budget.memory.max) {\r\n violations.push({\r\n id: `memory-${Date.now()}-${Math.random()}`,\r\n metric: 'memory',\r\n current: metrics.memory.used,\r\n budget: this.budget.memory.max,\r\n severity: metrics.memory.used > this.budget.memory.max * 1.2 ? 'error' : 'warning',\r\n timestamp: performance.now(),\r\n message: `Memory usage is ${(metrics.memory.used / (1024 * 1024)).toFixed(2)}MB (budget: ${(this.budget.memory.max / (1024 * 1024)).toFixed(2)}MB)`,\r\n });\r\n }\r\n }\r\n\r\n if (this.budget.memory.jsHeap?.maxPercentage !== undefined && metrics.memory?.jsHeapPercentage !== undefined) {\r\n if (metrics.memory.jsHeapPercentage > this.budget.memory.jsHeap.maxPercentage) {\r\n violations.push({\r\n id: `jsHeap-${Date.now()}-${Math.random()}`,\r\n metric: 'jsHeap',\r\n current: metrics.memory.jsHeapPercentage,\r\n budget: this.budget.memory.jsHeap.maxPercentage,\r\n severity: metrics.memory.jsHeapPercentage > this.budget.memory.jsHeap.maxPercentage * 1.1 ? 'error' : 'warning',\r\n timestamp: performance.now(),\r\n message: `JS Heap usage is ${metrics.memory.jsHeapPercentage.toFixed(1)}% (budget: ${this.budget.memory.jsHeap.maxPercentage}%)`,\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Check GPU\r\n if (this.budget.gpu) {\r\n if (this.budget.gpu.drawCalls?.max !== undefined && metrics.gpu?.drawCalls !== undefined) {\r\n if (metrics.gpu.drawCalls > this.budget.gpu.drawCalls.max) {\r\n violations.push({\r\n id: `drawCalls-${Date.now()}-${Math.random()}`,\r\n metric: 'drawCalls',\r\n current: metrics.gpu.drawCalls,\r\n budget: this.budget.gpu.drawCalls.max,\r\n severity: metrics.gpu.drawCalls > this.budget.gpu.drawCalls.max * 1.5 ? 'error' : 'warning',\r\n timestamp: performance.now(),\r\n message: `Draw calls: ${metrics.gpu.drawCalls} (budget: ${this.budget.gpu.drawCalls.max})`,\r\n });\r\n }\r\n }\r\n\r\n if (this.budget.gpu.triangles?.max !== undefined && metrics.gpu?.triangles !== undefined) {\r\n if (metrics.gpu.triangles > this.budget.gpu.triangles.max) {\r\n violations.push({\r\n id: `triangles-${Date.now()}-${Math.random()}`,\r\n metric: 'triangles',\r\n current: metrics.gpu.triangles,\r\n budget: this.budget.gpu.triangles.max,\r\n severity: metrics.gpu.triangles > this.budget.gpu.triangles.max * 1.5 ? 'error' : 'warning',\r\n timestamp: performance.now(),\r\n message: `Triangles: ${metrics.gpu.triangles.toLocaleString()} (budget: ${this.budget.gpu.triangles.max.toLocaleString()})`,\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Add violations to history\r\n if (violations.length > 0) {\r\n this.violations.push(...violations);\r\n \r\n // Keep only last N violations\r\n if (this.violations.length > this.maxHistorySize) {\r\n this.violations = this.violations.slice(-this.maxHistorySize);\r\n }\r\n\r\n this.notifyListeners();\r\n }\r\n\r\n return violations;\r\n }\r\n\r\n getViolations(): BudgetViolationHistory {\r\n return [...this.violations];\r\n }\r\n\r\n getRecentViolations(seconds: number = 60): BudgetViolation[] {\r\n const cutoff = performance.now() - (seconds * 1000);\r\n return this.violations.filter(v => v.timestamp >= cutoff);\r\n }\r\n\r\n getViolationsByMetric(metric: string): BudgetViolation[] {\r\n return this.violations.filter(v => v.metric === metric);\r\n }\r\n\r\n clearViolations(): void {\r\n this.violations = [];\r\n this.notifyListeners();\r\n }\r\n\r\n // Get default budget recommendations based on current metrics\r\n getRecommendedBudget(metrics: {\r\n fps?: number;\r\n frameTime?: number;\r\n memory?: { used: number };\r\n gpu?: { drawCalls: number; triangles: number };\r\n }): PerformanceBudget {\r\n const budget: PerformanceBudget = {};\r\n\r\n // FPS: recommend 90% of current as minimum\r\n if (metrics.fps !== undefined) {\r\n budget.fps = {\r\n min: Math.max(30, Math.floor(metrics.fps * 0.9)),\r\n };\r\n }\r\n\r\n // Frame Time: recommend 110% of current as maximum\r\n if (metrics.frameTime !== undefined) {\r\n budget.frameTime = {\r\n max: Math.ceil(metrics.frameTime * 1.1),\r\n };\r\n }\r\n\r\n // Memory: recommend 120% of current as maximum\r\n if (metrics.memory?.used !== undefined) {\r\n budget.memory = {\r\n max: Math.ceil(metrics.memory.used * 1.2),\r\n jsHeap: {\r\n maxPercentage: 80, // Default 80% of heap limit\r\n },\r\n };\r\n }\r\n\r\n // GPU: recommend 120% of current as maximum\r\n if (metrics.gpu) {\r\n budget.gpu = {};\r\n if (metrics.gpu.drawCalls !== undefined) {\r\n budget.gpu.drawCalls = {\r\n max: Math.ceil(metrics.gpu.drawCalls * 1.2),\r\n };\r\n }\r\n if (metrics.gpu.triangles !== undefined) {\r\n budget.gpu.triangles = {\r\n max: Math.ceil(metrics.gpu.triangles * 1.2),\r\n };\r\n }\r\n }\r\n\r\n return budget;\r\n }\r\n\r\n // Subscribe to violation changes\r\n subscribe(listener: (violations: BudgetViolation[]) => void): () => void {\r\n this.listeners.add(listener);\r\n return () => {\r\n this.listeners.delete(listener);\r\n };\r\n }\r\n\r\n private notifyListeners(): void {\r\n const recentViolations = this.getRecentViolations(60);\r\n this.listeners.forEach(listener => {\r\n try {\r\n listener(recentViolations);\r\n } catch (error) {\r\n console.error('Error in budget violation listener:', error);\r\n }\r\n });\r\n }\r\n\r\n reset(): void {\r\n this.budget = null;\r\n this.violations = [];\r\n this.listeners.clear();\r\n // Clear from localStorage\r\n localStorage.removeItem(this.STORAGE_KEY);\r\n }\r\n}\r\n\r\nexport const budgetManager = new BudgetManager();\r\n","import { useEffect, useState } from 'react';\r\nimport { budgetManager, type PerformanceBudget, type BudgetViolation } from '../core/budget-manager';\r\n\r\nexport function usePerformanceBudget() {\r\n const [budget, setBudgetState] = useState<PerformanceBudget | null>(null);\r\n const [violations, setViolations] = useState<BudgetViolation[]>([]);\r\n\r\n useEffect(() => {\r\n // Get current budget\r\n setBudgetState(budgetManager.getBudget());\r\n setViolations(budgetManager.getRecentViolations(60));\r\n\r\n // Subscribe to violations and budget changes\r\n const unsubscribe = budgetManager.subscribe((newViolations) => {\r\n setViolations(newViolations);\r\n // Also update budget state in case it changed\r\n setBudgetState(budgetManager.getBudget());\r\n });\r\n\r\n return () => {\r\n unsubscribe();\r\n };\r\n }, []);\r\n\r\n const setBudget = (newBudget: PerformanceBudget) => {\r\n budgetManager.setBudget(newBudget);\r\n setBudgetState(newBudget);\r\n setViolations([]);\r\n };\r\n\r\n const clearViolations = () => {\r\n budgetManager.clearViolations();\r\n setViolations([]);\r\n };\r\n\r\n const clearBudget = () => {\r\n budgetManager.setBudget({} as PerformanceBudget); // Set empty budget to clear\r\n setBudgetState(null);\r\n setViolations([]);\r\n };\r\n\r\n const getRecommendedBudget = (metrics: {\r\n fps?: number;\r\n frameTime?: number;\r\n memory?: { used: number };\r\n gpu?: { drawCalls: number; triangles: number };\r\n }) => {\r\n return budgetManager.getRecommendedBudget(metrics);\r\n };\r\n\r\n return {\r\n budget,\r\n violations,\r\n setBudget,\r\n clearViolations,\r\n clearBudget,\r\n getRecommendedBudget,\r\n };\r\n}\r\n","import type { BudgetViolation } from './budget-manager';\r\n\r\nexport interface Alert {\r\n id: string;\r\n type: 'budget' | 'memory-leak' | 'performance' | 'custom';\r\n severity: 'info' | 'warning' | 'error';\r\n title: string;\r\n message: string;\r\n timestamp: number;\r\n dismissed?: boolean;\r\n data?: Record<string, unknown>;\r\n}\r\n\r\nclass AlertSystem {\r\n private alerts: Alert[] = [];\r\n private readonly maxAlerts = 50;\r\n private listeners: Set<(alerts: Alert[]) => void> = new Set();\r\n private soundEnabled: boolean = false;\r\n\r\n // Create alert from budget violation\r\n createFromViolation(violation: BudgetViolation): Alert {\r\n return {\r\n id: `alert-${violation.id}`,\r\n type: 'budget',\r\n severity: violation.severity,\r\n title: `Budget Violation: ${violation.metric}`,\r\n message: violation.message,\r\n timestamp: violation.timestamp,\r\n dismissed: false,\r\n data: {\r\n violation,\r\n },\r\n };\r\n }\r\n\r\n // Create custom alert\r\n createAlert(\r\n type: Alert['type'],\r\n severity: Alert['severity'],\r\n title: string,\r\n message: string,\r\n data?: Record<string, unknown>\r\n ): Alert {\r\n const alert: Alert = {\r\n id: `alert-${Date.now()}-${Math.random()}`,\r\n type,\r\n severity,\r\n title,\r\n message,\r\n timestamp: performance.now(),\r\n dismissed: false,\r\n data,\r\n };\r\n\r\n this.addAlert(alert);\r\n return alert;\r\n }\r\n\r\n private addAlert(alert: Alert): void {\r\n // Remove old alerts of the same type and metric if they exist\r\n if (alert.type === 'budget' && alert.data?.violation) {\r\n const violation = alert.data.violation as BudgetViolation;\r\n this.alerts = this.alerts.filter(\r\n a => !(a.type === 'budget' && a.data?.violation && (a.data.violation as BudgetViolation).metric === violation.metric)\r\n );\r\n }\r\n\r\n this.alerts.push(alert);\r\n\r\n // Keep only last N alerts\r\n if (this.alerts.length > this.maxAlerts) {\r\n this.alerts = this.alerts.slice(-this.maxAlerts);\r\n }\r\n\r\n // Play sound if enabled and severity is error\r\n if (this.soundEnabled && alert.severity === 'error') {\r\n this.playAlertSound();\r\n }\r\n\r\n this.notifyListeners();\r\n }\r\n\r\n getAlerts(includeDismissed: boolean = false): Alert[] {\r\n if (includeDismissed) {\r\n return [...this.alerts];\r\n }\r\n return this.alerts.filter(a => !a.dismissed);\r\n }\r\n\r\n getActiveAlerts(): Alert[] {\r\n return this.alerts.filter(a => !a.dismissed);\r\n }\r\n\r\n getAlertsBySeverity(severity: Alert['severity']): Alert[] {\r\n return this.alerts.filter(a => !a.dismissed && a.severity === severity);\r\n }\r\n\r\n getAlertsByType(type: Alert['type']): Alert[] {\r\n return this.alerts.filter(a => !a.dismissed && a.type === type);\r\n }\r\n\r\n dismissAlert(id: string): void {\r\n const alert = this.alerts.find(a => a.id === id);\r\n if (alert) {\r\n alert.dismissed = true;\r\n this.notifyListeners();\r\n }\r\n }\r\n\r\n dismissAll(): void {\r\n this.alerts.forEach(alert => {\r\n alert.dismissed = true;\r\n });\r\n this.notifyListeners();\r\n }\r\n\r\n removeAlert(id: string): void {\r\n this.alerts = this.alerts.filter(a => a.id !== id);\r\n this.notifyListeners();\r\n }\r\n\r\n clearAlerts(): void {\r\n this.alerts = [];\r\n this.notifyListeners();\r\n }\r\n\r\n setSoundEnabled(enabled: boolean): void {\r\n this.soundEnabled = enabled;\r\n }\r\n\r\n isSoundEnabled(): boolean {\r\n return this.soundEnabled;\r\n }\r\n\r\n private playAlertSound(): void {\r\n // Create a simple beep sound using Web Audio API\r\n try {\r\n const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();\r\n const oscillator = audioContext.createOscillator();\r\n const gainNode = audioContext.createGain();\r\n\r\n oscillator.connect(gainNode);\r\n gainNode.connect(audioContext.destination);\r\n\r\n oscillator.frequency.value = 800; // Frequency in Hz\r\n oscillator.type = 'sine';\r\n\r\n gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);\r\n gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.1);\r\n\r\n oscillator.start(audioContext.currentTime);\r\n oscillator.stop(audioContext.currentTime + 0.1);\r\n } catch (error) {\r\n // Silently fail if audio context is not available\r\n console.debug('Could not play alert sound:', error);\r\n }\r\n }\r\n\r\n // Subscribe to alert changes\r\n subscribe(listener: (alerts: Alert[]) => void): () => void {\r\n this.listeners.add(listener);\r\n return () => {\r\n this.listeners.delete(listener);\r\n };\r\n }\r\n\r\n private notifyListeners(): void {\r\n const activeAlerts = this.getActiveAlerts();\r\n this.listeners.forEach(listener => {\r\n try {\r\n listener(activeAlerts);\r\n } catch (error) {\r\n console.error('Error in alert listener:', error);\r\n }\r\n });\r\n }\r\n\r\n reset(): void {\r\n this.alerts = [];\r\n this.listeners.clear();\r\n this.soundEnabled = false;\r\n }\r\n}\r\n\r\nexport const alertSystem = new AlertSystem();\r\n","import { useEffect, useRef } from 'react';\r\nimport { budgetManager } from '../core/budget-manager';\r\nimport { alertSystem } from '../core/alert-system';\r\nimport { useFrameHistory } from './useFrameHistory';\r\nimport { useProfilerData } from './useProfiler';\r\nimport { useGPUStats } from './useGPUStats';\r\nimport { useMemoryStats } from './useMemoryStats';\r\n\r\n/**\r\n * Hook that automatically checks budgets and creates alerts\r\n * Should be used in a component that has access to all the stats\r\n */\r\nexport function useBudgetChecker() {\r\n const frameHistory = useFrameHistory();\r\n const profilerData = useProfilerData();\r\n const gpuStats = useGPUStats();\r\n const memoryStats = useMemoryStats();\r\n const intervalRef = useRef<number | null>(null);\r\n\r\n useEffect(() => {\r\n const checkBudgets = () => {\r\n const budget = budgetManager.getBudget();\r\n if (!budget) {\r\n return; // No budget configured\r\n }\r\n\r\n // Calculate current metrics\r\n // Use profiler data for FPS calculation (more reliable)\r\n let fps = 0;\r\n let avgFrameTime = 0;\r\n\r\n if (profilerData && profilerData.totalTime > 0 && profilerData.frames > 0) {\r\n // Calculate from profiler data (most reliable)\r\n avgFrameTime = profilerData.totalTime / profilerData.frames;\r\n fps = 1000 / avgFrameTime;\r\n } else if (frameHistory.length > 0) {\r\n // Fallback to frame history\r\n avgFrameTime = frameHistory.reduce((sum, t) => sum + t, 0) / frameHistory.length;\r\n fps = avgFrameTime > 0 ? 1000 / avgFrameTime : 0;\r\n } else if (gpuStats && gpuStats.frameTime > 0) {\r\n // Fallback to GPU frame time\r\n avgFrameTime = gpuStats.frameTime;\r\n fps = avgFrameTime > 0 ? 1000 / avgFrameTime : 0;\r\n }\r\n\r\n const metrics = {\r\n fps,\r\n frameTime: avgFrameTime,\r\n memory: memoryStats ? {\r\n used: memoryStats.jsHeap.used,\r\n jsHeapPercentage: memoryStats.jsHeap.percentage,\r\n } : undefined,\r\n gpu: gpuStats ? {\r\n drawCalls: gpuStats.drawCalls,\r\n triangles: gpuStats.triangles,\r\n } : undefined,\r\n };\r\n\r\n // Check budgets\r\n const violations = budgetManager.checkBudget(metrics);\r\n\r\n // Create alerts from violations\r\n violations.forEach(violation => {\r\n const existingAlert = alertSystem.getAlerts().find(\r\n a => a.type === 'budget' && a.data?.violation && (a.data.violation as any).id === violation.id\r\n );\r\n\r\n if (!existingAlert) {\r\n alertSystem.createFromViolation(violation);\r\n }\r\n });\r\n };\r\n\r\n // Check budgets every second\r\n intervalRef.current = window.setInterval(checkBudgets, 1000);\r\n\r\n // Initial check\r\n checkBudgets();\r\n\r\n return () => {\r\n if (intervalRef.current !== null) {\r\n clearInterval(intervalRef.current);\r\n }\r\n };\r\n }, [frameHistory, profilerData, gpuStats, memoryStats]);\r\n}\r\n","import { useState, useMemo } from 'react';\r\nimport { usePerformanceBudget } from '../../hooks/usePerformanceBudget';\r\nimport { useFrameHistory } from '../../hooks/useFrameHistory';\r\nimport { useGPUStats } from '../../hooks/useGPUStats';\r\nimport { useMemoryStats } from '../../hooks/useMemoryStats';\r\nimport { useBudgetChecker } from '../../hooks/useBudgetChecker';\r\nimport { MetricCard, AlertBadge } from '../components';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\nimport type { PerformanceBudget } from '../../core/budget-manager';\r\n\r\nexport const BudgetPanel = () => {\r\n const { budget, violations, setBudget, clearViolations, clearBudget, getRecommendedBudget } = usePerformanceBudget();\r\n const frameHistory = useFrameHistory();\r\n const gpuStats = useGPUStats();\r\n const memoryStats = useMemoryStats();\r\n const theme = defaultTheme;\r\n\r\n // Automatically check budgets and create alerts\r\n useBudgetChecker();\r\n\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [editBudget, setEditBudget] = useState<PerformanceBudget>(budget || {});\r\n\r\n const currentMetrics = useMemo(() => {\r\n const avgFrameTime = frameHistory.length > 0\r\n ? frameHistory.reduce((sum, t) => sum + t, 0) / frameHistory.length\r\n : 0;\r\n const fps = avgFrameTime > 0 ? 1000 / avgFrameTime : 0;\r\n\r\n return {\r\n fps,\r\n frameTime: avgFrameTime,\r\n memory: memoryStats ? {\r\n used: memoryStats.jsHeap.used,\r\n jsHeapPercentage: memoryStats.jsHeap.percentage,\r\n } : undefined,\r\n gpu: gpuStats ? {\r\n drawCalls: gpuStats.drawCalls,\r\n triangles: gpuStats.triangles,\r\n } : undefined,\r\n };\r\n }, [frameHistory, gpuStats, memoryStats]);\r\n\r\n const formatBytes = (bytes: number): string => {\r\n if (bytes === 0) return '0 B';\r\n if (bytes < 1024) return `${formatNumber(bytes, 0)} B`;\r\n if (bytes < 1024 * 1024) return `${formatNumber(bytes / 1024, 2)} KB`;\r\n if (bytes < 1024 * 1024 * 1024) return `${formatNumber(bytes / (1024 * 1024), 2)} MB`;\r\n return `${formatNumber(bytes / (1024 * 1024 * 1024), 2)} GB`;\r\n };\r\n\r\n const handleSaveBudget = () => {\r\n setBudget(editBudget);\r\n setIsEditing(false);\r\n };\r\n\r\n const handleUseRecommended = () => {\r\n const recommended = getRecommendedBudget(currentMetrics);\r\n setEditBudget(recommended);\r\n setBudget(recommended);\r\n setIsEditing(false);\r\n };\r\n\r\n const handleCancel = () => {\r\n setEditBudget(budget || {});\r\n setIsEditing(false);\r\n };\r\n\r\n const violationsBySeverity = useMemo(() => {\r\n const errors = violations.filter(v => v.severity === 'error').length;\r\n const warnings = violations.filter(v => v.severity === 'warning').length;\r\n return { errors, warnings };\r\n }, [violations]);\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* Budget Status */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Budget Status\r\n </div>\r\n <div style={{\r\n display: 'flex',\r\n gap: theme.spacing.sm,\r\n alignItems: 'center',\r\n }}>\r\n {violationsBySeverity.errors > 0 && (\r\n <AlertBadge severity=\"error\" count={violationsBySeverity.errors} />\r\n )}\r\n {violationsBySeverity.warnings > 0 && (\r\n <AlertBadge severity=\"warning\" count={violationsBySeverity.warnings} />\r\n )}\r\n {!budget && (\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n No budget configured\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {budget ? (\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n gap: theme.spacing.sm,\r\n }}>\r\n {budget.fps && (\r\n <MetricCard\r\n label=\"FPS Min\"\r\n value={budget.fps.min}\r\n unit=\"FPS\"\r\n />\r\n )}\r\n {budget.frameTime && (\r\n <MetricCard\r\n label=\"Frame Time Max\"\r\n value={`${budget.frameTime.max.toFixed(2)}ms`}\r\n />\r\n )}\r\n {budget.memory?.max && (\r\n <MetricCard\r\n label=\"Memory Max\"\r\n value={formatBytes(budget.memory.max)}\r\n />\r\n )}\r\n {budget.gpu?.drawCalls?.max && (\r\n <MetricCard\r\n label=\"Draw Calls Max\"\r\n value={budget.gpu.drawCalls.max.toLocaleString()}\r\n />\r\n )}\r\n {budget.gpu?.triangles?.max && (\r\n <MetricCard\r\n label=\"Triangles Max\"\r\n value={budget.gpu.triangles.max.toLocaleString()}\r\n />\r\n )}\r\n </div>\r\n ) : (\r\n <div style={{\r\n padding: theme.spacing.md,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Configure a budget to start monitoring performance thresholds\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Budget Configuration */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n Budget Configuration\r\n </div>\r\n\r\n {!isEditing ? (\r\n <div style={{\r\n display: 'flex',\r\n gap: theme.spacing.sm,\r\n flexWrap: 'wrap',\r\n }}>\r\n <button\r\n onClick={() => setIsEditing(true)}\r\n style={{\r\n padding: `${theme.spacing.sm} ${theme.spacing.md}`,\r\n backgroundColor: theme.colors.primary,\r\n color: theme.colors.background,\r\n border: 'none',\r\n borderRadius: theme.borderRadius.sm,\r\n cursor: 'pointer',\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n transition: theme.transitions.fast,\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = theme.colors.primaryHover;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = theme.colors.primary;\r\n }}\r\n >\r\n {budget ? 'Edit Budget' : 'Set Budget'}\r\n </button>\r\n {!budget && (\r\n <button\r\n onClick={handleUseRecommended}\r\n style={{\r\n padding: `${theme.spacing.sm} ${theme.spacing.md}`,\r\n backgroundColor: 'transparent',\r\n color: theme.colors.primary,\r\n border: `1px solid ${theme.colors.primary}`,\r\n borderRadius: theme.borderRadius.sm,\r\n cursor: 'pointer',\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n transition: theme.transitions.fast,\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = `${theme.colors.primary}20`;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'transparent';\r\n }}\r\n >\r\n Use Recommended\r\n </button>\r\n )}\r\n {budget && (\r\n <button\r\n onClick={() => {\r\n if (window.confirm('Are you sure you want to delete the current budget?')) {\r\n clearBudget();\r\n }\r\n }}\r\n style={{\r\n padding: `${theme.spacing.sm} ${theme.spacing.md}`,\r\n backgroundColor: 'transparent',\r\n color: theme.colors.error,\r\n border: `1px solid ${theme.colors.error}`,\r\n borderRadius: theme.borderRadius.sm,\r\n cursor: 'pointer',\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n transition: theme.transitions.fast,\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = `${theme.colors.error}20`;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'transparent';\r\n }}\r\n >\r\n Delete Budget\r\n </button>\r\n )}\r\n </div>\r\n ) : (\r\n <div>\r\n <div style={{\r\n display: 'grid',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n <div>\r\n <label style={{\r\n display: 'block',\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.xs,\r\n }}>\r\n FPS Minimum\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={editBudget.fps?.min || ''}\r\n onChange={(e) => setEditBudget({\r\n ...editBudget,\r\n fps: { min: parseInt(e.target.value) || 0 },\r\n })}\r\n placeholder=\"60\"\r\n style={{\r\n width: '100%',\r\n padding: theme.spacing.sm,\r\n backgroundColor: theme.colors.background,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.sm,\r\n color: theme.colors.text,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}\r\n />\r\n </div>\r\n <div>\r\n <label style={{\r\n display: 'block',\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.xs,\r\n }}>\r\n Frame Time Maximum (ms)\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={editBudget.frameTime?.max || ''}\r\n onChange={(e) => setEditBudget({\r\n ...editBudget,\r\n frameTime: { max: parseFloat(e.target.value) || 0 },\r\n })}\r\n placeholder=\"16.67\"\r\n step=\"0.1\"\r\n style={{\r\n width: '100%',\r\n padding: theme.spacing.sm,\r\n backgroundColor: theme.colors.background,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.sm,\r\n color: theme.colors.text,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}\r\n />\r\n </div>\r\n <div>\r\n <label style={{\r\n display: 'block',\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.xs,\r\n }}>\r\n Memory Maximum (MB)\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={editBudget.memory?.max ? editBudget.memory.max / (1024 * 1024) : ''}\r\n onChange={(e) => setEditBudget({\r\n ...editBudget,\r\n memory: {\r\n ...editBudget.memory,\r\n max: (parseFloat(e.target.value) || 0) * 1024 * 1024,\r\n },\r\n })}\r\n placeholder=\"512\"\r\n step=\"1\"\r\n style={{\r\n width: '100%',\r\n padding: theme.spacing.sm,\r\n backgroundColor: theme.colors.background,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.sm,\r\n color: theme.colors.text,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}\r\n />\r\n </div>\r\n <div>\r\n <label style={{\r\n display: 'block',\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.xs,\r\n }}>\r\n Draw Calls Maximum\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={editBudget.gpu?.drawCalls?.max || ''}\r\n onChange={(e) => setEditBudget({\r\n ...editBudget,\r\n gpu: {\r\n ...editBudget.gpu,\r\n drawCalls: { max: parseInt(e.target.value) || 0 },\r\n },\r\n })}\r\n placeholder=\"100\"\r\n style={{\r\n width: '100%',\r\n padding: theme.spacing.sm,\r\n backgroundColor: theme.colors.background,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.sm,\r\n color: theme.colors.text,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}\r\n />\r\n </div>\r\n <div>\r\n <label style={{\r\n display: 'block',\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.xs,\r\n }}>\r\n Triangles Maximum\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={editBudget.gpu?.triangles?.max || ''}\r\n onChange={(e) => setEditBudget({\r\n ...editBudget,\r\n gpu: {\r\n ...editBudget.gpu,\r\n triangles: { max: parseInt(e.target.value) || 0 },\r\n },\r\n })}\r\n placeholder=\"100000\"\r\n style={{\r\n width: '100%',\r\n padding: theme.spacing.sm,\r\n backgroundColor: theme.colors.background,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.sm,\r\n color: theme.colors.text,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}\r\n />\r\n </div>\r\n </div>\r\n <div style={{\r\n display: 'flex',\r\n gap: theme.spacing.sm,\r\n }}>\r\n <button\r\n onClick={handleSaveBudget}\r\n style={{\r\n padding: `${theme.spacing.sm} ${theme.spacing.md}`,\r\n backgroundColor: theme.colors.success,\r\n color: theme.colors.background,\r\n border: 'none',\r\n borderRadius: theme.borderRadius.sm,\r\n cursor: 'pointer',\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}\r\n >\r\n Save\r\n </button>\r\n <button\r\n onClick={handleCancel}\r\n style={{\r\n padding: `${theme.spacing.sm} ${theme.spacing.md}`,\r\n backgroundColor: 'transparent',\r\n color: theme.colors.textSecondary,\r\n border: `1px solid ${theme.colors.border}`,\r\n borderRadius: theme.borderRadius.sm,\r\n cursor: 'pointer',\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n }}\r\n >\r\n Cancel\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Violations History */}\r\n {violations.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n marginBottom: theme.spacing.md,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Recent Violations ({violations.length})\r\n </div>\r\n <button\r\n onClick={clearViolations}\r\n style={{\r\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\r\n backgroundColor: 'transparent',\r\n color: theme.colors.textSecondary,\r\n border: 'none',\r\n cursor: 'pointer',\r\n fontSize: theme.typography.fontSize.xs,\r\n }}\r\n >\r\n Clear\r\n </button>\r\n </div>\r\n <div style={{\r\n maxHeight: '200px',\r\n overflowY: 'auto',\r\n fontSize: theme.typography.fontSize.xs,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n {violations.slice(-10).reverse().map((violation) => (\r\n <div\r\n key={violation.id}\r\n style={{\r\n padding: theme.spacing.sm,\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n }}\r\n >\r\n <div>\r\n <div style={{\r\n color: violation.severity === 'error' ? theme.colors.error : theme.colors.warning,\r\n fontWeight: 600,\r\n }}>\r\n {violation.metric}\r\n </div>\r\n <div style={{\r\n color: theme.colors.textSecondary,\r\n marginTop: theme.spacing.xs,\r\n }}>\r\n {violation.message}\r\n </div>\r\n </div>\r\n <AlertBadge severity={violation.severity} />\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import type { ProfilerOnRenderCallback } from 'react';\r\nimport { autoInstrumentation } from './auto-instrumentation';\r\n\r\nexport interface ReactComponentRender {\r\n id: string;\r\n name: string;\r\n phase: 'mount' | 'update';\r\n actualDuration: number; // ms\r\n baseDuration: number; // ms\r\n startTime: number; // ms\r\n commitTime: number; // ms\r\n timestamp: number;\r\n}\r\n\r\nexport interface ReactComponentStats {\r\n name: string;\r\n renderCount: number;\r\n totalDuration: number; // ms\r\n averageDuration: number; // ms\r\n maxDuration: number; // ms\r\n minDuration: number; // ms;\r\n lastRenderTime: number;\r\n phases: {\r\n mount: number;\r\n update: number;\r\n };\r\n}\r\n\r\nexport interface ReactPerformanceData {\r\n components: Map<string, ReactComponentStats>;\r\n recentRenders: ReactComponentRender[];\r\n totalRenders: number;\r\n slowComponents: ReactComponentStats[]; // Components with avg duration > threshold\r\n frequentRenders: ReactComponentStats[]; // Components with many renders\r\n timestamp: number;\r\n}\r\n\r\nclass ReactMonitor {\r\n private componentStats: Map<string, ReactComponentStats> = new Map();\r\n private recentRenders: ReactComponentRender[] = [];\r\n private totalRenders: number = 0;\r\n private readonly maxRecentRenders = 100;\r\n private readonly slowThreshold = 16; // ms (1 frame at 60fps)\r\n private readonly frequentThreshold = 10; // renders per second\r\n\r\n // React Profiler callback\r\n onRenderCallback: ProfilerOnRenderCallback = (\r\n id,\r\n phase,\r\n actualDuration,\r\n baseDuration,\r\n startTime,\r\n commitTime\r\n ) => {\r\n const componentName = this.getComponentName(id);\r\n const timestamp = performance.now();\r\n\r\n // Create render record\r\n const render: ReactComponentRender = {\r\n id,\r\n name: componentName,\r\n phase: phase as 'mount' | 'update',\r\n actualDuration,\r\n baseDuration,\r\n startTime,\r\n commitTime,\r\n timestamp,\r\n };\r\n\r\n // Add to recent renders\r\n this.recentRenders.push(render);\r\n if (this.recentRenders.length > this.maxRecentRenders) {\r\n this.recentRenders.shift();\r\n }\r\n\r\n // Update component stats\r\n this.updateComponentStats(componentName, render);\r\n\r\n // Notify auto-instrumentation about React render\r\n autoInstrumentation.onReactRender(actualDuration);\r\n\r\n this.totalRenders++;\r\n };\r\n\r\n private getComponentName(id: string): string {\r\n // Try to extract component name from id\r\n // React Profiler IDs are usually in format: \"ComponentName:index\"\r\n const parts = id.split(':');\r\n return parts[0] || id;\r\n }\r\n\r\n private updateComponentStats(name: string, render: ReactComponentRender): void {\r\n let stats = this.componentStats.get(name);\r\n\r\n if (!stats) {\r\n stats = {\r\n name,\r\n renderCount: 0,\r\n totalDuration: 0,\r\n averageDuration: 0,\r\n maxDuration: 0,\r\n minDuration: Infinity,\r\n lastRenderTime: 0,\r\n phases: {\r\n mount: 0,\r\n update: 0,\r\n },\r\n };\r\n this.componentStats.set(name, stats);\r\n }\r\n\r\n stats.renderCount++;\r\n stats.totalDuration += render.actualDuration;\r\n stats.averageDuration = stats.totalDuration / stats.renderCount;\r\n stats.maxDuration = Math.max(stats.maxDuration, render.actualDuration);\r\n stats.minDuration = Math.min(stats.minDuration, render.actualDuration);\r\n stats.lastRenderTime = render.timestamp;\r\n\r\n if (render.phase === 'mount') {\r\n stats.phases.mount++;\r\n } else {\r\n stats.phases.update++;\r\n }\r\n }\r\n\r\n getPerformanceData(): ReactPerformanceData {\r\n const components = new Map(this.componentStats);\r\n \r\n // Calculate slow components (average duration > threshold)\r\n const slowComponents = Array.from(components.values())\r\n .filter(stat => stat.averageDuration > this.slowThreshold)\r\n .sort((a, b) => b.averageDuration - a.averageDuration);\r\n\r\n // Calculate frequent renderers (render count > threshold in recent time)\r\n const now = performance.now();\r\n const recentTimeWindow = 1000; // 1 second\r\n const frequentComponents = Array.from(components.values())\r\n .filter(stat => {\r\n const timeSinceLastRender = now - stat.lastRenderTime;\r\n if (timeSinceLastRender > recentTimeWindow) return false;\r\n const rendersPerSecond = stat.renderCount / (recentTimeWindow / 1000);\r\n return rendersPerSecond > this.frequentThreshold;\r\n })\r\n .sort((a, b) => b.renderCount - a.renderCount);\r\n\r\n return {\r\n components,\r\n recentRenders: [...this.recentRenders],\r\n totalRenders: this.totalRenders,\r\n slowComponents,\r\n frequentRenders: frequentComponents,\r\n timestamp: performance.now(),\r\n };\r\n }\r\n\r\n getComponentStats(componentName: string): ReactComponentStats | null {\r\n return this.componentStats.get(componentName) || null;\r\n }\r\n\r\n getSlowComponents(): ReactComponentStats[] {\r\n const data = this.getPerformanceData();\r\n return data.slowComponents;\r\n }\r\n\r\n getFrequentRenders(): ReactComponentStats[] {\r\n const data = this.getPerformanceData();\r\n return data.frequentRenders;\r\n }\r\n\r\n reset(): void {\r\n this.componentStats.clear();\r\n this.recentRenders = [];\r\n this.totalRenders = 0;\r\n }\r\n}\r\n\r\nexport const reactMonitor = new ReactMonitor();\r\n","import { useEffect, useState } from 'react';\r\nimport { reactMonitor, type ReactPerformanceData } from '../core/react-monitor';\r\nimport { monitorState } from '../core/monitor-state';\r\n\r\nexport function useReactProfiler(): ReactPerformanceData | null {\r\n const [data, setData] = useState<ReactPerformanceData | null>(null);\r\n\r\n useEffect(() => {\r\n // Initial update\r\n const updateData = () => {\r\n if (!monitorState.getPaused()) {\r\n const newData = reactMonitor.getPerformanceData();\r\n setData(newData);\r\n }\r\n };\r\n\r\n updateData();\r\n\r\n // Update every 500ms for real-time monitoring\r\n const interval = setInterval(updateData, 500);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateData();\r\n }\r\n });\r\n\r\n return () => {\r\n clearInterval(interval);\r\n unsubscribePause();\r\n };\r\n }, []);\r\n\r\n return data;\r\n}\r\n","import { useMemo } from 'react';\r\nimport { useReactProfiler } from '../../hooks/useReactProfiler';\r\nimport { MetricCard, AlertBadge } from '../components';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\nimport type { ReactComponentStats } from '../../core/react-monitor';\r\n\r\nexport const ReactPanel = () => {\r\n const data = useReactProfiler();\r\n const theme = defaultTheme;\r\n\r\n const formatTime = (ms: number): string => {\r\n if (ms < 0.1) return `${formatNumber(ms * 1000, 0)} μs`;\r\n if (ms < 1) return `${formatNumber(ms, 2)} ms`;\r\n return `${formatNumber(ms, 2)} ms`;\r\n };\r\n\r\n const componentsList = useMemo(() => {\r\n if (!data) return [];\r\n return Array.from(data.components.values()).sort((a, b) => b.totalDuration - a.totalDuration);\r\n }, [data]);\r\n\r\n if (!data) {\r\n return (\r\n <div style={{\r\n padding: theme.spacing.lg,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Aucune donnée React disponible. Enveloppez vos composants avec <ReactProfiler> pour commencer le monitoring.\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* Overview Stats */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Overview\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\r\n gap: theme.spacing.sm,\r\n }}>\r\n <MetricCard\r\n label=\"Total Renders\"\r\n value={data.totalRenders.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Components\"\r\n value={data.components.size.toLocaleString()}\r\n />\r\n <MetricCard\r\n label=\"Slow Components\"\r\n value={data.slowComponents.length.toLocaleString()}\r\n status={data.slowComponents.length > 0 ? 'warning' : 'good'}\r\n />\r\n <MetricCard\r\n label=\"Frequent Renders\"\r\n value={data.frequentRenders.length.toLocaleString()}\r\n status={data.frequentRenders.length > 0 ? 'warning' : 'good'}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Slow Components Alert */}\r\n {data.slowComponents.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.warning}40`,\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n <AlertBadge severity=\"warning\" count={data.slowComponents.length} />\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Slow Components (avg > 16ms)\r\n </div>\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n {data.slowComponents.slice(0, 5).map((comp) => (\r\n <div key={comp.name} style={{ marginBottom: theme.spacing.xs }}>\r\n {comp.name}: {formatTime(comp.averageDuration)} avg ({comp.renderCount} renders)\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Frequent Renders Alert */}\r\n {data.frequentRenders.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.warning}40`,\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n <AlertBadge severity=\"warning\" count={data.frequentRenders.length} />\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Frequent Renders (> 10 renders/sec)\r\n </div>\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n {data.frequentRenders.slice(0, 5).map((comp) => (\r\n <div key={comp.name} style={{ marginBottom: theme.spacing.xs }}>\r\n {comp.name}: {comp.renderCount} renders\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Components List */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Components ({componentsList.length})\r\n </div>\r\n <div style={{\r\n maxHeight: '400px',\r\n overflowY: 'auto',\r\n }}>\r\n {componentsList.length === 0 ? (\r\n <div style={{\r\n padding: theme.spacing.md,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n No components profiled yet\r\n </div>\r\n ) : (\r\n <ComponentTable components={componentsList} formatTime={formatTime} />\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\ninterface ComponentTableProps {\r\n components: ReactComponentStats[];\r\n formatTime: (ms: number) => string;\r\n}\r\n\r\nconst ComponentTable = ({ components, formatTime }: ComponentTableProps) => {\r\n const theme = defaultTheme;\r\n\r\n return (\r\n <table style={{\r\n width: '100%',\r\n borderCollapse: 'collapse',\r\n fontSize: theme.typography.fontSize.xs,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n <thead>\r\n <tr style={{\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <th style={{\r\n textAlign: 'left',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Component\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Renders\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Avg Time\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Max Time\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Total Time\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {components.map((comp) => {\r\n const isSlow = comp.averageDuration > 16;\r\n const isFrequent = comp.renderCount > 10;\r\n \r\n return (\r\n <tr\r\n key={comp.name}\r\n style={{\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n backgroundColor: isSlow || isFrequent ? `${theme.colors.warning}10` : 'transparent',\r\n }}\r\n >\r\n <td style={{\r\n padding: theme.spacing.sm,\r\n color: theme.colors.text,\r\n fontWeight: isSlow || isFrequent ? 600 : 400,\r\n }}>\r\n {comp.name}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {comp.renderCount.toLocaleString()}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: isSlow ? theme.colors.warning : theme.colors.textSecondary,\r\n fontWeight: isSlow ? 600 : 400,\r\n }}>\r\n {formatTime(comp.averageDuration)}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {formatTime(comp.maxDuration)}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {formatTime(comp.totalDuration)}\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n );\r\n};\r\n","import type { ProfilerEntry } from '../core/profiler';\r\n\r\nexport interface FunctionCall {\r\n name: string;\r\n duration: number;\r\n timestamp: number;\r\n callCount: number;\r\n averageDuration: number;\r\n maxDuration: number;\r\n stack?: string[];\r\n}\r\n\r\nexport interface HotPath {\r\n id: string;\r\n path: string[]; // Chain of function calls\r\n totalDuration: number;\r\n averageDuration: number;\r\n callCount: number;\r\n frequency: number; // Calls per second\r\n impact: 'high' | 'medium' | 'low';\r\n recommendations: string[];\r\n}\r\n\r\nexport interface HotPathAnalysis {\r\n hotPaths: HotPath[];\r\n topFunctions: FunctionCall[];\r\n bottlenecks: HotPath[];\r\n recommendations: string[];\r\n timestamp: number;\r\n}\r\n\r\nclass HotPathDetector {\r\n private functionCalls: Map<string, FunctionCall> = new Map();\r\n private callHistory: Array<{ name: string; duration: number; timestamp: number }> = [];\r\n private readonly maxHistorySize = 1000;\r\n private readonly hotPathThreshold = 5; // ms - functions taking longer than this are considered hot\r\n private readonly frequencyThreshold = 10; // calls per second\r\n\r\n recordCall(name: string, duration: number, stack?: string[]): void {\r\n const timestamp = performance.now();\r\n \r\n // Update function call stats\r\n let funcCall = this.functionCalls.get(name);\r\n if (!funcCall) {\r\n funcCall = {\r\n name,\r\n duration: 0,\r\n timestamp,\r\n callCount: 0,\r\n averageDuration: 0,\r\n maxDuration: 0,\r\n stack: stack || [],\r\n };\r\n this.functionCalls.set(name, funcCall);\r\n }\r\n\r\n funcCall.callCount++;\r\n funcCall.duration += duration;\r\n funcCall.averageDuration = funcCall.duration / funcCall.callCount;\r\n funcCall.maxDuration = Math.max(funcCall.maxDuration, duration);\r\n funcCall.timestamp = timestamp;\r\n\r\n // Add to history\r\n this.callHistory.push({ name, duration, timestamp });\r\n if (this.callHistory.length > this.maxHistorySize) {\r\n this.callHistory.shift();\r\n }\r\n }\r\n\r\n analyze(profilerEntries?: ProfilerEntry[]): HotPathAnalysis {\r\n const now = performance.now();\r\n const timeWindow = 5000; // 5 seconds\r\n const cutoff = now - timeWindow;\r\n\r\n // Get recent calls\r\n const recentCalls = this.callHistory.filter(call => call.timestamp >= cutoff);\r\n\r\n // Calculate frequency for each function\r\n const functionFrequency = new Map<string, number>();\r\n recentCalls.forEach(call => {\r\n const freq = functionFrequency.get(call.name) || 0;\r\n functionFrequency.set(call.name, freq + 1);\r\n });\r\n\r\n // Normalize frequency to calls per second\r\n const normalizedFrequency = new Map<string, number>();\r\n functionFrequency.forEach((count, name) => {\r\n normalizedFrequency.set(name, (count / timeWindow) * 1000);\r\n });\r\n\r\n // Identify hot paths (functions that are slow and/or frequently called)\r\n const hotPaths: HotPath[] = [];\r\n const topFunctions: FunctionCall[] = [];\r\n const bottlenecks: HotPath[] = [];\r\n\r\n this.functionCalls.forEach((funcCall, name) => {\r\n const freq = normalizedFrequency.get(name) || 0;\r\n const isSlow = funcCall.averageDuration > this.hotPathThreshold;\r\n const isFrequent = freq > this.frequencyThreshold;\r\n const isHot = isSlow || isFrequent;\r\n\r\n if (isHot) {\r\n const impact: 'high' | 'medium' | 'low' = \r\n funcCall.averageDuration > 16 ? 'high' :\r\n funcCall.averageDuration > 8 ? 'medium' : 'low';\r\n\r\n const recommendations: string[] = [];\r\n if (isSlow) {\r\n recommendations.push(`Optimize ${name} - average duration: ${funcCall.averageDuration.toFixed(2)}ms`);\r\n }\r\n if (isFrequent) {\r\n recommendations.push(`Reduce calls to ${name} - ${freq.toFixed(1)} calls/sec`);\r\n }\r\n if (funcCall.maxDuration > funcCall.averageDuration * 2) {\r\n recommendations.push(`Investigate performance spikes in ${name} - max: ${funcCall.maxDuration.toFixed(2)}ms`);\r\n }\r\n\r\n const hotPath: HotPath = {\r\n id: `hotpath-${name}-${Date.now()}`,\r\n path: [name],\r\n totalDuration: funcCall.duration,\r\n averageDuration: funcCall.averageDuration,\r\n callCount: funcCall.callCount,\r\n frequency: freq,\r\n impact,\r\n recommendations,\r\n };\r\n\r\n hotPaths.push(hotPath);\r\n\r\n if (isSlow) {\r\n bottlenecks.push(hotPath);\r\n }\r\n }\r\n\r\n // Add to top functions (sorted by total duration)\r\n topFunctions.push(funcCall);\r\n });\r\n\r\n // Sort top functions by total duration\r\n topFunctions.sort((a, b) => b.duration - a.duration);\r\n\r\n // Generate general recommendations\r\n const recommendations: string[] = [];\r\n if (bottlenecks.length > 0) {\r\n recommendations.push(`Found ${bottlenecks.length} performance bottlenecks`);\r\n }\r\n if (hotPaths.length > 5) {\r\n recommendations.push('Consider optimizing multiple hot paths simultaneously');\r\n }\r\n\r\n // Analyze profiler entries if provided\r\n if (profilerEntries) {\r\n profilerEntries.forEach(entry => {\r\n if (entry.avg > this.hotPathThreshold) {\r\n recommendations.push(`Hook \"${entry.name}\" takes ${entry.avg.toFixed(2)}ms on average`);\r\n }\r\n });\r\n }\r\n\r\n return {\r\n hotPaths: hotPaths.sort((a, b) => b.averageDuration - a.averageDuration),\r\n topFunctions: topFunctions.slice(0, 10), // Top 10\r\n bottlenecks: bottlenecks.sort((a, b) => b.averageDuration - a.averageDuration),\r\n recommendations,\r\n timestamp: now,\r\n };\r\n }\r\n\r\n detectCallChain(_stack: string[]): HotPath[] {\r\n // Analyze call chains to find hot paths\r\n const chains: Map<string, { path: string[]; duration: number; count: number }> = new Map();\r\n\r\n // This is a simplified version - in a real implementation, you'd track call chains\r\n // by monitoring the call stack during execution\r\n this.callHistory.forEach(call => {\r\n const key = call.name;\r\n let chain = chains.get(key);\r\n if (!chain) {\r\n chain = { path: [call.name], duration: 0, count: 0 };\r\n chains.set(key, chain);\r\n }\r\n chain.duration += call.duration;\r\n chain.count++;\r\n });\r\n\r\n const hotPaths: HotPath[] = [];\r\n chains.forEach((chain, key) => {\r\n const avgDuration = chain.duration / chain.count;\r\n if (avgDuration > this.hotPathThreshold) {\r\n hotPaths.push({\r\n id: `chain-${key}-${Date.now()}`,\r\n path: chain.path,\r\n totalDuration: chain.duration,\r\n averageDuration: avgDuration,\r\n callCount: chain.count,\r\n frequency: chain.count / 5, // Approximate\r\n impact: avgDuration > 16 ? 'high' : avgDuration > 8 ? 'medium' : 'low',\r\n recommendations: [`Optimize call chain: ${chain.path.join(' -> ')}`],\r\n });\r\n }\r\n });\r\n\r\n return hotPaths;\r\n }\r\n\r\n reset(): void {\r\n this.functionCalls.clear();\r\n this.callHistory = [];\r\n }\r\n\r\n getTopFunctions(limit: number = 10): FunctionCall[] {\r\n return Array.from(this.functionCalls.values())\r\n .sort((a, b) => b.duration - a.duration)\r\n .slice(0, limit);\r\n }\r\n}\r\n\r\nexport const hotPathDetector = new HotPathDetector();\r\n","import { useEffect, useState } from 'react';\r\nimport { hotPathDetector, type HotPathAnalysis } from '../collectors/hot-path-detector';\r\nimport { monitorState } from '../core/monitor-state';\r\nimport { useProfilerData } from './useProfiler';\r\n\r\nexport function useHotPath(): HotPathAnalysis | null {\r\n const [analysis, setAnalysis] = useState<HotPathAnalysis | null>(null);\r\n const profilerData = useProfilerData();\r\n\r\n useEffect(() => {\r\n const updateAnalysis = () => {\r\n if (!monitorState.getPaused()) {\r\n const newAnalysis = hotPathDetector.analyze(profilerData?.entries);\r\n setAnalysis(newAnalysis);\r\n }\r\n };\r\n\r\n // Initial update\r\n updateAnalysis();\r\n\r\n // Update every 2 seconds\r\n const interval = setInterval(updateAnalysis, 2000);\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribePause = monitorState.subscribe((paused) => {\r\n if (!paused) {\r\n // Resume: update immediately\r\n updateAnalysis();\r\n }\r\n });\r\n\r\n return () => {\r\n clearInterval(interval);\r\n unsubscribePause();\r\n };\r\n }, [profilerData]);\r\n\r\n return analysis;\r\n}\r\n","import { useHotPath } from '../../hooks/useHotPath';\r\nimport { MetricCard, AlertBadge } from '../components';\r\nimport { defaultTheme, formatNumber } from '../styles/theme';\r\n\r\nexport const HotPathPanel = () => {\r\n const analysis = useHotPath();\r\n const theme = defaultTheme;\r\n\r\n const formatTime = (ms: number): string => {\r\n if (ms < 0.1) return `${formatNumber(ms * 1000, 0)} μs`;\r\n if (ms < 1) return `${formatNumber(ms, 2)} ms`;\r\n return `${formatNumber(ms, 2)} ms`;\r\n };\r\n\r\n const impactColors = {\r\n high: theme.colors.error,\r\n medium: theme.colors.warning,\r\n low: theme.colors.info,\r\n };\r\n\r\n if (!analysis) {\r\n return (\r\n <div style={{\r\n padding: theme.spacing.lg,\r\n textAlign: 'center',\r\n color: theme.colors.textSecondary,\r\n fontSize: theme.typography.fontSize.sm,\r\n }}>\r\n Aucune analyse de hot path disponible. Les hot paths sont détectés automatiquement à partir des données du profiler.\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={{ padding: theme.spacing.md }}>\r\n {/* Overview */}\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Overview\r\n </div>\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\r\n gap: theme.spacing.sm,\r\n }}>\r\n <MetricCard\r\n label=\"Hot Paths\"\r\n value={analysis.hotPaths.length.toLocaleString()}\r\n status={analysis.hotPaths.length > 0 ? 'warning' : 'good'}\r\n />\r\n <MetricCard\r\n label=\"Bottlenecks\"\r\n value={analysis.bottlenecks.length.toLocaleString()}\r\n status={analysis.bottlenecks.length > 0 ? 'error' : 'good'}\r\n />\r\n <MetricCard\r\n label=\"Top Functions\"\r\n value={analysis.topFunctions.length.toLocaleString()}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Recommendations */}\r\n {analysis.recommendations.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.warning}40`,\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n <AlertBadge severity=\"warning\" />\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Recommendations\r\n </div>\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n {analysis.recommendations.map((rec, index) => (\r\n <div key={index} style={{ marginBottom: theme.spacing.xs }}>\r\n • {rec}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Bottlenecks */}\r\n {analysis.bottlenecks.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.error}40`,\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.sm,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n <AlertBadge severity=\"error\" count={analysis.bottlenecks.length} />\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Performance Bottlenecks\r\n </div>\r\n </div>\r\n <div style={{\r\n maxHeight: '300px',\r\n overflowY: 'auto',\r\n }}>\r\n {analysis.bottlenecks.map((bottleneck) => (\r\n <div\r\n key={bottleneck.id}\r\n style={{\r\n padding: theme.spacing.sm,\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n backgroundColor: `${impactColors[bottleneck.impact]}10`,\r\n }}\r\n >\r\n <div style={{\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: theme.spacing.xs,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: impactColors[bottleneck.impact],\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n {bottleneck.path.join(' -> ')}\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {formatTime(bottleneck.averageDuration)} avg\r\n </div>\r\n </div>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textSecondary,\r\n marginBottom: theme.spacing.xs,\r\n }}>\r\n {bottleneck.callCount.toLocaleString()} calls • {bottleneck.frequency.toFixed(1)} calls/sec\r\n </div>\r\n {bottleneck.recommendations.length > 0 && (\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.textTertiary,\r\n fontStyle: 'italic',\r\n }}>\r\n {bottleneck.recommendations[0]}\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Hot Paths */}\r\n {analysis.hotPaths.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n marginBottom: theme.spacing.lg,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Hot Paths ({analysis.hotPaths.length})\r\n </div>\r\n <div style={{\r\n maxHeight: '400px',\r\n overflowY: 'auto',\r\n }}>\r\n <table style={{\r\n width: '100%',\r\n borderCollapse: 'collapse',\r\n fontSize: theme.typography.fontSize.xs,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n }}>\r\n <thead>\r\n <tr style={{\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <th style={{\r\n textAlign: 'left',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Path\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Avg Time\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Calls\r\n </th>\r\n <th style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Freq/sec\r\n </th>\r\n <th style={{\r\n textAlign: 'center',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n fontWeight: 600,\r\n }}>\r\n Impact\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {analysis.hotPaths.map((path) => (\r\n <tr\r\n key={path.id}\r\n style={{\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n backgroundColor: `${impactColors[path.impact]}10`,\r\n }}\r\n >\r\n <td style={{\r\n padding: theme.spacing.sm,\r\n color: theme.colors.text,\r\n }}>\r\n {path.path.join(' -> ')}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: impactColors[path.impact],\r\n fontWeight: 600,\r\n }}>\r\n {formatTime(path.averageDuration)}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {path.callCount.toLocaleString()}\r\n </td>\r\n <td style={{\r\n textAlign: 'right',\r\n padding: theme.spacing.sm,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {formatNumber(path.frequency, 1)}\r\n </td>\r\n <td style={{\r\n textAlign: 'center',\r\n padding: theme.spacing.sm,\r\n }}>\r\n <AlertBadge severity={path.impact === 'high' ? 'error' : path.impact === 'medium' ? 'warning' : 'info'} />\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Top Functions */}\r\n {analysis.topFunctions.length > 0 && (\r\n <div style={{\r\n backgroundColor: theme.colors.surface,\r\n borderRadius: theme.borderRadius.md,\r\n padding: theme.spacing.md,\r\n border: `1px solid ${theme.colors.border}`,\r\n }}>\r\n <div style={{\r\n fontSize: theme.typography.fontSize.sm,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n marginBottom: theme.spacing.sm,\r\n }}>\r\n Top Functions (by total duration)\r\n </div>\r\n <div style={{\r\n maxHeight: '300px',\r\n overflowY: 'auto',\r\n fontSize: theme.typography.fontSize.xs,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n color: theme.colors.textSecondary,\r\n }}>\r\n {analysis.topFunctions.map((func, index) => (\r\n <div\r\n key={func.name}\r\n style={{\r\n padding: theme.spacing.sm,\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n }}\r\n >\r\n <span>{index + 1}. {func.name}</span>\r\n <span>{formatTime(func.averageDuration)} avg ({func.callCount.toLocaleString()} calls)</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import { useEffect, useState, useRef, useCallback } from 'react';\r\nimport { isProfilerEnabled } from '../core/profiler';\r\nimport { monitorState } from '../core/monitor-state';\r\nimport { Tabs, type Tab } from './components';\r\nimport { FramePanel, GPUPanel, ScenePanel, MemoryPanel, FrameTimePanel, BudgetPanel, ReactPanel, HotPathPanel } from './panels';\r\nimport { defaultTheme } from './styles/theme';\r\n\r\nexport interface PerformanceMonitorProps {\r\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\r\n defaultTab?: string;\r\n collapsed?: boolean;\r\n}\r\n\r\nexport const PerformanceMonitor = ({\r\n position = 'top-right',\r\n defaultTab = 'frames',\r\n collapsed: initialCollapsed = false,\r\n}: PerformanceMonitorProps) => {\r\n const [visible, setVisible] = useState(false);\r\n const [activeTab, setActiveTab] = useState(defaultTab);\r\n const [collapsed, setCollapsed] = useState(initialCollapsed);\r\n const [isPaused, setIsPaused] = useState(monitorState.getPaused());\r\n const [isDragging, setIsDragging] = useState(false);\r\n const [positionState, setPositionState] = useState<{ x: number; y: number } | null>(null);\r\n const dragStartPos = useRef<{ x: number; y: number } | null>(null);\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const theme = defaultTheme;\r\n\r\n const STORAGE_KEY = 'r3f-profiler-state';\r\n\r\n // Load saved state from localStorage\r\n useEffect(() => {\r\n const savedState = localStorage.getItem(STORAGE_KEY);\r\n if (savedState) {\r\n try {\r\n const parsed = JSON.parse(savedState);\r\n \r\n // Restore position\r\n if (parsed.position && typeof parsed.position.x === 'number' && typeof parsed.position.y === 'number') {\r\n setPositionState({ x: parsed.position.x, y: parsed.position.y });\r\n }\r\n \r\n // Restore collapsed state\r\n if (typeof parsed.collapsed === 'boolean') {\r\n setCollapsed(parsed.collapsed);\r\n }\r\n \r\n // Restore active tab\r\n if (typeof parsed.activeTab === 'string' && parsed.activeTab) {\r\n setActiveTab(parsed.activeTab);\r\n }\r\n } catch (e) {\r\n // Invalid saved state, ignore\r\n console.warn('Failed to load saved profiler state:', e);\r\n }\r\n }\r\n\r\n // Subscribe to pause state changes\r\n const unsubscribe = monitorState.subscribe((paused) => {\r\n setIsPaused(paused);\r\n });\r\n\r\n return () => {\r\n unsubscribe();\r\n };\r\n }, []);\r\n\r\n // Save state to localStorage\r\n const saveState = useCallback((updates: Partial<{\r\n position: { x: number; y: number };\r\n collapsed: boolean;\r\n activeTab: string;\r\n }>) => {\r\n try {\r\n const currentState = localStorage.getItem(STORAGE_KEY);\r\n const existingState = currentState ? JSON.parse(currentState) : {};\r\n \r\n const newState = {\r\n ...existingState,\r\n ...updates,\r\n };\r\n \r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(newState));\r\n } catch (e) {\r\n console.warn('Failed to save profiler state:', e);\r\n }\r\n }, []);\r\n\r\n // Save position to localStorage\r\n const savePosition = useCallback((x: number, y: number) => {\r\n saveState({ position: { x, y } });\r\n }, [saveState]);\r\n\r\n // Handle drag start\r\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\r\n // Only drag on header area, not on buttons\r\n if ((e.target as HTMLElement).closest('button')) {\r\n return;\r\n }\r\n \r\n setIsDragging(true);\r\n if (containerRef.current) {\r\n const rect = containerRef.current.getBoundingClientRect();\r\n dragStartPos.current = {\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top,\r\n };\r\n }\r\n }, []);\r\n\r\n // Handle drag\r\n useEffect(() => {\r\n if (!isDragging) return;\r\n\r\n const handleMouseMove = (e: MouseEvent) => {\r\n if (!dragStartPos.current || !containerRef.current) return;\r\n\r\n const container = containerRef.current;\r\n const containerRect = container.getBoundingClientRect();\r\n const windowWidth = window.innerWidth;\r\n const windowHeight = window.innerHeight;\r\n\r\n // Calculate new position\r\n let newX = e.clientX - dragStartPos.current.x;\r\n let newY = e.clientY - dragStartPos.current.y;\r\n\r\n // Constrain to window bounds\r\n newX = Math.max(0, Math.min(newX, windowWidth - containerRect.width));\r\n newY = Math.max(0, Math.min(newY, windowHeight - containerRect.height));\r\n\r\n const newPosition = { x: newX, y: newY };\r\n setPositionState(newPosition);\r\n saveState({ position: newPosition });\r\n };\r\n\r\n const handleMouseUp = () => {\r\n setIsDragging(false);\r\n dragStartPos.current = null;\r\n };\r\n\r\n window.addEventListener('mousemove', handleMouseMove);\r\n window.addEventListener('mouseup', handleMouseUp);\r\n\r\n return () => {\r\n window.removeEventListener('mousemove', handleMouseMove);\r\n window.removeEventListener('mouseup', handleMouseUp);\r\n };\r\n }, [isDragging, savePosition]);\r\n\r\n useEffect(() => {\r\n const checkEnabled = () => {\r\n return isProfilerEnabled();\r\n };\r\n\r\n setVisible(checkEnabled());\r\n\r\n const handleStorageChange = () => {\r\n setVisible(checkEnabled());\r\n };\r\n\r\n window.addEventListener('storage', handleStorageChange);\r\n\r\n return () => {\r\n window.removeEventListener('storage', handleStorageChange);\r\n };\r\n }, []);\r\n\r\n if (!visible) {\r\n return null;\r\n }\r\n\r\n const tabs: Tab[] = [\r\n { id: 'frames', label: 'Frames' },\r\n { id: 'gpu', label: 'GPU' },\r\n { id: 'scene', label: 'Scene' },\r\n { id: 'memory', label: 'Memory' },\r\n { id: 'frame-time', label: 'Frame Time' },\r\n { id: 'budget', label: 'Budget' },\r\n { id: 'react', label: 'React' },\r\n { id: 'hot-path', label: 'Hot Path' },\r\n ];\r\n\r\n // Calculate position styles\r\n const getPositionStyles = () => {\r\n if (positionState) {\r\n // Use saved position\r\n return {\r\n left: `${positionState.x}px`,\r\n top: `${positionState.y}px`,\r\n right: 'auto',\r\n bottom: 'auto',\r\n };\r\n }\r\n \r\n // Use default position prop\r\n const positionStyles = {\r\n 'top-left': { top: theme.spacing.md, left: theme.spacing.md, right: 'auto', bottom: 'auto' },\r\n 'top-right': { top: theme.spacing.md, right: theme.spacing.md, left: 'auto', bottom: 'auto' },\r\n 'bottom-left': { bottom: theme.spacing.md, left: theme.spacing.md, right: 'auto', top: 'auto' },\r\n 'bottom-right': { bottom: theme.spacing.md, right: theme.spacing.md, left: 'auto', top: 'auto' },\r\n };\r\n return positionStyles[position];\r\n };\r\n\r\n const currentPosition = getPositionStyles();\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n style={{\r\n position: 'fixed',\r\n ...currentPosition,\r\n width: collapsed ? 'auto' : '600px',\r\n maxWidth: collapsed ? 'auto' : '90vw',\r\n maxHeight: '80vh',\r\n backgroundColor: theme.colors.background,\r\n backdropFilter: 'blur(10px)',\r\n borderRadius: theme.borderRadius.lg,\r\n boxShadow: theme.shadows.xl,\r\n border: `1px solid ${theme.colors.border}`,\r\n zIndex: theme.zIndex.base,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n overflow: 'hidden',\r\n transition: isDragging ? 'none' : theme.transitions.normal,\r\n userSelect: isDragging ? 'none' : 'auto',\r\n }}\r\n >\r\n {/* Header */}\r\n <div\r\n onMouseDown={handleMouseDown}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n padding: theme.spacing.md,\r\n borderBottom: `1px solid ${theme.colors.border}`,\r\n backgroundColor: theme.colors.surface,\r\n cursor: isDragging ? 'grabbing' : 'grab',\r\n userSelect: 'none',\r\n }}\r\n >\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.sm,\r\n flex: 1,\r\n }}>\r\n <div style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: theme.spacing.xs,\r\n color: theme.colors.textTertiary,\r\n fontSize: theme.typography.fontSize.xs,\r\n }}>\r\n <span>⋮⋮</span>\r\n </div>\r\n <div style={{\r\n width: '8px',\r\n height: '8px',\r\n borderRadius: '50%',\r\n backgroundColor: theme.colors.success,\r\n boxShadow: `0 0 8px ${theme.colors.success}`,\r\n }} />\r\n <h2 style={{\r\n margin: 0,\r\n fontSize: theme.typography.fontSize.lg,\r\n fontWeight: 600,\r\n color: theme.colors.text,\r\n }}>\r\n Performance Monitor\r\n </h2>\r\n </div>\r\n <div style={{\r\n display: 'flex',\r\n gap: theme.spacing.xs,\r\n alignItems: 'center',\r\n }}>\r\n {isPaused && (\r\n <div style={{\r\n fontSize: theme.typography.fontSize.xs,\r\n color: theme.colors.warning,\r\n fontFamily: theme.typography.fontFamilyMono,\r\n padding: `0 ${theme.spacing.xs}`,\r\n }}>\r\n PAUSED\r\n </div>\r\n )}\r\n <button\r\n onClick={() => {\r\n monitorState.toggle();\r\n }}\r\n style={{\r\n background: 'transparent',\r\n border: 'none',\r\n color: isPaused ? theme.colors.warning : theme.colors.textSecondary,\r\n cursor: 'pointer',\r\n padding: theme.spacing.xs,\r\n borderRadius: theme.borderRadius.sm,\r\n transition: theme.transitions.fast,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = theme.colors.surfaceElevated;\r\n e.currentTarget.style.color = isPaused ? theme.colors.warning : theme.colors.text;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'transparent';\r\n e.currentTarget.style.color = isPaused ? theme.colors.warning : theme.colors.textSecondary;\r\n }}\r\n title={isPaused ? 'Resume' : 'Pause'}\r\n >\r\n {isPaused ? '▶' : '⏸'}\r\n </button>\r\n <button\r\n onClick={async () => {\r\n const { profiler } = await import('../core/profiler');\r\n await profiler.copyReportToClipboard();\r\n alert('📊 Performance report copied to clipboard!');\r\n }}\r\n style={{\r\n background: 'transparent',\r\n border: 'none',\r\n color: theme.colors.textSecondary,\r\n cursor: 'pointer',\r\n padding: theme.spacing.xs,\r\n borderRadius: theme.borderRadius.sm,\r\n transition: theme.transitions.fast,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = theme.colors.surfaceElevated;\r\n e.currentTarget.style.color = theme.colors.success;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'transparent';\r\n e.currentTarget.style.color = theme.colors.textSecondary;\r\n }}\r\n title=\"Copy Performance Report (for AI analysis)\"\r\n >\r\n 📊\r\n </button>\r\n <button\r\n onClick={() => {\r\n const newCollapsed = !collapsed;\r\n setCollapsed(newCollapsed);\r\n saveState({ collapsed: newCollapsed });\r\n }}\r\n style={{\r\n background: 'transparent',\r\n border: 'none',\r\n color: theme.colors.textSecondary,\r\n cursor: 'pointer',\r\n padding: theme.spacing.xs,\r\n borderRadius: theme.borderRadius.sm,\r\n transition: theme.transitions.fast,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = theme.colors.surfaceElevated;\r\n e.currentTarget.style.color = theme.colors.text;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'transparent';\r\n e.currentTarget.style.color = theme.colors.textSecondary;\r\n }}\r\n title={collapsed ? 'Expand' : 'Collapse'}\r\n >\r\n {collapsed ? '◀' : '▼'}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {!collapsed && (\r\n <>\r\n {/* Tabs */}\r\n <div style={{\r\n padding: `0 ${theme.spacing.md}`,\r\n backgroundColor: theme.colors.surface,\r\n }}>\r\n <Tabs\r\n tabs={tabs}\r\n activeTab={activeTab}\r\n onTabChange={(tab) => {\r\n setActiveTab(tab);\r\n saveState({ activeTab: tab });\r\n }}\r\n />\r\n </div>\r\n\r\n {/* Content */}\r\n <div style={{\r\n flex: 1,\r\n overflow: 'auto',\r\n backgroundColor: theme.colors.background,\r\n }}>\r\n {activeTab === 'frames' && <FramePanel />}\r\n {activeTab === 'gpu' && <GPUPanel />}\r\n {activeTab === 'scene' && <ScenePanel />}\r\n {activeTab === 'memory' && <MemoryPanel />}\r\n {activeTab === 'frame-time' && <FrameTimePanel />}\r\n {activeTab === 'budget' && <BudgetPanel />}\r\n {activeTab === 'react' && <ReactPanel />}\r\n {activeTab === 'hot-path' && <HotPathPanel />}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n"],"names":["Profiler","reportGenerator","urlParams","name","fn","start","result","duration","entry","removed","profiler","args","entries","data","totalTime","sum","e","listener","size","fps","frameTime","memoryMB","value","hotPathDetector","hotPathDetector$1","profile","isProfilerEnabled","reportMetric","ProfilerDataCollector","lastFrameTime","useRef","useFrame","now","GPUCollector","renderer","info","memory","render","points","lines","texturesMemory","geometriesMemory","stats","gpuCollector","SceneCollector","scene","objects","materials","textures","geometries","visible","materialSet","textureSet","geometrySet","countedMeshes","isInternalObject","obj","isRealMesh","Mesh","mesh","isRealLight","Light","traverse","object","depth","parentIsInternal","isInternal","geo","count","mat","type","key","texture","Texture","format","Camera","child","averageVerticesPerMesh","averageFacesPerMesh","image","width","height","bytesPerPixel","formatValue","sceneCollector","MemoryCollector","jsHeap","gpuMemory","leaks","used","total","limit","percentage","shortTerm","longTerm","shortFirst","shortLast","shortTimeDiff","shortMemoryDiff","shortGrowthRate","longFirst","longLast","longTimeDiff","longMemoryDiff","longGrowthRate","growthRate","leakThreshold","consistentGrowth","detected","trend","memoryCollector","FrameTimeCollector","phase","end","interval","phases","accountedTime","val","breakdown","frameTimeCollector","AutoInstrumentation","root","originalMark","options","actualDuration","autoInstrumentation","MonitorState","saved","error","monitorState","R3FStatsCollector","gl","useThree","useEffect","_state","_delta","frameBreakdown","frameInterval","realFrameTime","calculatedFps","darkTheme","defaultTheme","getPerformanceColor","thresholds","formatNumber","decimals","MetricCard","label","unit","status","color","icon","onClick","className","theme","statusColor","displayValue","displayUnit","jsxs","jsx","Tabs","tabs","activeTab","onTabChange","tab","isActive","AlertBadge","severity","children","backgroundColor","useProfilerData","setData","useState","updateData","unsubscribe","newData","unsubscribePause","paused","MAX_HISTORY_SIZE","useFrameHistory","history","setHistory","lastFrameCountRef","intervalRef","updateHistory","prev","lastValue","newHistory","currentAvgFrameTime","framesDelta","framesToAdd","i","useFrameTime","setBreakdown","updateBreakdown","newBreakdown","FrameGraph","showGrid","showLabels","maxValue","minValue","frameHistory","isPercentage","actualWidth","normalizedData","chartMax","chartMin","useMemo","dataMax","dataMin","range","normalized","svgWidthNum","pointSpacing","pathData","y","x","areaPath","targetY","ratio","isSlow","TimelineView","timeWindow","timelineData","recentFrames","index","frameTimeMax","d","frameTimeMin","fpsMax","fpsMin","chartHeight","frameTimePath","fpsPath","svgWidth","useMemoryHistory","MemoryChart","metric","memoryHistory","chartData","cutoff","recent","jsHeapData","gpuMemoryData","allValues","v","internalWidth","jsHeapPath","gpuMemoryPath","formatBytes","bytes","Fragment","FramePanel","sortedEntries","a","b","processingTime","frameTimeStatus","frameTimeHistory","maxFrameTime","entryColor","useGPUStats","setStats","updateStats","newStats","GPUPanel","drawCallsStatus","trianglesStatus","useSceneStats","ScenePanel","useMemoryStats","MemoryPanel","jsHeapStatus","leakStatus","FrameTimePanel","formatTime","ms","formatPercentage","maxPhaseValue","p","left","BudgetManager","savedBudget","parsed","budget","metrics","violations","seconds","recentViolations","budgetManager","usePerformanceBudget","setBudgetState","setViolations","newViolations","newBudget","AlertSystem","violation","title","message","alert","includeDismissed","id","enabled","audioContext","oscillator","gainNode","activeAlerts","alertSystem","useBudgetChecker","profilerData","gpuStats","memoryStats","checkBudgets","avgFrameTime","t","BudgetPanel","setBudget","clearViolations","clearBudget","getRecommendedBudget","isEditing","setIsEditing","editBudget","setEditBudget","currentMetrics","handleSaveBudget","handleUseRecommended","recommended","handleCancel","violationsBySeverity","errors","warnings","ReactMonitor","baseDuration","startTime","commitTime","componentName","timestamp","components","slowComponents","stat","recentTimeWindow","frequentComponents","reactMonitor","useReactProfiler","ReactPanel","componentsList","comp","ComponentTable","isFrequent","HotPathDetector","stack","funcCall","profilerEntries","recentCalls","call","functionFrequency","freq","normalizedFrequency","hotPaths","topFunctions","bottlenecks","impact","recommendations","hotPath","_stack","chains","chain","avgDuration","useHotPath","analysis","setAnalysis","updateAnalysis","newAnalysis","HotPathPanel","impactColors","rec","bottleneck","path","func","PerformanceMonitor","position","defaultTab","initialCollapsed","setVisible","setActiveTab","collapsed","setCollapsed","isPaused","setIsPaused","isDragging","setIsDragging","positionState","setPositionState","dragStartPos","containerRef","STORAGE_KEY","savedState","saveState","useCallback","updates","currentState","newState","savePosition","handleMouseDown","rect","handleMouseMove","containerRect","windowWidth","windowHeight","newX","newY","newPosition","handleMouseUp","checkEnabled","handleStorageChange","currentPosition","profiler$1","newCollapsed"],"mappings":"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"}
|