react-chess-puzzle-kit 1.0.1 → 1.0.3
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/LICENSE +21 -21
- package/README.md +331 -331
- package/dist/features/board/LineBoard.d.ts +2 -1
- package/dist/features/board/PuzzleBoardWithControls.d.ts +7 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +83 -34
- package/dist/index.js +82 -33
- package/package.json +87 -87
package/README.md
CHANGED
|
@@ -1,331 +1,331 @@
|
|
|
1
|
-
# react-chess-puzzle-kit
|
|
2
|
-
|
|
3
|
-
```bash
|
|
4
|
-
npm install
|
|
5
|
-
npm run build
|
|
6
|
-
```
|
|
7
|
-
|
|
8
|
-
Build output: `dist/` (`index.js`, `index.esm.js`, `index.d.ts`). Re-run after source changes when consuming this package via `file:../react-chess-puzzle-kit`.
|
|
9
|
-
|
|
10
|
-
React components for **interactive chess puzzles** and **post-puzzle analysis**, built on [react-chessboard](https://github.com/Clariity/react-chessboard) and [chess.js](https://github.com/jhlywa/chess.js). Used in production at [endchess.com](https://endchess.com).
|
|
11
|
-
|
|
12
|
-
The library owns puzzle logic, move history, themes, and optional Stockfish analysis. **Defaults are included** for a full demo (controls + analysis UI); production apps usually replace those with custom render props.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Install
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install react-chess-puzzle-kit
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**Peer dependencies:** `react`, `react-chessboard`, `chess.js`, **`react-chess-core`** (required — see `package.json`).
|
|
23
|
-
|
|
24
|
-
Install both packages in your app:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npm install react-chess-puzzle-kit react-chess-core
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Local development: `file:../react-chess-core` and `file:../react-chess-puzzle-kit` — build core first (`npm run build` in that repo), then puzzle-kit, then `npm install` in the app.
|
|
31
|
-
|
|
32
|
-
**Board theme, `HighlightChessboard`, Stockfish hooks, and eval formatters** are exported from **`react-chess-core`**, not re-exported from puzzle-kit. Puzzle-kit covers puzzle play, analysis orchestration, and optional default analysis UI.
|
|
33
|
-
|
|
34
|
-
For engine analysis in the browser, also install Stockfish and copy WASM into your app’s static folder (see [Stockfish](#stockfish-browser-engine) below).
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## See it in action (Storybook)
|
|
39
|
-
|
|
40
|
-
Storybook is the living docs and playground for every export.
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
git clone https://github.com/reblackwell3/react-chess-puzzle-kit.git
|
|
44
|
-
cd react-chess-puzzle-kit
|
|
45
|
-
npm install
|
|
46
|
-
npm run storybook # http://localhost:6006
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
| Story | What it demonstrates |
|
|
50
|
-
|-------|----------------------|
|
|
51
|
-
| **PuzzleBoardWithControls** | Full puzzle flow with default controls (via decorator) |
|
|
52
|
-
| **PuzzleBoardWithControls → All library defaults** | Default controls + default analysis modal, sidebar, engine panel |
|
|
53
|
-
| **PuzzleBoard** | Puzzle board only (drag-and-drop, feedback highlights) |
|
|
54
|
-
| **Analysis / AnalysisBoard (defaults)** | Default modal, sidebar, grid, and engine panel |
|
|
55
|
-
| **HighlightChessboard** | Themed board with check / hint / incorrect square styles |
|
|
56
|
-
|
|
57
|
-
Optional: `npm run copy:stockfish` then open **Analysis → WithStockfishEngine** to exercise the worker.
|
|
58
|
-
|
|
59
|
-
Build a static catalog: `npm run build-storybook` → `npm run serve-storybook`.
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Quick start
|
|
64
|
-
|
|
65
|
-
`PuzzleBoardWithControls` is the main integration point: puzzle play, then analysis when the puzzle is finished or failed.
|
|
66
|
-
|
|
67
|
-
### All library defaults
|
|
68
|
-
|
|
69
|
-
Omit every render prop to use built-in puzzle controls and analysis UI. This matches **PuzzleBoardWithControls → All library defaults** in Storybook.
|
|
70
|
-
|
|
71
|
-
```tsx
|
|
72
|
-
import { PuzzleBoardWithControls } from 'react-chess-puzzle-kit';
|
|
73
|
-
|
|
74
|
-
export function PuzzleDemo() {
|
|
75
|
-
return (
|
|
76
|
-
<PuzzleBoardWithControls
|
|
77
|
-
theme="dark"
|
|
78
|
-
apiProxy={{
|
|
79
|
-
onFetch: () => fetchPuzzleFromApi(),
|
|
80
|
-
onFeedback: (data) => sendFeedbackToApi(data),
|
|
81
|
-
}}
|
|
82
|
-
engine={{ enabled: false }}
|
|
83
|
-
/>
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Defaults used when props are omitted:
|
|
89
|
-
|
|
90
|
-
| Prop | Default |
|
|
91
|
-
|------|---------|
|
|
92
|
-
| `renderControls` | `DefaultPuzzleControls` (hint, next, analysis, result labels) |
|
|
93
|
-
| `renderAnalysis*` | `AnalysisBoard` modal, sidebar, and `EngineEvaluationPanel` |
|
|
94
|
-
| `puzzleBoardWidth` | `DEFAULT_PUZZLE_BOARD_WIDTH` (480) |
|
|
95
|
-
| `analysisLayout` | `DEFAULT_ANALYSIS_LAYOUT` |
|
|
96
|
-
|
|
97
|
-
Reuse the controls alone:
|
|
98
|
-
|
|
99
|
-
```tsx
|
|
100
|
-
import {
|
|
101
|
-
DefaultPuzzleControls,
|
|
102
|
-
defaultRenderControls,
|
|
103
|
-
} from 'react-chess-puzzle-kit';
|
|
104
|
-
|
|
105
|
-
// Inside your own layout:
|
|
106
|
-
<DefaultPuzzleControls
|
|
107
|
-
showHint={showHint}
|
|
108
|
-
nextPuzzle={nextPuzzle}
|
|
109
|
-
resultStatus={resultStatus}
|
|
110
|
-
analysis={analysis}
|
|
111
|
-
/>;
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
In Storybook, the `withDefaultPuzzleControls` decorator does the same for stories that leave `renderControls` unset (see `src/stories/withDefaultPuzzleControls.tsx`).
|
|
115
|
-
|
|
116
|
-
### Custom UI (production)
|
|
117
|
-
|
|
118
|
-
```tsx
|
|
119
|
-
import {
|
|
120
|
-
PuzzleBoardWithControls,
|
|
121
|
-
DEFAULT_ANALYSIS_LAYOUT,
|
|
122
|
-
} from 'react-chess-puzzle-kit';
|
|
123
|
-
|
|
124
|
-
export function PuzzlePage() {
|
|
125
|
-
return (
|
|
126
|
-
<PuzzleBoardWithControls
|
|
127
|
-
theme="dark"
|
|
128
|
-
puzzleBoardWidth={560}
|
|
129
|
-
analysisLayout={DEFAULT_ANALYSIS_LAYOUT}
|
|
130
|
-
apiProxy={{
|
|
131
|
-
onFetch: () => fetchPuzzleFromApi(),
|
|
132
|
-
onFeedback: (data) => sendFeedbackToApi(data),
|
|
133
|
-
}}
|
|
134
|
-
renderControls={(showHint, nextPuzzle, resultStatus, analysis) => (
|
|
135
|
-
<YourControls
|
|
136
|
-
onHint={showHint}
|
|
137
|
-
onNext={nextPuzzle}
|
|
138
|
-
onOpenAnalysis={analysis.openAnalysis}
|
|
139
|
-
canOpenAnalysis={analysis.visible}
|
|
140
|
-
/>
|
|
141
|
-
)}
|
|
142
|
-
renderAnalysisContainer={(props) => <YourAnalysisDialog {...props} />}
|
|
143
|
-
renderAnalysisSidebar={(props) => <YourMoveList {...props} />}
|
|
144
|
-
renderEngineEvaluation={(props) => <YourEnginePanel {...props} />}
|
|
145
|
-
engine={{ depth: 16, multiPv: 2 }}
|
|
146
|
-
/>
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
---
|
|
152
|
-
|
|
153
|
-
## What’s in the package
|
|
154
|
-
|
|
155
|
-
### Puzzle play
|
|
156
|
-
|
|
157
|
-
| Export | Role |
|
|
158
|
-
|--------|------|
|
|
159
|
-
| **`PuzzleBoardWithControls`** | Orchestrates fetch, puzzle board, controls slot, and analysis mode |
|
|
160
|
-
| **`DefaultPuzzleControls`** | Default hint / next / analysis button row |
|
|
161
|
-
| **`defaultRenderControls`** | Render-prop function wired to `DefaultPuzzleControls` |
|
|
162
|
-
| **`PuzzleBoard`** | Draggable puzzle board with correct/incorrect/hint feedback |
|
|
163
|
-
| **`PuzzlePosition`** | FEN + solution line, move index, guess judging |
|
|
164
|
-
| **`analysisSidebarColors`** | Default analysis move-list striping (override in your app) |
|
|
165
|
-
|
|
166
|
-
**From `react-chess-core` (install separately):** `HighlightChessboard`, `ThemeProvider`, `boardSquareHighlightColors`, `useAnalysisEngine`, `formatEvaluation`, `DEFAULT_STOCKFISH_SCRIPT_URL`, etc.
|
|
167
|
-
|
|
168
|
-
### Analysis
|
|
169
|
-
|
|
170
|
-
Analysis is split so apps can use **presets** or go **fully headless**:
|
|
171
|
-
|
|
172
|
-
| Layer | Location | Use when |
|
|
173
|
-
|-------|----------|----------|
|
|
174
|
-
| **Core** | `src/features/analysis/core/` | You want full control of layout and UI |
|
|
175
|
-
| **Defaults** | `src/features/analysis/defaults/` | You want a working modal + sidebar out of the box |
|
|
176
|
-
|
|
177
|
-
| Export | Role |
|
|
178
|
-
|--------|------|
|
|
179
|
-
| **`usePuzzleAnalysis`** | When analysis can open; snapshot of puzzle state |
|
|
180
|
-
| **`useAnalysisBoardModel`** | FEN, ply navigation, history, engine hook, drop handler (no JSX) |
|
|
181
|
-
| **`AnalysisBoardCore`** | Wires model + board; **requires** all `render*` props |
|
|
182
|
-
| **`AnalysisBoard`** | Same as core but fills missing render props with library defaults |
|
|
183
|
-
| **`AnalysisBoardLayout`** | Optional CSS grid: board column + sidebar column |
|
|
184
|
-
| **`AnalysisLayoutConfig`** | `{ boardWidth, sidebarWidth, columnGap }` |
|
|
185
|
-
|
|
186
|
-
### Engine
|
|
187
|
-
|
|
188
|
-
| Export | Package | Role |
|
|
189
|
-
|--------|---------|------|
|
|
190
|
-
| **`useAnalysisEngine`**, eval helpers | `react-chess-core` | Stockfish hook + PV formatting |
|
|
191
|
-
| **`EngineEvaluationPanel`** | puzzle-kit | Default engine UI (`AnalysisBoard` preset) |
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## Architecture
|
|
196
|
-
|
|
197
|
-
```
|
|
198
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
199
|
-
│ PuzzleBoardWithControls (host app) │
|
|
200
|
-
│ ├─ puzzle play → PuzzleBoard (puzzleBoardWidth) │
|
|
201
|
-
│ └─ analysis open → AnalysisBoardCore | AnalysisBoard │
|
|
202
|
-
│ ├─ renderContainer (modal / page shell) │
|
|
203
|
-
│ ├─ renderMain (board + sidebar placement) │
|
|
204
|
-
│ ├─ renderSidebar (move list, nav) │
|
|
205
|
-
│ └─ renderEngineEvaluation (Stockfish lines) │
|
|
206
|
-
└─────────────────────────────────────────────────────────────┘
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
**Separation of concerns**
|
|
210
|
-
|
|
211
|
-
- **Logic** — puzzle position, analysis context, ply navigation (`analysis/core/`); engine hook from **`react-chess-core`**.
|
|
212
|
-
- **UI** — host render props, or `defaults/` (`AnalysisBoard`, `DefaultAnalysisSidebar`, `DefaultAnalysisContainer`, `EngineEvaluationPanel`).
|
|
213
|
-
|
|
214
|
-
Production apps (e.g. endchess-frontend) typically pass custom `renderAnalysis*` implementations and sizes via `puzzleBoardWidth` + `analysisLayout`, while reusing `useAnalysisBoardModel` behavior through `AnalysisBoardCore`.
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## Board sizing
|
|
219
|
-
|
|
220
|
-
Puzzle and analysis boards can use **different pixel widths**:
|
|
221
|
-
|
|
222
|
-
```tsx
|
|
223
|
-
<PuzzleBoardWithControls
|
|
224
|
-
puzzleBoardWidth={560} // live puzzle
|
|
225
|
-
analysisLayout={{
|
|
226
|
-
boardWidth: 480, // analysis chessboard
|
|
227
|
-
sidebarWidth: 500,
|
|
228
|
-
columnGap: 16,
|
|
229
|
-
}}
|
|
230
|
-
/>
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Defaults: `DEFAULT_PUZZLE_BOARD_WIDTH` (480) and `DEFAULT_ANALYSIS_LAYOUT`. Override `renderAnalysisMain` for a fully custom layout (flex, MUI grid, etc.).
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
## Stockfish (browser engine)
|
|
238
|
-
|
|
239
|
-
Analysis runs Stockfish in a **Web Worker**. The host must serve the engine assets:
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
npm install stockfish --save-optional # or a regular dependency
|
|
243
|
-
npm run copy:stockfish # copies to public/stockfish/ in this repo
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
In your app, copy the same files to `public/stockfish/` (or equivalent). Default script URL:
|
|
247
|
-
|
|
248
|
-
`/stockfish/stockfish-18-lite-single.js` (`.wasm` must sit beside it).
|
|
249
|
-
|
|
250
|
-
```tsx
|
|
251
|
-
<PuzzleBoardWithControls
|
|
252
|
-
engine={{
|
|
253
|
-
enabled: true,
|
|
254
|
-
depth: 18,
|
|
255
|
-
multiPv: 2,
|
|
256
|
-
scriptUrl: '/stockfish/stockfish-18-lite-single.js',
|
|
257
|
-
}}
|
|
258
|
-
/>
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Disable the worker when you only need move replay: `engine={{ enabled: false }}`.
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## Headless analysis example
|
|
266
|
-
|
|
267
|
-
Use `AnalysisBoardCore` when every visual piece comes from the host:
|
|
268
|
-
|
|
269
|
-
```tsx
|
|
270
|
-
import {
|
|
271
|
-
AnalysisBoardCore,
|
|
272
|
-
AnalysisBoardLayout,
|
|
273
|
-
DEFAULT_ANALYSIS_LAYOUT,
|
|
274
|
-
} from 'react-chess-puzzle-kit';
|
|
275
|
-
|
|
276
|
-
<AnalysisBoardCore
|
|
277
|
-
analysisContext={snapshot}
|
|
278
|
-
theme="dark"
|
|
279
|
-
boardWidth={layout.boardWidth}
|
|
280
|
-
onClose={close}
|
|
281
|
-
renderContainer={(p) => <MyDialog {...p} />}
|
|
282
|
-
renderMain={({ board, sidebar, model }) => (
|
|
283
|
-
<AnalysisBoardLayout layout={layout} model={model} board={board} sidebar={sidebar} />
|
|
284
|
-
)}
|
|
285
|
-
renderSidebar={(p) => <MySidebar {...p} />}
|
|
286
|
-
renderEngineEvaluation={(p) => <MyEngine {...p} />}
|
|
287
|
-
/>;
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
## Development
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
npm run build # Rollup → dist/
|
|
296
|
-
npm run storybook # component docs & examples
|
|
297
|
-
npm run build-storybook # static Storybook export
|
|
298
|
-
npm run copy:stockfish # engine binaries for local Storybook
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## Migration: engine/board imports
|
|
304
|
-
|
|
305
|
-
If you previously imported these from `react-chess-puzzle-kit`, switch to `react-chess-core`:
|
|
306
|
-
|
|
307
|
-
```diff
|
|
308
|
-
- import { useAnalysisEngine, formatEvaluation, ThemeProvider } from 'react-chess-puzzle-kit';
|
|
309
|
-
+ import { useAnalysisEngine, formatEvaluation, ThemeProvider } from 'react-chess-core';
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
Keep puzzle-specific imports on puzzle-kit (`PuzzleBoardWithControls`, `usePuzzleAnalysis`, `AnalysisBoardCore`, render-prop types, etc.).
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
## Migration from `react-chessboard-with-controls`
|
|
317
|
-
|
|
318
|
-
The package was renamed to **`react-chess-puzzle-kit`** (v1.0.0). Update imports:
|
|
319
|
-
|
|
320
|
-
```diff
|
|
321
|
-
- import { PuzzleBoardWithControls } from 'react-chessboard-with-controls';
|
|
322
|
-
+ import { PuzzleBoardWithControls } from 'react-chess-puzzle-kit';
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
Component export names are unchanged for now. Rename the local clone folder to `react-chess-puzzle-kit` and point `file:../react-chess-puzzle-kit` in consuming apps.
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## License
|
|
330
|
-
|
|
331
|
-
MIT © 2022–2026 Robert Blackwell
|
|
1
|
+
# react-chess-puzzle-kit
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
npm install
|
|
5
|
+
npm run build
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
Build output: `dist/` (`index.js`, `index.esm.js`, `index.d.ts`). Re-run after source changes when consuming this package via `file:../react-chess-puzzle-kit`.
|
|
9
|
+
|
|
10
|
+
React components for **interactive chess puzzles** and **post-puzzle analysis**, built on [react-chessboard](https://github.com/Clariity/react-chessboard) and [chess.js](https://github.com/jhlywa/chess.js). Used in production at [endchess.com](https://endchess.com).
|
|
11
|
+
|
|
12
|
+
The library owns puzzle logic, move history, themes, and optional Stockfish analysis. **Defaults are included** for a full demo (controls + analysis UI); production apps usually replace those with custom render props.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install react-chess-puzzle-kit
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Peer dependencies:** `react`, `react-chessboard`, `chess.js`, **`react-chess-core`** (required — see `package.json`).
|
|
23
|
+
|
|
24
|
+
Install both packages in your app:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install react-chess-puzzle-kit react-chess-core
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Local development: `file:../react-chess-core` and `file:../react-chess-puzzle-kit` — build core first (`npm run build` in that repo), then puzzle-kit, then `npm install` in the app.
|
|
31
|
+
|
|
32
|
+
**Board theme, `HighlightChessboard`, Stockfish hooks, and eval formatters** are exported from **`react-chess-core`**, not re-exported from puzzle-kit. Puzzle-kit covers puzzle play, analysis orchestration, and optional default analysis UI.
|
|
33
|
+
|
|
34
|
+
For engine analysis in the browser, also install Stockfish and copy WASM into your app’s static folder (see [Stockfish](#stockfish-browser-engine) below).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## See it in action (Storybook)
|
|
39
|
+
|
|
40
|
+
Storybook is the living docs and playground for every export.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/reblackwell3/react-chess-puzzle-kit.git
|
|
44
|
+
cd react-chess-puzzle-kit
|
|
45
|
+
npm install
|
|
46
|
+
npm run storybook # http://localhost:6006
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
| Story | What it demonstrates |
|
|
50
|
+
|-------|----------------------|
|
|
51
|
+
| **PuzzleBoardWithControls** | Full puzzle flow with default controls (via decorator) |
|
|
52
|
+
| **PuzzleBoardWithControls → All library defaults** | Default controls + default analysis modal, sidebar, engine panel |
|
|
53
|
+
| **PuzzleBoard** | Puzzle board only (drag-and-drop, feedback highlights) |
|
|
54
|
+
| **Analysis / AnalysisBoard (defaults)** | Default modal, sidebar, grid, and engine panel |
|
|
55
|
+
| **HighlightChessboard** | Themed board with check / hint / incorrect square styles |
|
|
56
|
+
|
|
57
|
+
Optional: `npm run copy:stockfish` then open **Analysis → WithStockfishEngine** to exercise the worker.
|
|
58
|
+
|
|
59
|
+
Build a static catalog: `npm run build-storybook` → `npm run serve-storybook`.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Quick start
|
|
64
|
+
|
|
65
|
+
`PuzzleBoardWithControls` is the main integration point: puzzle play, then analysis when the puzzle is finished or failed.
|
|
66
|
+
|
|
67
|
+
### All library defaults
|
|
68
|
+
|
|
69
|
+
Omit every render prop to use built-in puzzle controls and analysis UI. This matches **PuzzleBoardWithControls → All library defaults** in Storybook.
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { PuzzleBoardWithControls } from 'react-chess-puzzle-kit';
|
|
73
|
+
|
|
74
|
+
export function PuzzleDemo() {
|
|
75
|
+
return (
|
|
76
|
+
<PuzzleBoardWithControls
|
|
77
|
+
theme="dark"
|
|
78
|
+
apiProxy={{
|
|
79
|
+
onFetch: () => fetchPuzzleFromApi(),
|
|
80
|
+
onFeedback: (data) => sendFeedbackToApi(data),
|
|
81
|
+
}}
|
|
82
|
+
engine={{ enabled: false }}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Defaults used when props are omitted:
|
|
89
|
+
|
|
90
|
+
| Prop | Default |
|
|
91
|
+
|------|---------|
|
|
92
|
+
| `renderControls` | `DefaultPuzzleControls` (hint, next, analysis, result labels) |
|
|
93
|
+
| `renderAnalysis*` | `AnalysisBoard` modal, sidebar, and `EngineEvaluationPanel` |
|
|
94
|
+
| `puzzleBoardWidth` | `DEFAULT_PUZZLE_BOARD_WIDTH` (480) |
|
|
95
|
+
| `analysisLayout` | `DEFAULT_ANALYSIS_LAYOUT` |
|
|
96
|
+
|
|
97
|
+
Reuse the controls alone:
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import {
|
|
101
|
+
DefaultPuzzleControls,
|
|
102
|
+
defaultRenderControls,
|
|
103
|
+
} from 'react-chess-puzzle-kit';
|
|
104
|
+
|
|
105
|
+
// Inside your own layout:
|
|
106
|
+
<DefaultPuzzleControls
|
|
107
|
+
showHint={showHint}
|
|
108
|
+
nextPuzzle={nextPuzzle}
|
|
109
|
+
resultStatus={resultStatus}
|
|
110
|
+
analysis={analysis}
|
|
111
|
+
/>;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
In Storybook, the `withDefaultPuzzleControls` decorator does the same for stories that leave `renderControls` unset (see `src/stories/withDefaultPuzzleControls.tsx`).
|
|
115
|
+
|
|
116
|
+
### Custom UI (production)
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import {
|
|
120
|
+
PuzzleBoardWithControls,
|
|
121
|
+
DEFAULT_ANALYSIS_LAYOUT,
|
|
122
|
+
} from 'react-chess-puzzle-kit';
|
|
123
|
+
|
|
124
|
+
export function PuzzlePage() {
|
|
125
|
+
return (
|
|
126
|
+
<PuzzleBoardWithControls
|
|
127
|
+
theme="dark"
|
|
128
|
+
puzzleBoardWidth={560}
|
|
129
|
+
analysisLayout={DEFAULT_ANALYSIS_LAYOUT}
|
|
130
|
+
apiProxy={{
|
|
131
|
+
onFetch: () => fetchPuzzleFromApi(),
|
|
132
|
+
onFeedback: (data) => sendFeedbackToApi(data),
|
|
133
|
+
}}
|
|
134
|
+
renderControls={(showHint, nextPuzzle, resultStatus, analysis) => (
|
|
135
|
+
<YourControls
|
|
136
|
+
onHint={showHint}
|
|
137
|
+
onNext={nextPuzzle}
|
|
138
|
+
onOpenAnalysis={analysis.openAnalysis}
|
|
139
|
+
canOpenAnalysis={analysis.visible}
|
|
140
|
+
/>
|
|
141
|
+
)}
|
|
142
|
+
renderAnalysisContainer={(props) => <YourAnalysisDialog {...props} />}
|
|
143
|
+
renderAnalysisSidebar={(props) => <YourMoveList {...props} />}
|
|
144
|
+
renderEngineEvaluation={(props) => <YourEnginePanel {...props} />}
|
|
145
|
+
engine={{ depth: 16, multiPv: 2 }}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## What’s in the package
|
|
154
|
+
|
|
155
|
+
### Puzzle play
|
|
156
|
+
|
|
157
|
+
| Export | Role |
|
|
158
|
+
|--------|------|
|
|
159
|
+
| **`PuzzleBoardWithControls`** | Orchestrates fetch, puzzle board, controls slot, and analysis mode |
|
|
160
|
+
| **`DefaultPuzzleControls`** | Default hint / next / analysis button row |
|
|
161
|
+
| **`defaultRenderControls`** | Render-prop function wired to `DefaultPuzzleControls` |
|
|
162
|
+
| **`PuzzleBoard`** | Draggable puzzle board with correct/incorrect/hint feedback |
|
|
163
|
+
| **`PuzzlePosition`** | FEN + solution line, move index, guess judging |
|
|
164
|
+
| **`analysisSidebarColors`** | Default analysis move-list striping (override in your app) |
|
|
165
|
+
|
|
166
|
+
**From `react-chess-core` (install separately):** `HighlightChessboard`, `ThemeProvider`, `boardSquareHighlightColors`, `useAnalysisEngine`, `formatEvaluation`, `DEFAULT_STOCKFISH_SCRIPT_URL`, etc.
|
|
167
|
+
|
|
168
|
+
### Analysis
|
|
169
|
+
|
|
170
|
+
Analysis is split so apps can use **presets** or go **fully headless**:
|
|
171
|
+
|
|
172
|
+
| Layer | Location | Use when |
|
|
173
|
+
|-------|----------|----------|
|
|
174
|
+
| **Core** | `src/features/analysis/core/` | You want full control of layout and UI |
|
|
175
|
+
| **Defaults** | `src/features/analysis/defaults/` | You want a working modal + sidebar out of the box |
|
|
176
|
+
|
|
177
|
+
| Export | Role |
|
|
178
|
+
|--------|------|
|
|
179
|
+
| **`usePuzzleAnalysis`** | When analysis can open; snapshot of puzzle state |
|
|
180
|
+
| **`useAnalysisBoardModel`** | FEN, ply navigation, history, engine hook, drop handler (no JSX) |
|
|
181
|
+
| **`AnalysisBoardCore`** | Wires model + board; **requires** all `render*` props |
|
|
182
|
+
| **`AnalysisBoard`** | Same as core but fills missing render props with library defaults |
|
|
183
|
+
| **`AnalysisBoardLayout`** | Optional CSS grid: board column + sidebar column |
|
|
184
|
+
| **`AnalysisLayoutConfig`** | `{ boardWidth, sidebarWidth, columnGap }` |
|
|
185
|
+
|
|
186
|
+
### Engine
|
|
187
|
+
|
|
188
|
+
| Export | Package | Role |
|
|
189
|
+
|--------|---------|------|
|
|
190
|
+
| **`useAnalysisEngine`**, eval helpers | `react-chess-core` | Stockfish hook + PV formatting |
|
|
191
|
+
| **`EngineEvaluationPanel`** | puzzle-kit | Default engine UI (`AnalysisBoard` preset) |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Architecture
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
199
|
+
│ PuzzleBoardWithControls (host app) │
|
|
200
|
+
│ ├─ puzzle play → PuzzleBoard (puzzleBoardWidth) │
|
|
201
|
+
│ └─ analysis open → AnalysisBoardCore | AnalysisBoard │
|
|
202
|
+
│ ├─ renderContainer (modal / page shell) │
|
|
203
|
+
│ ├─ renderMain (board + sidebar placement) │
|
|
204
|
+
│ ├─ renderSidebar (move list, nav) │
|
|
205
|
+
│ └─ renderEngineEvaluation (Stockfish lines) │
|
|
206
|
+
└─────────────────────────────────────────────────────────────┘
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Separation of concerns**
|
|
210
|
+
|
|
211
|
+
- **Logic** — puzzle position, analysis context, ply navigation (`analysis/core/`); engine hook from **`react-chess-core`**.
|
|
212
|
+
- **UI** — host render props, or `defaults/` (`AnalysisBoard`, `DefaultAnalysisSidebar`, `DefaultAnalysisContainer`, `EngineEvaluationPanel`).
|
|
213
|
+
|
|
214
|
+
Production apps (e.g. endchess-frontend) typically pass custom `renderAnalysis*` implementations and sizes via `puzzleBoardWidth` + `analysisLayout`, while reusing `useAnalysisBoardModel` behavior through `AnalysisBoardCore`.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Board sizing
|
|
219
|
+
|
|
220
|
+
Puzzle and analysis boards can use **different pixel widths**:
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
<PuzzleBoardWithControls
|
|
224
|
+
puzzleBoardWidth={560} // live puzzle
|
|
225
|
+
analysisLayout={{
|
|
226
|
+
boardWidth: 480, // analysis chessboard
|
|
227
|
+
sidebarWidth: 500,
|
|
228
|
+
columnGap: 16,
|
|
229
|
+
}}
|
|
230
|
+
/>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Defaults: `DEFAULT_PUZZLE_BOARD_WIDTH` (480) and `DEFAULT_ANALYSIS_LAYOUT`. Override `renderAnalysisMain` for a fully custom layout (flex, MUI grid, etc.).
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Stockfish (browser engine)
|
|
238
|
+
|
|
239
|
+
Analysis runs Stockfish in a **Web Worker**. The host must serve the engine assets:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
npm install stockfish --save-optional # or a regular dependency
|
|
243
|
+
npm run copy:stockfish # copies to public/stockfish/ in this repo
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
In your app, copy the same files to `public/stockfish/` (or equivalent). Default script URL:
|
|
247
|
+
|
|
248
|
+
`/stockfish/stockfish-18-lite-single.js` (`.wasm` must sit beside it).
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
<PuzzleBoardWithControls
|
|
252
|
+
engine={{
|
|
253
|
+
enabled: true,
|
|
254
|
+
depth: 18,
|
|
255
|
+
multiPv: 2,
|
|
256
|
+
scriptUrl: '/stockfish/stockfish-18-lite-single.js',
|
|
257
|
+
}}
|
|
258
|
+
/>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Disable the worker when you only need move replay: `engine={{ enabled: false }}`.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Headless analysis example
|
|
266
|
+
|
|
267
|
+
Use `AnalysisBoardCore` when every visual piece comes from the host:
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
import {
|
|
271
|
+
AnalysisBoardCore,
|
|
272
|
+
AnalysisBoardLayout,
|
|
273
|
+
DEFAULT_ANALYSIS_LAYOUT,
|
|
274
|
+
} from 'react-chess-puzzle-kit';
|
|
275
|
+
|
|
276
|
+
<AnalysisBoardCore
|
|
277
|
+
analysisContext={snapshot}
|
|
278
|
+
theme="dark"
|
|
279
|
+
boardWidth={layout.boardWidth}
|
|
280
|
+
onClose={close}
|
|
281
|
+
renderContainer={(p) => <MyDialog {...p} />}
|
|
282
|
+
renderMain={({ board, sidebar, model }) => (
|
|
283
|
+
<AnalysisBoardLayout layout={layout} model={model} board={board} sidebar={sidebar} />
|
|
284
|
+
)}
|
|
285
|
+
renderSidebar={(p) => <MySidebar {...p} />}
|
|
286
|
+
renderEngineEvaluation={(p) => <MyEngine {...p} />}
|
|
287
|
+
/>;
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Development
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
npm run build # Rollup → dist/
|
|
296
|
+
npm run storybook # component docs & examples
|
|
297
|
+
npm run build-storybook # static Storybook export
|
|
298
|
+
npm run copy:stockfish # engine binaries for local Storybook
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Migration: engine/board imports
|
|
304
|
+
|
|
305
|
+
If you previously imported these from `react-chess-puzzle-kit`, switch to `react-chess-core`:
|
|
306
|
+
|
|
307
|
+
```diff
|
|
308
|
+
- import { useAnalysisEngine, formatEvaluation, ThemeProvider } from 'react-chess-puzzle-kit';
|
|
309
|
+
+ import { useAnalysisEngine, formatEvaluation, ThemeProvider } from 'react-chess-core';
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Keep puzzle-specific imports on puzzle-kit (`PuzzleBoardWithControls`, `usePuzzleAnalysis`, `AnalysisBoardCore`, render-prop types, etc.).
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Migration from `react-chessboard-with-controls`
|
|
317
|
+
|
|
318
|
+
The package was renamed to **`react-chess-puzzle-kit`** (v1.0.0). Update imports:
|
|
319
|
+
|
|
320
|
+
```diff
|
|
321
|
+
- import { PuzzleBoardWithControls } from 'react-chessboard-with-controls';
|
|
322
|
+
+ import { PuzzleBoardWithControls } from 'react-chess-puzzle-kit';
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Component export names are unchanged for now. Rename the local clone folder to `react-chess-puzzle-kit` and point `file:../react-chess-puzzle-kit` in consuming apps.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## License
|
|
330
|
+
|
|
331
|
+
MIT © 2022–2026 Robert Blackwell
|