54 lines
1.3 KiB
TypeScript
54 lines
1.3 KiB
TypeScript
import { Clue, clueClass, CluedLetter, clueWord } from "./clue";
|
|
|
|
export enum RowState {
|
|
LockedIn,
|
|
Editing,
|
|
Pending,
|
|
}
|
|
|
|
interface RowProps {
|
|
rowState: RowState;
|
|
wordLength: number;
|
|
cluedLetters: CluedLetter[];
|
|
annotation?: string;
|
|
}
|
|
|
|
export function Row(props: RowProps) {
|
|
const isLockedIn = props.rowState === RowState.LockedIn;
|
|
const isEditing = props.rowState === RowState.Editing;
|
|
const letterDivs = props.cluedLetters
|
|
.concat(Array(props.wordLength).fill({ clue: Clue.Absent, letter: "" }))
|
|
.slice(0, props.wordLength)
|
|
.map(({ clue, letter }, i) => {
|
|
let letterClass = "Row-letter";
|
|
if (isLockedIn && clue !== undefined) {
|
|
letterClass += " " + clueClass(clue);
|
|
}
|
|
return (
|
|
<td
|
|
key={i}
|
|
className={letterClass}
|
|
aria-live={isEditing ? "assertive" : "off"}
|
|
aria-label={
|
|
isLockedIn
|
|
? letter.toUpperCase() +
|
|
(clue === undefined ? "" : ": " + clueWord(clue))
|
|
: ""
|
|
}
|
|
>
|
|
{letter}
|
|
</td>
|
|
);
|
|
});
|
|
let rowClass = "Row";
|
|
if (isLockedIn) rowClass += " Row-locked-in";
|
|
return (
|
|
<tr className={rowClass}>
|
|
{letterDivs}
|
|
{props.annotation && (
|
|
<span className="Row-annotation">{props.annotation}</span>
|
|
)}
|
|
</tr>
|
|
);
|
|
}
|