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

76.31% Statements 58/76
100% Branches 0/0
0% Functions 0/1
76.31% Lines 58/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 771x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                      
/**
 * 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])
}