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/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