react-chess-puzzle-kit 1.0.0

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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +331 -0
  3. package/dist/features/analysis/AnalysisBoard.d.ts +18 -0
  4. package/dist/features/analysis/AnalysisBoardCore.d.ts +28 -0
  5. package/dist/features/analysis/AnalysisBoardLayout.d.ts +12 -0
  6. package/dist/features/analysis/AnalysisChessboardView.d.ts +5 -0
  7. package/dist/features/analysis/AnalysisPosition.d.ts +53 -0
  8. package/dist/features/analysis/AnalysisTrigger.d.ts +6 -0
  9. package/dist/features/analysis/DefaultAnalysisContainer.d.ts +3 -0
  10. package/dist/features/analysis/DefaultAnalysisSidebar.d.ts +2 -0
  11. package/dist/features/analysis/analysisBoardHighlightColors.d.ts +12 -0
  12. package/dist/features/analysis/analysisContext.d.ts +8 -0
  13. package/dist/features/analysis/analysisLayout.d.ts +5 -0
  14. package/dist/features/analysis/core/AnalysisBoardCore.d.ts +28 -0
  15. package/dist/features/analysis/core/AnalysisChessboardView.d.ts +5 -0
  16. package/dist/features/analysis/core/AnalysisErrorBoundary.d.ts +14 -0
  17. package/dist/features/analysis/core/AnalysisPosition.d.ts +54 -0
  18. package/dist/features/analysis/core/analysisContext.d.ts +13 -0
  19. package/dist/features/analysis/core/analysisLayout.d.ts +5 -0
  20. package/dist/features/analysis/core/analysisLayoutConfig.d.ts +6 -0
  21. package/dist/features/analysis/core/index.d.ts +9 -0
  22. package/dist/features/analysis/core/renderProps.d.ts +39 -0
  23. package/dist/features/analysis/core/useAnalysisBoardModel.d.ts +36 -0
  24. package/dist/features/analysis/core/usePuzzleAnalysis.d.ts +10 -0
  25. package/dist/features/analysis/defaults/AnalysisBoard.d.ts +16 -0
  26. package/dist/features/analysis/defaults/AnalysisBoardLayout.d.ts +14 -0
  27. package/dist/features/analysis/defaults/DefaultAnalysisContainer.d.ts +4 -0
  28. package/dist/features/analysis/defaults/DefaultAnalysisSidebar.d.ts +3 -0
  29. package/dist/features/analysis/defaults/analysisLayout.d.ts +3 -0
  30. package/dist/features/analysis/defaults/analysisModalStyles.d.ts +7 -0
  31. package/dist/features/analysis/defaults/analysisSidebarColors.d.ts +37 -0
  32. package/dist/features/analysis/defaults/analysisSidebarRowStyle.d.ts +8 -0
  33. package/dist/features/analysis/defaults/index.d.ts +8 -0
  34. package/dist/features/analysis/index.d.ts +3 -0
  35. package/dist/features/analysis/renderProps.d.ts +39 -0
  36. package/dist/features/analysis/useAnalysisBoardModel.d.ts +33 -0
  37. package/dist/features/analysis/usePuzzleAnalysis.d.ts +10 -0
  38. package/dist/features/board/BlankPuzzleBoard.d.ts +5 -0
  39. package/dist/features/board/HighlightChessboard.d.ts +2 -0
  40. package/dist/features/board/LineBoard.d.ts +15 -0
  41. package/dist/features/board/LineBoardWithControls.d.ts +50 -0
  42. package/dist/features/board/PuzzleBoard.d.ts +10 -0
  43. package/dist/features/board/PuzzleBoardWithControls.d.ts +51 -0
  44. package/dist/features/board/PuzzlePlaySurface.d.ts +25 -0
  45. package/dist/features/board/boardSquareHighlightColors.d.ts +1 -0
  46. package/dist/features/board/chessboardTheme.d.ts +2 -0
  47. package/dist/features/board/defaults/DefaultLineControls.d.ts +5 -0
  48. package/dist/features/board/defaults/DefaultPuzzleControls.d.ts +18 -0
  49. package/dist/features/board/defaults/index.d.ts +1 -0
  50. package/dist/features/board/puzzleBoardLayout.d.ts +8 -0
  51. package/dist/features/engine/EngineEvaluationPanel.d.ts +8 -0
  52. package/dist/features/engine/StockfishBrowserEngine.d.ts +1 -0
  53. package/dist/features/engine/formatEvaluation.d.ts +1 -0
  54. package/dist/features/engine/index.d.ts +1 -0
  55. package/dist/features/engine/isAnalyzableFen.d.ts +1 -0
  56. package/dist/features/engine/parseUciInfo.d.ts +1 -0
  57. package/dist/features/engine/stockfishUrls.d.ts +1 -0
  58. package/dist/features/engine/types.d.ts +1 -0
  59. package/dist/features/engine/useAnalysisEngine.d.ts +1 -0
  60. package/dist/features/position/Position.d.ts +67 -0
  61. package/dist/features/position/Position.test.d.ts +1 -0
  62. package/dist/features/position/Traversable.d.ts +4 -0
  63. package/dist/features/position/moveHistory.d.ts +7 -0
  64. package/dist/features/theme/ThemeContext.d.ts +26 -0
  65. package/dist/features/theme/ThemeProvider.d.ts +7 -0
  66. package/dist/features/theme/squareHighlightColors.d.ts +50 -0
  67. package/dist/index.d.ts +26 -0
  68. package/dist/index.esm.js +861 -0
  69. package/dist/index.js +885 -0
  70. package/dist/stories/AnalysisBoard.stories.d.ts +9 -0
  71. package/dist/stories/HighlightChessboard.stories.d.ts +9 -0
  72. package/dist/stories/PuzzleBoard.stories.d.ts +6 -0
  73. package/dist/stories/PuzzleBoardWithControls.stories.d.ts +9 -0
  74. package/dist/stories/analysisFixtures.d.ts +4 -0
  75. package/dist/stories/regressions/PuzzleRegressions.stories.d.ts +7 -0
  76. package/dist/stories/regressions/StockfishAnalysisRegressions.stories.d.ts +7 -0
  77. package/dist/stories/regressions/fixtures.d.ts +18 -0
  78. package/dist/stories/regressions/regressionAnalysisContext.d.ts +5 -0
  79. package/dist/stories/storybookLayout.d.ts +4 -0
  80. package/dist/stories/withChessboardDnD.d.ts +4 -0
  81. package/dist/stories/withDefaultPuzzleControls.d.ts +7 -0
  82. package/dist/stories/withThemeProvider.d.ts +3 -0
  83. package/package.json +87 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022-2026 Robert Blackwell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +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.training](https://endchess.training).
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
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { AnalysisBoardCoreProps } from './AnalysisBoardCore';
3
+ import { AnalysisContainerRenderProps, AnalysisMainRenderProps, AnalysisSidebarRenderProps, EngineEvaluationRenderProps } from './renderProps';
4
+ export type { AnalysisBoardCoreProps, AnalysisBoardModel } from './AnalysisBoardCore';
5
+ export { ANALYSIS_BOARD_WIDTH, ANALYSIS_BODY_GAP, ANALYSIS_SIDEBAR_WIDTH, } from './analysisLayout';
6
+ export { AnalysisBoardLayout } from './AnalysisBoardLayout';
7
+ export { useAnalysisBoardModel } from './useAnalysisBoardModel';
8
+ export interface AnalysisBoardProps extends Omit<AnalysisBoardCoreProps, 'renderContainer' | 'renderMain' | 'renderSidebar' | 'renderEngineEvaluation'> {
9
+ renderContainer?: (props: AnalysisContainerRenderProps) => React.ReactNode;
10
+ renderMain?: (props: AnalysisMainRenderProps) => React.ReactNode;
11
+ renderSidebar?: (props: AnalysisSidebarRenderProps) => React.ReactNode;
12
+ renderEngineEvaluation?: (props: EngineEvaluationRenderProps) => React.ReactNode;
13
+ }
14
+ /**
15
+ * Full analysis UI with library defaults: modal shell, grid layout, sidebar, engine panel.
16
+ * For host-owned UI only, use {@link AnalysisBoardCore} and pass all render props.
17
+ */
18
+ export declare const AnalysisBoard: ({ renderContainer, renderMain, renderSidebar, renderEngineEvaluation, engine, ...modelArgs }: AnalysisBoardProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { AnalysisContainerRenderProps, AnalysisMainRenderProps, AnalysisSidebarRenderProps, EngineEvaluationRenderProps } from './renderProps';
3
+ import { AnalysisEngineOptions } from '../engine/types';
4
+ import { AnalysisBoardModel, UseAnalysisBoardModelArgs } from './useAnalysisBoardModel';
5
+ export type AnalysisBoardCoreProps = UseAnalysisBoardModelArgs & {
6
+ engine?: AnalysisEngineOptions;
7
+ /** Host-owned shell (modal, page layout, etc.). */
8
+ renderContainer: (props: AnalysisContainerRenderProps) => React.ReactNode;
9
+ /** Host-owned grid/placement of board + sidebar (no library default). */
10
+ renderMain: (props: AnalysisMainRenderProps) => React.ReactNode;
11
+ renderSidebar: (props: AnalysisSidebarRenderProps) => React.ReactNode;
12
+ renderEngineEvaluation: (props: EngineEvaluationRenderProps) => React.ReactNode;
13
+ };
14
+ /**
15
+ * Analysis logic + composition only: hook, board node, sidebar/engine slots.
16
+ * No layout divs — use {@link renderMain} (e.g. {@link AnalysisBoardLayout} from the host or default {@link AnalysisBoard}).
17
+ */
18
+ export declare const AnalysisBoardCore: ({ renderContainer, renderMain, renderSidebar, renderEngineEvaluation, ...modelArgs }: AnalysisBoardCoreProps) => import("react/jsx-runtime").JSX.Element;
19
+ type AnalysisBoardCoreViewProps = {
20
+ model: AnalysisBoardModel;
21
+ renderContainer: AnalysisBoardCoreProps['renderContainer'];
22
+ renderMain: AnalysisBoardCoreProps['renderMain'];
23
+ renderSidebar: AnalysisBoardCoreProps['renderSidebar'];
24
+ renderEngineEvaluation: AnalysisBoardCoreProps['renderEngineEvaluation'];
25
+ };
26
+ /** Pure composition (no layout styles) for testing and reuse. */
27
+ export declare const AnalysisBoardCoreView: ({ model, renderContainer, renderMain, renderSidebar, renderEngineEvaluation, }: AnalysisBoardCoreViewProps) => React.ReactNode;
28
+ export type { AnalysisBoardModel, UseAnalysisBoardModelArgs };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { AnalysisBoardModel } from './useAnalysisBoardModel';
3
+ export type AnalysisBoardLayoutProps = {
4
+ model: AnalysisBoardModel;
5
+ board: React.ReactNode;
6
+ sidebar: React.ReactNode;
7
+ };
8
+ /**
9
+ * Default analysis layout: board column + sidebar column.
10
+ * Used by {@link AnalysisBoard}; hosts may reuse via {@link defaultAnalysisMainLayout}.
11
+ */
12
+ export declare const AnalysisBoardLayout: ({ model, board, sidebar, }: AnalysisBoardLayoutProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { AnalysisBoardModel } from './useAnalysisBoardModel';
2
+ /** Draggable analysis board (no surrounding layout chrome). */
3
+ export declare const AnalysisChessboardView: ({ model }: {
4
+ model: AnalysisBoardModel;
5
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,53 @@
1
+ import { PuzzleAnalysisContext } from './analysisContext';
2
+ export type SolutionMoveDisplay = {
3
+ ply: number;
4
+ uci: string;
5
+ san: string;
6
+ };
7
+ export type AnalysisHistoryRow = {
8
+ key: string;
9
+ label: string;
10
+ indent: number;
11
+ kind: 'start' | 'main' | 'variation';
12
+ mainPly: number;
13
+ variationIndex: number;
14
+ };
15
+ export declare class AnalysisPosition {
16
+ private chess;
17
+ private readonly initialFen;
18
+ private readonly solutionMoves;
19
+ private readonly solutionSans;
20
+ private mainPly;
21
+ private variation;
22
+ private variationCursor;
23
+ constructor(context: PuzzleAnalysisContext);
24
+ private static buildSolutionSans;
25
+ private fenAtMainPly;
26
+ private rebuildChess;
27
+ private findLegalMove;
28
+ private uciFromVerboseMove;
29
+ private matchesMainMove;
30
+ getNavPly(): number;
31
+ getMaxNavPly(): number;
32
+ /** @deprecated Use getNavPly */
33
+ getPly(): number;
34
+ /** @deprecated Use getMaxNavPly */
35
+ getMaxPly(): number;
36
+ getSolutionSans(): SolutionMoveDisplay[];
37
+ getHistoryRows(): AnalysisHistoryRow[];
38
+ isHistoryRowSelected(row: AnalysisHistoryRow): boolean;
39
+ selectHistoryRow(row: AnalysisHistoryRow): void;
40
+ selectMainLine(ply: number): void;
41
+ /** @deprecated Use selectMainLine or goToNavPly */
42
+ goToPly(ply: number): void;
43
+ goToNavPly(navPly: number): void;
44
+ tryPlayMove(sourceSquare: string, targetSquare: string, piece: string): boolean;
45
+ next(): boolean;
46
+ prev(): boolean;
47
+ getLastMoveSquares(): {
48
+ from: string;
49
+ to: string;
50
+ } | null;
51
+ fen(): string;
52
+ getCheckSquare(): string;
53
+ }
@@ -0,0 +1,6 @@
1
+ export interface AnalysisTriggerProps {
2
+ visible: boolean;
3
+ onClick: () => void;
4
+ theme: 'light' | 'dark';
5
+ }
6
+ export declare const AnalysisTrigger: ({ visible, onClick, theme, }: AnalysisTriggerProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,3 @@
1
+ import { AnalysisContainerRenderProps } from './renderProps';
2
+ /** Default full-screen modal shell for analysis (library preset UI). */
3
+ export declare const DefaultAnalysisContainer: ({ theme, onClose, onBackdropMouseDown, children, }: AnalysisContainerRenderProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { AnalysisSidebarRenderProps } from './renderProps';
2
+ export declare const DefaultAnalysisSidebar: ({ historyRows, isHistoryRowSelected, onSelectHistoryRow, ply, maxPly, onSelectPly, theme, engineEvaluationPanel, }: AnalysisSidebarRenderProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Square overlay colors for analysis board replay (last move highlight).
3
+ */
4
+ export declare const analysisBoardHighlightColors: {
5
+ readonly lastMove: {
6
+ readonly light: "rgba(253, 216, 53, 0.55)";
7
+ readonly dark: "rgba(144, 202, 249, 0.5)";
8
+ };
9
+ };
10
+ export declare const getLastMoveSquareStyles: (from: string, to: string, theme: "light" | "dark") => Record<string, {
11
+ backgroundColor: string;
12
+ }>;
@@ -0,0 +1,8 @@
1
+ import type { AnalysisContext } from 'react-chess-core';
2
+ import { PuzzlePosition } from '../position/Position';
3
+ export type PuzzleResultStatus = 'none' | 'incorrect' | 'complete';
4
+ /** @deprecated Use {@link AnalysisContext} from `react-chess-core`. */
5
+ export type PuzzleAnalysisContext = AnalysisContext;
6
+ export declare const emptyAnalysisContext: () => AnalysisContext;
7
+ export declare const buildAnalysisContext: (position: PuzzlePosition | null) => AnalysisContext;
8
+ export declare const isAnalysisAvailable: (position: PuzzlePosition | null, resultStatus: PuzzleResultStatus) => boolean;
@@ -0,0 +1,5 @@
1
+ /** Board column width in analysis grid (matches endchess-frontend sidebar layout). */
2
+ export declare const ANALYSIS_BOARD_WIDTH = 480;
3
+ /** Sidebar column width (move list + engine). */
4
+ export declare const ANALYSIS_SIDEBAR_WIDTH = 500;
5
+ export declare const ANALYSIS_BODY_GAP = 16;
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { AnalysisContainerRenderProps, AnalysisMainRenderProps, AnalysisSidebarRenderProps, EngineEvaluationRenderProps } from './renderProps';
3
+ import { AnalysisEngineOptions } from 'react-chess-core';
4
+ import { AnalysisBoardModel, UseAnalysisBoardModelArgs } from './useAnalysisBoardModel';
5
+ export type AnalysisBoardCoreProps = UseAnalysisBoardModelArgs & {
6
+ engine?: AnalysisEngineOptions;
7
+ /** Host-owned shell (modal, page layout, etc.). */
8
+ renderContainer: (props: AnalysisContainerRenderProps) => React.ReactNode;
9
+ /** Host-owned grid/placement of board + sidebar (no library default). */
10
+ renderMain: (props: AnalysisMainRenderProps) => React.ReactNode;
11
+ renderSidebar: (props: AnalysisSidebarRenderProps) => React.ReactNode;
12
+ renderEngineEvaluation: (props: EngineEvaluationRenderProps) => React.ReactNode;
13
+ };
14
+ /**
15
+ * Analysis logic + composition only: hook, board node, sidebar/engine slots.
16
+ * No layout divs — use {@link renderMain} (e.g. `AnalysisBoardLayout` from `analysis/defaults` or a host layout).
17
+ */
18
+ export declare const AnalysisBoardCore: ({ renderContainer, renderMain, renderSidebar, renderEngineEvaluation, ...modelArgs }: AnalysisBoardCoreProps) => React.JSX.Element;
19
+ type AnalysisBoardCoreViewProps = {
20
+ model: AnalysisBoardModel;
21
+ renderContainer: AnalysisBoardCoreProps['renderContainer'];
22
+ renderMain: AnalysisBoardCoreProps['renderMain'];
23
+ renderSidebar: AnalysisBoardCoreProps['renderSidebar'];
24
+ renderEngineEvaluation: AnalysisBoardCoreProps['renderEngineEvaluation'];
25
+ };
26
+ /** Pure composition (no layout styles) for testing and reuse. */
27
+ export declare const AnalysisBoardCoreView: ({ model, renderContainer, renderMain, renderSidebar, renderEngineEvaluation, }: AnalysisBoardCoreViewProps) => React.ReactNode;
28
+ export type { AnalysisBoardModel, UseAnalysisBoardModelArgs };
@@ -0,0 +1,5 @@
1
+ import { AnalysisBoardModel } from './useAnalysisBoardModel';
2
+ /** Draggable analysis board (no surrounding layout chrome). */
3
+ export declare const AnalysisChessboardView: ({ model }: {
4
+ model: AnalysisBoardModel;
5
+ }) => import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { Component, ReactNode } from 'react';
2
+ type AnalysisErrorBoundaryProps = {
3
+ children: ReactNode;
4
+ onClose?: () => void;
5
+ };
6
+ type AnalysisErrorBoundaryState = {
7
+ error: Error | null;
8
+ };
9
+ export declare class AnalysisErrorBoundary extends Component<AnalysisErrorBoundaryProps, AnalysisErrorBoundaryState> {
10
+ state: AnalysisErrorBoundaryState;
11
+ static getDerivedStateFromError(error: Error): AnalysisErrorBoundaryState;
12
+ render(): string | number | boolean | Iterable<ReactNode> | import("react").JSX.Element | null | undefined;
13
+ }
14
+ export {};
@@ -0,0 +1,54 @@
1
+ import { PuzzleAnalysisContext } from './analysisContext';
2
+ export type SolutionMoveDisplay = {
3
+ ply: number;
4
+ uci: string;
5
+ san: string;
6
+ };
7
+ export type AnalysisHistoryRow = {
8
+ key: string;
9
+ label: string;
10
+ indent: number;
11
+ kind: 'start' | 'main' | 'variation';
12
+ mainPly: number;
13
+ variationIndex: number;
14
+ };
15
+ export declare class AnalysisPosition {
16
+ private chess;
17
+ private readonly initialFen;
18
+ private readonly solutionMoves;
19
+ private readonly solutionSans;
20
+ private mainPly;
21
+ private variation;
22
+ private variationCursor;
23
+ constructor(context: PuzzleAnalysisContext);
24
+ private static buildSolutionSans;
25
+ private static applySolutionMove;
26
+ private fenAtMainPly;
27
+ private rebuildChess;
28
+ private findLegalMove;
29
+ private uciFromVerboseMove;
30
+ private matchesMainMove;
31
+ getNavPly(): number;
32
+ getMaxNavPly(): number;
33
+ /** @deprecated Use getNavPly */
34
+ getPly(): number;
35
+ /** @deprecated Use getMaxNavPly */
36
+ getMaxPly(): number;
37
+ getSolutionSans(): SolutionMoveDisplay[];
38
+ getHistoryRows(): AnalysisHistoryRow[];
39
+ isHistoryRowSelected(row: AnalysisHistoryRow): boolean;
40
+ selectHistoryRow(row: AnalysisHistoryRow): void;
41
+ selectMainLine(ply: number): void;
42
+ /** @deprecated Use selectMainLine or goToNavPly */
43
+ goToPly(ply: number): void;
44
+ goToNavPly(navPly: number): void;
45
+ tryPlayMove(sourceSquare: string, targetSquare: string, piece: string): boolean;
46
+ next(): boolean;
47
+ prev(): boolean;
48
+ getLastMoveSquares(): {
49
+ from: string;
50
+ to: string;
51
+ } | null;
52
+ fen(): string;
53
+ getCheckSquare(): string;
54
+ }
@@ -0,0 +1,13 @@
1
+ import { PuzzleMoveRecord } from '../../position/moveHistory';
2
+ import { PuzzlePosition } from '../../position/Position';
3
+ export type PuzzleResultStatus = 'none' | 'incorrect' | 'complete';
4
+ export type PuzzleAnalysisContext = {
5
+ initialFen: string;
6
+ solutionMoves: string[];
7
+ moveHistory: PuzzleMoveRecord[];
8
+ currentPly: number;
9
+ boardOrientation: 'white' | 'black';
10
+ };
11
+ export declare const emptyAnalysisContext: () => PuzzleAnalysisContext;
12
+ export declare const buildAnalysisContext: (position: PuzzlePosition | null) => PuzzleAnalysisContext;
13
+ export declare const isAnalysisAvailable: (position: PuzzlePosition | null, resultStatus: PuzzleResultStatus) => boolean;
@@ -0,0 +1,5 @@
1
+ /** Board column width in analysis grid (matches endchess-frontend sidebar layout). */
2
+ export declare const ANALYSIS_BOARD_WIDTH = 480;
3
+ /** Sidebar column width (move list + engine). */
4
+ export declare const ANALYSIS_SIDEBAR_WIDTH = 500;
5
+ export declare const ANALYSIS_BODY_GAP = 16;
@@ -0,0 +1,6 @@
1
+ /** Host-provided dimensions for analysis board + sidebar grid (defaults package only). */
2
+ export type AnalysisLayoutConfig = {
3
+ boardWidth: number;
4
+ sidebarWidth: number;
5
+ columnGap: number;
6
+ };
@@ -0,0 +1,9 @@
1
+ export * from './AnalysisErrorBoundary';
2
+ export * from './analysisContext';
3
+ export * from './analysisLayoutConfig';
4
+ export * from './AnalysisBoardCore';
5
+ export * from './AnalysisChessboardView';
6
+ export * from './AnalysisPosition';
7
+ export * from './renderProps';
8
+ export * from './useAnalysisBoardModel';
9
+ export * from './usePuzzleAnalysis';