Add bottom-right corner mode switching with 3s hover timer
This commit is contained in:
parent
5ebfa1a3ce
commit
8018d8ec68
1 changed files with 69 additions and 3 deletions
|
|
@ -96,6 +96,16 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
|
||||||
const handleSquareClick = (row: number, col: number) => {
|
const handleSquareClick = (row: number, col: number) => {
|
||||||
if (isComplete) return;
|
if (isComplete) return;
|
||||||
|
|
||||||
|
// Special case for bottom-right corner
|
||||||
|
if (row === 7 && col === 7) {
|
||||||
|
if (bottomRightMode === 'row') {
|
||||||
|
repaintRow(7);
|
||||||
|
} else {
|
||||||
|
repaintColumn(7);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If clicking on the rightmost column, repaint the entire row
|
// If clicking on the rightmost column, repaint the entire row
|
||||||
if (col === 7) {
|
if (col === 7) {
|
||||||
repaintRow(row);
|
repaintRow(row);
|
||||||
|
|
@ -112,11 +122,49 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
|
||||||
repaint2x2Square(row, col);
|
repaint2x2Square(row, col);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleBottomRightHover = () => {
|
||||||
|
// Clear any existing timer
|
||||||
|
if (hoverTimer) {
|
||||||
|
clearTimeout(hoverTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a new timer to switch mode after 3 seconds
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setBottomRightMode(prev => prev === 'row' ? 'column' : 'row');
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
setHoverTimer(timer);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBottomRightLeave = () => {
|
||||||
|
// Clear the timer when leaving the square
|
||||||
|
if (hoverTimer) {
|
||||||
|
clearTimeout(hoverTimer);
|
||||||
|
setHoverTimer(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const [hoveredSquare, setHoveredSquare] = useState<{row: number, col: number} | null>(null);
|
const [hoveredSquare, setHoveredSquare] = useState<{row: number, col: number} | null>(null);
|
||||||
|
const [bottomRightMode, setBottomRightMode] = useState<'row' | 'column'>('row');
|
||||||
|
const [hoverTimer, setHoverTimer] = useState<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
const getAffectedSquares = (row: number, col: number) => {
|
const getAffectedSquares = (row: number, col: number) => {
|
||||||
const squares: {row: number, col: number}[] = [];
|
const squares: {row: number, col: number}[] = [];
|
||||||
|
|
||||||
|
// Special case for bottom-right corner
|
||||||
|
if (row === 7 && col === 7) {
|
||||||
|
if (bottomRightMode === 'row') {
|
||||||
|
for (let c = 0; c < 8; c++) {
|
||||||
|
squares.push({row: 7, col: c});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let r = 0; r < 8; r++) {
|
||||||
|
squares.push({row: r, col: 7});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return squares;
|
||||||
|
}
|
||||||
|
|
||||||
// If clicking on the rightmost column, repaint the entire row
|
// If clicking on the rightmost column, repaint the entire row
|
||||||
if (col === 7) {
|
if (col === 7) {
|
||||||
for (let c = 0; c < 8; c++) {
|
for (let c = 0; c < 8; c++) {
|
||||||
|
|
@ -146,6 +194,7 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
|
||||||
const isBlack = board[row][col];
|
const isBlack = board[row][col];
|
||||||
const isBottomRow = row === 7;
|
const isBottomRow = row === 7;
|
||||||
const isRightmostCol = col === 7;
|
const isRightmostCol = col === 7;
|
||||||
|
const isBottomRight = row === 7 && col === 7;
|
||||||
|
|
||||||
// Check if this square would be affected by hovering over the hovered square
|
// Check if this square would be affected by hovering over the hovered square
|
||||||
const isAffected = hoveredSquare && getAffectedSquares(hoveredSquare.row, hoveredSquare.col)
|
const isAffected = hoveredSquare && getAffectedSquares(hoveredSquare.row, hoveredSquare.col)
|
||||||
|
|
@ -155,14 +204,26 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
|
||||||
<div
|
<div
|
||||||
key={`${row}-${col}`}
|
key={`${row}-${col}`}
|
||||||
onClick={() => handleSquareClick(row, col)}
|
onClick={() => handleSquareClick(row, col)}
|
||||||
onMouseEnter={() => setHoveredSquare({row, col})}
|
onMouseEnter={() => {
|
||||||
onMouseLeave={() => setHoveredSquare(null)}
|
setHoveredSquare({row, col});
|
||||||
|
if (isBottomRight) {
|
||||||
|
handleBottomRightHover();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setHoveredSquare(null);
|
||||||
|
if (isBottomRight) {
|
||||||
|
handleBottomRightLeave();
|
||||||
|
}
|
||||||
|
}}
|
||||||
className={`
|
className={`
|
||||||
w-12 h-12 border border-gray-300 flex items-center justify-center cursor-pointer
|
w-12 h-12 border border-gray-300 flex items-center justify-center cursor-pointer
|
||||||
transition-all duration-200 hover:scale-105
|
transition-all duration-200 hover:scale-105
|
||||||
${isBlack ? 'bg-gray-800' : 'bg-gray-100'}
|
${isBlack ? 'bg-gray-800' : 'bg-gray-100'}
|
||||||
${isAffected ? 'border-2 border-red-500' : ''}
|
${isAffected ? 'border-2 border-red-500' : ''}
|
||||||
|
${isBottomRight ? 'bg-yellow-50' : ''}
|
||||||
`}
|
`}
|
||||||
|
title={isBottomRight ? `Hover for 3s to switch mode (current: ${bottomRightMode})` : undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -237,7 +298,7 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
|
||||||
{isComplete ? (
|
{isComplete ? (
|
||||||
"🎉 Congratulations! You achieved exactly one black square!"
|
"🎉 Congratulations! You achieved exactly one black square!"
|
||||||
) : (
|
) : (
|
||||||
"Click any square to repaint the 2×2 region with that square as top-left. Click rightmost column to repaint entire row, or bottom row to repaint entire column. Hover to preview affected squares!"
|
"Click any square to repaint the 2×2 region with that square as top-left. Click rightmost column to repaint entire row, or bottom row to repaint entire column. Bottom-right corner switches between row/column mode on 3s hover. Hover to preview affected squares!"
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -259,6 +320,10 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
|
||||||
<div className="w-5 h-5 border-2 border-red-500"></div>
|
<div className="w-5 h-5 border-2 border-red-500"></div>
|
||||||
<span>Hover to preview affected squares</span>
|
<span>Hover to preview affected squares</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="w-5 h-5 bg-yellow-50 border border-gray-300"></div>
|
||||||
|
<span>Bottom-right corner (switchable mode)</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
@ -290,6 +355,7 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
|
||||||
<li><strong>Repaint a 2×2 square:</strong> Click any square to flip all four squares in the 2×2 region with that square as the top-left corner.</li>
|
<li><strong>Repaint a 2×2 square:</strong> Click any square to flip all four squares in the 2×2 region with that square as the top-left corner.</li>
|
||||||
<li><strong>Repaint a row:</strong> Click any square in the rightmost column to flip all squares in that entire row.</li>
|
<li><strong>Repaint a row:</strong> Click any square in the rightmost column to flip all squares in that entire row.</li>
|
||||||
<li><strong>Repaint a column:</strong> Click any square in the bottom row to flip all squares in that entire column.</li>
|
<li><strong>Repaint a column:</strong> Click any square in the bottom row to flip all squares in that entire column.</li>
|
||||||
|
<li><strong>Bottom-right corner:</strong> Hover for 3 seconds to switch between row and column mode. The corner square is highlighted in light yellow.</li>
|
||||||
<li><strong>Preview:</strong> Hover over any square to see which squares will be affected (highlighted with red border).</li>
|
<li><strong>Preview:</strong> Hover over any square to see which squares will be affected (highlighted with red border).</li>
|
||||||
<li><strong>Goal:</strong> Achieve exactly one black square on the entire board.</li>
|
<li><strong>Goal:</strong> Achieve exactly one black square on the entire board.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue