{"version":3,"file":"useStreamPriority.mjs","sources":["../../../../src/lib/streaming/hooks/useStreamPriority.ts"],"sourcesContent":["/**\n * @file useStreamPriority Hook\n * @description Hook for controlling stream priority dynamically.\n *\n * Enables runtime priority adjustment for stream boundaries,\n * allowing components to escalate or de-escalate their streaming\n * priority based on user interaction or visibility changes.\n *\n * @module streaming/hooks/useStreamPriority\n * @version 1.0.0\n * @author Harbor Framework Team\n *\n * @example\n * ```tsx\n * function HoverableCard({ boundaryId }: { boundaryId: string }) {\n *   const { priority, escalate, deescalate } = useStreamPriority(boundaryId);\n *\n *   return (\n *     <div\n *       onMouseEnter={escalate}\n *       onMouseLeave={deescalate}\n *     >\n *       <p>Priority: {priority}</p>\n *       <StreamBoundary id={boundaryId} priority={priority}>\n *         <CardContent />\n *       </StreamBoundary>\n *     </div>\n *   );\n * }\n * ```\n */\n\nimport { useState, useCallback, useEffect, useRef, useMemo } from 'react';\n\nimport { useOptionalStreamContext } from '../StreamProvider';\n\nimport { type UseStreamPriorityResult, StreamPriority, PRIORITY_VALUES } from '../types';\n\n// ============================================================================\n// Priority Level Ordering\n// ============================================================================\n\n/**\n * Ordered array of priority levels from highest to lowest.\n */\nconst PRIORITY_ORDER: StreamPriority[] = [\n  StreamPriority.Critical,\n  StreamPriority.High,\n  StreamPriority.Normal,\n  StreamPriority.Low,\n];\n\n/**\n * Gets the next higher priority level.\n */\nfunction getHigherPriority(current: StreamPriority): StreamPriority {\n  const index = PRIORITY_ORDER.indexOf(current);\n  const [highestPriority] = PRIORITY_ORDER;\n  if (index <= 0) return highestPriority ?? StreamPriority.Critical;\n  const nextPriority = PRIORITY_ORDER[index - 1];\n  return nextPriority ?? StreamPriority.Critical;\n}\n\n/**\n * Gets the next lower priority level.\n */\nfunction getLowerPriority(current: StreamPriority): StreamPriority {\n  const index = PRIORITY_ORDER.indexOf(current);\n  const lowestPriority = PRIORITY_ORDER[PRIORITY_ORDER.length - 1];\n  if (index >= PRIORITY_ORDER.length - 1) return lowestPriority ?? StreamPriority.Low;\n  const nextPriority = PRIORITY_ORDER[index + 1];\n  return nextPriority ?? StreamPriority.Low;\n}\n\n// ============================================================================\n// Hook Options\n// ============================================================================\n\n/**\n * Options for the useStreamPriority hook.\n */\nexport interface UseStreamPriorityOptions {\n  /**\n   * Initial priority level.\n   * @default StreamPriority.Normal\n   */\n  initialPriority?: StreamPriority;\n\n  /**\n   * Minimum priority level (highest allowed).\n   * @default StreamPriority.Critical\n   */\n  minPriority?: StreamPriority;\n\n  /**\n   * Maximum priority level (lowest allowed).\n   * @default StreamPriority.Low\n   */\n  maxPriority?: StreamPriority;\n\n  /**\n   * Callback when priority changes.\n   */\n  onPriorityChange?: (priority: StreamPriority) => void;\n\n  /**\n   * Auto-escalate on user interaction.\n   * @default false\n   */\n  escalateOnInteraction?: boolean;\n\n  /**\n   * Auto-escalate when element becomes visible.\n   * @default false\n   */\n  escalateOnVisible?: boolean;\n\n  /**\n   * Visibility threshold for auto-escalation.\n   * @default 0.5\n   */\n  visibilityThreshold?: number;\n\n  /**\n   * Cooldown period before de-escalation in milliseconds.\n   * @default 0\n   */\n  deescalateCooldown?: number;\n}\n\n// ============================================================================\n// Default Result\n// ============================================================================\n\nconst DEFAULT_RESULT: UseStreamPriorityResult = {\n  priority: StreamPriority.Normal,\n  setPriority: () => {},\n  escalate: () => {},\n  deescalate: () => {},\n};\n\n// ============================================================================\n// Main Hook Implementation\n// ============================================================================\n\n/**\n * Hook for controlling stream priority.\n *\n * @description\n * Provides an interface for dynamically adjusting stream priority,\n * enabling responsive streaming based on user behavior and visibility.\n *\n * Features:\n * - Manual priority control\n * - Escalation and de-escalation helpers\n * - Optional auto-escalation on interaction\n * - Optional auto-escalation on visibility\n * - Priority bounds enforcement\n * - Cooldown support for de-escalation\n *\n * @param boundaryId - Boundary ID to control\n * @param options - Optional configuration\n * @returns Priority control interface\n *\n * @example\n * ```tsx\n * // Basic usage\n * const { priority, setPriority, escalate, deescalate } = useStreamPriority('content');\n *\n * // With options\n * const { priority, escalate } = useStreamPriority('content', {\n *   initialPriority: StreamPriority.Low,\n *   escalateOnInteraction: true,\n *   deescalateCooldown: 5000,\n * });\n *\n * // Manual control\n * setPriority(StreamPriority.High);\n *\n * // Incremental adjustment\n * escalate();   // Low -> Normal -> High -> Critical\n * deescalate(); // Critical -> High -> Normal -> Low\n * ```\n */\nexport function useStreamPriority(\n  boundaryId: string,\n  options: UseStreamPriorityOptions = {}\n): UseStreamPriorityResult {\n  const {\n    initialPriority = StreamPriority.Normal,\n    minPriority = StreamPriority.Critical,\n    maxPriority = StreamPriority.Low,\n    onPriorityChange,\n    escalateOnVisible = false,\n    visibilityThreshold = 0.5,\n    deescalateCooldown = 0,\n  } = options;\n\n  const context = useOptionalStreamContext();\n  const [priority, setPriorityState] = useState<StreamPriority>(initialPriority);\n  const cooldownTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const elementRef = useRef<HTMLElement | null>(null);\n\n  // ==========================================================================\n  // Priority Bounds\n  // ==========================================================================\n\n  const minPriorityValue = PRIORITY_VALUES[minPriority];\n  const maxPriorityValue = PRIORITY_VALUES[maxPriority];\n\n  /**\n   * Clamps priority within configured bounds.\n   */\n  const clampPriority = useCallback(\n    (targetPriority: StreamPriority): StreamPriority => {\n      const targetValue = PRIORITY_VALUES[targetPriority];\n      if (targetValue < minPriorityValue) return minPriority;\n      if (targetValue > maxPriorityValue) return maxPriority;\n      return targetPriority;\n    },\n    [minPriority, maxPriority, minPriorityValue, maxPriorityValue]\n  );\n\n  // ==========================================================================\n  // Priority Control\n  // ==========================================================================\n\n  const setPriority = useCallback(\n    (newPriority: StreamPriority) => {\n      const clampedPriority = clampPriority(newPriority);\n      setPriorityState(clampedPriority);\n      onPriorityChange?.(clampedPriority);\n    },\n    [clampPriority, onPriorityChange]\n  );\n\n  const escalate = useCallback(() => {\n    setPriorityState((current) => {\n      const newPriority = clampPriority(getHigherPriority(current));\n      if (newPriority !== current) {\n        onPriorityChange?.(newPriority);\n      }\n      return newPriority;\n    });\n\n    // Clear any pending de-escalation\n    if (cooldownTimeoutRef.current) {\n      clearTimeout(cooldownTimeoutRef.current);\n      cooldownTimeoutRef.current = null;\n    }\n  }, [clampPriority, onPriorityChange]);\n\n  const deescalate = useCallback(() => {\n    const performDeescalate = (): void => {\n      setPriorityState((current) => {\n        const newPriority = clampPriority(getLowerPriority(current));\n        if (newPriority !== current) {\n          onPriorityChange?.(newPriority);\n        }\n        return newPriority;\n      });\n    };\n\n    if (deescalateCooldown > 0) {\n      // Schedule de-escalation after cooldown\n      if (cooldownTimeoutRef.current) {\n        clearTimeout(cooldownTimeoutRef.current);\n      }\n      cooldownTimeoutRef.current = setTimeout(performDeescalate, deescalateCooldown);\n    } else {\n      performDeescalate();\n    }\n  }, [clampPriority, onPriorityChange, deescalateCooldown]);\n\n  // ==========================================================================\n  // Auto-Escalation on Visibility\n  // ==========================================================================\n\n  useEffect(() => {\n    if (!escalateOnVisible || typeof IntersectionObserver === 'undefined') {\n      return;\n    }\n\n    // Find the element by boundary ID\n    const element = document.querySelector(`[data-stream-id=\"${boundaryId}\"]`);\n    if (!element) return;\n\n    elementRef.current = element as HTMLElement;\n\n    const observer = new IntersectionObserver(\n      (entries) => {\n        for (const entry of entries) {\n          if (entry.isIntersecting && entry.intersectionRatio >= visibilityThreshold) {\n            // Escalate when visible\n            escalate();\n          } else {\n            // De-escalate when not visible\n            deescalate();\n          }\n        }\n      },\n      { threshold: visibilityThreshold }\n    );\n\n    observer.observe(element);\n\n    return () => {\n      observer.disconnect();\n    };\n  }, [boundaryId, escalateOnVisible, visibilityThreshold, escalate, deescalate]);\n\n  // ==========================================================================\n  // Cleanup\n  // ==========================================================================\n\n  useEffect(() => {\n    return () => {\n      if (cooldownTimeoutRef.current) {\n        clearTimeout(cooldownTimeoutRef.current);\n      }\n    };\n  }, []);\n\n  // Return default if no context\n  if (!context) {\n    return DEFAULT_RESULT;\n  }\n\n  return {\n    priority,\n    setPriority,\n    escalate,\n    deescalate,\n  };\n}\n\n// ============================================================================\n// Extended Priority Hook\n// ============================================================================\n\n/**\n * Extended result with additional controls.\n */\nexport interface UseExtendedStreamPriorityResult extends UseStreamPriorityResult {\n  /** Whether at maximum priority (critical) */\n  isMaxPriority: boolean;\n  /** Whether at minimum priority (low) */\n  isMinPriority: boolean;\n  /** Set to maximum priority */\n  maximize: () => void;\n  /** Set to minimum priority */\n  minimize: () => void;\n  /** Reset to initial priority */\n  reset: () => void;\n  /** Priority value (0-3, lower is higher priority) */\n  priorityValue: number;\n  /** Props to spread on element for auto-escalation on hover */\n  hoverProps: {\n    onMouseEnter: () => void;\n    onMouseLeave: () => void;\n  };\n  /** Props to spread on element for auto-escalation on focus */\n  focusProps: {\n    onFocus: () => void;\n    onBlur: () => void;\n  };\n}\n\n/**\n * Extended stream priority hook with additional controls.\n *\n * @description\n * Provides all the functionality of useStreamPriority plus\n * additional convenience methods and computed values.\n *\n * @example\n * ```tsx\n * function InteractiveCard({ boundaryId }: { boundaryId: string }) {\n *   const {\n *     priority,\n *     isMaxPriority,\n *     maximize,\n *     reset,\n *     hoverProps,\n *     focusProps,\n *   } = useExtendedStreamPriority(boundaryId);\n *\n *   return (\n *     <div {...hoverProps} {...focusProps}>\n *       <p>Priority: {priority}</p>\n *       <button onClick={maximize} disabled={isMaxPriority}>\n *         Maximize Priority\n *       </button>\n *       <button onClick={reset}>Reset</button>\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useExtendedStreamPriority(\n  boundaryId: string,\n  options: UseStreamPriorityOptions = {}\n): UseExtendedStreamPriorityResult {\n  const { initialPriority = StreamPriority.Normal } = options;\n  const basePriority = useStreamPriority(boundaryId, options);\n\n  const isMaxPriority = basePriority.priority === StreamPriority.Critical;\n  const isMinPriority = basePriority.priority === StreamPriority.Low;\n  const priorityValue = PRIORITY_VALUES[basePriority.priority];\n\n  const maximize = useCallback(() => {\n    basePriority.setPriority(StreamPriority.Critical);\n  }, [basePriority]);\n\n  const minimize = useCallback(() => {\n    basePriority.setPriority(StreamPriority.Low);\n  }, [basePriority]);\n\n  const reset = useCallback(() => {\n    basePriority.setPriority(initialPriority);\n  }, [basePriority, initialPriority]);\n\n  const hoverProps = useMemo(\n    () => ({\n      onMouseEnter: basePriority.escalate,\n      onMouseLeave: basePriority.deescalate,\n    }),\n    [basePriority.escalate, basePriority.deescalate]\n  );\n\n  const focusProps = useMemo(\n    () => ({\n      onFocus: basePriority.escalate,\n      onBlur: basePriority.deescalate,\n    }),\n    [basePriority.escalate, basePriority.deescalate]\n  );\n\n  return {\n    ...basePriority,\n    isMaxPriority,\n    isMinPriority,\n    priorityValue,\n    maximize,\n    minimize,\n    reset,\n    hoverProps,\n    focusProps,\n  };\n}\n\n// ============================================================================\n// Priority Preset Hooks\n// ============================================================================\n\n/**\n * Hook for critical priority streams.\n *\n * @description\n * Pre-configured for critical priority with no ability\n * to de-escalate below high priority.\n */\nexport function useCriticalPriority(\n  boundaryId: string,\n  options: Omit<UseStreamPriorityOptions, 'initialPriority' | 'maxPriority'> = {}\n): UseStreamPriorityResult {\n  return useStreamPriority(boundaryId, {\n    ...options,\n    initialPriority: StreamPriority.Critical,\n    maxPriority: StreamPriority.High,\n  });\n}\n\n/**\n * Hook for deferred priority streams.\n *\n * @description\n * Pre-configured for low priority with ability\n * to escalate on interaction.\n */\nexport function useDeferredPriority(\n  boundaryId: string,\n  options: Omit<UseStreamPriorityOptions, 'initialPriority'> = {}\n): UseStreamPriorityResult {\n  return useStreamPriority(boundaryId, {\n    ...options,\n    initialPriority: StreamPriority.Low,\n    escalateOnInteraction: true,\n  });\n}\n"],"names":["PRIORITY_ORDER","StreamPriority","getHigherPriority","current","index","highestPriority","getLowerPriority","lowestPriority","DEFAULT_RESULT","useStreamPriority","boundaryId","options","initialPriority","minPriority","maxPriority","onPriorityChange","escalateOnVisible","visibilityThreshold","deescalateCooldown","context","useOptionalStreamContext","priority","setPriorityState","useState","cooldownTimeoutRef","useRef","elementRef","minPriorityValue","PRIORITY_VALUES","maxPriorityValue","clampPriority","useCallback","targetPriority","targetValue","setPriority","newPriority","clampedPriority","escalate","deescalate","performDeescalate","useEffect","element","observer","entries","entry","useExtendedStreamPriority","basePriority","isMaxPriority","isMinPriority","priorityValue","maximize","minimize","reset","hoverProps","useMemo","focusProps","useCriticalPriority","useDeferredPriority"],"mappings":"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"}