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 | 'use client' import { useCallback } from 'react' import { css } from '../../../../styled-system/css' import type { KeyboardLayout } from '../types' interface OnScreenKeyboardProps { onKeyPress: (letter: string) => void highlightedLetter?: string layout?: KeyboardLayout } const LAYOUTS: Record<KeyboardLayout, string[][]> = { qwerty: [ ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'], ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'], ['z', 'x', 'c', 'v', 'b', 'n', 'm'], ], dvorak: [ ['p', 'y', 'f', 'g', 'c', 'r', 'l'], ['a', 'o', 'e', 'u', 'i', 'd', 'h', 't', 'n', 's'], ['q', 'j', 'k', 'x', 'b', 'm', 'w', 'v', 'z'], ], abc: [ ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], ['j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r'], ['s', 't', 'u', 'v', 'w', 'x', 'y', 'z'], ], } /** * On-screen keyboard for touch devices. * Supports QWERTY, Dvorak, and ABC layouts. */ export function OnScreenKeyboard({ onKeyPress, highlightedLetter, layout = 'qwerty', }: OnScreenKeyboardProps) { const handlePress = useCallback( (letter: string) => { onKeyPress(letter) }, [onKeyPress] ) const rows = LAYOUTS[layout] return ( <div data-component="OnScreenKeyboard" className={css({ display: 'flex', flexDirection: 'column', gap: '6px', p: '3', bg: 'gray.100', borderRadius: 'xl', maxWidth: '500px', mx: 'auto', width: '100%', })} > {rows.map((row, rowIdx) => ( <div key={rowIdx} className={css({ display: 'flex', gap: '4px', justifyContent: 'center', })} > {row.map((letter) => { const isHighlighted = letter === highlightedLetter return ( <button key={letter} type="button" onClick={() => handlePress(letter)} data-action="type-letter" data-letter={letter} className={css({ flex: '1 1 0', maxWidth: '44px', minHeight: '48px', fontSize: '18px', fontWeight: 'bold', textTransform: 'uppercase', border: '2px solid', borderRadius: 'lg', cursor: 'pointer', transition: 'all 0.1s ease', userSelect: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', _active: { transform: 'scale(0.92)', }, })} style={{ backgroundColor: isHighlighted ? '#dbeafe' : 'white', borderColor: isHighlighted ? '#3b82f6' : '#d1d5db', color: isHighlighted ? '#1d4ed8' : '#374151', boxShadow: isHighlighted ? '0 0 8px rgba(59, 130, 246, 0.3)' : undefined, }} > {letter} </button> ) })} </div> ))} </div> ) } |