@react-chess-tools/react-chess-game 0.5.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +399 -0
  3. package/dist/index.cjs +785 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +278 -0
  6. package/dist/index.d.ts +278 -0
  7. package/dist/{index.mjs → index.js} +339 -196
  8. package/dist/index.js.map +1 -0
  9. package/package.json +19 -9
  10. package/src/components/ChessGame/Theme.stories.tsx +242 -0
  11. package/src/components/ChessGame/ThemePresets.stories.tsx +144 -0
  12. package/src/components/ChessGame/parts/Board.tsx +215 -204
  13. package/src/components/ChessGame/parts/KeyboardControls.tsx +9 -0
  14. package/src/components/ChessGame/parts/Root.tsx +13 -1
  15. package/src/components/ChessGame/parts/Sounds.tsx +9 -0
  16. package/src/components/ChessGame/parts/__tests__/Board.test.tsx +122 -0
  17. package/src/components/ChessGame/parts/__tests__/KeyboardControls.test.tsx +34 -0
  18. package/src/components/ChessGame/parts/__tests__/Root.test.tsx +50 -0
  19. package/src/components/ChessGame/parts/__tests__/Sounds.test.tsx +22 -0
  20. package/src/docs/Theming.mdx +281 -0
  21. package/src/hooks/useChessGame.ts +23 -7
  22. package/src/index.ts +19 -0
  23. package/src/theme/__tests__/context.test.tsx +60 -0
  24. package/src/theme/__tests__/defaults.test.ts +61 -0
  25. package/src/theme/__tests__/utils.test.ts +106 -0
  26. package/src/theme/context.tsx +37 -0
  27. package/src/theme/defaults.ts +22 -0
  28. package/src/theme/index.ts +36 -0
  29. package/src/theme/presets.ts +41 -0
  30. package/src/theme/types.ts +56 -0
  31. package/src/theme/utils.ts +47 -0
  32. package/src/utils/__tests__/board.test.ts +118 -0
  33. package/src/utils/board.ts +18 -9
  34. package/src/utils/chess.ts +25 -5
  35. package/README.MD +0 -190
  36. package/coverage/clover.xml +0 -6
  37. package/coverage/coverage-final.json +0 -1
  38. package/coverage/lcov-report/base.css +0 -224
  39. package/coverage/lcov-report/block-navigation.js +0 -87
  40. package/coverage/lcov-report/favicon.png +0 -0
  41. package/coverage/lcov-report/index.html +0 -101
  42. package/coverage/lcov-report/prettify.css +0 -1
  43. package/coverage/lcov-report/prettify.js +0 -2
  44. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  45. package/coverage/lcov-report/sorter.js +0 -196
  46. package/coverage/lcov.info +0 -0
  47. package/dist/index.d.mts +0 -158
  48. package/dist/index.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @react-chess-tools/react-chess-game
2
2
 
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - f9b7665: feat: add ref forwarding, HTML attributes, and improved asChild pattern
8
+
9
+ ## 1.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - b8f72df: Add comprehensive theming system with ThemeProvider, preset themes (Default, Lichess, Chess.com), Storybook documentation with interactive playgrounds, and comprehensive tests.
14
+
15
+ ### Minor Changes
16
+
17
+ - 8f16568: Add dual package ESM + CJS support with conditional exports for better compatibility across different environments and build tools.
18
+ - 15482ec: Upgrade dependencies including ESLint 9, TypeScript-ESLint 8, Jest 30, React 19.2.3, chess.js 1.4.0, and more.
19
+
20
+ ### Patch Changes
21
+
22
+ - b38be2f: Add automated release workflow with modern CI/CD pipeline. Fix changesets config and simplify package.json scripts.
23
+
3
24
  ## 0.5.2
4
25
 
5
26
  ### Patch Changes
