feat : add square highlight on right click
This commit is contained in:
@@ -1,15 +1,16 @@
|
|||||||
import { Grid } from "@mui/material";
|
import { Grid } from "@mui/material";
|
||||||
import { Chessboard } from "react-chessboard";
|
import { Chessboard } from "react-chessboard";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue, useSetAtom } from "jotai";
|
||||||
import {
|
import {
|
||||||
boardAtom,
|
boardAtom,
|
||||||
boardOrientationAtom,
|
boardOrientationAtom,
|
||||||
|
clickedSquaresAtom,
|
||||||
currentPositionAtom,
|
currentPositionAtom,
|
||||||
showBestMoveArrowAtom,
|
showBestMoveArrowAtom,
|
||||||
} from "../states";
|
} from "../states";
|
||||||
import { Arrow, Square } from "react-chessboard/dist/chessboard/types";
|
import { Arrow, Square } from "react-chessboard/dist/chessboard/types";
|
||||||
import { useChessActions } from "@/hooks/useChessActions";
|
import { useChessActions } from "@/hooks/useChessActions";
|
||||||
import { useMemo, useRef } from "react";
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
import PlayerInfo from "./playerInfo";
|
import PlayerInfo from "./playerInfo";
|
||||||
import EvaluationBar from "./evaluationBar";
|
import EvaluationBar from "./evaluationBar";
|
||||||
import { useScreenSize } from "@/hooks/useScreenSize";
|
import { useScreenSize } from "@/hooks/useScreenSize";
|
||||||
@@ -24,6 +25,13 @@ export default function Board() {
|
|||||||
const showBestMoveArrow = useAtomValue(showBestMoveArrowAtom);
|
const showBestMoveArrow = useAtomValue(showBestMoveArrowAtom);
|
||||||
const { makeMove: makeBoardMove } = useChessActions(boardAtom);
|
const { makeMove: makeBoardMove } = useChessActions(boardAtom);
|
||||||
const position = useAtomValue(currentPositionAtom);
|
const position = useAtomValue(currentPositionAtom);
|
||||||
|
const setClickedSquares = useSetAtom(clickedSquaresAtom);
|
||||||
|
|
||||||
|
const boardFen = board.fen();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setClickedSquares([]);
|
||||||
|
}, [boardFen]);
|
||||||
|
|
||||||
const onPieceDrop = (
|
const onPieceDrop = (
|
||||||
source: Square,
|
source: Square,
|
||||||
@@ -96,7 +104,7 @@ export default function Board() {
|
|||||||
>
|
>
|
||||||
<Chessboard
|
<Chessboard
|
||||||
id="AnalysisBoard"
|
id="AnalysisBoard"
|
||||||
position={board.fen()}
|
position={boardFen}
|
||||||
onPieceDrop={onPieceDrop}
|
onPieceDrop={onPieceDrop}
|
||||||
boardOrientation={boardOrientation ? "white" : "black"}
|
boardOrientation={boardOrientation ? "white" : "black"}
|
||||||
customArrows={customArrows}
|
customArrows={customArrows}
|
||||||
|
|||||||
@@ -1,22 +1,40 @@
|
|||||||
import { currentPositionAtom, showPlayerMoveIconAtom } from "../states";
|
import {
|
||||||
|
clickedSquaresAtom,
|
||||||
|
currentPositionAtom,
|
||||||
|
showPlayerMoveIconAtom,
|
||||||
|
} from "../states";
|
||||||
import { MoveClassification } from "@/types/enums";
|
import { MoveClassification } from "@/types/enums";
|
||||||
import { useAtomValue } from "jotai";
|
import { atom, useAtom, useAtomValue } from "jotai";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { CSSProperties, forwardRef } from "react";
|
import { CSSProperties, MouseEventHandler, forwardRef } from "react";
|
||||||
import { CustomSquareProps } from "react-chessboard/dist/chessboard/types";
|
import { CustomSquareProps } from "react-chessboard/dist/chessboard/types";
|
||||||
|
|
||||||
|
const rightClickEventSquareAtom = atom<string | null>(null);
|
||||||
|
|
||||||
const SquareRenderer = forwardRef<HTMLDivElement, CustomSquareProps>(
|
const SquareRenderer = forwardRef<HTMLDivElement, CustomSquareProps>(
|
||||||
(props, ref) => {
|
(props, ref) => {
|
||||||
const { children, square, style } = props;
|
const { children, square, style } = props;
|
||||||
const showPlayerMoveIcon = useAtomValue(showPlayerMoveIconAtom);
|
const showPlayerMoveIcon = useAtomValue(showPlayerMoveIconAtom);
|
||||||
const position = useAtomValue(currentPositionAtom);
|
const position = useAtomValue(currentPositionAtom);
|
||||||
|
const [clickedSquares, setClickedSquares] = useAtom(clickedSquaresAtom);
|
||||||
|
const [rightClickEventSquare, setRightClickEventSquare] = useAtom(
|
||||||
|
rightClickEventSquareAtom
|
||||||
|
);
|
||||||
|
|
||||||
const fromSquare = position.lastMove?.from;
|
const fromSquare = position.lastMove?.from;
|
||||||
const toSquare = position.lastMove?.to;
|
const toSquare = position.lastMove?.to;
|
||||||
const moveClassification = position?.eval?.moveClassification;
|
const moveClassification = position?.eval?.moveClassification;
|
||||||
|
|
||||||
const customSquareStyle: CSSProperties | undefined =
|
const customSquareStyle: CSSProperties | undefined =
|
||||||
fromSquare === square || toSquare === square
|
clickedSquares.includes(square)
|
||||||
|
? {
|
||||||
|
position: "absolute",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
backgroundColor: "#eb6150",
|
||||||
|
opacity: "0.8",
|
||||||
|
}
|
||||||
|
: fromSquare === square || toSquare === square
|
||||||
? {
|
? {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@@ -28,8 +46,35 @@ const SquareRenderer = forwardRef<HTMLDivElement, CustomSquareProps>(
|
|||||||
}
|
}
|
||||||
: undefined;
|
: 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]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} style={{ ...style, position: "relative" }}>
|
<div
|
||||||
|
ref={ref}
|
||||||
|
style={{ ...style, position: "relative" }}
|
||||||
|
onClick={handleSquareLeftClick}
|
||||||
|
onMouseDown={(e) => e.button === 2 && setRightClickEventSquare(square)}
|
||||||
|
onMouseUp={handleSquareRightClick}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
{customSquareStyle && <div style={customSquareStyle} />}
|
{customSquareStyle && <div style={customSquareStyle} />}
|
||||||
{moveClassification && showPlayerMoveIcon && square === toSquare && (
|
{moveClassification && showPlayerMoveIcon && square === toSquare && (
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export const currentPositionAtom = atom<CurrentPosition>({});
|
|||||||
export const boardOrientationAtom = atom(true);
|
export const boardOrientationAtom = atom(true);
|
||||||
export const showBestMoveArrowAtom = atom(true);
|
export const showBestMoveArrowAtom = atom(true);
|
||||||
export const showPlayerMoveIconAtom = atom(true);
|
export const showPlayerMoveIconAtom = atom(true);
|
||||||
|
export const clickedSquaresAtom = atom<string[]>([]);
|
||||||
|
|
||||||
export const engineDepthAtom = atom(16);
|
export const engineDepthAtom = atom(16);
|
||||||
export const engineMultiPvAtom = atom(3);
|
export const engineMultiPvAtom = atom(3);
|
||||||
|
|||||||
Reference in New Issue
Block a user