feat : add piece drag hint

This commit is contained in:
GuillaumeSD
2024-03-19 01:56:35 +01:00
parent cd927ed6d7
commit 4864bf61f5
7 changed files with 113 additions and 82 deletions

View File

@@ -6,6 +6,7 @@ import {
boardOrientationAtom,
clickedSquaresAtom,
currentPositionAtom,
playableSquaresAtom,
showBestMoveArrowAtom,
} from "../states";
import { Arrow, Square } from "react-chessboard/dist/chessboard/types";
@@ -26,6 +27,7 @@ export default function Board() {
const { makeMove: makeBoardMove } = useChessActions(boardAtom);
const position = useAtomValue(currentPositionAtom);
const setClickedSquares = useSetAtom(clickedSquaresAtom);
const setPlayableSquares = useSetAtom(playableSquaresAtom);
const boardFen = board.fen();
@@ -51,6 +53,27 @@ export default function Board() {
}
};
const handleSquareLeftClick = () => {
setClickedSquares([]);
};
const handleSquareRightClick = (square: Square) => {
setClickedSquares((prev) =>
prev.includes(square)
? prev.filter((s) => s !== square)
: [...prev, square]
);
};
const handlePieceDragBegin = (_: string, square: Square) => {
const moves = board.moves({ square, verbose: true });
setPlayableSquares(moves.map((m) => m.to));
};
const handlePieceDragEnd = () => {
setPlayableSquares([]);
};
const customArrows: Arrow[] = useMemo(() => {
const bestMove = position?.lastEval?.bestMove;
const moveClassification = position?.eval?.moveClassification;
@@ -113,6 +136,10 @@ export default function Board() {
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.5)",
}}
customSquare={SquareRenderer}
onSquareClick={handleSquareLeftClick}
onSquareRightClick={handleSquareRightClick}
onPieceDragBegin={handlePieceDragBegin}
onPieceDragEnd={handlePieceDragEnd}
/>
</Grid>

View File

@@ -1,31 +1,28 @@
import {
clickedSquaresAtom,
currentPositionAtom,
playableSquaresAtom,
showPlayerMoveIconAtom,
} from "../states";
import { MoveClassification } from "@/types/enums";
import { atom, useAtom, useAtomValue } from "jotai";
import { useAtomValue } from "jotai";
import Image from "next/image";
import { CSSProperties, MouseEventHandler, forwardRef } from "react";
import { CSSProperties, forwardRef } from "react";
import { CustomSquareProps } from "react-chessboard/dist/chessboard/types";
const rightClickEventSquareAtom = atom<string | null>(null);
const SquareRenderer = forwardRef<HTMLDivElement, CustomSquareProps>(
(props, ref) => {
const { children, square, style } = props;
const showPlayerMoveIcon = useAtomValue(showPlayerMoveIconAtom);
const position = useAtomValue(currentPositionAtom);
const [clickedSquares, setClickedSquares] = useAtom(clickedSquaresAtom);
const [rightClickEventSquare, setRightClickEventSquare] = useAtom(
rightClickEventSquareAtom
);
const clickedSquares = useAtomValue(clickedSquaresAtom);
const playableSquares = useAtomValue(playableSquaresAtom);
const fromSquare = position.lastMove?.from;
const toSquare = position.lastMove?.to;
const moveClassification = position?.eval?.moveClassification;
const customSquareStyle: CSSProperties | undefined =
const highlightSquareStyle: CSSProperties | undefined =
clickedSquares.includes(square)
? {
position: "absolute",
@@ -46,37 +43,25 @@ const SquareRenderer = forwardRef<HTMLDivElement, CustomSquareProps>(
}
: undefined;
const handleSquareLeftClick: MouseEventHandler<HTMLDivElement> = () => {
setClickedSquares([]);
};
const handleSquareRightClick: MouseEventHandler<HTMLDivElement> = (
event
) => {
if (event.button !== 2) return;
if (rightClickEventSquare !== square) {
setRightClickEventSquare(null);
return;
}
setClickedSquares((prev) =>
prev.includes(square)
? prev.filter((s) => s !== square)
: [...prev, square]
);
};
const playableSquareStyle: CSSProperties | undefined =
playableSquares.includes(square)
? {
position: "absolute",
width: "100%",
height: "100%",
backgroundColor: "rgba(0,0,0,.14)",
padding: "35%",
backgroundClip: "content-box",
borderRadius: "50%",
boxSizing: "border-box",
}
: undefined;
return (
<div
ref={ref}
style={{ ...style, position: "relative" }}
onClick={handleSquareLeftClick}
onMouseDown={(e) => e.button === 2 && setRightClickEventSquare(square)}
onMouseUp={handleSquareRightClick}
>
<div ref={ref} style={{ ...style, position: "relative" }}>
{children}
{customSquareStyle && <div style={customSquareStyle} />}
{highlightSquareStyle && <div style={highlightSquareStyle} />}
{playableSquareStyle && <div style={playableSquareStyle} />}
{moveClassification && showPlayerMoveIcon && square === toSquare && (
<Image
src={`/icons/${moveClassification}.png`}

View File

@@ -11,6 +11,7 @@ export const boardOrientationAtom = atom(true);
export const showBestMoveArrowAtom = atom(true);
export const showPlayerMoveIconAtom = atom(true);
export const clickedSquaresAtom = atom<string[]>([]);
export const playableSquaresAtom = atom<string[]>([]);
export const engineDepthAtom = atom(16);
export const engineMultiPvAtom = atom(3);