{"version":3,"file":"useHydrationPriority.mjs","sources":["../../../../src/lib/hydration/hooks/useHydrationPriority.ts"],"sourcesContent":["/**\n * @file useHydrationPriority Hook\n * @description Hook for dynamically controlling hydration priority of boundaries.\n *\n * This hook enables runtime adjustment of hydration priorities based on\n * user behavior, viewport changes, or application state.\n *\n * @module hydration/hooks/useHydrationPriority\n *\n * @example\n * ```tsx\n * function SmartComponent({ boundaryId }: { boundaryId: string }) {\n *   const { priority, setPriority, boost, reduce } = useHydrationPriority(boundaryId);\n *\n *   // Boost priority on hover\n *   const handleMouseEnter = () => boost();\n *\n *   // Reduce when scrolled away\n *   useEffect(() => {\n *     const observer = new IntersectionObserver(([entry]) => {\n *       if (!entry.isIntersecting) {\n *         reduce();\n *       } else {\n *         setPriority('normal');\n *       }\n *     });\n *\n *     observer.observe(ref.current);\n *     return () => observer.disconnect();\n *   }, [reduce, setPriority]);\n *\n *   return (\n *     <div ref={ref} onMouseEnter={handleMouseEnter}>\n *       Current priority: {priority}\n *     </div>\n *   );\n * }\n * ```\n */\n\nimport { useState, useEffect, useCallback, useMemo, type RefObject } from 'react';\n\nimport { useOptionalHydrationContext } from '../HydrationProvider';\nimport { getHydrationScheduler } from '../hydration-scheduler';\n\nimport type { HydrationPriority, HydrationBoundaryId } from '../types';\n\nimport { createBoundaryId } from '../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Priority level as a numeric value (0 = highest, 4 = lowest).\n */\nexport type PriorityLevel = 0 | 1 | 2 | 3 | 4;\n\n/**\n * Return type for the useHydrationPriority hook.\n */\nexport interface UseHydrationPriorityReturn {\n  /**\n   * Current priority level as a string.\n   */\n  readonly priority: HydrationPriority;\n\n  /**\n   * Current priority as a numeric value (0 = highest, 4 = lowest).\n   */\n  readonly priorityLevel: PriorityLevel;\n\n  /**\n   * Sets the priority to a specific level.\n   *\n   * @param priority - New priority level\n   */\n  readonly setPriority: (priority: HydrationPriority) => void;\n\n  /**\n   * Increases priority by one level (towards critical).\n   * No-op if already at critical priority.\n   */\n  readonly boost: () => void;\n\n  /**\n   * Decreases priority by one level (towards idle).\n   * No-op if already at idle priority.\n   */\n  readonly reduce: () => void;\n\n  /**\n   * Sets priority to critical (highest).\n   */\n  readonly makeCritical: () => void;\n\n  /**\n   * Sets priority to idle (lowest).\n   */\n  readonly makeIdle: () => void;\n\n  /**\n   * Resets priority to the original/default level.\n   */\n  readonly reset: () => void;\n\n  /**\n   * The original priority before any changes.\n   */\n  readonly originalPriority: HydrationPriority;\n}\n\n/**\n * Options for the useHydrationPriority hook.\n */\nexport interface UseHydrationPriorityOptions {\n  /**\n   * Initial priority level if boundary is not yet registered.\n   *\n   * @default 'normal'\n   */\n  readonly defaultPriority?: HydrationPriority;\n\n  /**\n   * Whether to persist priority changes across renders.\n   *\n   * @default true\n   */\n  readonly persist?: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Priority levels ordered from highest to lowest.\n */\nconst PRIORITY_ORDER: readonly HydrationPriority[] = [\n  'critical',\n  'high',\n  'normal',\n  'low',\n  'idle',\n] as const;\n\n/**\n * Maps priority strings to numeric levels.\n */\nconst PRIORITY_TO_LEVEL: Record<HydrationPriority, PriorityLevel> = {\n  critical: 0,\n  high: 1,\n  normal: 2,\n  low: 3,\n  idle: 4,\n};\n\n/**\n * Maps numeric levels to priority strings.\n */\nconst LEVEL_TO_PRIORITY: Record<PriorityLevel, HydrationPriority> = {\n  0: 'critical',\n  1: 'high',\n  2: 'normal',\n  3: 'low',\n  4: 'idle',\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Clamps a priority level to valid bounds.\n */\nfunction clampLevel(level: number): PriorityLevel {\n  return Math.max(0, Math.min(4, Math.round(level))) as PriorityLevel;\n}\n\n/**\n * Gets the next higher priority (towards critical).\n */\nfunction getHigherPriority(current: HydrationPriority): HydrationPriority {\n  const currentLevel = PRIORITY_TO_LEVEL[current];\n  const newLevel = clampLevel(currentLevel - 1);\n  return LEVEL_TO_PRIORITY[newLevel];\n}\n\n/**\n * Gets the next lower priority (towards idle).\n */\nfunction getLowerPriority(current: HydrationPriority): HydrationPriority {\n  const currentLevel = PRIORITY_TO_LEVEL[current];\n  const newLevel = clampLevel(currentLevel + 1);\n  return LEVEL_TO_PRIORITY[newLevel];\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for dynamically controlling hydration priority.\n *\n * Enables runtime adjustment of hydration priorities based on\n * user behavior or application state.\n *\n * @param boundaryId - ID of the boundary to control\n * @param options - Hook options\n * @returns Priority control interface\n *\n * @example\n * ```tsx\n * // Basic priority control\n * function PriorityControls({ boundaryId }: { boundaryId: string }) {\n *   const { priority, boost, reduce, makeCritical, makeIdle } = useHydrationPriority(boundaryId);\n *\n *   return (\n *     <div>\n *       <span>Priority: {priority}</span>\n *       <button onClick={boost}>Boost</button>\n *       <button onClick={reduce}>Reduce</button>\n *       <button onClick={makeCritical}>Critical</button>\n *       <button onClick={makeIdle}>Idle</button>\n *     </div>\n *   );\n * }\n *\n * // Automatic priority based on visibility\n * function VisibilityAwarePriority({ boundaryId }: { boundaryId: string }) {\n *   const containerRef = useRef<HTMLDivElement>(null);\n *   const { setPriority } = useHydrationPriority(boundaryId);\n *\n *   useEffect(() => {\n *     const observer = new IntersectionObserver(\n *       ([entry]) => {\n *         if (entry.isIntersecting) {\n *           setPriority(entry.intersectionRatio > 0.5 ? 'high' : 'normal');\n *         } else {\n *           setPriority('low');\n *         }\n *       },\n *       { threshold: [0, 0.5, 1] }\n *     );\n *\n *     if (containerRef.current) {\n *       observer.observe(containerRef.current);\n *     }\n *\n *     return () => observer.disconnect();\n *   }, [setPriority]);\n *\n *   return <div ref={containerRef}>...</div>;\n * }\n * ```\n */\nexport function useHydrationPriority(\n  boundaryId: string | HydrationBoundaryId,\n  options: UseHydrationPriorityOptions = {}\n): UseHydrationPriorityReturn {\n  const { defaultPriority = 'normal' } = options;\n\n  // Normalize boundary ID\n  const normalizedId = useMemo(\n    () =>\n      typeof boundaryId === 'string'\n        ? createBoundaryId(boundaryId)\n        : boundaryId,\n    [boundaryId]\n  );\n\n  // Get context (optional)\n  const context = useOptionalHydrationContext();\n\n  // ==========================================================================\n  // State\n  // ==========================================================================\n\n  const [currentPriority, setCurrentPriority] = useState<HydrationPriority>(defaultPriority);\n  const [originalPriority] = useState<HydrationPriority>(defaultPriority);\n\n  // ==========================================================================\n  // Sync with Scheduler\n  // ==========================================================================\n\n  useEffect(() => {\n    // Try to get current priority from scheduler\n    try {\n      const scheduler = getHydrationScheduler();\n      const status = scheduler.getStatus(normalizedId);\n\n      if (status) {\n        // We don't have direct access to task priority from status,\n        // so we keep the local state as source of truth\n      }\n    } catch {\n      // Scheduler not available\n    }\n  }, [normalizedId]);\n\n  // ==========================================================================\n  // Priority Setter\n  // ==========================================================================\n\n  const setPriority = useCallback(\n    (priority: HydrationPriority): void => {\n      setCurrentPriority(priority);\n\n      // Update scheduler if available\n      if (context) {\n        context.updatePriority(normalizedId, priority);\n      } else {\n        try {\n          const scheduler = getHydrationScheduler();\n          scheduler.updatePriority(normalizedId, priority);\n        } catch {\n          // Scheduler not available\n        }\n      }\n    },\n    [context, normalizedId]\n  );\n\n  // ==========================================================================\n  // Priority Controls\n  // ==========================================================================\n\n  const boost = useCallback((): void => {\n    const newPriority = getHigherPriority(currentPriority);\n    if (newPriority !== currentPriority) {\n      setPriority(newPriority);\n    }\n  }, [currentPriority, setPriority]);\n\n  const reduce = useCallback((): void => {\n    const newPriority = getLowerPriority(currentPriority);\n    if (newPriority !== currentPriority) {\n      setPriority(newPriority);\n    }\n  }, [currentPriority, setPriority]);\n\n  const makeCritical = useCallback((): void => {\n    setPriority('critical');\n  }, [setPriority]);\n\n  const makeIdle = useCallback((): void => {\n    setPriority('idle');\n  }, [setPriority]);\n\n  const reset = useCallback((): void => {\n    setPriority(originalPriority);\n  }, [originalPriority, setPriority]);\n\n  // ==========================================================================\n  // Return\n  // ==========================================================================\n\n  return useMemo<UseHydrationPriorityReturn>(\n    () => ({\n      priority: currentPriority,\n      priorityLevel: PRIORITY_TO_LEVEL[currentPriority],\n      setPriority,\n      boost,\n      reduce,\n      makeCritical,\n      makeIdle,\n      reset,\n      originalPriority,\n    }),\n    [\n      currentPriority,\n      setPriority,\n      boost,\n      reduce,\n      makeCritical,\n      makeIdle,\n      reset,\n      originalPriority,\n    ]\n  );\n}\n\n/**\n * Hook for adaptive priority based on user engagement signals.\n *\n * Automatically adjusts priority based on:\n * - Hover: Boosts priority\n * - Focus: Boosts priority\n * - Visibility: Adjusts based on viewport intersection\n *\n * @param boundaryId - ID of the boundary to control\n * @param elementRef - React ref to the element to observe\n * @returns Priority control interface\n *\n * @example\n * ```tsx\n * function AdaptiveComponent({ boundaryId }: { boundaryId: string }) {\n *   const containerRef = useRef<HTMLDivElement>(null);\n *   const { priority } = useAdaptiveHydrationPriority(boundaryId, containerRef);\n *\n *   return (\n *     <div ref={containerRef} tabIndex={0}>\n *       <span>Auto-adjusted priority: {priority}</span>\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useAdaptiveHydrationPriority(\n  boundaryId: string | HydrationBoundaryId,\n  elementRef: RefObject<HTMLElement>\n): UseHydrationPriorityReturn {\n  const priorityControl = useHydrationPriority(boundaryId);\n\n  useEffect(() => {\n    const element = elementRef.current;\n    if (element === null || element === undefined) return;\n\n    // Hover handler - boost on hover\n    const handleMouseEnter = (): void => {\n      if (priorityControl.priorityLevel > 1) {\n        priorityControl.boost();\n      }\n    };\n\n    const handleMouseLeave = (): void => {\n      // Optional: restore after a delay\n    };\n\n    // Focus handler - boost on focus\n    const handleFocus = (): void => {\n      priorityControl.makeCritical();\n    };\n\n    const handleBlur = (): void => {\n      priorityControl.reset();\n    };\n\n    // Add listeners\n    element.addEventListener('mouseenter', handleMouseEnter);\n    element.addEventListener('mouseleave', handleMouseLeave);\n    element.addEventListener('focusin', handleFocus);\n    element.addEventListener('focusout', handleBlur);\n\n    // Intersection observer for visibility\n    const observer = new IntersectionObserver(\n      ([entry]) => {\n        if (!entry) return;\n        if (!entry.isIntersecting) {\n          priorityControl.reduce();\n        } else if (entry.intersectionRatio > 0.5) {\n          priorityControl.boost();\n        }\n      },\n      { threshold: [0, 0.5] }\n    );\n\n    observer.observe(element);\n\n    return () => {\n      element.removeEventListener('mouseenter', handleMouseEnter);\n      element.removeEventListener('mouseleave', handleMouseLeave);\n      element.removeEventListener('focusin', handleFocus);\n      element.removeEventListener('focusout', handleBlur);\n      observer.disconnect();\n    };\n  }, [elementRef, priorityControl]);\n\n  return priorityControl;\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { PRIORITY_ORDER, PRIORITY_TO_LEVEL, LEVEL_TO_PRIORITY };\n// Types are already exported inline above\n"],"names":["PRIORITY_ORDER","PRIORITY_TO_LEVEL","LEVEL_TO_PRIORITY","clampLevel","level","getHigherPriority","current","currentLevel","newLevel","getLowerPriority","useHydrationPriority","boundaryId","options","defaultPriority","normalizedId","useMemo","createBoundaryId","context","useOptionalHydrationContext","currentPriority","setCurrentPriority","useState","originalPriority","useEffect","status","getHydrationScheduler","setPriority","useCallback","priority","boost","newPriority","reduce","makeCritical","makeIdle","reset","useAdaptiveHydrationPriority","elementRef","priorityControl","element","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","observer","entry"],"mappings":"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"}