@react-chess-tools/react-chess-puzzle 0.6.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +568 -0
- package/dist/index.cjs +513 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +128 -0
- package/dist/index.d.ts +128 -0
- package/dist/{index.mjs → index.js} +143 -92
- package/dist/index.js.map +1 -0
- package/package.json +19 -9
- package/src/components/ChessPuzzle/ThemePuzzle.stories.tsx +300 -0
- package/src/components/ChessPuzzle/parts/Hint.tsx +32 -23
- package/src/components/ChessPuzzle/parts/PuzzleBoard.tsx +33 -27
- package/src/components/ChessPuzzle/parts/Reset.tsx +56 -36
- package/src/components/ChessPuzzle/parts/Root.tsx +29 -5
- package/src/components/ChessPuzzle/parts/__tests__/Hint.test.tsx +158 -0
- package/src/components/ChessPuzzle/parts/__tests__/PuzzleBoard.test.tsx +140 -0
- package/src/components/ChessPuzzle/parts/__tests__/Reset.test.tsx +341 -0
- package/src/components/ChessPuzzle/parts/__tests__/Root.test.tsx +42 -0
- package/src/docs/Theming.mdx +255 -0
- package/src/index.ts +14 -0
- package/src/theme/__tests__/context.test.tsx +66 -0
- package/src/theme/__tests__/defaults.test.ts +48 -0
- package/src/theme/__tests__/utils.test.ts +76 -0
- package/src/theme/context.tsx +36 -0
- package/src/theme/defaults.ts +16 -0
- package/src/theme/index.ts +20 -0
- package/src/theme/types.ts +29 -0
- package/src/theme/utils.ts +28 -0
- package/src/utils/__tests__/index.test.ts +0 -17
- package/src/utils/index.ts +21 -21
- package/README.MD +0 -344
- package/dist/index.d.mts +0 -57
- package/dist/index.mjs.map +0 -1
package/src/utils/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type Color, Chess, Move } from "chess.js";
|
|
2
2
|
import React, { CSSProperties, ReactElement, ReactNode } from "react";
|
|
3
3
|
import _ from "lodash";
|
|
4
|
+
import type { ChessPuzzleTheme } from "../theme/types";
|
|
5
|
+
import { defaultPuzzleTheme } from "../theme/defaults";
|
|
4
6
|
|
|
5
7
|
export type Status = "not-started" | "in-progress" | "solved" | "failed";
|
|
6
8
|
|
|
@@ -13,10 +15,6 @@ export type Puzzle = {
|
|
|
13
15
|
makeFirstMove?: boolean;
|
|
14
16
|
};
|
|
15
17
|
|
|
16
|
-
const FAIL_COLOR = "rgba(201, 52, 48, 0.5)";
|
|
17
|
-
const SUCCESS_COLOR = "rgba(172, 206, 89, 0.5)";
|
|
18
|
-
const HINT_COLOR = "rgba(27, 172, 166, 0.5)";
|
|
19
|
-
|
|
20
18
|
export const getOrientation = (puzzle: Puzzle): Color => {
|
|
21
19
|
const fen = puzzle.fen;
|
|
22
20
|
const game = new Chess(fen);
|
|
@@ -26,22 +24,24 @@ export const getOrientation = (puzzle: Puzzle): Color => {
|
|
|
26
24
|
return game.turn();
|
|
27
25
|
};
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Generates custom square styles for puzzle states based on theme.
|
|
29
|
+
*
|
|
30
|
+
* @param status - Current puzzle status
|
|
31
|
+
* @param hint - Current hint level
|
|
32
|
+
* @param isPlayerTurn - Whether it's the player's turn
|
|
33
|
+
* @param game - Chess.js game instance
|
|
34
|
+
* @param nextMove - The next expected move (for hints)
|
|
35
|
+
* @param theme - Theme configuration (defaults to defaultPuzzleTheme)
|
|
36
|
+
* @returns Record of square names to CSS properties
|
|
37
|
+
*/
|
|
39
38
|
export const getCustomSquareStyles = (
|
|
40
39
|
status: Status,
|
|
41
40
|
hint: Hint,
|
|
42
41
|
isPlayerTurn: boolean,
|
|
43
42
|
game: Chess,
|
|
44
43
|
nextMove?: Move | null,
|
|
44
|
+
theme: ChessPuzzleTheme = defaultPuzzleTheme,
|
|
45
45
|
) => {
|
|
46
46
|
const customSquareStyles: Record<string, CSSProperties> = {};
|
|
47
47
|
|
|
@@ -49,10 +49,10 @@ export const getCustomSquareStyles = (
|
|
|
49
49
|
|
|
50
50
|
if (status === "failed" && lastMove) {
|
|
51
51
|
customSquareStyles[lastMove.from] = {
|
|
52
|
-
backgroundColor:
|
|
52
|
+
backgroundColor: theme.puzzle.failure,
|
|
53
53
|
};
|
|
54
54
|
customSquareStyles[lastMove.to] = {
|
|
55
|
-
backgroundColor:
|
|
55
|
+
backgroundColor: theme.puzzle.failure,
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -61,17 +61,17 @@ export const getCustomSquareStyles = (
|
|
|
61
61
|
(status === "solved" || (status !== "failed" && !isPlayerTurn))
|
|
62
62
|
) {
|
|
63
63
|
customSquareStyles[lastMove.from] = {
|
|
64
|
-
backgroundColor:
|
|
64
|
+
backgroundColor: theme.puzzle.success,
|
|
65
65
|
};
|
|
66
66
|
customSquareStyles[lastMove.to] = {
|
|
67
|
-
backgroundColor:
|
|
67
|
+
backgroundColor: theme.puzzle.success,
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
if (hint === "piece") {
|
|
72
72
|
if (nextMove) {
|
|
73
73
|
customSquareStyles[nextMove.from] = {
|
|
74
|
-
backgroundColor:
|
|
74
|
+
backgroundColor: theme.puzzle.hint,
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -79,10 +79,10 @@ export const getCustomSquareStyles = (
|
|
|
79
79
|
if (hint === "move") {
|
|
80
80
|
if (nextMove) {
|
|
81
81
|
customSquareStyles[nextMove.from] = {
|
|
82
|
-
backgroundColor:
|
|
82
|
+
backgroundColor: theme.puzzle.hint,
|
|
83
83
|
};
|
|
84
84
|
customSquareStyles[nextMove.to] = {
|
|
85
|
-
backgroundColor:
|
|
85
|
+
backgroundColor: theme.puzzle.hint,
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
}
|
package/README.MD
DELETED
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
<h1>react-chess-puzzle</h1>
|
|
3
|
-
A lightweight, customizable React component library for rendering and interacting with chess puzzles.
|
|
4
|
-
</div>
|
|
5
|
-
|
|
6
|
-
## Project Description
|
|
7
|
-
|
|
8
|
-
This project is a React-based chess puzzle component that allows users to solve chess puzzles online. It is part of the `react-chess-tools` package and is designed to be easy to use and customizable. It is built on top of `react-chess-game` component.
|
|
9
|
-
|
|
10
|
-
## Preview
|
|
11
|
-
|
|
12
|
-
Visit the [demo](https://react-chess-tools.vercel.app/) to see the `react-chess-puzzle` component in action.
|
|
13
|
-
|
|
14
|
-
## Table of Contents
|
|
15
|
-
|
|
16
|
-
- [Installation](#installation)
|
|
17
|
-
- [Quick Start](#quick-start)
|
|
18
|
-
- [Puzzle Solving Flow](#puzzle-solving-flow)
|
|
19
|
-
- [API Reference](#api-reference)
|
|
20
|
-
- [ChessPuzzle.Root](#chesspuzzleroot)
|
|
21
|
-
- [ChessPuzzle.Board](#chesspuzzleboard)
|
|
22
|
-
- [ChessPuzzle.Reset](#chesspuzzlereset)
|
|
23
|
-
- [ChessPuzzle.Hint](#chesspuzzlehint)
|
|
24
|
-
- [Hooks and Context](#hooks-and-context)
|
|
25
|
-
- [useChessPuzzleContext](#usechesspuzzlecontext)
|
|
26
|
-
- [useChessGameContext](#usechessgamecontext)
|
|
27
|
-
- [Integration with react-chess-game](#using-react-chess-game-components)
|
|
28
|
-
- [Complete Example](#complete-example)
|
|
29
|
-
- [License](#-license)
|
|
30
|
-
|
|
31
|
-
## Installation
|
|
32
|
-
|
|
33
|
-
To install the `react-chess-puzzle` package, run the following command:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
$ npm install @react-chess-tools/react-chess-puzzle
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Quick Start
|
|
40
|
-
|
|
41
|
-
To use the `react-chess-puzzle` package, you can import the `ChessPuzzle` component and use it as follows:
|
|
42
|
-
|
|
43
|
-
```tsx
|
|
44
|
-
import { ChessPuzzle } from "@react-chess-tools/react-chess-puzzle";
|
|
45
|
-
|
|
46
|
-
const App = () => {
|
|
47
|
-
const puzzle = {
|
|
48
|
-
fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
|
|
49
|
-
moves: ["d2d4", "e5d4", "f3d4"],
|
|
50
|
-
makeFirstMove: false,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<ChessPuzzle.Root puzzle={puzzle}>
|
|
55
|
-
<ChessPuzzle.Board />
|
|
56
|
-
<div className="controls">
|
|
57
|
-
<ChessPuzzle.Reset>Restart Puzzle</ChessPuzzle.Reset>
|
|
58
|
-
<ChessPuzzle.Hint showOn={["in-progress"]}>Get Hint</ChessPuzzle.Hint>
|
|
59
|
-
</div>
|
|
60
|
-
</ChessPuzzle.Root>
|
|
61
|
-
);
|
|
62
|
-
};
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Puzzle Solving Flow
|
|
66
|
-
|
|
67
|
-
The puzzle-solving flow follows these steps:
|
|
68
|
-
|
|
69
|
-
1. **Initial Setup**: The board is set up using the provided FEN string
|
|
70
|
-
2. **First Move**: If `makeFirstMove` is `true`, the component automatically makes the first move in the solution sequence
|
|
71
|
-
3. **User Interaction**: The user attempts to solve the puzzle by making the correct moves
|
|
72
|
-
4. **Feedback**: The component validates each move and provides feedback:
|
|
73
|
-
- If the move is correct, the puzzle continues
|
|
74
|
-
- If the move is incorrect, the puzzle is marked as failed
|
|
75
|
-
5. **Completion**: When all correct moves have been made, the puzzle is marked as solved
|
|
76
|
-
|
|
77
|
-
## API Reference
|
|
78
|
-
|
|
79
|
-
The `react-chess-puzzle` package provides a set of components that you can use to build your chess app. The following sections describe the components and their usage.
|
|
80
|
-
|
|
81
|
-
### ChessPuzzle.Root
|
|
82
|
-
|
|
83
|
-
The `ChessPuzzle.Root` component is the root component of the `react-chess-puzzle` package. It is used to provide the `ChessPuzzleContext` to the rest of the components. It accepts a `puzzle` prop that is used to instantiate the puzzle.
|
|
84
|
-
|
|
85
|
-
#### Props
|
|
86
|
-
|
|
87
|
-
The `ChessPuzzle.Root` component accepts the following props:
|
|
88
|
-
|
|
89
|
-
| Name | Type | Default | Description |
|
|
90
|
-
| ----------- | ------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
91
|
-
| `puzzle` | `Puzzle` | | The puzzle to be solved |
|
|
92
|
-
| `onSolve` | `(puzzleContext: ChessPuzzleContextType) => void` | `undefined` | Callback function that is triggered when the puzzle is successfully solved, receives the puzzle context as parameter |
|
|
93
|
-
| `onFail` | `(puzzleContext: ChessPuzzleContextType) => void` | `undefined` | Callback function that is triggered when an incorrect move is played, receives the puzzle context as parameter |
|
|
94
|
-
| `children?` | `ReactNode` | | The children to be rendered |
|
|
95
|
-
|
|
96
|
-
The `puzzle` prop contains the following properties:
|
|
97
|
-
|
|
98
|
-
| Name | Type | Default | Description |
|
|
99
|
-
| --------------- | ---------- | ------- | -------------------------------------------------------------------------- |
|
|
100
|
-
| `fen` | `string` | | The FEN string representing the initial position of the puzzle |
|
|
101
|
-
| `moves` | `string[]` | | The sequence of moves (in algebraic or UCI notation) that solve the puzzle |
|
|
102
|
-
| `makeFirstMove` | `boolean` | `false` | Whether the first move is part of the problem or must be played by the CPU |
|
|
103
|
-
|
|
104
|
-
### ChessPuzzle.Board
|
|
105
|
-
|
|
106
|
-
The `ChessPuzzle.Board` component renders the chess board and delegates to `ChessGame.Board` under the hood.
|
|
107
|
-
|
|
108
|
-
#### Props
|
|
109
|
-
|
|
110
|
-
It accepts the same props as `ChessGame.Board`:
|
|
111
|
-
|
|
112
|
-
| Name | Type | Description |
|
|
113
|
-
| -------- | ------------------- | ---------------------------------------------------------------------- |
|
|
114
|
-
| options? | `ChessboardOptions` | Forwarded to `react-chessboard` v5 via `ChessGame.Board({ options })`. |
|
|
115
|
-
|
|
116
|
-
Any other props are passed through to `ChessGame.Board` unchanged.
|
|
117
|
-
|
|
118
|
-
### ChessPuzzle.Reset
|
|
119
|
-
|
|
120
|
-
A button component that resets the current puzzle or loads a new one.
|
|
121
|
-
|
|
122
|
-
#### Props
|
|
123
|
-
|
|
124
|
-
| Name | Type | Default | Description |
|
|
125
|
-
| --------- | --------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
126
|
-
| `puzzle` | `Puzzle \| undefined` | `undefined` | The puzzle object for a new puzzle. If not provided, the current puzzle is reset. |
|
|
127
|
-
| `onReset` | `() => void` | `undefined` | A callback function that is called when the puzzle is reset. |
|
|
128
|
-
| `showOn` | `Status[]` | `["not-started", "in-progress", "solved", "failed"]` | The state(s) in which the button is shown. Valid states are: "not-started", "in-progress", "solved", "failed" |
|
|
129
|
-
| `asChild` | `boolean` | `false` | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
|
|
130
|
-
|
|
131
|
-
### ChessPuzzle.Hint
|
|
132
|
-
|
|
133
|
-
A button component that provides a hint by highlighting the next move in the solution.
|
|
134
|
-
|
|
135
|
-
#### Props
|
|
136
|
-
|
|
137
|
-
| Name | Type | Default | Description |
|
|
138
|
-
| --------- | ---------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
139
|
-
| `showOn` | `Status[]` | `["in-progress"]` | The state(s) in which the button is shown. Valid states are: "not-started", "in-progress", "solved", "failed" |
|
|
140
|
-
| `asChild` | `boolean` | `false` | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
|
|
141
|
-
|
|
142
|
-
## Hooks and Context
|
|
143
|
-
|
|
144
|
-
### useChessPuzzleContext
|
|
145
|
-
|
|
146
|
-
A hook that provides access to the puzzle state and methods.
|
|
147
|
-
|
|
148
|
-
```tsx
|
|
149
|
-
import { useChessPuzzleContext } from "@react-chess-tools/react-chess-puzzle";
|
|
150
|
-
|
|
151
|
-
const MyComponent = () => {
|
|
152
|
-
const {
|
|
153
|
-
puzzleState, // "not-started" | "in-progress" | "solved" | "failed"
|
|
154
|
-
resetPuzzle, // Function to reset the current puzzle
|
|
155
|
-
onHint, // Function to show a hint
|
|
156
|
-
movesPlayed, // Number of moves played so far
|
|
157
|
-
totalMoves, // Total number of moves in the solution
|
|
158
|
-
} = useChessPuzzleContext();
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<div>
|
|
162
|
-
<p>Puzzle state: {puzzleState}</p>
|
|
163
|
-
<p>
|
|
164
|
-
Progress: {movesPlayed}/{totalMoves} moves
|
|
165
|
-
</p>
|
|
166
|
-
<button onClick={resetPuzzle}>Reset</button>
|
|
167
|
-
<button onClick={onHint}>Show Hint</button>
|
|
168
|
-
</div>
|
|
169
|
-
);
|
|
170
|
-
};
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### useChessGameContext
|
|
174
|
-
|
|
175
|
-
Since `react-chess-puzzle` is built on top of `react-chess-game`, you can also use the `useChessGameContext` hook to access the underlying game state and methods.
|
|
176
|
-
|
|
177
|
-
```tsx
|
|
178
|
-
import { useChessGameContext } from "@react-chess-tools/react-chess-game";
|
|
179
|
-
|
|
180
|
-
const MyComponent = () => {
|
|
181
|
-
const { currentFen, info, methods } = useChessGameContext();
|
|
182
|
-
|
|
183
|
-
return (
|
|
184
|
-
<div>
|
|
185
|
-
<p>Current FEN: {currentFen}</p>
|
|
186
|
-
<p>Current turn: {info.turn === "w" ? "White" : "Black"}</p>
|
|
187
|
-
<button onClick={() => methods.flipBoard()}>Flip</button>
|
|
188
|
-
</div>
|
|
189
|
-
);
|
|
190
|
-
};
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## Using react-chess-game Components
|
|
194
|
-
|
|
195
|
-
Since `react-chess-puzzle` is built on top of `react-chess-game`, you can use any of its components within your puzzle interface:
|
|
196
|
-
|
|
197
|
-
### ChessGame.Sounds
|
|
198
|
-
|
|
199
|
-
Add sound effects for moves, captures, and other chess events.
|
|
200
|
-
|
|
201
|
-
```tsx
|
|
202
|
-
import { ChessPuzzle } from "@react-chess-tools/react-chess-puzzle";
|
|
203
|
-
import { ChessGame } from "@react-chess-tools/react-chess-game";
|
|
204
|
-
|
|
205
|
-
const App = () => (
|
|
206
|
-
<ChessPuzzle.Root puzzle={...}>
|
|
207
|
-
<ChessGame.Sounds />
|
|
208
|
-
<ChessPuzzle.Board />
|
|
209
|
-
</ChessPuzzle.Root>
|
|
210
|
-
);
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### ChessGame.KeyboardControls
|
|
214
|
-
|
|
215
|
-
Add keyboard navigation for accessible play.
|
|
216
|
-
|
|
217
|
-
```tsx
|
|
218
|
-
import { ChessPuzzle } from "@react-chess-tools/react-chess-puzzle";
|
|
219
|
-
import { ChessGame } from "@react-chess-tools/react-chess-game";
|
|
220
|
-
|
|
221
|
-
const App = () => (
|
|
222
|
-
<ChessPuzzle.Root puzzle={...}>
|
|
223
|
-
<ChessGame.KeyboardControls />
|
|
224
|
-
<ChessPuzzle.Board />
|
|
225
|
-
</ChessPuzzle.Root>
|
|
226
|
-
);
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
## Complete Example
|
|
230
|
-
|
|
231
|
-
Here's a complete example of a chess puzzle component with sounds, keyboard controls, and custom styling:
|
|
232
|
-
|
|
233
|
-
```tsx
|
|
234
|
-
import {
|
|
235
|
-
ChessPuzzle,
|
|
236
|
-
type ChessPuzzleContextType,
|
|
237
|
-
} from "@react-chess-tools/react-chess-puzzle";
|
|
238
|
-
import { ChessGame } from "@react-chess-tools/react-chess-game";
|
|
239
|
-
import { useState } from "react";
|
|
240
|
-
import "./ChessPuzzleStyles.css"; // Your custom CSS
|
|
241
|
-
|
|
242
|
-
export const PuzzleSolver = () => {
|
|
243
|
-
// Example puzzles
|
|
244
|
-
const puzzles = [
|
|
245
|
-
{
|
|
246
|
-
fen: "4kb1r/p2r1ppp/4qn2/1B2p1B1/4P3/1Q6/PPP2PPP/2KR4 w k - 0 1",
|
|
247
|
-
moves: ["Bxd7+", "Nxd7", "Qb8+", "Nxb8", "Rd8#"],
|
|
248
|
-
makeFirstMove: false,
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
fen: "6k1/5p1p/p1q1p1p1/1pB1P3/1Pr3Pn/P4P1P/4Q3/3R2K1 b - - 0 31",
|
|
252
|
-
moves: ["h4f3", "e2f3", "c4c5", "d1d8", "g8g7", "f3f6"],
|
|
253
|
-
makeFirstMove: true,
|
|
254
|
-
},
|
|
255
|
-
];
|
|
256
|
-
|
|
257
|
-
const [currentPuzzle, setCurrentPuzzle] = useState(0);
|
|
258
|
-
const [score, setScore] = useState(0);
|
|
259
|
-
|
|
260
|
-
const nextPuzzle = () => {
|
|
261
|
-
const nextPuzzle = (currentPuzzle + 1) % puzzles.length;
|
|
262
|
-
setCurrentPuzzle(nextPuzzle);
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
const handleSolve = (puzzleContext: ChessPuzzleContextType) => {
|
|
266
|
-
setScore((prev) => prev + 10);
|
|
267
|
-
console.log(`Puzzle solved in ${puzzleContext.movesPlayed} moves`);
|
|
268
|
-
nextPuzzle();
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
const handleFail = (puzzleContext: ChessPuzzleContextType) => {
|
|
272
|
-
setScore((prev) => Math.max(0, prev - 5));
|
|
273
|
-
console.log(`Puzzle failed in ${puzzleContext.movesPlayed} moves`);
|
|
274
|
-
|
|
275
|
-
nextPuzzle();
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
const handleReset = (puzzleContext: ChessPuzzleContextType) => {
|
|
279
|
-
puzzleContext.resetPuzzle();
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
return (
|
|
283
|
-
<div className="puzzle-container">
|
|
284
|
-
<div className="score">Score: {score}</div>
|
|
285
|
-
<ChessPuzzle.Root
|
|
286
|
-
puzzle={puzzles[currentPuzzle]!}
|
|
287
|
-
onSolve={handleSolve}
|
|
288
|
-
onFail={handleFail}
|
|
289
|
-
>
|
|
290
|
-
<ChessGame.Sounds />
|
|
291
|
-
<ChessGame.KeyboardControls />
|
|
292
|
-
|
|
293
|
-
<div className="board-container">
|
|
294
|
-
<ChessPuzzle.Board />
|
|
295
|
-
</div>
|
|
296
|
-
|
|
297
|
-
<div className="controls">
|
|
298
|
-
<div className="buttons">
|
|
299
|
-
<ChessPuzzle.Reset>Restart</ChessPuzzle.Reset>
|
|
300
|
-
<ChessPuzzle.Hint showOn={["in-progress"]}>Hint</ChessPuzzle.Hint>
|
|
301
|
-
<ChessPuzzle.Reset
|
|
302
|
-
puzzle={puzzles[(currentPuzzle + 1) % puzzles.length]}
|
|
303
|
-
onReset={handleReset}
|
|
304
|
-
>
|
|
305
|
-
Next Puzzle
|
|
306
|
-
</ChessPuzzle.Reset>
|
|
307
|
-
</div>
|
|
308
|
-
</div>
|
|
309
|
-
</ChessPuzzle.Root>
|
|
310
|
-
</div>
|
|
311
|
-
);
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
// Custom component using the context
|
|
315
|
-
const PuzzleStatus = () => {
|
|
316
|
-
const { puzzleState, movesPlayed, totalMoves } = useChessPuzzleContext();
|
|
317
|
-
|
|
318
|
-
let message = "";
|
|
319
|
-
switch (puzzleState) {
|
|
320
|
-
case "not-started":
|
|
321
|
-
message = "Make your move to start the puzzle";
|
|
322
|
-
break;
|
|
323
|
-
case "in-progress":
|
|
324
|
-
message = `Progress: ${movesPlayed}/${totalMoves} moves`;
|
|
325
|
-
break;
|
|
326
|
-
case "solved":
|
|
327
|
-
message = "Puzzle solved! Well done!";
|
|
328
|
-
break;
|
|
329
|
-
case "failed":
|
|
330
|
-
message = "Incorrect move. Try again!";
|
|
331
|
-
break;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return <div className={`status ${puzzleState}`}>{message}</div>;
|
|
335
|
-
};
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
## 📝 License
|
|
339
|
-
|
|
340
|
-
This project is [MIT](https://opensource.org/licenses/MIT) licensed.
|
|
341
|
-
|
|
342
|
-
## Show your support
|
|
343
|
-
|
|
344
|
-
Give a ⭐️ if this project helped you!
|
package/dist/index.d.mts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import React__default from 'react';
|
|
3
|
-
import { ChessGame } from '@react-chess-tools/react-chess-game';
|
|
4
|
-
|
|
5
|
-
type Status = "not-started" | "in-progress" | "solved" | "failed";
|
|
6
|
-
type Hint = "none" | "piece" | "move";
|
|
7
|
-
type Puzzle = {
|
|
8
|
-
fen: string;
|
|
9
|
-
moves: string[];
|
|
10
|
-
makeFirstMove?: boolean;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
interface HintProps {
|
|
14
|
-
asChild?: boolean;
|
|
15
|
-
showOn?: Status[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface ResetProps {
|
|
19
|
-
asChild?: boolean;
|
|
20
|
-
puzzle?: Puzzle;
|
|
21
|
-
onReset?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
22
|
-
showOn?: Status[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface PuzzleBoardProps extends React__default.ComponentProps<typeof ChessGame.Board> {
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
type ChessPuzzleContextType = {
|
|
29
|
-
status: Status;
|
|
30
|
-
changePuzzle: (puzzle: Puzzle) => void;
|
|
31
|
-
resetPuzzle: () => void;
|
|
32
|
-
puzzle: Puzzle;
|
|
33
|
-
hint: Hint;
|
|
34
|
-
nextMove?: string | null;
|
|
35
|
-
isPlayerTurn: boolean;
|
|
36
|
-
onHint: () => void;
|
|
37
|
-
puzzleState: Status;
|
|
38
|
-
movesPlayed: number;
|
|
39
|
-
totalMoves: number;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
interface RootProps {
|
|
43
|
-
puzzle: Puzzle;
|
|
44
|
-
onSolve?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
45
|
-
onFail?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
declare const ChessPuzzle: {
|
|
49
|
-
Root: React.FC<React.PropsWithChildren<RootProps>>;
|
|
50
|
-
Board: React.FC<PuzzleBoardProps>;
|
|
51
|
-
Reset: React.FC<React.PropsWithChildren<ResetProps>>;
|
|
52
|
-
Hint: React.FC<React.PropsWithChildren<HintProps>>;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
declare const useChessPuzzleContext: () => ChessPuzzleContextType;
|
|
56
|
-
|
|
57
|
-
export { ChessPuzzle, type ChessPuzzleContextType, type Hint, type HintProps, type Puzzle, type PuzzleBoardProps, type ResetProps, type RootProps, type Status, useChessPuzzleContext };
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ChessPuzzle/parts/Root.tsx","../src/utils/index.ts","../src/hooks/useChessPuzzle.ts","../src/hooks/reducer.ts","../src/hooks/useChessPuzzleContext.ts","../src/components/ChessPuzzle/parts/PuzzleBoard.tsx","../src/components/ChessPuzzle/parts/Reset.tsx","../src/components/ChessPuzzle/parts/Hint.tsx","../src/components/ChessPuzzle/index.ts"],"sourcesContent":["import React from \"react\";\nimport { Puzzle, getOrientation } from \"../../../utils\";\nimport {\n ChessPuzzleContextType,\n useChessPuzzle,\n} from \"../../../hooks/useChessPuzzle\";\nimport { ChessGame } from \"@react-chess-tools/react-chess-game\";\nimport { ChessPuzzleContext } from \"../../../hooks/useChessPuzzleContext\";\n\nexport interface RootProps {\n puzzle: Puzzle;\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void;\n onFail?: (puzzleContext: ChessPuzzleContextType) => void;\n}\n\nconst PuzzleRoot: React.FC<React.PropsWithChildren<RootProps>> = ({\n puzzle,\n onSolve,\n onFail,\n children,\n}) => {\n const context = useChessPuzzle(puzzle, onSolve, onFail);\n\n return (\n <ChessPuzzleContext.Provider value={context}>\n {children}\n </ChessPuzzleContext.Provider>\n );\n};\n\nexport const Root: React.FC<React.PropsWithChildren<RootProps>> = ({\n puzzle,\n onSolve,\n onFail,\n children,\n}) => {\n return (\n <ChessGame.Root fen={puzzle.fen} orientation={getOrientation(puzzle)}>\n <PuzzleRoot puzzle={puzzle} onSolve={onSolve} onFail={onFail}>\n {children}\n </PuzzleRoot>\n </ChessGame.Root>\n );\n};\n","import { type Color, Chess, Move } from \"chess.js\";\nimport React, { CSSProperties, ReactElement, ReactNode } from \"react\";\nimport _ from \"lodash\";\n\nexport type Status = \"not-started\" | \"in-progress\" | \"solved\" | \"failed\";\n\nexport type Hint = \"none\" | \"piece\" | \"move\";\n\nexport type Puzzle = {\n fen: string;\n moves: string[];\n // if the first move of the puzzle has to be made by the cpu, as in chess.com puzzles\n makeFirstMove?: boolean;\n};\n\nconst FAIL_COLOR = \"rgba(201, 52, 48, 0.5)\";\nconst SUCCESS_COLOR = \"rgba(172, 206, 89, 0.5)\";\nconst HINT_COLOR = \"rgba(27, 172, 166, 0.5)\";\n\nexport const getOrientation = (puzzle: Puzzle): Color => {\n const fen = puzzle.fen;\n const game = new Chess(fen);\n if (puzzle.makeFirstMove) {\n game.move(puzzle.moves[0]);\n }\n return game.turn();\n};\n\ninterface ClickableElement extends ReactElement {\n props: {\n onClick?: () => void;\n };\n}\n\nexport const isClickableElement = (\n element: ReactNode,\n): element is ClickableElement => React.isValidElement(element);\n\nexport const getCustomSquareStyles = (\n status: Status,\n hint: Hint,\n isPlayerTurn: boolean,\n game: Chess,\n nextMove?: Move | null,\n) => {\n const customSquareStyles: Record<string, CSSProperties> = {};\n\n const lastMove = _.last(game.history({ verbose: true }));\n\n if (status === \"failed\" && lastMove) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: FAIL_COLOR,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: FAIL_COLOR,\n };\n }\n\n if (\n lastMove &&\n (status === \"solved\" || (status !== \"failed\" && !isPlayerTurn))\n ) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: SUCCESS_COLOR,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: SUCCESS_COLOR,\n };\n }\n\n if (hint === \"piece\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: HINT_COLOR,\n };\n }\n }\n\n if (hint === \"move\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: HINT_COLOR,\n };\n customSquareStyles[nextMove.to] = {\n backgroundColor: HINT_COLOR,\n };\n }\n }\n\n return customSquareStyles;\n};\n\nexport const stringToMove = (game: Chess, move: string | null | undefined) => {\n const copy = new Chess(game.fen());\n if (move === null || move === undefined) {\n return null;\n }\n try {\n return copy.move(move);\n } catch (e) {\n return null;\n }\n};\n","import { useEffect, useReducer, useCallback, useMemo } from \"react\";\nimport { initializePuzzle, reducer } from \"./reducer\";\nimport { getOrientation, type Puzzle, type Hint, type Status } from \"../utils\";\nimport { useChessGameContext } from \"@react-chess-tools/react-chess-game\";\n\nexport type ChessPuzzleContextType = {\n status: Status;\n changePuzzle: (puzzle: Puzzle) => void;\n resetPuzzle: () => void;\n puzzle: Puzzle;\n hint: Hint;\n nextMove?: string | null;\n isPlayerTurn: boolean;\n onHint: () => void;\n puzzleState: Status;\n movesPlayed: number;\n totalMoves: number;\n};\n\nexport const useChessPuzzle = (\n puzzle: Puzzle,\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void,\n onFail?: (puzzleContext: ChessPuzzleContextType) => void,\n): ChessPuzzleContextType => {\n const gameContext = useChessGameContext();\n\n const [state, dispatch] = useReducer(reducer, { puzzle }, initializePuzzle);\n\n const {\n game,\n methods: { makeMove, setPosition },\n } = gameContext;\n\n const changePuzzle = useCallback(\n (puzzle: Puzzle) => {\n setPosition(puzzle.fen, getOrientation(puzzle));\n dispatch({ type: \"INITIALIZE\", payload: { puzzle } });\n },\n [setPosition],\n );\n\n useEffect(() => {\n changePuzzle(puzzle);\n }, [JSON.stringify(puzzle), changePuzzle]);\n\n useEffect(() => {\n if (gameContext && game.fen() === puzzle.fen && state.needCpuMove) {\n setTimeout(\n () =>\n dispatch({\n type: \"CPU_MOVE\",\n }),\n 0,\n );\n }\n }, [gameContext, state.needCpuMove]);\n\n useEffect(() => {\n if (state.cpuMove) {\n makeMove(state.cpuMove);\n }\n }, [state.cpuMove]);\n\n if (!gameContext) {\n throw new Error(\"useChessPuzzle must be used within a ChessGameContext\");\n }\n\n const onHint = useCallback(() => {\n dispatch({ type: \"TOGGLE_HINT\" });\n }, []);\n\n const resetPuzzle = useCallback(() => {\n changePuzzle(puzzle);\n }, [changePuzzle, puzzle]);\n\n const puzzleContext: ChessPuzzleContextType = useMemo(\n () => ({\n status: state.status,\n changePuzzle,\n resetPuzzle,\n puzzle,\n hint: state.hint,\n onHint,\n nextMove: state.nextMove,\n isPlayerTurn: state.isPlayerTurn,\n puzzleState: state.status,\n movesPlayed: state.currentMoveIndex,\n totalMoves: puzzle.moves.length,\n }),\n [\n state.status,\n changePuzzle,\n resetPuzzle,\n puzzle,\n state.hint,\n onHint,\n state.nextMove,\n state.isPlayerTurn,\n state.currentMoveIndex,\n ],\n );\n\n useEffect(() => {\n if (game?.history()?.length <= 0 + (puzzle.makeFirstMove ? 1 : 0)) {\n return;\n }\n if (game.history().length % 2 === (puzzle.makeFirstMove ? 0 : 1)) {\n dispatch({\n type: \"PLAYER_MOVE\",\n payload: {\n move: gameContext?.game?.history({ verbose: true })?.pop() ?? null,\n puzzleContext,\n game: game,\n },\n });\n\n dispatch({\n type: \"CPU_MOVE\",\n });\n }\n }, [game?.history()?.length]);\n\n useEffect(() => {\n if (state.status === \"solved\" && !state.onSolveInvoked && onSolve) {\n onSolve(puzzleContext);\n dispatch({ type: \"MARK_SOLVE_INVOKED\" });\n }\n }, [state.status, state.onSolveInvoked]);\n\n useEffect(() => {\n if (state.status === \"failed\" && !state.onFailInvoked && onFail) {\n onFail(puzzleContext);\n dispatch({ type: \"MARK_FAIL_INVOKED\" });\n }\n }, [state.status, state.onFailInvoked]);\n\n return puzzleContext;\n};\n","import { Chess, Move } from \"chess.js\";\nimport { type Puzzle, type Hint, type Status } from \"../utils\";\nimport { ChessPuzzleContextType } from \"./useChessPuzzle\";\n\nexport type State = {\n puzzle: Puzzle;\n currentMoveIndex: number;\n status: Status;\n cpuMove?: string | null;\n nextMove?: string | null;\n hint: Hint;\n needCpuMove: boolean;\n isPlayerTurn: boolean;\n onSolveInvoked: boolean;\n onFailInvoked: boolean;\n};\n\nexport type Action =\n | {\n type: \"INITIALIZE\";\n payload: {\n puzzle: Puzzle;\n };\n }\n | {\n type: \"RESET\";\n }\n | { type: \"TOGGLE_HINT\" }\n | {\n type: \"CPU_MOVE\";\n }\n | {\n type: \"PLAYER_MOVE\";\n payload: {\n move?: Move | null;\n puzzleContext: ChessPuzzleContextType;\n game: Chess;\n };\n }\n | { type: \"MARK_SOLVE_INVOKED\" }\n | { type: \"MARK_FAIL_INVOKED\" };\n\nexport const initializePuzzle = ({ puzzle }: { puzzle: Puzzle }): State => {\n return {\n puzzle,\n currentMoveIndex: 0,\n status: \"not-started\",\n nextMove: puzzle.moves[0],\n hint: \"none\",\n cpuMove: null,\n needCpuMove: !!puzzle.makeFirstMove,\n isPlayerTurn: !puzzle.makeFirstMove,\n onSolveInvoked: false,\n onFailInvoked: false,\n };\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"INITIALIZE\":\n return {\n ...state,\n ...initializePuzzle(action.payload),\n };\n case \"RESET\":\n return {\n ...state,\n ...initializePuzzle({\n puzzle: state.puzzle,\n }),\n };\n case \"TOGGLE_HINT\":\n if (state.hint === \"none\") {\n return { ...state, hint: \"piece\" };\n }\n return { ...state, hint: \"move\" };\n case \"CPU_MOVE\":\n if (state.isPlayerTurn) {\n return state;\n }\n if ([\"solved\", \"failed\"].includes(state.status)) {\n return state;\n }\n\n return {\n ...state,\n currentMoveIndex: state.currentMoveIndex + 1,\n cpuMove: state.puzzle.moves[state.currentMoveIndex],\n nextMove:\n state.currentMoveIndex < state.puzzle.moves.length - 1\n ? state.puzzle.moves[state.currentMoveIndex + 1]\n : null,\n needCpuMove: false,\n isPlayerTurn: true,\n status: \"in-progress\",\n };\n\n case \"PLAYER_MOVE\": {\n const { move } = action.payload;\n\n const isMoveRight = [move?.san, move?.lan].includes(\n state?.nextMove || \"\",\n );\n const isPuzzleSolved =\n state.currentMoveIndex === state.puzzle.moves.length - 1;\n\n if (!isMoveRight) {\n return {\n ...state,\n status: \"failed\",\n nextMove: null,\n hint: \"none\",\n isPlayerTurn: false,\n onFailInvoked: false,\n };\n }\n\n if (isPuzzleSolved) {\n return {\n ...state,\n status: \"solved\",\n nextMove: null,\n hint: \"none\",\n isPlayerTurn: false,\n onSolveInvoked: false,\n };\n }\n\n return {\n ...state,\n hint: \"none\",\n currentMoveIndex: state.currentMoveIndex + 1,\n nextMove: state.puzzle.moves[state.currentMoveIndex + 1],\n status: \"in-progress\",\n needCpuMove: true,\n isPlayerTurn: false,\n };\n }\n\n case \"MARK_SOLVE_INVOKED\":\n return {\n ...state,\n onSolveInvoked: true,\n };\n\n case \"MARK_FAIL_INVOKED\":\n return {\n ...state,\n onFailInvoked: true,\n };\n\n default:\n return state;\n }\n};\n","import React from \"react\";\nimport { useChessPuzzle } from \"./useChessPuzzle\";\n\nexport const ChessPuzzleContext = React.createContext<ReturnType<\n typeof useChessPuzzle\n> | null>(null);\n\nexport const useChessPuzzleContext = () => {\n const context = React.useContext(ChessPuzzleContext);\n if (!context) {\n throw new Error(\n `useChessPuzzleContext must be used within a ChessPuzzle component. Make sure your component is wrapped with <ChessPuzzle.Root> or ensure the ChessPuzzle component is properly rendered in the component tree.`,\n );\n }\n return context;\n};\n","import React from \"react\";\nimport {\n ChessGame,\n deepMergeChessboardOptions,\n useChessGameContext,\n} from \"@react-chess-tools/react-chess-game\";\nimport { getCustomSquareStyles, stringToMove } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\n\nexport interface PuzzleBoardProps\n extends React.ComponentProps<typeof ChessGame.Board> {}\nexport const PuzzleBoard: React.FC<PuzzleBoardProps> = ({\n options = {},\n ...rest\n}) => {\n const puzzleContext = useChessPuzzleContext();\n const gameContext = useChessGameContext();\n\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n if (!gameContext) {\n throw new Error(\"ChessGameContext not found\");\n }\n\n const { game } = gameContext;\n const { status, hint, isPlayerTurn, nextMove } = puzzleContext;\n\n const mergedOptions = deepMergeChessboardOptions(options, {\n squareStyles: getCustomSquareStyles(\n status,\n hint,\n isPlayerTurn,\n game,\n stringToMove(game, nextMove),\n ),\n });\n\n return <ChessGame.Board {...rest} options={mergedOptions} />;\n};\n","import React from \"react\";\nimport { isClickableElement, type Puzzle, type Status } from \"../../../utils\";\nimport { useChessPuzzleContext, type ChessPuzzleContextType } from \"../../..\";\n\nexport interface ResetProps {\n asChild?: boolean;\n puzzle?: Puzzle;\n onReset?: (puzzleContext: ChessPuzzleContextType) => void;\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"failed\", \"solved\"];\n\nexport const Reset: React.FC<React.PropsWithChildren<ResetProps>> = ({\n children,\n asChild,\n puzzle,\n onReset,\n showOn = defaultShowOn,\n}) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { changePuzzle, status } = puzzleContext;\n const handleClick = () => {\n changePuzzle(puzzle || puzzleContext.puzzle);\n onReset?.(puzzleContext);\n };\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n if (asChild) {\n const child = React.Children.only(children);\n if (isClickableElement(child)) {\n return React.cloneElement(child, {\n onClick: handleClick,\n });\n } else {\n throw new Error(\"Change child must be a clickable element\");\n }\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n","import React from \"react\";\nimport { Status, isClickableElement } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\n\nexport interface HintProps {\n asChild?: boolean;\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"not-started\", \"in-progress\"];\n\nexport const Hint: React.FC<React.PropsWithChildren<HintProps>> = ({\n children,\n asChild,\n showOn = defaultShowOn,\n}) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { onHint, status } = puzzleContext;\n const handleClick = () => {\n onHint();\n };\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n if (asChild) {\n const child = React.Children.only(children);\n if (isClickableElement(child)) {\n return React.cloneElement(child, {\n onClick: handleClick,\n });\n } else {\n throw new Error(\"Change child must be a clickable element\");\n }\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n","import { Root } from \"./parts/Root\";\nimport { PuzzleBoard } from \"./parts/PuzzleBoard\";\nimport { Reset } from \"./parts/Reset\";\nimport { Hint } from \"./parts/Hint\";\n\nexport const ChessPuzzle = {\n Root,\n Board: PuzzleBoard,\n Reset,\n Hint,\n};\n"],"mappings":"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","names":["React","puzzle","_a","React","React","React","ChessGame","useChessGameContext","useChessGameContext","React","ChessGame","React","React","React","defaultShowOn","React"]}
|