@react-chess-tools/react-chess-puzzle 1.0.0 → 1.0.2

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @react-chess-tools/react-chess-puzzle
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - aa6db4a: feat: add solveOnCheckmate prop
8
+
9
+ ## 1.0.1
10
+
11
+ ### Patch Changes
12
+
13
+ - f9b7665: feat: add ref forwarding, HTML attributes, and improved asChild pattern
14
+ - Updated dependencies [f9b7665]
15
+ - @react-chess-tools/react-chess-game@1.0.1
16
+
3
17
  ## 1.0.0
4
18
 
5
19
  ### Major Changes
package/README.md ADDED
@@ -0,0 +1,570 @@
1
+ <div align="center">
2
+ <h1>@react-chess-tools/react-chess-puzzle</h1>
3
+ <p>A lightweight, customizable React component library for rendering and interacting with chess puzzles</p>
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@react-chess-tools/react-chess-puzzle.svg)](https://www.npmjs.com/package/@react-chess-tools/react-chess-puzzle)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@react-chess-tools/react-chess-puzzle.svg)](https://www.npmjs.com/package/@react-chess-tools/react-chess-puzzle)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
9
+
10
+ </div>
11
+
12
+ ## Table of Contents
13
+
14
+ - [Overview](#overview)
15
+ - [Features](#features)
16
+ - [Installation](#installation)
17
+ - [Quick Start](#quick-start)
18
+ - [Demo](#demo)
19
+ - [Puzzle Solving Flow](#puzzle-solving-flow)
20
+ - [API Reference](#api-reference)
21
+ - [ChessPuzzle.Root](#chesspuzzleroot)
22
+ - [ChessPuzzle.Board](#chesspuzzleboard)
23
+ - [ChessPuzzle.Reset](#chesspuzzlereset)
24
+ - [ChessPuzzle.Hint](#chesspuzzlehint)
25
+ - [Hooks](#hooks)
26
+ - [useChessPuzzleContext](#usechesspuzzlecontext)
27
+ - [useChessGameContext](#usechessgamecontext)
28
+ - [Integration with react-chess-game](#integration-with-react-chess-game)
29
+ - [Examples](#examples)
30
+ - [License](#license)
31
+
32
+ ## Overview
33
+
34
+ `@react-chess-tools/react-chess-puzzle` is a React component library for creating interactive chess puzzle experiences. Built on top of [@react-chess-tools/react-chess-game](https://www.npmjs.com/package/@react-chess-tools/react-chess-game), it provides puzzle-specific features like move validation, hints, and progress tracking.
35
+
36
+ ## Features
37
+
38
+ - **Move Validation** - Automatically validates moves against the puzzle solution
39
+ - **Hints** - Show the next correct move to help users
40
+ - **Progress Tracking** - Track puzzle state (not-started, in-progress, solved, failed)
41
+ - **Callbacks** - React to puzzle solve/fail events
42
+ - **Built-in Reset** - Easily restart puzzles or load new ones
43
+ - **Sound Effects** - Integrates with ChessGame.Sounds for audio feedback
44
+ - **Keyboard Controls** - Navigate through puzzle moves with keyboard
45
+ - **TypeScript** - Full TypeScript support with comprehensive type definitions
46
+ - **Multiple solutions** - Accept any checkmate as a solution (configurable via `solveOnCheckmate`)
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ npm install @react-chess-tools/react-chess-puzzle
52
+ ```
53
+
54
+ ```bash
55
+ yarn add @react-chess-tools/react-chess-puzzle
56
+ ```
57
+
58
+ ```bash
59
+ pnpm add @react-chess-tools/react-chess-puzzle
60
+ ```
61
+
62
+ ## Quick Start
63
+
64
+ ```tsx
65
+ import { ChessPuzzle } from "@react-chess-tools/react-chess-puzzle";
66
+
67
+ function App() {
68
+ const puzzle = {
69
+ fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
70
+ moves: ["d2d4", "e5d4", "f3d4"],
71
+ makeFirstMove: false,
72
+ };
73
+
74
+ return (
75
+ <ChessPuzzle.Root puzzle={puzzle}>
76
+ <ChessPuzzle.Board />
77
+ <ChessPuzzle.Reset>Restart</ChessPuzzle.Reset>
78
+ <ChessPuzzle.Hint>Get Hint</ChessPuzzle.Hint>
79
+ </ChessPuzzle.Root>
80
+ );
81
+ }
82
+ ```
83
+
84
+ ## Demo
85
+
86
+ Visit the [live demo](https://react-chess-tools.vercel.app/) to see the component in action.
87
+
88
+ ## Puzzle Solving Flow
89
+
90
+ 1. **Initial Setup** - The board displays the position from the FEN string
91
+ 2. **First Move** - If `makeFirstMove` is `true`, the component automatically plays the first move
92
+ 3. **User Interaction** - The user attempts to solve the puzzle by making moves
93
+ 4. **Validation** - Each move is validated against the solution:
94
+ - Correct move: The puzzle continues, opponent's response is auto-played
95
+ - Incorrect move: The puzzle is marked as failed
96
+ 5. **Completion** - When all correct moves are made, the puzzle is marked as solved
97
+
98
+ ## API Reference
99
+
100
+ ### ChessPuzzle.Root
101
+
102
+ The root component that provides puzzle context to all child components.
103
+
104
+ **Note:** This is a logic-only component (Context Provider). It does not render any DOM elements.
105
+
106
+ #### Props
107
+
108
+ | Name | Type | Default | Description |
109
+ | ------------------ | --------------------------------------- | ------- | ----------------------------------------------- |
110
+ | `puzzle` | `Puzzle` | - | The puzzle configuration (required) |
111
+ | `onSolve` | `(ctx: ChessPuzzleContextType) => void` | - | Callback when puzzle is solved |
112
+ | `onFail` | `(ctx: ChessPuzzleContextType) => void` | - | Callback when an incorrect move is made |
113
+ | `solveOnCheckmate` | `boolean` | `true` | When true, any checkmate move solves the puzzle |
114
+ | `theme` | `PartialChessPuzzleTheme` | - | Optional theme configuration |
115
+ | `children` | `ReactNode` | - | Child components |
116
+
117
+ #### Puzzle Object
118
+
119
+ | Property | Type | Default | Description |
120
+ | --------------- | ---------- | ------- | ------------------------------------------- |
121
+ | `fen` | `string` | - | Initial position in FEN notation |
122
+ | `moves` | `string[]` | - | Solution moves in algebraic or UCI notation |
123
+ | `makeFirstMove` | `boolean` | `false` | Whether to auto-play the first move |
124
+
125
+ #### Example
126
+
127
+ ```tsx
128
+ <ChessPuzzle.Root
129
+ puzzle={{
130
+ fen: "4kb1r/p2r1ppp/4qn2/1B2p1B1/4P3/1Q6/PPP2PPP/2KR4 w k - 0 1",
131
+ moves: ["Bxd7+", "Nxd7", "Qb8+", "Nxb8", "Rd8#"],
132
+ makeFirstMove: false,
133
+ }}
134
+ onSolve={(ctx) => console.log("Solved!", ctx.movesPlayed)}
135
+ onFail={(ctx) => console.log("Failed at move", ctx.movesPlayed)}
136
+ >
137
+ <ChessPuzzle.Board />
138
+ </ChessPuzzle.Root>
139
+ ```
140
+
141
+ ### ChessPuzzle.Board
142
+
143
+ Renders the chess board. Delegates to `ChessGame.Board` under the hood.
144
+
145
+ Supports **ref forwarding** and all standard **HTML div attributes** (className, style, id, data-_, aria-_, etc.).
146
+
147
+ #### Props
148
+
149
+ | Name | Type | Description |
150
+ | ----------- | -------------------------------- | --------------------------------------------- |
151
+ | `options` | `ChessboardOptions` | Options forwarded to `react-chessboard` v5 |
152
+ | `ref` | `Ref<HTMLDivElement>` | Forwarded ref to the underlying board element |
153
+ | `className` | `string` | Custom CSS class names |
154
+ | `style` | `CSSProperties` | Custom inline styles |
155
+ | `...` | `HTMLAttributes<HTMLDivElement>` | All standard HTML div attributes |
156
+
157
+ #### Example
158
+
159
+ ```tsx
160
+ <ChessPuzzle.Root puzzle={puzzle}>
161
+ <ChessPuzzle.Board
162
+ options={{
163
+ showNotation: true,
164
+ animationDurationInMs: 200,
165
+ }}
166
+ className="puzzle-board"
167
+ style={{ boxShadow: "0 4px 6px rgba(0,0,0,0.1)" }}
168
+ />
169
+ </ChessPuzzle.Root>
170
+ ```
171
+
172
+ ### ChessPuzzle.Reset
173
+
174
+ A button component that resets the current puzzle or loads a new one.
175
+
176
+ Supports **ref forwarding**, **asChild pattern**, and all standard **HTML button attributes** (className, style, disabled, etc.).
177
+
178
+ #### Props
179
+
180
+ | Name | Type | Default | Description |
181
+ | ----------- | ----------------------------------------- | ----------------------------------- | --------------------------------------------------- |
182
+ | `puzzle` | `Puzzle` | - | New puzzle to load (resets current if not provided) |
183
+ | `onReset` | `(ctx: ChessPuzzleContextType) => void` | - | Callback after reset |
184
+ | `showOn` | `Status[]` | `["failed", "solved"]` | States in which the button is visible |
185
+ | `asChild` | `boolean` | `false` | Render as child element (slot pattern) |
186
+ | `ref` | `Ref<HTMLButtonElement>` | Forwarded ref to the button element |
187
+ | `className` | `string` | Custom CSS class names |
188
+ | `...` | `ButtonHTMLAttributes<HTMLButtonElement>` | All standard HTML button attributes |
189
+
190
+ **Status values:** `"not-started"`, `"in-progress"`, `"solved"`, `"failed"`
191
+
192
+ #### Example
193
+
194
+ ```tsx
195
+ <ChessPuzzle.Root puzzle={puzzle}>
196
+ <ChessPuzzle.Board />
197
+ <ChessPuzzle.Reset>Try Again</ChessPuzzle.Reset>
198
+ <ChessPuzzle.Reset puzzle={nextPuzzle}>Next Puzzle</ChessPuzzle.Reset>
199
+ </ChessPuzzle.Root>
200
+ ```
201
+
202
+ #### Using asChild Pattern
203
+
204
+ ```tsx
205
+ // Render as a custom button component
206
+ import { MyCustomButton } from './MyButton';
207
+
208
+ <ChessPuzzle.Root puzzle={puzzle}>
209
+ <ChessPuzzle.Board />
210
+ <ChessPuzzle.Reset asChild>
211
+ <MyCustomButton variant="primary">Try Again</MyCustomButton>
212
+ </ChessPuzzle.Reset>
213
+ </ChessPuzzle.Root>
214
+
215
+ // Render as a link
216
+ <ChessPuzzle.Root puzzle={puzzle}>
217
+ <ChessPuzzle.Board />
218
+ <ChessPuzzle.Reset asChild>
219
+ <a href="#" onClick={(e) => e.preventDefault()}>
220
+ Restart Puzzle
221
+ </a>
222
+ </ChessPuzzle.Reset>
223
+ </ChessPuzzle.Root>
224
+ ```
225
+
226
+ #### Event Handler Composition
227
+
228
+ When using `asChild`, both your component's onClick and the Reset's onClick handler will work together:
229
+
230
+ ```tsx
231
+ <ChessPuzzle.Reset asChild>
232
+ <button onClick={() => console.log("Custom handler")} className="custom-btn">
233
+ Try Again
234
+ </button>
235
+ </ChessPuzzle.Reset>
236
+ // Both custom handler and reset logic will execute
237
+ ```
238
+
239
+ ### ChessPuzzle.Hint
240
+
241
+ A button that highlights the next correct move on the board.
242
+
243
+ Supports **ref forwarding**, **asChild pattern**, and all standard **HTML button attributes** (className, style, disabled, etc.).
244
+
245
+ #### Props
246
+
247
+ | Name | Type | Default | Description |
248
+ | ----------- | ----------------------------------------- | ----------------------------------- | -------------------------------------- |
249
+ | `showOn` | `Status[]` | `["not-started", "in-progress"]` | States in which the button is visible |
250
+ | `asChild` | `boolean` | `false` | Render as child element (slot pattern) |
251
+ | `ref` | `Ref<HTMLButtonElement>` | Forwarded ref to the button element |
252
+ | `className` | `string` | Custom CSS class names |
253
+ | `...` | `ButtonHTMLAttributes<HTMLButtonElement>` | All standard HTML button attributes |
254
+
255
+ #### Example
256
+
257
+ ```tsx
258
+ const puzzle = {
259
+ fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
260
+ moves: ["d2d4", "e5d4", "f3d4"],
261
+ makeFirstMove: false,
262
+ };
263
+
264
+ <ChessPuzzle.Root puzzle={puzzle}>
265
+ <ChessPuzzle.Board />
266
+ <ChessPuzzle.Hint>Show Hint</ChessPuzzle.Hint>
267
+ </ChessPuzzle.Root>;
268
+ ```
269
+
270
+ #### Using asChild Pattern
271
+
272
+ ```tsx
273
+ <ChessPuzzle.Root puzzle={puzzle}>
274
+ <ChessPuzzle.Board />
275
+ <ChessPuzzle.Hint asChild>
276
+ <button className="hint-btn">💡 Show Hint</button>
277
+ </ChessPuzzle.Hint>
278
+ </ChessPuzzle.Root>
279
+ ```
280
+
281
+ ## Hooks
282
+
283
+ ### useChessPuzzleContext
284
+
285
+ Access the puzzle state and methods from any child component.
286
+
287
+ ```tsx
288
+ import { useChessPuzzleContext } from "@react-chess-tools/react-chess-puzzle";
289
+
290
+ function PuzzleStatus() {
291
+ const { puzzleState, movesPlayed, totalMoves, resetPuzzle, onHint } =
292
+ useChessPuzzleContext();
293
+
294
+ return (
295
+ <div>
296
+ <p>Status: {puzzleState}</p>
297
+ <p>
298
+ Progress: {movesPlayed}/{totalMoves} moves
299
+ </p>
300
+ <button onClick={resetPuzzle}>Reset</button>
301
+ <button onClick={onHint}>Hint</button>
302
+ </div>
303
+ );
304
+ }
305
+ ```
306
+
307
+ #### Return Values
308
+
309
+ | Property | Type | Description |
310
+ | -------------- | -------------------------- | -------------------------------------- |
311
+ | `status` | `Status` | Current puzzle state |
312
+ | `puzzleState` | `Status` | Alias for `status` |
313
+ | `movesPlayed` | `number` | Number of correct moves made |
314
+ | `totalMoves` | `number` | Total moves in the solution |
315
+ | `puzzle` | `Puzzle` | The current puzzle object |
316
+ | `hint` | `Hint` | Current hint state |
317
+ | `nextMove` | `string \| null` | The next correct move |
318
+ | `isPlayerTurn` | `boolean` | Whether it's the player's turn to move |
319
+ | `changePuzzle` | `(puzzle: Puzzle) => void` | Load a new puzzle |
320
+ | `resetPuzzle` | `() => void` | Reset the current puzzle |
321
+ | `onHint` | `() => void` | Show hint for next move |
322
+
323
+ ### useChessGameContext
324
+
325
+ Since `react-chess-puzzle` is built on `react-chess-game`, you can also access the underlying game context.
326
+
327
+ ```tsx
328
+ import { useChessGameContext } from "@react-chess-tools/react-chess-game";
329
+
330
+ function BoardInfo() {
331
+ const { currentFen, info, methods } = useChessGameContext();
332
+
333
+ return (
334
+ <div>
335
+ <p>Turn: {info.turn === "w" ? "White" : "Black"}</p>
336
+ <button onClick={() => methods.flipBoard()}>Flip Board</button>
337
+ </div>
338
+ );
339
+ }
340
+ ```
341
+
342
+ ## Integration with react-chess-game
343
+
344
+ Since `react-chess-puzzle` is built on `react-chess-game`, you can use any of its components:
345
+
346
+ ### Adding Sound Effects
347
+
348
+ ```tsx
349
+ import { ChessPuzzle } from "@react-chess-tools/react-chess-puzzle";
350
+ import { ChessGame } from "@react-chess-tools/react-chess-game";
351
+
352
+ function PuzzleWithSounds() {
353
+ const puzzle = {
354
+ fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
355
+ moves: ["d2d4", "e5d4", "f3d4"],
356
+ };
357
+
358
+ return (
359
+ <ChessPuzzle.Root puzzle={puzzle}>
360
+ <ChessGame.Sounds />
361
+ <ChessPuzzle.Board />
362
+ </ChessPuzzle.Root>
363
+ );
364
+ }
365
+ ```
366
+
367
+ ### Adding Keyboard Controls
368
+
369
+ ```tsx
370
+ import { ChessPuzzle } from "@react-chess-tools/react-chess-puzzle";
371
+ import { ChessGame } from "@react-chess-tools/react-chess-game";
372
+
373
+ function PuzzleWithKeyboard() {
374
+ const puzzle = {
375
+ fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
376
+ moves: ["d2d4", "e5d4", "f3d4"],
377
+ };
378
+
379
+ return (
380
+ <ChessPuzzle.Root puzzle={puzzle}>
381
+ <ChessGame.KeyboardControls />
382
+ <ChessPuzzle.Board />
383
+ </ChessPuzzle.Root>
384
+ );
385
+ }
386
+ ```
387
+
388
+ ## Examples
389
+
390
+ ### Basic Puzzle
391
+
392
+ ```tsx
393
+ import { ChessPuzzle } from "@react-chess-tools/react-chess-puzzle";
394
+
395
+ function BasicPuzzle() {
396
+ const puzzle = {
397
+ fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
398
+ moves: ["d2d4", "e5d4", "f3d4"],
399
+ makeFirstMove: false,
400
+ };
401
+
402
+ return (
403
+ <ChessPuzzle.Root puzzle={puzzle}>
404
+ <ChessPuzzle.Board />
405
+ <ChessPuzzle.Reset>Restart</ChessPuzzle.Reset>
406
+ <ChessPuzzle.Hint>Hint</ChessPuzzle.Hint>
407
+ </ChessPuzzle.Root>
408
+ );
409
+ }
410
+ ```
411
+
412
+ ### Puzzle with Callbacks
413
+
414
+ ```tsx
415
+ import {
416
+ ChessPuzzle,
417
+ type ChessPuzzleContextType,
418
+ } from "@react-chess-tools/react-chess-puzzle";
419
+ import { useState } from "react";
420
+
421
+ function PuzzleWithScore() {
422
+ const [score, setScore] = useState(0);
423
+
424
+ const handleSolve = (ctx: ChessPuzzleContextType) => {
425
+ setScore((prev) => prev + 10);
426
+ console.log(`Solved in ${ctx.movesPlayed} moves!`);
427
+ };
428
+
429
+ const handleFail = (ctx: ChessPuzzleContextType) => {
430
+ setScore((prev) => Math.max(0, prev - 5));
431
+ console.log("Incorrect move!");
432
+ };
433
+
434
+ return (
435
+ <div>
436
+ <p>Score: {score}</p>
437
+ <ChessPuzzle.Root
438
+ puzzle={puzzle}
439
+ onSolve={handleSolve}
440
+ onFail={handleFail}
441
+ >
442
+ <ChessPuzzle.Board />
443
+ <ChessPuzzle.Reset>Try Again</ChessPuzzle.Reset>
444
+ </ChessPuzzle.Root>
445
+ </div>
446
+ );
447
+ }
448
+ ```
449
+
450
+ ### Puzzle Trainer with Multiple Puzzles
451
+
452
+ ```tsx
453
+ import {
454
+ ChessPuzzle,
455
+ type ChessPuzzleContextType,
456
+ } from "@react-chess-tools/react-chess-puzzle";
457
+ import { ChessGame } from "@react-chess-tools/react-chess-game";
458
+ import { useState } from "react";
459
+
460
+ const puzzles = [
461
+ {
462
+ fen: "4kb1r/p2r1ppp/4qn2/1B2p1B1/4P3/1Q6/PPP2PPP/2KR4 w k - 0 1",
463
+ moves: ["Bxd7+", "Nxd7", "Qb8+", "Nxb8", "Rd8#"],
464
+ makeFirstMove: false,
465
+ },
466
+ {
467
+ fen: "6k1/5p1p/p1q1p1p1/1pB1P3/1Pr3Pn/P4P1P/4Q3/3R2K1 b - - 0 31",
468
+ moves: ["h4f3", "e2f3", "c4c5", "d1d8", "g8g7", "f3f6"],
469
+ makeFirstMove: true,
470
+ },
471
+ ];
472
+
473
+ function PuzzleTrainer() {
474
+ const [currentIndex, setCurrentIndex] = useState(0);
475
+ const [score, setScore] = useState(0);
476
+
477
+ const nextPuzzle = () => {
478
+ setCurrentIndex((prev) => (prev + 1) % puzzles.length);
479
+ };
480
+
481
+ const handleSolve = (ctx: ChessPuzzleContextType) => {
482
+ setScore((prev) => prev + 10);
483
+ nextPuzzle();
484
+ };
485
+
486
+ const handleFail = () => {
487
+ setScore((prev) => Math.max(0, prev - 5));
488
+ nextPuzzle();
489
+ };
490
+
491
+ return (
492
+ <div className="puzzle-trainer">
493
+ <div className="score">Score: {score}</div>
494
+
495
+ <ChessPuzzle.Root
496
+ puzzle={puzzles[currentIndex]}
497
+ onSolve={handleSolve}
498
+ onFail={handleFail}
499
+ >
500
+ <ChessGame.Sounds />
501
+ <ChessGame.KeyboardControls />
502
+
503
+ <ChessPuzzle.Board />
504
+
505
+ <div className="controls">
506
+ <ChessPuzzle.Reset>Restart</ChessPuzzle.Reset>
507
+ <ChessPuzzle.Hint>Hint</ChessPuzzle.Hint>
508
+ <ChessPuzzle.Reset
509
+ puzzle={puzzles[(currentIndex + 1) % puzzles.length]}
510
+ >
511
+ Skip
512
+ </ChessPuzzle.Reset>
513
+ </div>
514
+ </ChessPuzzle.Root>
515
+ </div>
516
+ );
517
+ }
518
+ ```
519
+
520
+ ### Custom Status Display
521
+
522
+ ```tsx
523
+ import {
524
+ ChessPuzzle,
525
+ useChessPuzzleContext,
526
+ } from "@react-chess-tools/react-chess-puzzle";
527
+
528
+ function PuzzleStatusDisplay() {
529
+ const { puzzleState, movesPlayed, totalMoves } = useChessPuzzleContext();
530
+
531
+ const messages = {
532
+ "not-started": "Make your move to start",
533
+ "in-progress": `Progress: ${movesPlayed}/${totalMoves} moves`,
534
+ solved: "Puzzle solved! Well done!",
535
+ failed: "Incorrect move. Try again!",
536
+ };
537
+
538
+ return <div className={`status ${puzzleState}`}>{messages[puzzleState]}</div>;
539
+ }
540
+
541
+ function ResetLabel() {
542
+ const { puzzleState } = useChessPuzzleContext();
543
+ return puzzleState === "solved" ? "Next Puzzle" : "Try Again";
544
+ }
545
+
546
+ function PuzzleWithStatus() {
547
+ const puzzle = {
548
+ fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
549
+ moves: ["d2d4", "e5d4", "f3d4"],
550
+ };
551
+
552
+ return (
553
+ <ChessPuzzle.Root puzzle={puzzle}>
554
+ <PuzzleStatusDisplay />
555
+ <ChessPuzzle.Board />
556
+ <ChessPuzzle.Reset showOn={["solved", "failed"]}>
557
+ <ResetLabel />
558
+ </ChessPuzzle.Reset>
559
+ </ChessPuzzle.Root>
560
+ );
561
+ }
562
+ ```
563
+
564
+ ## License
565
+
566
+ This project is [MIT](https://opensource.org/licenses/MIT) licensed.
567
+
568
+ ## Show Your Support
569
+
570
+ Give a star if this project helped you!