Kraft102's picture
fix: sql.js Docker/Alpine compatibility layer for PatternMemory and FailureMemory
5a81b95
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<HTMLDivElement>(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<T>(
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<HTMLDivElement>) => {
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 };
}