Build in basic drag & drop for tiles
This commit is contained in:
parent
44e3b97f14
commit
1fb5235f2b
2 changed files with 51 additions and 6 deletions
|
@ -1,7 +1,7 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {GameWasm, Letter as LetterData, Tray} from "word_grid";
|
import {GameWasm, Letter as LetterData, Tray} from "word_grid";
|
||||||
import {createRoot} from "react-dom/client";
|
import {createRoot} from "react-dom/client";
|
||||||
import {useReducer, useState} from "react";
|
import {Children, useReducer, useState} from "react";
|
||||||
|
|
||||||
export enum LocationType {
|
export enum LocationType {
|
||||||
GRID,
|
GRID,
|
||||||
|
@ -29,6 +29,8 @@ function matchCoordinate(playerLetters: PlayableLetterData[], coords: Coordinate
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TileDispatch = React.Dispatch<{start: CoordinateData, end: CoordinateData}>;
|
||||||
|
|
||||||
function movePlayableLetters(playerLetters: PlayableLetterData[], update: {start: CoordinateData, end: CoordinateData}) {
|
function movePlayableLetters(playerLetters: PlayableLetterData[], update: {start: CoordinateData, end: CoordinateData}) {
|
||||||
|
|
||||||
let startIndex = matchCoordinate(playerLetters, update.start);
|
let startIndex = matchCoordinate(playerLetters, update.start);
|
||||||
|
@ -66,7 +68,7 @@ export function Game(props: {wasm: GameWasm}) {
|
||||||
|
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<TileTray letters={playerLetters} trayLength={7}/>
|
<TileTray letters={playerLetters} trayLength={7} dispatch={dispatch}/>
|
||||||
<button onClick={(e) => {
|
<button onClick={(e) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -84,6 +86,32 @@ export function Game(props: {wasm: GameWasm}) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<HTMLDivElement>) {
|
||||||
|
e.dataTransfer.effectAllowed = "move";
|
||||||
|
e.dataTransfer.setData("wordGrid/coords", JSON.stringify(props.location));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDrop(e: React.DragEvent<HTMLDivElement>) {
|
||||||
|
const startLocation: CoordinateData = JSON.parse(e.dataTransfer.getData("wordGrid/coords"));
|
||||||
|
const thisLocation = props.location;
|
||||||
|
|
||||||
|
props.dispatch({start: startLocation, end: thisLocation});
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="tileSpot"
|
||||||
|
draggable={isDraggable}
|
||||||
|
onDragStart={onDragStart}
|
||||||
|
onDrop={onDrop}
|
||||||
|
onDragOver={(e) => {e.preventDefault()}}
|
||||||
|
>
|
||||||
|
{props.tile}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export function Letter(props: { data: LetterData }): React.JSX.Element {
|
export function Letter(props: { data: LetterData }): React.JSX.Element {
|
||||||
return <div className="letter">
|
return <div className="letter">
|
||||||
<div className="text">{props.data.text}</div>
|
<div className="text">{props.data.text}</div>
|
||||||
|
@ -92,18 +120,28 @@ export function Letter(props: { data: LetterData }): React.JSX.Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function TileTray(props: { letters: Array<PlayableLetterData>, trayLength: number }): React.JSX.Element {
|
export function TileTray(props: { letters: Array<PlayableLetterData>, trayLength: number, dispatch: TileDispatch }): React.JSX.Element {
|
||||||
|
|
||||||
let elements: JSX.Element[] = [];
|
let elements: JSX.Element[] = [];
|
||||||
for (let i=0; i<props.trayLength; i++) {
|
for (let i=0; i<props.trayLength; i++) {
|
||||||
elements.push(
|
elements.push(
|
||||||
<div key={"empty" + i}></div>
|
<TileSlot
|
||||||
|
tile={undefined}
|
||||||
|
key={"empty" + i}
|
||||||
|
location={{location: LocationType.TRAY, index: i}}
|
||||||
|
dispatch={props.dispatch} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let letter of props.letters) {
|
for (let letter of props.letters) {
|
||||||
if (letter.location === LocationType.TRAY) {
|
if (letter.location === LocationType.TRAY) {
|
||||||
elements[letter.index] = <Letter data={letter} key={"letter" + letter.index} />
|
elements[letter.index] =
|
||||||
|
<TileSlot
|
||||||
|
tile={<Letter data={letter} />}
|
||||||
|
key={"letter" + letter.index}
|
||||||
|
location={{location: LocationType.TRAY, index: letter.index}}
|
||||||
|
dispatch={props.dispatch} />
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,17 @@
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tileSpot {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.letter {
|
.letter {
|
||||||
background-color: #e5cca9;
|
background-color: #e5cca9;
|
||||||
position: relative; // Used for the positioning of the sub-components
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
position: relative; // Used for the positioning of the sub-components
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
Loading…
Reference in a new issue