"use client" import * as React from "react" export interface IncrementalRenderOptions { enabled?: boolean threshold?: number chunkSize?: number intervalMs?: number } export interface IncrementalRenderState { renderCount: number isLazyLoading: boolean shouldIncrementalRender: boolean } const DEFAULT_THRESHOLD = 300 const DEFAULT_CHUNK_SIZE = 200 const DEFAULT_INTERVAL_MS = 48 /** * Progressive render utility for large in-memory datasets. * Renders an initial chunk immediately, then appends rows over idle ticks. */ export function useIncrementalRender( totalCount: number, { enabled = true, threshold = DEFAULT_THRESHOLD, chunkSize = DEFAULT_CHUNK_SIZE, intervalMs = DEFAULT_INTERVAL_MS, }: IncrementalRenderOptions = {}, ): IncrementalRenderState { const safeTotal = Math.max(0, totalCount) const shouldIncrementalRender = enabled && safeTotal > threshold const initialCount = shouldIncrementalRender ? Math.min(safeTotal, chunkSize) : safeTotal const [renderCount, setRenderCount] = React.useState(initialCount) React.useEffect(() => { setRenderCount(initialCount) }, [initialCount, safeTotal]) React.useEffect(() => { if (!shouldIncrementalRender) return if (renderCount >= safeTotal) return let cancelled = false const flush = () => { if (cancelled) return setRenderCount(prev => Math.min(safeTotal, prev + chunkSize)) } if ( typeof globalThis !== "undefined" && "requestIdleCallback" in globalThis && typeof globalThis.requestIdleCallback === "function" ) { const idleId = globalThis.requestIdleCallback(flush, { timeout: intervalMs }) return () => { cancelled = true globalThis.cancelIdleCallback(idleId) } } const timer = globalThis.setTimeout(flush, intervalMs) return () => { cancelled = true globalThis.clearTimeout(timer) } }, [chunkSize, intervalMs, renderCount, safeTotal, shouldIncrementalRender]) return { renderCount, isLazyLoading: shouldIncrementalRender && renderCount < safeTotal, shouldIncrementalRender, } }