{"version":3,"file":"usePerformanceBudget.mjs","sources":["../../../../src/lib/performance/hooks/usePerformanceBudget.ts"],"sourcesContent":["/**\n * @file usePerformanceBudget Hook\n * @description React hook for performance budget awareness and enforcement.\n *\n * Provides components with real-time awareness of performance budget status,\n * enabling adaptive UI rendering based on budget violations.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const { isWithinBudget, degradationState, checkBudget } = usePerformanceBudget();\n *\n *   // Adapt rendering based on budget status\n *   if (!isWithinBudget('bundle.initial')) {\n *     return <LightweightVersion />;\n *   }\n *\n *   // Check custom budget\n *   const renderTime = measureRenderTime();\n *   checkBudget('customRender', renderTime, 16);\n *\n *   return <FullFeaturedVersion />;\n * }\n * ```\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react';\nimport {\n  getBudgetManager,\n  type PerformanceBudgetManager,\n  type BudgetStatusSummary,\n  type BudgetViolationRecord,\n  type DegradationState,\n  type BudgetThreshold,\n  formatBudgetValue,\n} from '../performance-budgets';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Budget status for a specific metric\n */\nexport interface BudgetStatus {\n  readonly name: string;\n  readonly status: 'ok' | 'warning' | 'critical' | 'unknown';\n  readonly currentValue: number | null;\n  readonly threshold: BudgetThreshold | undefined;\n  readonly percentOfBudget: number;\n  readonly formattedValue: string;\n  readonly formattedThreshold: string;\n}\n\n/**\n * Hook options\n */\nexport interface UsePerformanceBudgetOptions {\n  /** Specific budgets to monitor (default: all) */\n  readonly budgets?: string[];\n  /** Callback on violation */\n  readonly onViolation?: (violation: BudgetViolationRecord) => void;\n  /** Callback on degradation change */\n  readonly onDegradationChange?: (state: DegradationState) => void;\n  /** Enable debug logging */\n  readonly debug?: boolean;\n}\n\n/**\n * Hook return value\n */\nexport interface UsePerformanceBudgetReturn {\n  /** Check if a specific budget is within limits */\n  readonly isWithinBudget: (budgetName: string) => boolean;\n  /** Get status for a specific budget */\n  readonly getBudgetStatus: (budgetName: string) => BudgetStatus | null;\n  /** Get all monitored budget statuses */\n  readonly budgetStatuses: BudgetStatus[];\n  /** Current degradation state */\n  readonly degradationState: DegradationState;\n  /** Whether any budget is violated */\n  readonly hasViolations: boolean;\n  /** Recent violations */\n  readonly recentViolations: BudgetViolationRecord[];\n  /** Overall health score (0-100) */\n  readonly healthScore: number;\n  /** Check a custom budget value */\n  readonly checkBudget: (name: string, value: number, threshold?: number) => boolean;\n  /** Record a metric value */\n  readonly recordMetric: (name: string, value: number) => void;\n  /** Check if degradation strategy is active */\n  readonly isStrategyActive: (strategy: string) => boolean;\n  /** Force degradation deactivation */\n  readonly deactivateDegradation: () => void;\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for performance budget awareness\n */\nexport function usePerformanceBudget(\n  options: UsePerformanceBudgetOptions = {}\n): UsePerformanceBudgetReturn {\n  const { budgets, onViolation, onDegradationChange, debug = false } = options;\n\n  // State\n  const [budgetStatuses, setBudgetStatuses] = useState<BudgetStatusSummary[]>([]);\n  const [degradationState, setDegradationState] = useState<DegradationState>({\n    isActive: false,\n    level: 'none',\n    activeStrategies: [],\n    reason: null,\n    activatedAt: null,\n  });\n\n  // Get budget manager instance - use useState for initialization\n  const [manager] = useState<PerformanceBudgetManager>(() => {\n    return getBudgetManager({\n      debug,\n      onViolation: (violation) => {\n        onViolation?.(violation);\n      },\n      onDegradationChange: (state) => {\n        setDegradationState(state);\n        onDegradationChange?.(state);\n      },\n    });\n  });\n  const [healthScore, setHealthScore] = useState<number>(100);\n  const [recentViolations, setRecentViolations] = useState<BudgetViolationRecord[]>([]);\n\n  // Update statuses periodically\n  useEffect(() => {\n    const updateStatuses = (): void => {\n      let statuses = manager.getAllStatuses();\n\n      // Filter to specific budgets if specified\n      if (budgets && budgets.length > 0) {\n        statuses = statuses.filter((s) => budgets.includes(s.budgetName));\n      }\n\n      setBudgetStatuses(statuses);\n      setHealthScore(manager.getHealthScore());\n      setDegradationState(manager.getDegradationState());\n      setRecentViolations(manager.getViolations().slice(-10));\n    };\n\n    // Initial update\n    updateStatuses();\n\n    // Periodic updates\n    const intervalId = setInterval(updateStatuses, 1000);\n\n    return () => {\n      clearInterval(intervalId);\n    };\n  }, [manager, budgets]);\n\n  // Convert BudgetStatusSummary to BudgetStatus\n  const formattedStatuses = useMemo<BudgetStatus[]>(() => {\n    return budgetStatuses.map((summary) => {\n      const unit = summary.threshold?.unit ?? 'ms';\n      const percentOfBudget = summary.currentValue !== null && summary.threshold !== undefined\n        ? (summary.currentValue / summary.threshold.warning) * 100\n        : 0;\n\n      return {\n        name: summary.budgetName,\n        status: summary.status,\n        currentValue: summary.currentValue,\n        threshold: summary.threshold,\n        percentOfBudget,\n        formattedValue: summary.currentValue !== null\n          ? formatBudgetValue(summary.currentValue, unit)\n          : 'N/A',\n        formattedThreshold: summary.threshold !== undefined\n          ? formatBudgetValue(summary.threshold.warning, unit)\n          : 'N/A',\n      };\n    });\n  }, [budgetStatuses]);\n\n  // Check if within budget\n  const isWithinBudget = useCallback(\n    (budgetName: string): boolean => {\n      const status = manager.getStatus(budgetName);\n      return status?.status === 'ok' || status?.status === 'unknown';\n    },\n    [manager]\n  );\n\n  // Get budget status\n  const getBudgetStatus = useCallback(\n    (budgetName: string): BudgetStatus | null => {\n      const summary = manager.getStatus(budgetName);\n      if (!summary) return null;\n\n      const unit = summary.threshold?.unit ?? 'ms';\n      const percentOfBudget = summary.currentValue !== null && summary.threshold !== undefined\n        ? (summary.currentValue / summary.threshold.warning) * 100\n        : 0;\n\n      return {\n        name: summary.budgetName,\n        status: summary.status,\n        currentValue: summary.currentValue,\n        threshold: summary.threshold,\n        percentOfBudget,\n        formattedValue: summary.currentValue !== null\n          ? formatBudgetValue(summary.currentValue, unit)\n          : 'N/A',\n        formattedThreshold: summary.threshold !== undefined\n          ? formatBudgetValue(summary.threshold.warning, unit)\n          : 'N/A',\n      };\n    },\n    [manager]\n  );\n\n  // Check custom budget\n  const checkBudget = useCallback(\n    (name: string, value: number, threshold?: number): boolean => {\n      const budget = manager.getBudget(name);\n      const effectiveThreshold = threshold ?? budget?.warning;\n\n      if (effectiveThreshold === undefined) {\n        if (debug) {\n          console.warn(`[usePerformanceBudget] No threshold for budget: ${name}`);\n        }\n        return true;\n      }\n\n      manager.record(name, value);\n      return value <= effectiveThreshold;\n    },\n    [manager, debug]\n  );\n\n  // Record metric\n  const recordMetric = useCallback(\n    (name: string, value: number): void => {\n      manager.record(name, value);\n    },\n    [manager]\n  );\n\n  // Check if strategy is active\n  const isStrategyActive = useCallback(\n    (strategy: string): boolean => {\n      // Validate strategy is a valid DegradationStrategy\n      const validStrategies = [\n        'reduce-animations',\n        'reduce-images',\n        'reduce-features',\n        'reduce-polling',\n        'defer-non-critical',\n        'custom',\n      ] as const;\n      type ValidStrategy = (typeof validStrategies)[number];\n      if (validStrategies.includes(strategy as ValidStrategy)) {\n        return manager.isStrategyActive(strategy as ValidStrategy);\n      }\n      return false;\n    },\n    [manager]\n  );\n\n  // Deactivate degradation\n  const deactivateDegradation = useCallback((): void => {\n    manager.deactivateDegradation();\n  }, [manager]);\n\n  // Compute hasViolations\n  const hasViolations = useMemo(() => {\n    return formattedStatuses.some((s) => s.status === 'warning' || s.status === 'critical');\n  }, [formattedStatuses]);\n\n  return {\n    isWithinBudget,\n    getBudgetStatus,\n    budgetStatuses: formattedStatuses,\n    degradationState,\n    hasViolations,\n    recentViolations,\n    healthScore,\n    checkBudget,\n    recordMetric,\n    isStrategyActive,\n    deactivateDegradation,\n  };\n}\n\n// ============================================================================\n// Utility Hooks\n// ============================================================================\n\n/**\n * Hook to get a single budget status\n */\nexport function useBudgetStatus(budgetName: string): BudgetStatus | null {\n  const { getBudgetStatus } = usePerformanceBudget({ budgets: [budgetName] });\n  return getBudgetStatus(budgetName);\n}\n\n/**\n * Hook to check if in degraded mode\n */\nexport function useDegradedMode(): {\n  isDegraded: boolean;\n  level: DegradationState['level'];\n  strategies: string[];\n} {\n  const { degradationState } = usePerformanceBudget();\n\n  return {\n    isDegraded: degradationState.isActive,\n    level: degradationState.level,\n    strategies: degradationState.activeStrategies,\n  };\n}\n\n/**\n * Hook to conditionally render based on budget\n */\nexport function useBudgetConditional<T>(\n  budgetName: string,\n  fullValue: T,\n  reducedValue: T\n): T {\n  const { isWithinBudget } = usePerformanceBudget({ budgets: [budgetName] });\n\n  return isWithinBudget(budgetName) ? fullValue : reducedValue;\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n// Types are already exported at their declaration sites\n"],"names":["usePerformanceBudget","options","budgets","onViolation","onDegradationChange","debug","budgetStatuses","setBudgetStatuses","useState","degradationState","setDegradationState","manager","getBudgetManager","violation","state","healthScore","setHealthScore","recentViolations","setRecentViolations","useEffect","updateStatuses","statuses","s","intervalId","formattedStatuses","useMemo","summary","unit","percentOfBudget","formatBudgetValue","isWithinBudget","useCallback","budgetName","status","getBudgetStatus","checkBudget","name","value","threshold","budget","effectiveThreshold","recordMetric","isStrategyActive","strategy","deactivateDegradation","hasViolations","useBudgetStatus","useDegradedMode","useBudgetConditional","fullValue","reducedValue"],"mappings":"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"}