All files / web/src/arcade-games/know-your-world/features/precision PrecisionModeIndicator.tsx

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

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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181                                                                                                                                                                                                                                                                                                                                                                         
/**
 * Precision Mode Indicator Component
 *
 * Visual overlays that indicate precision mode status:
 * - Gold scrim when at threshold (precision mode recommended)
 * - Filter effect for "disabled" appearance when zoom is capped
 *
 * These overlays help communicate to the user when they should
 * click to activate precision mode for fine-grained cursor control.
 */

'use client'

import type { CSSProperties } from 'react'

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

export interface PrecisionModeScrimProps {
  /** Whether the scrim should be visible */
  show: boolean
  /** Border radius to match container */
  borderRadius?: string
}

export interface PrecisionModeFilterProps {
  /** Whether to apply the disabled filter effect */
  isAtThreshold: boolean
  /** Whether precision mode is active (filter should not apply) */
  pointerLocked: boolean
  /** Whether device supports precision mode */
  canUsePrecisionMode: boolean
}

// ============================================================================
// Scrim Component
// ============================================================================

/**
 * Gold scrim overlay that appears when precision mode is at threshold.
 *
 * This visual indicator shows that the magnifier is at a zoom level
 * where precision mode should be activated for accurate selection.
 *
 * @example
 * ```tsx
 * <PrecisionModeScrim
 *   show={isAtThreshold && !pointerLocked && canUsePrecisionMode}
 *   borderRadius="12px"
 * />
 * ```
 */
export function PrecisionModeScrim({ show, borderRadius = '12px' }: PrecisionModeScrimProps) {
  if (!show) return null

  return (
    <div
      data-element="precision-mode-scrim"
      style={{
        position: 'absolute',
        inset: 0,
        background: 'rgba(251, 191, 36, 0.15)', // Gold scrim
        pointerEvents: 'none',
        borderRadius,
      }}
    />
  )
}

// ============================================================================
// Filter Style Utility
// ============================================================================

/**
 * Get the CSS filter style for precision mode threshold indication.
 *
 * When at threshold but not in precision mode, applies a "disabled"
 * visual effect (reduced brightness and saturation) to indicate
 * that the user should click to activate precision mode.
 *
 * @param props - Filter configuration
 * @returns CSS filter string ('none' or 'brightness(0.6) saturate(0.5)')
 *
 * @example
 * ```tsx
 * const filterStyle = getPrecisionModeFilter({
 *   isAtThreshold: true,
 *   pointerLocked: false,
 *   canUsePrecisionMode: true,
 * })
 * // Returns: 'brightness(0.6) saturate(0.5)'
 * ```
 */
export function getPrecisionModeFilter({
  isAtThreshold,
  pointerLocked,
  canUsePrecisionMode,
}: PrecisionModeFilterProps): CSSProperties['filter'] {
  // No filter when in precision mode (pointer locked)
  if (pointerLocked) return 'none'

  // No filter when precision mode isn't available
  if (!canUsePrecisionMode) return 'none'

  // No filter when below threshold
  if (!isAtThreshold) return 'none'

  // Apply "disabled" visual effect when at threshold but not in precision mode
  return 'brightness(0.6) saturate(0.5)'
}

// ============================================================================
// Status Label Utility
// ============================================================================

export interface PrecisionModeStatusLabelOptions {
  /** Current zoom level */
  currentZoom: number
  /** Current screen pixel ratio */
  screenPixelRatio: number
  /** Whether at threshold */
  isAtThreshold: boolean
  /** Whether pointer is locked (precision mode active) */
  pointerLocked: boolean
  /** Whether device supports precision mode */
  canUsePrecisionMode: boolean
  /** Whether to show debug info */
  showDebugInfo: boolean
}

/**
 * Get the status label text for the magnifier overlay.
 *
 * Returns different messages based on precision mode state:
 * - "Click to activate precision mode" when at threshold
 * - Debug info (zoom + ratio) when debug is enabled
 * - Simple zoom level otherwise
 *
 * @param options - Status label options
 * @returns Status label text
 *
 * @example
 * ```tsx
 * const label = getPrecisionModeStatusLabel({
 *   currentZoom: 25,
 *   screenPixelRatio: 22,
 *   isAtThreshold: true,
 *   pointerLocked: false,
 *   canUsePrecisionMode: true,
 *   showDebugInfo: false,
 * })
 * // Returns: 'Click to activate precision mode'
 * ```
 */
export function getPrecisionModeStatusLabel({
  currentZoom,
  screenPixelRatio,
  isAtThreshold,
  pointerLocked,
  canUsePrecisionMode,
  showDebugInfo,
}: PrecisionModeStatusLabelOptions): string {
  // When in precision mode, just show zoom
  if (pointerLocked) {
    return `${currentZoom.toFixed(1)}×`
  }

  // When at threshold and precision mode is available, show activation message
  if (canUsePrecisionMode && isAtThreshold) {
    return 'Click to activate precision mode'
  }

  // Below threshold - show debug info or simple zoom
  if (showDebugInfo) {
    return `${currentZoom.toFixed(1)}× | ${screenPixelRatio.toFixed(1)} px/px`
  }

  return `${currentZoom.toFixed(1)}×`
}