All files / web/src/arcade-games/know-your-world/features/magnifier useMagnifierStyle.ts

0% Statements 0/76
0% Branches 0/1
0% Functions 0/1
0% Lines 0/76

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                                                                                                                                         
/**
 * Magnifier Style Hook
 *
 * Memoizes heat-based styling calculations for the magnifier and crosshair.
 * Consolidates repeated calls to getHeatBorderColors and getHeatCrosshairStyle.
 */

import { useMemo } from 'react'
import {
  getHeatBorderColors,
  getHeatCrosshairStyle,
  type HeatBorderStyle,
  type HeatCrosshairStyle,
} from '../../utils/heatStyles'
import type { FeedbackType } from '../../utils/hotColdPhrases'

// ============================================================================
// Types
// ============================================================================

export interface MagnifierStyleInputs {
  /** Current hot/cold feedback type */
  feedbackType: FeedbackType | null
  /** Whether dark mode is active */
  isDark: boolean
  /** Whether hot/cold feedback is enabled */
  hotColdEnabled: boolean
}

export interface MagnifierStyleResult {
  /** Crosshair styling (color, opacity, rotation speed, glow) */
  crosshairStyle: HeatCrosshairStyle
  /** Border styling for magnifier (border color, glow, width) */
  borderStyle: HeatBorderStyle
  /** Target rotation speed in degrees per second (derived from crosshairStyle) */
  rotationSpeedDegPerSec: number
}

// ============================================================================
// Hook Implementation
// ============================================================================

/**
 * Memoizes heat-based magnifier styling calculations.
 *
 * Instead of calling getHeatCrosshairStyle and getHeatBorderColors multiple times
 * in the render path, this hook computes them once and memoizes the result.
 *
 * @example
 * ```tsx
 * const { crosshairStyle, borderStyle, rotationSpeedDegPerSec } = useMagnifierStyle({
 *   feedbackType: hotColdFeedbackType,
 *   isDark,
 *   hotColdEnabled: effectiveHotColdEnabled,
 * })
 * ```
 */
export function useMagnifierStyle({
  feedbackType,
  isDark,
  hotColdEnabled,
}: MagnifierStyleInputs): MagnifierStyleResult {
  return useMemo(() => {
    const crosshairStyle = getHeatCrosshairStyle(feedbackType, isDark, hotColdEnabled)
    const borderStyle = getHeatBorderColors(feedbackType, isDark)

    // Convert rotation speed from degrees/frame@60fps to degrees/second
    const rotationSpeedDegPerSec = crosshairStyle.rotationSpeed * 60

    return {
      crosshairStyle,
      borderStyle,
      rotationSpeedDegPerSec,
    }
  }, [feedbackType, isDark, hotColdEnabled])
}