All files / components/screens/controls/components VisualKeyboard3D.tsx

100% Statements 5/5
100% Branches 0/0
100% Functions 3/3
100% Lines 5/5

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                                                                                2x       190x 99x     190x                                                                   3472x                                                                  
/**
 * VisualKeyboard3D - 3D keyboard visualization with all keys
 * 
 * Renders a complete 3D keyboard with keys filtered by selected category.
 * Uses grid layout with proper spacing and lighting for visual clarity.
 * 
 * @module components/screens/controls/components
 */
 
import React, { useMemo } from "react";
import { KOREAN_COLORS } from "../../../../types/constants/colors";
import { filterKeysByCategory, KEYBOARD_LAYOUT, type KeyData } from "../constants/ControlsConstants";
import { Key3D } from "./Key3D";
 
/**
 * Props for VisualKeyboard3D component
 */
export interface VisualKeyboard3DProps {
  /** Set of currently pressed key codes */
  readonly pressedKeys: Set<string>;
  /** Selected control category to filter keys */
  readonly selectedTab: 'combat' | 'movement' | 'system';
}
 
/**
 * VisualKeyboard3D Component
 * 
 * 3D keyboard visualization showing all keys filtered by selected category.
 * Keys are positioned in a grid layout with proper spacing.
 * 
 * @example
 * ```tsx
 * <Canvas>
 *   <VisualKeyboard3D
 *     pressedKeys={new Set(['Space', 'KeyW'])}
 *     selectedTab="combat"
 *   />
 * </Canvas>
 * ```
 */
export const VisualKeyboard3D: React.FC<VisualKeyboard3DProps> = ({
  pressedKeys,
  selectedTab,
}) => {
  const filteredKeys = useMemo<readonly KeyData[]>(() => {
    return filterKeysByCategory(KEYBOARD_LAYOUT, selectedTab);
  }, [selectedTab]);
 
  return (
    <group
      position={[0, -1, 0]}
      rotation={[-Math.PI / 6, 0, 0]}
      data-testid="visual-keyboard"
    >
      {/* Ambient light for overall illumination */}
      <ambientLight intensity={0.4} />
 
      {/* Directional light for depth and shadows */}
      <directionalLight
        position={[5, 5, 5]}
        intensity={1.0}
        castShadow
        shadow-mapSize-width={2048}
        shadow-mapSize-height={2048}
      />
 
      {/* Additional directional light from the side */}
      <directionalLight
        position={[-3, 3, 2]}
        intensity={0.5}
      />
 
      {/* Point light for accent highlights */}
      <pointLight
        position={[0, 2, 2]}
        intensity={0.6}
        distance={10}
        decay={2}
      />
 
      {/* Render all filtered keys */}
      {filteredKeys.map((keyData) => (
        <Key3D
          key={keyData.code}
          keyData={keyData}
          isPressed={pressedKeys.has(keyData.code)}
        />
      ))}
 
      {/* Background plane for keyboard base */}
      <mesh
        position={[0, 0, -0.2]}
        receiveShadow
      >
        <planeGeometry args={[12, 6]} />
        <meshStandardMaterial
          color={KOREAN_COLORS.ARENA_BACKGROUND}
          metalness={0.8}
          roughness={0.3}
          opacity={0.9}
          transparent
        />
      </mesh>
 
      {/* Grid helper for visual reference (subtle) */}
      <gridHelper
        args={[12, 20, KOREAN_COLORS.UI_STEEL_GRAY_DARK, KOREAN_COLORS.UI_BACKGROUND_MEDIUM]}
        position={[0, 0, -0.19]}
        rotation={[0, 0, 0]}
      />
    </group>
  );
};
 
export default VisualKeyboard3D;