ltbxd-actorle/assets/react/controllers/GameRow.jsx

83 lines
3 KiB
React
Raw Normal View History

import React, { useRef, useCallback, useMemo } from 'react';
import LetterInput from './LetterInput';
import ActorPopover from './ActorPopover';
function isLetter(ch) {
return /[a-zA-Z]/.test(ch);
}
export default function GameRow({ actorName, pos, colStart, totalWidth, hintType, hintText, rowIndex, attemptedLetters = null, revealed = false }) {
const inputRefs = useRef([]);
const letters = actorName.split('');
const letterIndices = useMemo(
() => letters.reduce((acc, ch, i) => { if (isLetter(ch)) acc.push(i); return acc; }, []),
[actorName]
);
const setInputRef = useCallback((index) => (el) => {
inputRefs.current[index] = el;
}, []);
const focusNextInput = useCallback((charIndex, direction) => {
const currentPos = letterIndices.indexOf(charIndex);
const nextPos = currentPos + direction;
if (nextPos >= 0 && nextPos < letterIndices.length) {
inputRefs.current[letterIndices[nextPos]]?.focus();
}
}, [letterIndices]);
return (
<tr>
<td className="hint-cell">
<ActorPopover hintType={hintType} hintText={hintText} />
</td>
{Array.from({ length: totalWidth + 1 }, (_, colIndex) => {
const charIndex = colIndex - colStart;
const isInRange = charIndex >= 0 && charIndex < letters.length;
if (!isInRange) {
return <td key={colIndex} />;
}
const ch = letters[charIndex];
if (!isLetter(ch)) {
return (
<td key={colIndex} className="letter-static">
{ch}
</td>
);
}
const attemptedLetter = typeof attemptedLetters?.[charIndex] === 'string'
? attemptedLetters[charIndex].toUpperCase()
: '';
const correctLetter = ch.toUpperCase();
const revealState = !revealed
? null
: attemptedLetter === ''
? null
: attemptedLetter === correctLetter
? 'correct'
: 'wrong';
return (
<LetterInput
key={colIndex}
rowIndex={rowIndex}
charIndex={charIndex}
highlighted={!revealed && charIndex === pos}
inputRef={setInputRef(charIndex)}
onNext={() => focusNextInput(charIndex, 1)}
onPrev={() => focusNextInput(charIndex, -1)}
value={revealed ? (revealState === 'correct' ? attemptedLetter : correctLetter) : undefined}
revealState={revealState}
disabled={revealed}
/>
);
})}
</tr>
);
}