import { useState, useEffect, useRef, useCallback } from 'react'; interface UseLazyWidgetOptions { rootMargin?: string; threshold?: number; delay?: number; } export function useLazyWidget(options: UseLazyWidgetOptions = {}) { const { rootMargin = '100px', threshold = 0, delay = 0 } = options; const [isVisible, setIsVisible] = useState(false); const [hasLoaded, setHasLoaded] = useState(false); const ref = useRef(null); useEffect(() => { const element = ref.current; if (!element) return; const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { if (delay > 0) { setTimeout(() => { setIsVisible(true); setHasLoaded(true); }, delay); } else { setIsVisible(true); setHasLoaded(true); } observer.unobserve(element); } }, { rootMargin, threshold } ); observer.observe(element); return () => observer.disconnect(); }, [rootMargin, threshold, delay]); return { ref, isVisible, hasLoaded }; } // Virtualization hook for large lists export function useVirtualList( items: T[], itemHeight: number, containerHeight: number, overscan: number = 3 ) { const [scrollTop, setScrollTop] = useState(0); const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan); const endIndex = Math.min( items.length - 1, Math.ceil((scrollTop + containerHeight) / itemHeight) + overscan ); const visibleItems = items.slice(startIndex, endIndex + 1).map((item, index) => ({ item, index: startIndex + index, style: { position: 'absolute' as const, top: (startIndex + index) * itemHeight, height: itemHeight, width: '100%', }, })); const totalHeight = items.length * itemHeight; const handleScroll = useCallback((e: React.UIEvent) => { setScrollTop(e.currentTarget.scrollTop); }, []); return { visibleItems, totalHeight, handleScroll, startIndex, endIndex, }; } // Performance monitoring hook export function usePerformanceMonitor(componentName: string) { const renderCount = useRef(0); const lastRenderTime = useRef(performance.now()); useEffect(() => { renderCount.current++; const now = performance.now(); const delta = now - lastRenderTime.current; lastRenderTime.current = now; if (process.env.NODE_ENV === 'development' && delta > 16) { console.warn(`[Performance] ${componentName} render took ${delta.toFixed(2)}ms (render #${renderCount.current})`); } }); return { renderCount: renderCount.current }; }