package/README.md ADDED
@@ -0,0 +1,399 @@
1
+ <div align="center">
2
+ <h1>@react-chess-tools/react-chess-game</h1>
3
+ <p>An easy-customizable, ready-to-use chess game component for React</p>
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@react-chess-tools/react-chess-game.svg)](https://www.npmjs.com/package/@react-chess-tools/react-chess-game)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@react-chess-tools/react-chess-game.svg)](https://www.npmjs.com/package/@react-chess-tools/react-chess-game)
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
+ <p>
11
+ <a href="https://github.com/Clariity/react-chessboard">react-chessboard</a> +
12
+ <a href="https://github.com/jhlywa/chess.js">chess.js</a> + nice defaults
13
+ </p>
14
+ </div>
15
+
16
+ ## Table of Contents
17
+
18
+ - [Overview](#overview)
19
+ - [Features](#features)
20
+ - [Installation](#installation)
21
+ - [Quick Start](#quick-start)
22
+ - [Demo](#demo)
23
+ - [API Reference](#api-reference)
24
+ - [ChessGame.Root](#chessgameroot)
25
+ - [ChessGame.Board](#chessgameboard)
26
+ - [ChessGame.Sounds](#chessgamesounds)
27
+ - [ChessGame.KeyboardControls](#chessgamekeyboardcontrols)
28
+ - [Hooks](#hooks)
29
+ - [useChessGameContext](#usechessgamecontext)
30
+ - [Examples](#examples)
31
+ - [License](#license)
32
+
33
+ ## Overview
34
+
35
+ `@react-chess-tools/react-chess-game` is a React component that bridges [chess.js](https://github.com/jhlywa/chess.js) with [react-chessboard](https://github.com/Clariity/react-chessboard) to offer a full-featured, ready-to-integrate chess board experience.
36
+
37
+ Built using a compound component pattern (similar to [Radix UI](https://www.radix-ui.com/)), it provides a `ChessGameContext` that you can use to customize and enhance the game while maintaining sensible defaults.
38
+
39
+ ## Features
40
+
41
+ - **Move-by-click** - Click to select and move pieces
42
+ - **Sound effects** - Built-in sounds for moves, captures, check, and game over
43
+ - **Square highlighting** - Visual feedback for valid moves and last move
44
+ - **Keyboard controls** - Navigate through game history with arrow keys
45
+ - **Full game state** - Access to check, checkmate, stalemate, draw detection
46
+ - **TypeScript** - Full TypeScript support with comprehensive type definitions
47
+ - **Customizable** - Override any default with your own implementation
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ npm install @react-chess-tools/react-chess-game
53
+ ```
54
+
55
+ ```bash
56
+ yarn add @react-chess-tools/react-chess-game
57
+ ```
58
+
59
+ ```bash
60
+ pnpm add @react-chess-tools/react-chess-game
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ```tsx
66
+ import { ChessGame } from "@react-chess-tools/react-chess-game";
67
+
68
+ function App() {
69
+ return (
70
+ <ChessGame.Root>
71
+ <ChessGame.Board />
72
+ <ChessGame.Sounds />
73
+ <ChessGame.KeyboardControls />
74
+ </ChessGame.Root>
75
+ );
76
+ }
77
+ ```
78
+
79
+ ## Demo
80
+
81
+ Visit the [live demo](https://react-chess-tools.vercel.app/) to see the component in action.
82
+
83
+ ## API Reference
84
+
85
+ ### ChessGame.Root
86
+
87
+ The root component that provides `ChessGameContext` to all child components. It instantiates a `Chess` instance using the `fen` prop.
88
+
89
+ **Note:** This is a logic-only component (Context Provider). It does not render any DOM elements.
90
+
91
+ #### Props
92
+
93
+ | Name | Type | Default | Description |
94
+ | ------------- | ----------------------- | ----------------- | -------------------------------------------- |
95
+ | `children` | `ReactNode` | - | Child components |
96
+ | `fen` | `string` | Starting position | Initial FEN string for the chess game |
97
+ | `orientation` | `"w" \| "b"` | `"w"` | Board orientation (white or black at bottom) |
98
+ | `theme` | `PartialChessGameTheme` | - | Optional theme configuration |
99
+
100
+ #### Example
101
+
102
+ ```tsx
103
+ <ChessGame.Root
104
+ fen="rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1"
105
+ orientation="b"
106
+ >
107
+ <ChessGame.Board />
108
+ </ChessGame.Root>
109
+ ```
110
+
111
+ ### ChessGame.Board
112
+
113
+ The main chess board component. Renders the board and pieces using `react-chessboard` v5.
114
+
115
+ Supports **ref forwarding** and all standard **HTML div attributes** (className, style, id, data-_, aria-_, etc.).
116
+
117
+ #### Props
118
+
119
+ | Name | Type | Description |
120
+ | ----------- | -------------------------------- | ------------------------------------------------------------------------- |
121
+ | `options` | `ChessboardOptions` | Options forwarded to `react-chessboard`. Your values merge with defaults. |
122
+ | `ref` | `Ref<HTMLDivElement>` | Forwarded ref to the wrapper div element |
123
+ | `className` | `string` | Custom CSS class names |
124
+ | `style` | `CSSProperties` | Custom inline styles |
125
+ | `...` | `HTMLAttributes<HTMLDivElement>` | All standard HTML div attributes |
126
+
127
+ #### Example
128
+
129
+ ```tsx
130
+ <ChessGame.Root>
131
+ <ChessGame.Board
132
+ options={{
133
+ squareStyles: { e4: { boxShadow: "inset 0 0 0 2px #4f46e5" } },
134
+ onPieceDrop: ({ sourceSquare, targetSquare }) => {
135
+ console.log(`Move: ${sourceSquare} -> ${targetSquare}`);
136
+ return true;
137
+ },
138
+ showNotation: true,
139
+ animationDurationInMs: 300,
140
+ }}
141
+ className="my-custom-board"
142
+ style={{ borderRadius: "8px" }}
143
+ id="game-board"
144
+ data-testid="chess-board"
145
+ />
146
+ </ChessGame.Root>
147
+ ```
148
+
149
+ ### ChessGame.Sounds
150
+
151
+ Provides sound effects for the chess game. Uses built-in sounds by default, but custom sounds can be provided as base64-encoded strings.
152
+
153
+ **Note:** This is a logic-only component that returns `null`. It sets up audio functionality via hooks.
154
+
155
+ #### Props
156
+
157
+ | Name | Type | Default | Description |
158
+ | -------- | -------------------------------- | ------- | ------------------------------------------------------------------------- |
159
+ | `sounds` | `Partial<Record<Sound, string>>` | - | Custom sounds configuration. Keys: `move`, `capture`, `check`, `gameOver` |
160
+
161
+ #### Example
162
+
163
+ ```tsx
164
+ <ChessGame.Root>
165
+ <ChessGame.Sounds
166
+ sounds={{
167
+ move: customMoveSound,
168
+ capture: customCaptureSound,
169
+ }}
170
+ />
171
+ <ChessGame.Board />
172
+ </ChessGame.Root>
173
+ ```
174
+
175
+ ### ChessGame.KeyboardControls
176
+
177
+ Enables keyboard navigation through the game history.
178
+
179
+ **Note:** This is a logic-only component that returns `null`. It sets up keyboard event listeners via hooks.
180
+
181
+ #### Props
182
+
183
+ | Name | Type | Default | Description |
184
+ | ---------- | ------------------ | ------------------------- | --------------------------------------------- |
185
+ | `controls` | `KeyboardControls` | `defaultKeyboardControls` | Object mapping key names to handler functions |
186
+
187
+ **Default Controls:**
188
+
189
+ - `ArrowLeft` - Go to previous move
190
+ - `ArrowRight` - Go to next move
191
+ - `ArrowUp` - Go to starting position
192
+ - `ArrowDown` - Go to latest move
193
+
194
+ #### Example
195
+
196
+ ```tsx
197
+ <ChessGame.Root>
198
+ <ChessGame.KeyboardControls
199
+ controls={{
200
+ ArrowLeft: (ctx) => ctx.methods.goToPreviousMove(),
201
+ ArrowRight: (ctx) => ctx.methods.goToNextMove(),
202
+ Home: (ctx) => ctx.methods.goToStart(),
203
+ End: (ctx) => ctx.methods.goToEnd(),
204
+ }}
205
+ />
206
+ <ChessGame.Board />
207
+ </ChessGame.Root>
208
+ ```
209
+
210
+ ## Hooks
211
+
212
+ ### useChessGameContext
213
+
214
+ Access the chess game context from any child component.
215
+
216
+ ```tsx
217
+ import { useChessGameContext } from "@react-chess-tools/react-chess-game";
218
+
219
+ function GameStatus() {
220
+ const { currentFen, info, methods } = useChessGameContext();
221
+
222
+ return (
223
+ <div>
224
+ <p>Turn: {info.turn === "w" ? "White" : "Black"}</p>
225
+ {info.isCheck && <p>Check!</p>}
226
+ {info.isCheckmate && <p>Checkmate!</p>}
227
+ <button onClick={() => methods.flipBoard()}>Flip Board</button>
228
+ </div>
229
+ );
230
+ }
231
+ ```
232
+
233
+ #### Return Values
234
+
235
+ | Name | Type | Description |
236
+ | ------------------ | ------------ | ----------------------------------- |
237
+ | `game` | `Chess` | The underlying chess.js instance |
238
+ | `orientation` | `"w" \| "b"` | Current board orientation |
239
+ | `currentFen` | `string` | Current FEN string |
240
+ | `currentPosition` | `string` | Current position in game history |
241
+ | `currentMoveIndex` | `number` | Index of current move in history |
242
+ | `isLatestMove` | `boolean` | Whether viewing the latest position |
243
+ | `methods` | `Methods` | Methods to interact with the game |
244
+ | `info` | `Info` | Game state information |
245
+
246
+ #### Methods
247
+
248
+ | Method | Type | Description |
249
+ | ------------------ | ------------------------------------------------ | --------------------------------------- |
250
+ | `makeMove` | `(move: string \| MoveObject) => boolean` | Make a move, returns true if successful |
251
+ | `setPosition` | `(fen: string, orientation: "w" \| "b") => void` | Set a new position |
252
+ | `flipBoard` | `() => void` | Flip the board orientation |
253
+ | `goToMove` | `(moveIndex: number) => void` | Jump to specific move (-1 = start) |
254
+ | `goToStart` | `() => void` | Go to starting position |
255
+ | `goToEnd` | `() => void` | Go to latest move |
256
+ | `goToPreviousMove` | `() => void` | Go to previous move |
257
+ | `goToNextMove` | `() => void` | Go to next move |
258
+
259
+ #### Info Object
260
+
261
+ | Property | Type | Description |
262
+ | ------------------------ | ------------ | ------------------------------------- |
263
+ | `turn` | `"w" \| "b"` | Current turn |
264
+ | `isPlayerTurn` | `boolean` | Whether it's the player's turn |
265
+ | `isOpponentTurn` | `boolean` | Whether it's the opponent's turn |
266
+ | `moveNumber` | `number` | Current move number |
267
+ | `lastMove` | `Move` | Last move made |
268
+ | `isCheck` | `boolean` | Whether current player is in check |
269
+ | `isCheckmate` | `boolean` | Whether it's checkmate |
270
+ | `isDraw` | `boolean` | Whether the game is a draw |
271
+ | `isDrawn` | `boolean` | Alias for `isDraw` |
272
+ | `isStalemate` | `boolean` | Whether it's stalemate |
273
+ | `isThreefoldRepetition` | `boolean` | Whether threefold repetition occurred |
274
+ | `isInsufficientMaterial` | `boolean` | Whether there's insufficient material |
275
+ | `isGameOver` | `boolean` | Whether the game has ended |
276
+ | `hasPlayerWon` | `boolean` | Whether the player has won |
277
+ | `hasPlayerLost` | `boolean` | Whether the player has lost |
278
+
279
+ ## Examples
280
+
281
+ ### Basic Game with All Features
282
+
283
+ ```tsx
284
+ import { ChessGame } from "@react-chess-tools/react-chess-game";
285
+
286
+ function FullFeaturedGame() {
287
+ return (
288
+ <ChessGame.Root>
289
+ <ChessGame.Sounds />
290
+ <ChessGame.KeyboardControls />
291
+ <ChessGame.Board />
292
+ </ChessGame.Root>
293
+ );
294
+ }
295
+ ```
296
+
297
+ ### Custom Starting Position
298
+
299
+ ```tsx
300
+ import { ChessGame } from "@react-chess-tools/react-chess-game";
301
+
302
+ function CustomPosition() {
303
+ // Sicilian Defense starting position
304
+ const sicilianFen =
305
+ "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2";
306
+
307
+ return (
308
+ <ChessGame.Root fen={sicilianFen}>
309
+ <ChessGame.Board />
310
+ </ChessGame.Root>
311
+ );
312
+ }
313
+ ```
314
+
315
+ ### Game with Move History Display
316
+
317
+ ```tsx
318
+ import {
319
+ ChessGame,
320
+ useChessGameContext,
321
+ } from "@react-chess-tools/react-chess-game";
322
+
323
+ function MoveHistory() {
324
+ const { game, currentMoveIndex, methods } = useChessGameContext();
325
+ const history = game.history();
326
+
327
+ return (
328
+ <div className="move-history">
329
+ {history.map((move, index) => (
330
+ <button
331
+ key={index}
332
+ onClick={() => methods.goToMove(index)}
333
+ className={index === currentMoveIndex ? "active" : ""}
334
+ >
335
+ {move}
336
+ </button>
337
+ ))}
338
+ </div>
339
+ );
340
+ }
341
+
342
+ function GameWithHistory() {
343
+ return (
344
+ <ChessGame.Root>
345
+ <ChessGame.Board />
346
+ <MoveHistory />
347
+ <ChessGame.KeyboardControls />
348
+ </ChessGame.Root>
349
+ );
350
+ }
351
+ ```
352
+
353
+ ### Game with Status Display
354
+
355
+ ```tsx
356
+ import {
357
+ ChessGame,
358
+ useChessGameContext,
359
+ } from "@react-chess-tools/react-chess-game";
360
+
361
+ function GameStatus() {
362
+ const { info } = useChessGameContext();
363
+
364
+ if (info.isCheckmate) {
365
+ return (
366
+ <div className="status">
367
+ Checkmate! {info.hasPlayerWon ? "You win!" : "You lose!"}
368
+ </div>
369
+ );
370
+ }
371
+ if (info.isDraw) {
372
+ return <div className="status">Draw!</div>;
373
+ }
374
+ if (info.isCheck) {
375
+ return <div className="status">Check!</div>;
376
+ }
377
+ return (
378
+ <div className="status">Turn: {info.turn === "w" ? "White" : "Black"}</div>
379
+ );
380
+ }
381
+
382
+ function GameWithStatus() {
383
+ return (
384
+ <ChessGame.Root>
385
+ <GameStatus />
386
+ <ChessGame.Board />
387
+ <ChessGame.Sounds />
388
+ </ChessGame.Root>
389
+ );
390
+ }
391
+ ```
392
+
393
+ ## License
394
+
395
+ This project is [MIT](https://opensource.org/licenses/MIT) licensed.
396
+
397
+ ## Show Your Support
398
+
399
+ Give a star if this project helped you!