diff --git a/ui/src/elements.tsx b/ui/src/elements.tsx index 391b2af..cf9402e 100644 --- a/ui/src/elements.tsx +++ b/ui/src/elements.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import {GameWasm, Letter as LetterData, MyResult, PlayedTile, PlayerAndScore, Tray, WordResult} from "word_grid"; -import {JSX, useEffect, useMemo, useReducer, useState} from "react"; +import {ChangeEvent, JSX, useEffect, useMemo, useReducer, useState} from "react"; export enum LocationType { GRID, @@ -75,8 +75,9 @@ function matchCoordinate(playerLetters: PlayableLetterData[], coords: Coordinate enum TileDispatchActionType { MOVE, RETRIEVE, + SET_BLANK, } -type TileDispatchAction = {action: TileDispatchActionType, start?: CoordinateData, end?: CoordinateData}; +type TileDispatchAction = {action: TileDispatchActionType, start?: CoordinateData, end?: CoordinateData, newBlankValue?: string, blankIndex?: number}; type TileDispatch = React.Dispatch; function addLogInfo(existingLog: React.JSX.Element[], newItem: React.JSX.Element) { @@ -124,6 +125,15 @@ export function Game(props: {wasm: GameWasm}) { setConfirmedScorePoints(-1); + return playerLetters.slice(); + } if (update.action === TileDispatchActionType.SET_BLANK) { + const blankLetter = playerLetters[update.blankIndex]; + if(blankLetter.text !== update.newBlankValue) { + blankLetter.text = update.newBlankValue; + if (blankLetter.location == LocationType.GRID) { + setConfirmedScorePoints(-1); + } + } return playerLetters.slice(); } else { console.error("Unknown tray update"); @@ -221,7 +231,7 @@ export function Game(props: {wasm: GameWasm}) { -export function TileSlot(props: { tile: React.JSX.Element | undefined, location: CoordinateData, dispatch: TileDispatch }): React.JSX.Element { +export function TileSlot(props: { tile?: React.JSX.Element | undefined, location: CoordinateData, dispatch: TileDispatch }): React.JSX.Element { let isDraggable = props.tile !== undefined; function onDragStart(e: React.DragEvent) { @@ -252,11 +262,51 @@ export function TileSlot(props: { tile: React.JSX.Element | undefined, location: } -export function Letter(props: { data: LetterData }): React.JSX.Element { - return
-
{props.data.text}
-
{props.data.points}
-
+export function Letter(props: { data: LetterData, letterUpdater?: (value: string) => void }): React.JSX.Element { + + function modifyThisLetter(value:string){ + props.letterUpdater(value); + } + + + function onBlankInput(e: ChangeEvent){ + let value = e.target.value.toUpperCase(); + if(value.length > 1){ + value = value[value.length - 1]; + } else if(value.length == 0){ + modifyThisLetter(value); + return; + } + + // Now check that it's a letter + let is_letter = value.match("[A-Z]") != null; + if(is_letter){ + modifyThisLetter(value); + } else { + // Cancel and do nothing + e.preventDefault(); + } + + } + + if(props.data.is_blank && props.data.ephemeral) { + return
+ +
{props.data.points}
+
+ } else { + let className = "text"; + if (props.data.is_blank) { // not ephemeral + className += " prev-blank"; + } + return
+
{props.data.text}
+
{props.data.points}
+
+ } + + + } @@ -266,24 +316,28 @@ export function TileTray(props: { letters: Array, trayLength for (let i=0; i ); } - for (let letter of props.letters) { + props.letters.forEach((letter, i) => { if (letter.location === LocationType.TRAY) { elements[letter.index] = } + tile={ { + props.dispatch({action: TileDispatchActionType.SET_BLANK, blankIndex: i, newBlankValue: value}) + }} + />} key={"letter" + letter.index} location={{location: LocationType.TRAY, index: letter.index}} dispatch={props.dispatch} /> } - } + }); return (
@@ -309,7 +363,6 @@ function Grid(props: { tileElement = <> {text} ; } @@ -320,7 +373,7 @@ function Grid(props: {
; }); - for (let letter of props.playerLetters) { + props.playerLetters.forEach((letter, i) => { if (letter.location === LocationType.GRID) { const ct = props.cellTypes[letter.index]; const {className, text} = cell_type_to_details(ct); @@ -328,14 +381,19 @@ function Grid(props: { elements[letter.index] =
} + tile={ { + props.dispatch({action: TileDispatchActionType.SET_BLANK, blankIndex: i, newBlankValue: value}); + }} + />} location={{location: LocationType.GRID, index: letter.index}} dispatch={props.dispatch} />
; } - } + }); return
{elements} diff --git a/ui/src/style.less b/ui/src/style.less index 152ddd5..b9af0ea 100644 --- a/ui/src/style.less +++ b/ui/src/style.less @@ -105,6 +105,23 @@ padding-right: 5px; } + input { + position: absolute; + width: 100%; + top: 5px; + text-align: center; + font-size: @tile-font-size; + background: none; + border: none; + padding: 0; + font-style: italic; + left: 0; /* Fixes a weird display bug where the input is shifted to the right when the tile is on the grid */ + } + + .prev-blank { + font-style: italic; + } + } .board-log {