All files / web/src/arcade-games/know-your-world/features/hint useHintAnimation.ts

60.37% Statements 64/106
100% Branches 0/0
0% Functions 0/1
60.37% Lines 64/106

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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 1071x 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 1x 1x 1x 1x 1x 1x                                                                                      
/**
 * Hint Animation Hook
 *
 * Manages the pulsing animation effect when a hint is shown to highlight
 * the target region on the map.
 *
 * Usage:
 * ```tsx
 * const { hintFlashProgress, isHintAnimating } = useHintAnimation({
 *   hintActive: props.hintActive,
 * })
 * ```
 */
 
'use client'
 
import { useEffect, useState } from 'react'
import { usePulsingAnimation } from '../animations'
 
// ============================================================================
// Types
// ============================================================================
 
export interface HintActive {
  regionId: string
  timestamp: number
}
 
export interface UseHintAnimationOptions {
  /** The currently active hint, or null if no hint */
  hintActive: HintActive | null
}
 
export interface UseHintAnimationReturn {
  /** Pulsing value 0-1 for flash animation */
  hintFlashProgress: number
  /** Whether animation is currently in progress */
  isHintAnimating: boolean
}
 
// ============================================================================
// Constants
// ============================================================================
 
/** Duration of the hint animation in milliseconds */
const HINT_ANIMATION_DURATION = 1500
 
/** Number of pulses during the hint animation */
const HINT_ANIMATION_PULSES = 2
 
// ============================================================================
// Hook Implementation
// ============================================================================
 
/**
 * Hook for managing hint pulsing animation.
 *
 * When hintActive changes (detected by timestamp), triggers a brief pulsing
 * animation to draw attention to the target region.
 *
 * @param options - Configuration options
 * @returns Hint animation state
 */
export function useHintAnimation(options: UseHintAnimationOptions): UseHintAnimationReturn {
  const { hintActive } = options

  // Animation state
  const [hintFlashProgress, setHintFlashProgress] = useState(0)
  const [isHintAnimating, setIsHintAnimating] = useState(false)

  // Animation controller
  const hintAnimation = usePulsingAnimation()

  // Hint animation effect - brief pulse to highlight target region
  useEffect(() => {
    if (!hintActive) {
      setHintFlashProgress(0)
      setIsHintAnimating(false)
      return
    }

    // Start animation
    setIsHintAnimating(true)

    // Animation: 2 pulses over 1.5 seconds (shorter than give-up)
    hintAnimation.start({
      duration: HINT_ANIMATION_DURATION,
      pulses: HINT_ANIMATION_PULSES,
      onProgress: setHintFlashProgress,
      onComplete: () => {
        setHintFlashProgress(0)
        setIsHintAnimating(false)
      },
    })

    // Cleanup
    return () => {
      hintAnimation.cancel()
    }
  }, [hintActive?.timestamp, hintAnimation]) // Re-run when timestamp changes

  return {
    hintFlashProgress,
    isHintAnimating,
  }
}