{"version":3,"file":"render-scheduler.mjs","sources":["../../../src/lib/performance/render-scheduler.ts"],"sourcesContent":["/**\n * @file Intelligent Render Scheduler\n * @description PhD-level render scheduling infrastructure with frame budget awareness,\n * priority queues, and automatic work deferral for optimal INP and responsiveness.\n *\n * Features:\n * - Frame budget tracking (16.67ms for 60fps)\n * - Priority queues with deadline enforcement\n * - Yield to main thread for responsiveness\n * - Concurrent work coordination\n * - Automatic work deferral to idle periods\n * - Render deadline enforcement\n * - React 18 concurrent features integration\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type DependencyList } from 'react';\n\n// ============================================================================\n// Utility Hook for Dynamic Dependencies\n// ============================================================================\n\n/**\n * Custom hook to track dependency array changes with a stable version number.\n * This allows proper ESLint compliance when using dynamic dependency arrays.\n */\n/* eslint-disable react-hooks/refs */\nfunction useDepsVersion(deps: DependencyList): number {\n  const versionRef = useRef(0);\n  const prevDepsRef = useRef<DependencyList>(deps);\n\n  // Compare deps and increment version if changed\n  const depsChanged =\n    deps.length !== prevDepsRef.current.length ||\n    deps.some((dep, i) => !Object.is(dep, prevDepsRef.current[i]));\n\n  if (depsChanged) {\n    versionRef.current++;\n    prevDepsRef.current = deps;\n  }\n\n  return versionRef.current;\n}\n/* eslint-enable react-hooks/refs */\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type for the experimental Scheduler API\n */\ninterface GlobalWithScheduler {\n  scheduler: {\n    yield: () => Promise<void>;\n  };\n}\n\n/**\n * Type guard for checking if globalThis has the scheduler.yield API\n */\nfunction hasSchedulerYieldAPI(\n  obj: typeof globalThis\n): obj is typeof globalThis & GlobalWithScheduler {\n  return (\n    'scheduler' in obj &&\n    typeof (obj as GlobalWithScheduler).scheduler === 'object' &&\n    (obj as GlobalWithScheduler).scheduler !== null &&\n    'yield' in (obj as GlobalWithScheduler).scheduler\n  );\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Render priority levels\n */\nexport type RenderPriority = 'immediate' | 'user-blocking' | 'normal' | 'low' | 'idle';\n\n/**\n * Task status\n */\nexport type TaskStatus = 'pending' | 'running' | 'completed' | 'cancelled';\n\n/**\n * Scheduled task\n */\nexport interface ScheduledTask {\n  id: string;\n  priority: RenderPriority;\n  callback: () => void | Promise<void>;\n  status: TaskStatus;\n  deadline?: number;\n  createdAt: number;\n  startedAt?: number;\n  completedAt?: number;\n  estimatedDuration?: number;\n}\n\n/**\n * Scheduler statistics\n */\nexport interface SchedulerStats {\n  totalTasks: number;\n  completedTasks: number;\n  cancelledTasks: number;\n  averageWaitTime: number;\n  averageExecutionTime: number;\n  droppedFrames: number;\n  frameTime: number;\n  utilization: number;\n}\n\n/**\n * Frame budget configuration\n */\nexport interface FrameBudgetConfig {\n  /** Target frames per second */\n  targetFPS: number;\n  /** Reserved time for browser work (ms) */\n  browserReserve: number;\n  /** Maximum time for a single task (ms) */\n  maxTaskDuration: number;\n  /** Enable adaptive budgeting */\n  adaptive: boolean;\n}\n\n/**\n * Scheduler configuration\n */\nexport interface RenderSchedulerConfig {\n  /** Frame budget settings */\n  frameBudget?: Partial<FrameBudgetConfig>;\n  /** Enable debug logging */\n  debug?: boolean;\n  /** Maximum queue size per priority */\n  maxQueueSize?: number;\n  /** Enable automatic cleanup */\n  autoCleanup?: boolean;\n  /** Cleanup interval (ms) */\n  cleanupInterval?: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_FRAME_BUDGET: FrameBudgetConfig = {\n  targetFPS: 60,\n  browserReserve: 4, // Reserve 4ms for browser rendering\n  maxTaskDuration: 8, // Max 8ms per task\n  adaptive: true,\n};\n\nconst PRIORITY_VALUES: Record<RenderPriority, number> = {\n  immediate: 0,\n  'user-blocking': 1,\n  normal: 2,\n  low: 3,\n  idle: 4,\n};\n\nconst PRIORITY_TIMEOUTS: Record<RenderPriority, number> = {\n  immediate: 0,\n  'user-blocking': 100,\n  normal: 500,\n  low: 2000,\n  idle: 10000,\n};\n\n// ============================================================================\n// Frame Budget Tracker\n// ============================================================================\n\n/**\n * Tracks frame budget and provides timing utilities\n */\nclass FrameBudgetTracker {\n  private config: FrameBudgetConfig;\n  private frameTimes: number[] = [];\n  private frameStartTime = 0;\n  private droppedFrames = 0;\n\n  constructor(config: FrameBudgetConfig) {\n    this.config = config;\n  }\n\n  /**\n   * Get frame budget in milliseconds\n   */\n  get frameBudget(): number {\n    return 1000 / this.config.targetFPS;\n  }\n\n  /**\n   * Get available time for tasks\n   */\n  get availableBudget(): number {\n    return this.frameBudget - this.config.browserReserve;\n  }\n\n  /**\n   * Get adaptive budget based on recent frame times\n   */\n  getAdaptiveBudget(): number {\n    if (!this.config.adaptive || this.frameTimes.length < 3) {\n      return this.availableBudget;\n    }\n\n    // Calculate average recent frame time\n    const recentFrames = this.frameTimes.slice(-10);\n    const avgFrameTime = recentFrames.reduce((a, b) => a + b, 0) / recentFrames.length;\n\n    // If running behind, reduce budget\n    if (avgFrameTime > this.frameBudget) {\n      return Math.max(4, this.availableBudget * 0.5);\n    }\n\n    // If ahead, can use more budget\n    if (avgFrameTime < this.frameBudget * 0.8) {\n      return Math.min(this.config.maxTaskDuration, this.availableBudget * 1.2);\n    }\n\n    return this.availableBudget;\n  }\n\n  /**\n   * Start frame timing\n   */\n  startFrame(): void {\n    this.frameStartTime = performance.now();\n  }\n\n  /**\n   * End frame and record timing\n   */\n  endFrame(): number {\n    const frameTime = performance.now() - this.frameStartTime;\n    this.frameTimes.push(frameTime);\n\n    // Keep only last 60 frames\n    if (this.frameTimes.length > 60) {\n      this.frameTimes.shift();\n    }\n\n    // Track dropped frames\n    if (frameTime > this.frameBudget) {\n      this.droppedFrames++;\n    }\n\n    return frameTime;\n  }\n\n  /**\n   * Check if there's remaining budget\n   */\n  hasRemainingBudget(): boolean {\n    const elapsed = performance.now() - this.frameStartTime;\n    return elapsed < this.getAdaptiveBudget();\n  }\n\n  /**\n   * Get remaining time in current frame\n   */\n  getRemainingTime(): number {\n    const elapsed = performance.now() - this.frameStartTime;\n    return Math.max(0, this.getAdaptiveBudget() - elapsed);\n  }\n\n  /**\n   * Get statistics\n   */\n  getStats(): { avgFrameTime: number; droppedFrames: number } {\n    const avgFrameTime =\n      this.frameTimes.length > 0\n        ? this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length\n        : 0;\n\n    return { avgFrameTime, droppedFrames: this.droppedFrames };\n  }\n\n  /**\n   * Reset statistics\n   */\n  reset(): void {\n    this.frameTimes = [];\n    this.droppedFrames = 0;\n  }\n}\n\n// ============================================================================\n// Priority Queue\n// ============================================================================\n\n/**\n * Priority queue for scheduled tasks\n */\nclass TaskPriorityQueue {\n  private queues: Map<RenderPriority, ScheduledTask[]> = new Map();\n  private readonly maxSize: number;\n\n  constructor(maxSize = 100) {\n    this.maxSize = maxSize;\n    for (const priority of Object.keys(PRIORITY_VALUES) as RenderPriority[]) {\n      this.queues.set(priority, []);\n    }\n  }\n\n  /**\n   * Get total pending task count\n   */\n  get size(): number {\n    let total = 0;\n    this.queues.forEach((queue) => (total += queue.length));\n    return total;\n  }\n\n  /**\n   * Check if queue is empty\n   */\n  get isEmpty(): boolean {\n    return this.size === 0;\n  }\n\n  /**\n   * Add task to queue\n   */\n  enqueue(task: ScheduledTask): boolean {\n    const queue = this.queues.get(task.priority);\n    if (queue === undefined) return false;\n\n    if (queue.length >= this.maxSize) {\n      // Drop lowest priority task if queue is full\n      const lowestPriority = this.getLowestPriorityWithTasks();\n      if (\n        lowestPriority != null &&\n        PRIORITY_VALUES[lowestPriority] > PRIORITY_VALUES[task.priority]\n      ) {\n        const lowestQueue = this.queues.get(lowestPriority);\n        if (lowestQueue != null) {\n          lowestQueue.pop();\n        }\n      } else {\n        return false;\n      }\n    }\n\n    queue.push(task);\n    return true;\n  }\n\n  /**\n   * Get next task (highest priority)\n   */\n  dequeue(): ScheduledTask | null {\n    for (const priority of Object.keys(PRIORITY_VALUES) as RenderPriority[]) {\n      const queue = this.queues.get(priority);\n      if (queue != null && queue.length > 0) {\n        return queue.shift() ?? null;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Peek at next task without removing\n   */\n  peek(): ScheduledTask | null {\n    for (const priority of Object.keys(PRIORITY_VALUES) as RenderPriority[]) {\n      const queue = this.queues.get(priority);\n      if (queue !== undefined && queue.length > 0) {\n        return queue[0] ?? null;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Get all pending tasks of a priority\n   */\n  getTasksByPriority(priority: RenderPriority): ScheduledTask[] {\n    return [...(this.queues.get(priority) ?? [])];\n  }\n\n  /**\n   * Remove task by ID\n   */\n  removeById(id: string): boolean {\n    for (const queue of this.queues.values()) {\n      const index = queue.findIndex((t) => t.id === id);\n      if (index !== -1) {\n        queue.splice(index, 1);\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Clear all queues\n   */\n  clear(): void {\n    this.queues.forEach((queue) => (queue.length = 0));\n  }\n\n  /**\n   * Get lowest priority with pending tasks\n   */\n  private getLowestPriorityWithTasks(): RenderPriority | null {\n    const priorities = Object.keys(PRIORITY_VALUES) as RenderPriority[];\n    for (let i = priorities.length - 1; i >= 0; i--) {\n      const priority = priorities[i];\n      if (priority === undefined) continue;\n      const queue = this.queues.get(priority);\n      if (queue !== undefined && queue.length > 0) {\n        return priority;\n      }\n    }\n    return null;\n  }\n}\n\n// ============================================================================\n// Render Scheduler\n// ============================================================================\n\n/**\n * Intelligent render scheduler with frame budget awareness\n */\nexport class RenderScheduler {\n  private static instance: RenderScheduler;\n  private config: Required<RenderSchedulerConfig>;\n  private frameBudget: FrameBudgetTracker;\n  private queue: TaskPriorityQueue;\n  private isProcessing = false;\n  private animationFrameId: number | null = null;\n  private idleCallbackId: number | null = null;\n  private completedTasks: ScheduledTask[] = [];\n  private taskIdCounter = 0;\n  private cleanupIntervalId: ReturnType<typeof setInterval> | null = null;\n\n  constructor(config: RenderSchedulerConfig = {}) {\n    this.config = {\n      frameBudget: { ...DEFAULT_FRAME_BUDGET, ...config.frameBudget },\n      debug: config.debug ?? false,\n      maxQueueSize: config.maxQueueSize ?? 100,\n      autoCleanup: config.autoCleanup ?? true,\n      cleanupInterval: config.cleanupInterval ?? 30000,\n    };\n\n    this.frameBudget = new FrameBudgetTracker(this.config.frameBudget as FrameBudgetConfig);\n    this.queue = new TaskPriorityQueue(this.config.maxQueueSize);\n\n    if (this.config.autoCleanup) {\n      this.startCleanup();\n    }\n  }\n\n  /**\n   * Get singleton instance\n   */\n  static getInstance(config?: RenderSchedulerConfig): RenderScheduler {\n    RenderScheduler.instance ??= new RenderScheduler(config);\n    return RenderScheduler.instance;\n  }\n\n  /**\n   * Reset singleton (for testing)\n   */\n  static reset(): void {\n    if (RenderScheduler.instance !== undefined && RenderScheduler.instance !== null) {\n      RenderScheduler.instance.stop();\n      // Type-safe null assignment for singleton reset\n      (RenderScheduler as unknown as { instance: RenderScheduler | null }).instance = null;\n    }\n  }\n\n  /**\n   * Schedule a task\n   */\n  schedule(\n    callback: () => void | Promise<void>,\n    options: {\n      priority?: RenderPriority;\n      deadline?: number;\n      estimatedDuration?: number;\n    } = {}\n  ): string {\n    const { priority = 'normal', deadline, estimatedDuration } = options;\n\n    const task: ScheduledTask = {\n      id: `task-${++this.taskIdCounter}`,\n      priority,\n      callback,\n      status: 'pending',\n      createdAt: performance.now(),\n      deadline: deadline ?? performance.now() + PRIORITY_TIMEOUTS[priority],\n      estimatedDuration,\n    };\n\n    this.queue.enqueue(task);\n    this.log(`Scheduled task ${task.id} with priority ${priority}`);\n\n    this.ensureProcessing();\n\n    return task.id;\n  }\n\n  /**\n   * Cancel a scheduled task\n   */\n  cancel(taskId: string): boolean {\n    return this.queue.removeById(taskId);\n  }\n\n  /**\n   * Schedule immediate work (runs synchronously if budget allows)\n   */\n  scheduleImmediate(callback: () => void): void {\n    if (this.frameBudget.hasRemainingBudget()) {\n      callback();\n    } else {\n      this.schedule(callback, { priority: 'immediate' });\n    }\n  }\n\n  /**\n   * Yield to main thread for responsiveness\n   */\n  async yieldToMain(): Promise<void> {\n    return new Promise((resolve) => {\n      // Use scheduler.yield() if available (Chrome 115+)\n      if (hasSchedulerYieldAPI(globalThis)) {\n        const { scheduler } = globalThis as typeof globalThis & {\n          scheduler: { yield: () => Promise<void> };\n        };\n        void scheduler.yield().then(resolve);\n      } else {\n        // Fallback to setTimeout\n        setTimeout(resolve, 0);\n      }\n    });\n  }\n\n  /**\n   * Run work in chunks, yielding between chunks\n   */\n  async runInChunks<T>(\n    items: T[],\n    processor: (item: T, index: number) => void,\n    options: { chunkSize?: number; yieldAfter?: number } = {}\n  ): Promise<void> {\n    const { chunkSize = 10, yieldAfter = 5 } = options;\n\n    for (let i = 0; i < items.length; i += chunkSize) {\n      const chunk = items.slice(i, i + chunkSize);\n\n      for (let j = 0; j < chunk.length; j++) {\n        const item = chunk[j];\n        if (item !== undefined) {\n          processor(item, i + j);\n        }\n\n        // Yield after processing yieldAfter items\n        if ((j + 1) % yieldAfter === 0) {\n          await this.yieldToMain();\n        }\n      }\n\n      // Always yield between chunks\n      if (i + chunkSize < items.length) {\n        await this.yieldToMain();\n      }\n    }\n  }\n\n  /**\n   * Stop the scheduler\n   */\n  stop(): void {\n    if (this.animationFrameId !== null) {\n      cancelAnimationFrame(this.animationFrameId);\n      this.animationFrameId = null;\n    }\n    if (this.idleCallbackId !== null) {\n      cancelIdleCallback(this.idleCallbackId);\n      this.idleCallbackId = null;\n    }\n    if (this.cleanupIntervalId !== null) {\n      clearInterval(this.cleanupIntervalId);\n      this.cleanupIntervalId = null;\n    }\n    this.queue.clear();\n    this.isProcessing = false;\n  }\n\n  /**\n   * Get scheduler statistics\n   */\n  getStats(): SchedulerStats {\n    const frameStats = this.frameBudget.getStats();\n    const completed = this.completedTasks.filter((t) => t.status === 'completed');\n    const cancelled = this.completedTasks.filter((t) => t.status === 'cancelled');\n\n    const avgWaitTime =\n      completed.length > 0\n        ? completed.reduce((sum, t) => sum + ((t.startedAt ?? t.createdAt) - t.createdAt), 0) /\n          completed.length\n        : 0;\n\n    const avgExecutionTime =\n      completed.length > 0\n        ? completed.reduce(\n            (sum, t) =>\n              sum + ((t.completedAt ?? t.startedAt ?? t.createdAt) - (t.startedAt ?? t.createdAt)),\n            0\n          ) / completed.length\n        : 0;\n\n    return {\n      totalTasks: this.completedTasks.length,\n      completedTasks: completed.length,\n      cancelledTasks: cancelled.length,\n      averageWaitTime: avgWaitTime,\n      averageExecutionTime: avgExecutionTime,\n      droppedFrames: frameStats.droppedFrames,\n      frameTime: frameStats.avgFrameTime,\n      utilization: this.isProcessing ? 1 : 0,\n    };\n  }\n\n  /**\n   * Ensure processing is happening\n   */\n  private ensureProcessing(): void {\n    if (this.isProcessing) return;\n    this.processQueue();\n  }\n\n  /**\n   * Process the task queue\n   */\n  private processQueue(): void {\n    if (this.queue.isEmpty) {\n      this.isProcessing = false;\n      return;\n    }\n\n    this.isProcessing = true;\n    this.frameBudget.startFrame();\n\n    // Process immediate tasks synchronously\n    this.processImmediateTasks();\n\n    // Schedule frame work\n    this.animationFrameId = requestAnimationFrame(() => {\n      this.processFrameTasks();\n      this.frameBudget.endFrame();\n\n      // Continue processing if more tasks\n      if (!this.queue.isEmpty) {\n        this.processQueue();\n      } else {\n        this.isProcessing = false;\n      }\n    });\n\n    // Schedule idle work\n    if (typeof requestIdleCallback !== 'undefined') {\n      this.idleCallbackId = requestIdleCallback((deadline) => {\n        this.processIdleTasks(deadline);\n      });\n    }\n  }\n\n  /**\n   * Process immediate priority tasks\n   */\n  private processImmediateTasks(): void {\n    const immediateTasks = this.queue.getTasksByPriority('immediate');\n    for (const task of immediateTasks) {\n      void this.executeTask(task);\n      this.queue.removeById(task.id);\n    }\n  }\n\n  /**\n   * Process tasks within frame budget\n   */\n  private processFrameTasks(): void {\n    while (this.frameBudget.hasRemainingBudget() && !this.queue.isEmpty) {\n      const task = this.queue.peek();\n      if (task === null) break;\n\n      // Skip idle tasks in frame processing\n      if (task.priority === 'idle') break;\n\n      // Check if task would exceed budget\n      if (\n        task.estimatedDuration !== undefined &&\n        task.estimatedDuration > this.frameBudget.getRemainingTime()\n      ) {\n        break;\n      }\n\n      this.queue.dequeue();\n      void this.executeTask(task);\n    }\n  }\n\n  /**\n   * Process idle tasks during browser idle time\n   */\n  private processIdleTasks(deadline: IdleDeadline): void {\n    while (deadline.timeRemaining() > 0 && !this.queue.isEmpty) {\n      const task = this.queue.peek();\n      if (task === null) break;\n\n      // Only process low and idle tasks here\n      if (task.priority !== 'idle' && task.priority !== 'low') break;\n\n      this.queue.dequeue();\n      void this.executeTask(task);\n    }\n  }\n\n  /**\n   * Execute a single task\n   */\n  private async executeTask(task: ScheduledTask): Promise<void> {\n    task.status = 'running';\n    task.startedAt = performance.now();\n\n    try {\n      await task.callback();\n      task.status = 'completed';\n    } catch (error) {\n      task.status = 'cancelled';\n      this.log(`Task ${task.id} failed:`, error);\n    }\n\n    task.completedAt = performance.now();\n    this.completedTasks.push(task);\n  }\n\n  /**\n   * Start cleanup interval\n   */\n  private startCleanup(): void {\n    this.cleanupIntervalId = setInterval(() => {\n      // Keep only last 100 completed tasks\n      if (this.completedTasks.length > 100) {\n        this.completedTasks = this.completedTasks.slice(-100);\n      }\n    }, this.config.cleanupInterval);\n  }\n\n  /**\n   * Debug logging\n   */\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      console.info(`[RenderScheduler] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Hook for optimized rendering with frame budget awareness\n */\nexport function useOptimizedRender<T>(\n  computeFn: () => T,\n  deps: DependencyList,\n  options: {\n    priority?: RenderPriority;\n    defer?: boolean;\n  } = {}\n): T | undefined {\n  const { priority = 'normal', defer = false } = options;\n  const [value, setValue] = useState<T | undefined>(undefined);\n  const scheduler = useRef(RenderScheduler.getInstance());\n  const isFirstRender = useRef(true);\n\n  // Track dependency changes with stable version number\n  const depsVersion = useDepsVersion(deps);\n\n  useEffect(() => {\n    if (isFirstRender.current && !defer) {\n      // Compute immediately on first render\n      setValue(computeFn());\n      isFirstRender.current = false;\n      return;\n    }\n\n    // Schedule subsequent updates\n    const taskId = scheduler.current.schedule(\n      () => {\n        setValue(computeFn());\n      },\n      { priority }\n    );\n\n    return () => {\n      /* eslint-disable-next-line react-hooks/exhaustive-deps */\n      scheduler.current.cancel(taskId);\n    };\n  }, [depsVersion, computeFn, defer, priority]);\n\n  return value;\n}\n\n/**\n * Hook for deferred rendering\n */\nexport function useDeferredRender(\n  shouldDefer: boolean,\n  delay = 0\n): { isDeferred: boolean; isDeferring: boolean } {\n  const [isDeferred, setIsDeferred] = useState(shouldDefer);\n  const [isDeferring, setIsDeferring] = useState(false);\n\n  useEffect(() => {\n    if (!shouldDefer) {\n      /* eslint-disable-next-line react-hooks/set-state-in-effect */\n      setIsDeferred(false);\n      setIsDeferring(false);\n      return;\n    }\n\n    setIsDeferring(true);\n\n    const scheduler = RenderScheduler.getInstance();\n    const taskId = scheduler.schedule(\n      () => {\n        setIsDeferred(true);\n        setIsDeferring(false);\n      },\n      { priority: 'low' }\n    );\n\n    const timeoutId =\n      delay > 0\n        ? setTimeout(() => {\n            setIsDeferred(true);\n            setIsDeferring(false);\n            scheduler.cancel(taskId);\n          }, delay)\n        : undefined;\n\n    return () => {\n      scheduler.cancel(taskId);\n      if (timeoutId !== undefined) clearTimeout(timeoutId);\n    };\n  }, [shouldDefer, delay]);\n\n  return { isDeferred, isDeferring };\n}\n\n/**\n * Hook for scheduling work with yield to main\n */\nexport function useScheduledWork(): {\n  schedule: (callback: () => void | Promise<void>, priority?: RenderPriority) => string;\n  cancel: (taskId: string) => void;\n  yieldToMain: () => Promise<void>;\n  runInChunks: <T>(\n    items: T[],\n    processor: (item: T, index: number) => void,\n    options?: { chunkSize?: number; yieldAfter?: number }\n  ) => Promise<void>;\n} {\n  const scheduler = useMemo(() => RenderScheduler.getInstance(), []);\n\n  const schedule = useCallback(\n    (callback: () => void | Promise<void>, priority: RenderPriority = 'normal') => {\n      return scheduler.schedule(callback, { priority });\n    },\n    [scheduler]\n  );\n\n  const cancel = useCallback(\n    (taskId: string) => {\n      scheduler.cancel(taskId);\n    },\n    [scheduler]\n  );\n\n  const yieldToMain = useCallback(async () => scheduler.yieldToMain(), [scheduler]);\n\n  const runInChunks = useCallback(\n    async <T>(\n      items: T[],\n      processor: (item: T, index: number) => void,\n      options?: { chunkSize?: number; yieldAfter?: number }\n    ) => scheduler.runInChunks(items, processor, options),\n    [scheduler]\n  );\n\n  return { schedule, cancel, yieldToMain, runInChunks };\n}\n\n/**\n * Hook for tracking render performance\n */\nexport function useRenderBudget(): {\n  hasRemainingBudget: boolean;\n  remainingTime: number;\n  stats: SchedulerStats;\n} {\n  const [stats, setStats] = useState<SchedulerStats>({\n    totalTasks: 0,\n    completedTasks: 0,\n    cancelledTasks: 0,\n    averageWaitTime: 0,\n    averageExecutionTime: 0,\n    droppedFrames: 0,\n    frameTime: 0,\n    utilization: 0,\n  });\n\n  const scheduler = useMemo(() => RenderScheduler.getInstance(), []);\n\n  useEffect(() => {\n    const updateStats = (): void => {\n      setStats(scheduler.getStats());\n    };\n\n    const intervalId = setInterval(updateStats, 1000);\n    return () => clearInterval(intervalId);\n  }, [scheduler]);\n\n  return {\n    hasRemainingBudget: stats.frameTime < 16.67,\n    remainingTime: Math.max(0, 16.67 - stats.frameTime),\n    stats,\n  };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get the global render scheduler instance\n */\nexport function getRenderScheduler(config?: RenderSchedulerConfig): RenderScheduler {\n  return RenderScheduler.getInstance(config);\n}\n\n/**\n * Reset the global scheduler (for testing)\n */\nexport function resetRenderScheduler(): void {\n  RenderScheduler.reset();\n}\n\n/**\n * Schedule work at a given priority\n */\nexport function scheduleWork(\n  callback: () => void | Promise<void>,\n  priority: RenderPriority = 'normal'\n): string {\n  return RenderScheduler.getInstance().schedule(callback, { priority });\n}\n\n/**\n * Cancel scheduled work\n */\nexport function cancelWork(taskId: string): boolean {\n  return RenderScheduler.getInstance().cancel(taskId);\n}\n\n/**\n * Yield to main thread\n */\nexport async function yieldToMain(): Promise<void> {\n  return RenderScheduler.getInstance().yieldToMain();\n}\n\n/**\n * Run work in chunks with yielding\n */\nexport async function runInChunks<T>(\n  items: T[],\n  processor: (item: T, index: number) => void,\n  options?: { chunkSize?: number; yieldAfter?: number }\n): Promise<void> {\n  return RenderScheduler.getInstance().runInChunks(items, processor, options);\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport default {\n  RenderScheduler,\n  getRenderScheduler,\n  resetRenderScheduler,\n  scheduleWork,\n  cancelWork,\n  yieldToMain,\n  runInChunks,\n  useOptimizedRender,\n  useDeferredRender,\n  useScheduledWork,\n  useRenderBudget,\n};\n\n// ============================================================================\n// HMR Support\n// ============================================================================\n\n// Vite HMR disposal to prevent memory leaks during hot module replacement\nif (import.meta.hot) {\n  import.meta.hot.dispose(() => {\n    RenderScheduler.reset();\n  });\n}\n"],"names":["useDepsVersion","deps","versionRef","useRef","prevDepsRef","dep","i","hasSchedulerYieldAPI","obj","DEFAULT_FRAME_BUDGET","PRIORITY_VALUES","PRIORITY_TIMEOUTS","FrameBudgetTracker","config","recentFrames","avgFrameTime","a","b","frameTime","elapsed","TaskPriorityQueue","maxSize","priority","total","queue","task","lowestPriority","lowestQueue","id","index","t","priorities","RenderScheduler","callback","options","deadline","estimatedDuration","taskId","resolve","scheduler","items","processor","chunkSize","yieldAfter","chunk","j","item","frameStats","completed","cancelled","avgWaitTime","sum","avgExecutionTime","immediateTasks","error","message","args","useOptimizedRender","computeFn","defer","value","setValue","useState","isFirstRender","depsVersion","useEffect","useScheduledWork","useMemo","schedule","useCallback","cancel","yieldToMain","runInChunks","useRenderBudget","stats","setStats","intervalId","getRenderScheduler","resetRenderScheduler","scheduleWork","cancelWork"],"mappings":"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"}