"use client"; import type { Square as ChessSquare } from "chess.js"; import React from "react"; import { motion } from "motion/react"; import type { ChessPiece } from "~/utils/chess-helpers"; import type { BoardTheme } from "~/utils/theme-utils"; import { cn } from "~/lib/utils"; import { isLightSquare } from "~/utils/chess-helpers"; import { getHighlightClass, getSquareColorClasses } from "~/utils/theme-utils"; import { Piece } from "./piece"; interface SquareProps { square: ChessSquare; piece: ChessPiece | null; theme: BoardTheme; selected?: boolean; validMove?: boolean; lastMove?: boolean; check?: boolean; showCoordinates?: boolean; isFileEdge?: boolean; isRankEdge?: boolean; orientation?: "white" | "black"; onClick?: () => void; onDragStart?: (square: ChessSquare) => void; onDragOver?: (e: React.DragEvent) => void; onDrop?: (square: ChessSquare) => void; } /** * Individual chess board square with piece rendering */ const Square: React.FC = ({ square, piece, theme, selected = false, validMove = false, lastMove = false, check = false, showCoordinates = true, isFileEdge = false, isRankEdge = false, onClick, onDragStart, onDragOver, onDrop, }) => { const isLight = isLightSquare(square); const file = square[0]; const rank = square[1]; const baseClasses = getSquareColorClasses(isLight, theme); // Determine highlight let highlightClass = ""; if (check) { highlightClass = getHighlightClass("check", theme); } else if (selected) { highlightClass = getHighlightClass("selected", theme); } else if (lastMove) { highlightClass = getHighlightClass("lastMove", theme); } else if (validMove) { highlightClass = piece ? getHighlightClass("validCapture", theme) : getHighlightClass("valid", theme); } const handleDragStart = (e: React.DragEvent) => { if (piece && onDragStart) { e.dataTransfer.effectAllowed = "move"; e.dataTransfer.setData("text/plain", square); onDragStart(square); } }; const handleDragOver = (e: React.DragEvent) => { if (onDragOver) { e.preventDefault(); e.dataTransfer.dropEffect = "move"; onDragOver(e); } }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); if (onDrop) { onDrop(square); } }; const showFileLabel = showCoordinates && isRankEdge; const showRankLabel = showCoordinates && isFileEdge; return (
{/* File label (bottom) */} {showFileLabel && ( {file} )} {/* Rank label (left) */} {showRankLabel && ( {rank} )} {/* Valid move indicator */} {validMove && !piece && ( )} {/* Valid capture indicator */} {validMove && piece && ( )} {/* Piece */} {piece && (
)}
); }; export { Square };