gigaboard 1.2.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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -0
  3. package/dist/board-model-BvJOtwQ3.d.cts +675 -0
  4. package/dist/board-model-BvJOtwQ3.d.ts +675 -0
  5. package/dist/canvas.cjs +8 -0
  6. package/dist/canvas.cjs.map +1 -0
  7. package/dist/canvas.d.cts +14 -0
  8. package/dist/canvas.d.ts +14 -0
  9. package/dist/canvas.js +6 -0
  10. package/dist/canvas.js.map +1 -0
  11. package/dist/chunk-3HNIF4ZE.js +3 -0
  12. package/dist/chunk-3HNIF4ZE.js.map +1 -0
  13. package/dist/chunk-44YKPXXT.js +63 -0
  14. package/dist/chunk-44YKPXXT.js.map +1 -0
  15. package/dist/chunk-5WAOEWKS.js +16 -0
  16. package/dist/chunk-5WAOEWKS.js.map +1 -0
  17. package/dist/chunk-AYVQCHSG.cjs +10 -0
  18. package/dist/chunk-AYVQCHSG.cjs.map +1 -0
  19. package/dist/chunk-B26QLI2K.cjs +18 -0
  20. package/dist/chunk-B26QLI2K.cjs.map +1 -0
  21. package/dist/chunk-B2TBDDJN.cjs +10 -0
  22. package/dist/chunk-B2TBDDJN.cjs.map +1 -0
  23. package/dist/chunk-BFN5JI3T.js +8 -0
  24. package/dist/chunk-BFN5JI3T.js.map +1 -0
  25. package/dist/chunk-BWNBPN3P.cjs +10 -0
  26. package/dist/chunk-BWNBPN3P.cjs.map +1 -0
  27. package/dist/chunk-CXDGJMYL.js +105 -0
  28. package/dist/chunk-CXDGJMYL.js.map +1 -0
  29. package/dist/chunk-EOSX5UX3.js +8 -0
  30. package/dist/chunk-EOSX5UX3.js.map +1 -0
  31. package/dist/chunk-FNRS6YJI.cjs +67 -0
  32. package/dist/chunk-FNRS6YJI.cjs.map +1 -0
  33. package/dist/chunk-G6ZFOJZR.cjs +18 -0
  34. package/dist/chunk-G6ZFOJZR.cjs.map +1 -0
  35. package/dist/chunk-HSMILJKQ.cjs +18 -0
  36. package/dist/chunk-HSMILJKQ.cjs.map +1 -0
  37. package/dist/chunk-I4BQGFP5.cjs +113 -0
  38. package/dist/chunk-I4BQGFP5.cjs.map +1 -0
  39. package/dist/chunk-J6GGNP5S.js +1104 -0
  40. package/dist/chunk-J6GGNP5S.js.map +1 -0
  41. package/dist/chunk-JQSBAWIZ.cjs +4 -0
  42. package/dist/chunk-JQSBAWIZ.cjs.map +1 -0
  43. package/dist/chunk-KW56FEBY.js +8 -0
  44. package/dist/chunk-KW56FEBY.js.map +1 -0
  45. package/dist/chunk-N7ED2MZS.cjs +10 -0
  46. package/dist/chunk-N7ED2MZS.cjs.map +1 -0
  47. package/dist/chunk-NAA5O4BT.js +16 -0
  48. package/dist/chunk-NAA5O4BT.js.map +1 -0
  49. package/dist/chunk-OQLY5GJF.js +16 -0
  50. package/dist/chunk-OQLY5GJF.js.map +1 -0
  51. package/dist/chunk-P72B3YTG.js +16 -0
  52. package/dist/chunk-P72B3YTG.js.map +1 -0
  53. package/dist/chunk-U6WAD322.js +8 -0
  54. package/dist/chunk-U6WAD322.js.map +1 -0
  55. package/dist/chunk-UUTEFNFO.cjs +1148 -0
  56. package/dist/chunk-UUTEFNFO.cjs.map +1 -0
  57. package/dist/chunk-VYSVIIZA.cjs +18 -0
  58. package/dist/chunk-VYSVIIZA.cjs.map +1 -0
  59. package/dist/core.cjs +180 -0
  60. package/dist/core.cjs.map +1 -0
  61. package/dist/core.d.cts +164 -0
  62. package/dist/core.d.ts +164 -0
  63. package/dist/core.js +3 -0
  64. package/dist/core.js.map +1 -0
  65. package/dist/create-image-piece-set-BcmRKGql.d.cts +100 -0
  66. package/dist/create-image-piece-set-BcmRKGql.d.ts +100 -0
  67. package/dist/gigachess-3BDD--yT.d.cts +22 -0
  68. package/dist/gigachess-DolQlR82.d.ts +22 -0
  69. package/dist/index.cjs +2972 -0
  70. package/dist/index.cjs.map +1 -0
  71. package/dist/index.d.cts +435 -0
  72. package/dist/index.d.ts +435 -0
  73. package/dist/index.js +2898 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/pieces/alpha.cjs +13 -0
  76. package/dist/pieces/alpha.cjs.map +1 -0
  77. package/dist/pieces/alpha.d.cts +17 -0
  78. package/dist/pieces/alpha.d.ts +17 -0
  79. package/dist/pieces/alpha.js +4 -0
  80. package/dist/pieces/alpha.js.map +1 -0
  81. package/dist/pieces/cburnett.cjs +13 -0
  82. package/dist/pieces/cburnett.cjs.map +1 -0
  83. package/dist/pieces/cburnett.d.cts +19 -0
  84. package/dist/pieces/cburnett.d.ts +19 -0
  85. package/dist/pieces/cburnett.js +4 -0
  86. package/dist/pieces/cburnett.js.map +1 -0
  87. package/dist/pieces/chesscom.cjs +14 -0
  88. package/dist/pieces/chesscom.cjs.map +1 -0
  89. package/dist/pieces/chesscom.d.cts +3 -0
  90. package/dist/pieces/chesscom.d.ts +3 -0
  91. package/dist/pieces/chesscom.js +5 -0
  92. package/dist/pieces/chesscom.js.map +1 -0
  93. package/dist/pieces/merida.cjs +13 -0
  94. package/dist/pieces/merida.cjs.map +1 -0
  95. package/dist/pieces/merida.d.cts +17 -0
  96. package/dist/pieces/merida.d.ts +17 -0
  97. package/dist/pieces/merida.js +4 -0
  98. package/dist/pieces/merida.js.map +1 -0
  99. package/dist/pieces/neo.cjs +13 -0
  100. package/dist/pieces/neo.cjs.map +1 -0
  101. package/dist/pieces/neo.d.cts +18 -0
  102. package/dist/pieces/neo.d.ts +18 -0
  103. package/dist/pieces/neo.js +4 -0
  104. package/dist/pieces/neo.js.map +1 -0
  105. package/dist/pieces.cjs +55 -0
  106. package/dist/pieces.cjs.map +1 -0
  107. package/dist/pieces.d.cts +21 -0
  108. package/dist/pieces.d.ts +21 -0
  109. package/dist/pieces.js +24 -0
  110. package/dist/pieces.js.map +1 -0
  111. package/dist/server.cjs +207 -0
  112. package/dist/server.cjs.map +1 -0
  113. package/dist/server.d.cts +60 -0
  114. package/dist/server.d.ts +60 -0
  115. package/dist/server.js +205 -0
  116. package/dist/server.js.map +1 -0
  117. package/dist/sounds/capture.mp3 +0 -0
  118. package/dist/sounds/castle.mp3 +0 -0
  119. package/dist/sounds/game-end.mp3 +0 -0
  120. package/dist/sounds/move-check.mp3 +0 -0
  121. package/dist/sounds/move-opponent.mp3 +0 -0
  122. package/dist/sounds/move-self.mp3 +0 -0
  123. package/dist/sounds/promote.mp3 +0 -0
  124. package/dist/themes/blue.cjs +12 -0
  125. package/dist/themes/blue.cjs.map +1 -0
  126. package/dist/themes/blue.d.cts +102 -0
  127. package/dist/themes/blue.d.ts +102 -0
  128. package/dist/themes/blue.js +3 -0
  129. package/dist/themes/blue.js.map +1 -0
  130. package/dist/themes/brown.cjs +12 -0
  131. package/dist/themes/brown.cjs.map +1 -0
  132. package/dist/themes/brown.d.cts +1 -0
  133. package/dist/themes/brown.d.ts +1 -0
  134. package/dist/themes/brown.js +3 -0
  135. package/dist/themes/brown.js.map +1 -0
  136. package/dist/themes/green.cjs +12 -0
  137. package/dist/themes/green.cjs.map +1 -0
  138. package/dist/themes/green.d.cts +1 -0
  139. package/dist/themes/green.d.ts +1 -0
  140. package/dist/themes/green.js +3 -0
  141. package/dist/themes/green.js.map +1 -0
  142. package/dist/themes/wood.cjs +12 -0
  143. package/dist/themes/wood.cjs.map +1 -0
  144. package/dist/themes/wood.d.cts +1 -0
  145. package/dist/themes/wood.d.ts +1 -0
  146. package/dist/themes/wood.js +3 -0
  147. package/dist/themes/wood.js.map +1 -0
  148. package/dist/themes.cjs +36 -0
  149. package/dist/themes.cjs.map +1 -0
  150. package/dist/themes.d.cts +1 -0
  151. package/dist/themes.d.ts +1 -0
  152. package/dist/themes.js +21 -0
  153. package/dist/themes.js.map +1 -0
  154. package/dist/types-Bg2xiUHE.d.cts +501 -0
  155. package/dist/types-D5eBJGzj.d.ts +501 -0
  156. package/package.json +210 -0
@@ -0,0 +1,675 @@
1
+ /**
2
+ * Public types and branded primitives for `gigaboard/core`.
3
+ *
4
+ * Design goals:
5
+ * - Primitives carry their meaning in the type (`SquareIndex` never silently
6
+ * mixes with a piece code or a file number).
7
+ * - Encoding of a board cell is a single byte suitable for `Uint8Array(64)`.
8
+ * - Every symbol exported here is a type or a zero-cost helper — no classes,
9
+ * no allocations per call, nothing that would eat into the budget.
10
+ */
11
+ /**
12
+ * A square on the board, in LERF indexing: `0 = a1`, `7 = h1`, `56 = a8`,
13
+ * `63 = h8`. Aligned with standard 0..63 square indexing.
14
+ */
15
+ type SquareIndex = number & {
16
+ readonly __brand: "SquareIndex";
17
+ };
18
+ /**
19
+ * A packed u16 move conforming to the 16-bit Move2 wire format:
20
+ * bits 0–5: from square index (0..63)
21
+ * bits 6–11: to square index (0..63)
22
+ * bits 12–15: promotion code (0 = none, 1 = Knight, 2 = Bishop, 3 = Rook, 4 = Queen).
23
+ */
24
+ type PackedMove = number & {
25
+ readonly __brand: "PackedMove";
26
+ };
27
+ /** Move2 promotion codes */
28
+ declare const MOVE2_PROMO_NONE = 0;
29
+ declare const MOVE2_PROMO_KNIGHT = 1;
30
+ declare const MOVE2_PROMO_BISHOP = 2;
31
+ declare const MOVE2_PROMO_ROOK = 3;
32
+ declare const MOVE2_PROMO_QUEEN = 4;
33
+ /**
34
+ * Packs from/to/promo into one 16-bit Move2 word.
35
+ */
36
+ declare function packMove(from: number, to: number, promo?: number): PackedMove;
37
+ /**
38
+ * Unpacks a 16-bit Move2 word into its from/to/promo fields.
39
+ */
40
+ declare function unpackMove(move: PackedMove | number): {
41
+ from: SquareIndex;
42
+ to: SquareIndex;
43
+ promo: number;
44
+ };
45
+ /**
46
+ * 64-bit Zobrist key represented as two 32-bit unsigned integers (zero-BigInt).
47
+ */
48
+ type ZobristKey = {
49
+ readonly lo: number;
50
+ readonly hi: number;
51
+ };
52
+ /**
53
+ * A single byte representing one square of the board. `0` is empty; values
54
+ * `1..12` encode a piece. The encoding is a stable contract: consumers may
55
+ * rely on `BOARD_CELL_*` constants (below) instead of remembering numbers.
56
+ */
57
+ type BoardCell = number & {
58
+ readonly __brand: "BoardCell";
59
+ };
60
+ /** Piece color (White = 0, Black = 1). */
61
+ declare const Color: {
62
+ readonly White: 0;
63
+ readonly Black: 1;
64
+ };
65
+ /** Colour value. */
66
+ type Color = (typeof Color)[keyof typeof Color];
67
+ /** Piece type (0 = Pawn .. 5 = King). */
68
+ declare const PieceType: {
69
+ readonly Pawn: 0;
70
+ readonly Knight: 1;
71
+ readonly Bishop: 2;
72
+ readonly Rook: 3;
73
+ readonly Queen: 4;
74
+ readonly King: 5;
75
+ };
76
+ /** Piece-type value (0 = Pawn .. 5 = King). */
77
+ type PieceType = (typeof PieceType)[keyof typeof PieceType];
78
+ /** Board-cell constants for readability at call sites. */
79
+ declare const BOARD_CELL_EMPTY: BoardCell;
80
+ declare const BOARD_CELL_WP: BoardCell;
81
+ declare const BOARD_CELL_WN: BoardCell;
82
+ declare const BOARD_CELL_WB: BoardCell;
83
+ declare const BOARD_CELL_WR: BoardCell;
84
+ declare const BOARD_CELL_WQ: BoardCell;
85
+ declare const BOARD_CELL_WK: BoardCell;
86
+ declare const BOARD_CELL_BP: BoardCell;
87
+ declare const BOARD_CELL_BN: BoardCell;
88
+ declare const BOARD_CELL_BB: BoardCell;
89
+ declare const BOARD_CELL_BR: BoardCell;
90
+ declare const BOARD_CELL_BQ: BoardCell;
91
+ declare const BOARD_CELL_BK: BoardCell;
92
+ /** Narrow a number into a `SquareIndex`. Validates in dev, no-op at runtime. */
93
+ declare function toSquareIndex(n: number): SquareIndex;
94
+ /** Type-guard: is `n` a valid square index? */
95
+ declare function isSquareIndex(n: number): n is SquareIndex;
96
+ /**
97
+ * Pack a `(color, type)` pair into a `BoardCell`.
98
+ *
99
+ * @remarks Inlined constant arithmetic — stays zero-allocation.
100
+ */
101
+ declare function encodeBoardCell(color: Color, type: PieceType): BoardCell;
102
+ /** `true` if the cell is empty. */
103
+ declare function isEmptyCell(cell: BoardCell): boolean;
104
+ /** Extract the color from a non-empty `BoardCell`. Undefined for empty cells. */
105
+ declare function colorOf(cell: BoardCell): Color;
106
+ /** Extract the piece type from a non-empty `BoardCell`. Undefined for empty. */
107
+ declare function pieceTypeOf(cell: BoardCell): PieceType;
108
+ /**
109
+ * Optional text label rendered alongside an arrow. Positioned at the
110
+ * endpoint by default; use `ArrowShape["labelCenter"]` to anchor it on
111
+ * `"orig"` (source square) or at the arrow's midpoint instead.
112
+ */
113
+ interface ArrowLabel {
114
+ readonly text: string;
115
+ /** CSS color for the label glyph. Defaults to the arrow's `color`. */
116
+ readonly fill?: string;
117
+ }
118
+ /**
119
+ * Arbitrary inline SVG payload rendered on top of the canvas overlay.
120
+ * `html` is injected into an `<svg>` group as a `foreignObject`-free
121
+ * child so downstream CSS animations and `stroke-dasharray` tricks
122
+ * work as-is. The renderer never parses or sanitises the string —
123
+ * consumers are responsible for trusting the source. Typical uses:
124
+ * - Stockfish best-move numerals ("+1.2", "♔")
125
+ * - Coach annotations (stars, exclamations, `!!`/`??`)
126
+ * - Custom variation markers
127
+ */
128
+ interface ArrowCustomSvg {
129
+ /** SVG fragment injected as-is. Must be safe markup — no sanitisation. */
130
+ readonly html: string;
131
+ /**
132
+ * Anchor point for the fragment. Default `"dest"`. `"orig"` is useful
133
+ * for same-square marks (circles); `"label"` centres on the midpoint.
134
+ */
135
+ readonly center?: "orig" | "dest" | "label";
136
+ }
137
+ /**
138
+ * An on-board arrow annotation. Identity is the tuple
139
+ * `(from, to, color, brush, label.text, customSvg.html, below)` — two
140
+ * arrows that agree on every field are considered equal.
141
+ *
142
+ * @remarks
143
+ * The original `(from, to, color)` identity is preserved: any arrow
144
+ * that doesn't carry the optional decorations behaves exactly as in
145
+ * M1. Additive-only extension.
146
+ */
147
+ interface Arrow {
148
+ readonly from: SquareIndex;
149
+ readonly to: SquareIndex;
150
+ /** Any CSS-legal color string. Common values: `"green"`, `"red"`, `"blue"`. */
151
+ readonly color: string;
152
+ /**
153
+ * Optional palette key that lets the renderer resolve the arrow's
154
+ * visual style (colour, stroke width, opacity) from a user-supplied
155
+ * `ArrowColors` map at draw time. When absent, `color` is used as-is
156
+ * and the modifier-key channels (`default`/`shift`/`alt`/`ctrl`)
157
+ * continue to work.
158
+ */
159
+ readonly brush?: string;
160
+ /** Optional text label. See {@link ArrowLabel}. */
161
+ readonly label?: ArrowLabel;
162
+ /** Optional custom SVG payload. See {@link ArrowCustomSvg}. */
163
+ readonly customSvg?: ArrowCustomSvg;
164
+ /**
165
+ * When `true`, the arrow renders **beneath** the piece layer instead
166
+ * of on top. Useful for "heatmap" tints that shouldn't occlude pieces
167
+ * (analysis boards, pawn-structure overlays).
168
+ */
169
+ readonly below?: boolean;
170
+ /**
171
+ * Marks an arrow as owned by the application rather than the user.
172
+ * "Managed" arrows survive the two reflex-clearing hooks
173
+ * (`clearArrowsOnClick`, `clearArrowsOnMove`) — the idiomatic use-case
174
+ * is an engine best-move hint on an analysis board, where the hint
175
+ * should update when the position changes but ignore the user's
176
+ * click-to-dismiss gesture on the board.
177
+ *
178
+ * User-drawn arrows (right-click gesture) always land with
179
+ * `managed: false`; programmatic callers opt in explicitly.
180
+ *
181
+ * A nuclear `model.clearArrows()` still wipes managed arrows —
182
+ * consumers who want a stricter partition call `clearUserArrows()`
183
+ * instead. Default `false` (unset).
184
+ */
185
+ readonly managed?: boolean;
186
+ }
187
+ /** A queued premove awaiting the opponent's reply. */
188
+ interface Premove {
189
+ readonly from: SquareIndex;
190
+ readonly to: SquareIndex;
191
+ readonly promotion?: PieceType;
192
+ }
193
+ /**
194
+ * Immutable snapshot of the board at a single instant. Produced by the store
195
+ * on every commit; never mutated. React's `useSyncExternalStore` relies on
196
+ * referential equality here — a new snapshot object is emitted per commit,
197
+ * but bytes of `board` that didn't change share values with the previous one
198
+ * (read as primitives), so per-square subscribers skip untouched squares.
199
+ */
200
+ interface BoardSnapshot {
201
+ /** 64-byte board, LERF-indexed. See {@link BoardCell}. */
202
+ readonly board: Readonly<Uint8Array>;
203
+ /** Side to move. */
204
+ readonly turn: Color;
205
+ /** Zobrist hash of the position (from the engine). */
206
+ readonly hash: ZobristKey | bigint;
207
+ /** The packed move that produced this position, or `null` for the initial. */
208
+ readonly lastMove: PackedMove | null;
209
+ /** Currently-selected square (UI state), or `null`. */
210
+ readonly selected: SquareIndex | null;
211
+ /** Legal target squares from `selected`. Empty set if nothing is selected. */
212
+ readonly legalTargets: ReadonlySet<SquareIndex>;
213
+ /** `true` if the side to move is in check. */
214
+ readonly inCheck: boolean;
215
+ /** `true` if the position ends the game (mate, stalemate, draw). */
216
+ readonly isGameOver: boolean;
217
+ /** How many plies from the initial position we are (includes undos). */
218
+ readonly historyPly: number;
219
+ /** Total history length, including any plies we've undone. */
220
+ readonly historyLength: number;
221
+ /** Active arrows drawn on the board. */
222
+ readonly arrows: readonly Arrow[];
223
+ /** Queued premoves, in FIFO order. */
224
+ readonly premoves: readonly Premove[];
225
+ }
226
+ /** Descriptor classifying one animated change between two snapshots. */
227
+ type AnimDescriptor = {
228
+ readonly kind: "move";
229
+ readonly from: SquareIndex;
230
+ readonly to: SquareIndex;
231
+ readonly piece: BoardCell;
232
+ } | {
233
+ readonly kind: "capture";
234
+ readonly from: SquareIndex;
235
+ readonly to: SquareIndex;
236
+ readonly piece: BoardCell;
237
+ readonly captured: BoardCell;
238
+ } | {
239
+ readonly kind: "en-passant";
240
+ readonly from: SquareIndex;
241
+ readonly to: SquareIndex;
242
+ readonly capturedSquare: SquareIndex;
243
+ readonly piece: BoardCell;
244
+ readonly captured: BoardCell;
245
+ } | {
246
+ readonly kind: "castle";
247
+ readonly kingFrom: SquareIndex;
248
+ readonly kingTo: SquareIndex;
249
+ readonly rookFrom: SquareIndex;
250
+ readonly rookTo: SquareIndex;
251
+ } | {
252
+ readonly kind: "promotion";
253
+ readonly from: SquareIndex;
254
+ readonly to: SquareIndex;
255
+ readonly pieceBefore: BoardCell;
256
+ readonly pieceAfter: BoardCell;
257
+ readonly captured: BoardCell | null;
258
+ } | {
259
+ readonly kind: "appear";
260
+ readonly at: SquareIndex;
261
+ readonly piece: BoardCell;
262
+ } | {
263
+ readonly kind: "disappear";
264
+ readonly at: SquareIndex;
265
+ readonly piece: BoardCell;
266
+ };
267
+ /** Pointer-driven drag state. Used by `drag-controller`. */
268
+ type DragState = {
269
+ readonly kind: "idle";
270
+ } | {
271
+ readonly kind: "pending";
272
+ readonly from: SquareIndex;
273
+ readonly pointerId: number;
274
+ readonly originX: number;
275
+ readonly originY: number;
276
+ } | {
277
+ readonly kind: "dragging";
278
+ readonly from: SquareIndex;
279
+ readonly pointerId: number;
280
+ readonly x: number;
281
+ readonly y: number;
282
+ };
283
+
284
+ /**
285
+ * Abstract engine protocol.
286
+ *
287
+ * The board model speaks to a chess engine exclusively through an
288
+ * `EngineAdapter`. Swapping the default `gigachess` adapter for another
289
+ * (chess.js, a variant engine, a custom server-backed validator) should not
290
+ * require changes to `board-model` or any React code.
291
+ *
292
+ * All methods are synchronous: adapter construction absorbs any async init.
293
+ * Every call is expected to be cheap in the steady state. Long-running adapters
294
+ * should cache aggressively on their own side.
295
+ */
296
+
297
+ /** The engine protocol. */
298
+ interface EngineAdapter {
299
+ /**
300
+ * Play a legal move. Returns the packed move on success, `null` if the move
301
+ * is illegal in the current position. Never throws on illegal input —
302
+ * callers may pass arbitrary from/to pairs (e.g. drag-and-drop drops onto
303
+ * any square).
304
+ */
305
+ makeMove(from: SquareIndex, to: SquareIndex, promotion?: PieceType): PackedMove | null;
306
+ /** Undo the most recent move. Returns the undone move, or `null` if none. */
307
+ undo(): PackedMove | null;
308
+ /**
309
+ * Legal moves from a single origin square (`from` provided) or all legal
310
+ * moves (`from` omitted). The returned array is fresh on every call; the
311
+ * caller is free to retain or discard it.
312
+ */
313
+ legalMoves(from?: SquareIndex): readonly PackedMove[];
314
+ /**
315
+ * Fill `out` with the current position as 64 `BoardCell` bytes (LERF). The
316
+ * caller supplies the buffer so adapters can avoid allocating per commit;
317
+ * `out.length` must be `64`.
318
+ */
319
+ readBoard(out: Uint8Array): void;
320
+ /** Current FEN. */
321
+ fen(): string;
322
+ /** Side to move. */
323
+ turn(): Color;
324
+ /** Zobrist hash of the current position. */
325
+ hash(): ZobristKey | bigint;
326
+ /** `true` if the side to move is in check. */
327
+ inCheck(): boolean;
328
+ /**
329
+ * Render a packed move as SAN (e.g. `"Nf3"`, `"O-O"`, `"exd5"`, `"e8=Q+"`).
330
+ * Used by the React layer's screen-reader announcer.
331
+ *
332
+ * Must be called BEFORE the move is played — SAN depends on the
333
+ * pre-move position for disambiguation and check markers.
334
+ */
335
+ san(move: PackedMove): string;
336
+ /** `true` if the position ends the game (mate, stalemate, draw). */
337
+ isGameOver(): boolean;
338
+ /** Load a FEN into the engine, replacing the current position and history. */
339
+ load(fen: string): void;
340
+ /** Reset to the starting position. Clears history. */
341
+ reset(): void;
342
+ /** Release engine resources. */
343
+ dispose(): void;
344
+ }
345
+ /**
346
+ * Opaque board-cell setter — lets adapters paint individual bytes into `out`
347
+ * without repeatedly importing `types.ts`'s `encodeBoardCell`.
348
+ *
349
+ * @param out Target 64-byte buffer.
350
+ * @param index LERF square index.
351
+ * @param cell The pre-encoded board cell value.
352
+ */
353
+ declare function writeBoardCell(out: Uint8Array, index: SquareIndex, cell: BoardCell): void;
354
+
355
+ /**
356
+ * Pointer-driven drag state machine.
357
+ *
358
+ * States: `idle → pending → dragging → idle`.
359
+ *
360
+ * - `pointerDown` on a source square moves us from `idle` to `pending`. We
361
+ * don't commit to "this is a drag" yet — a tap that releases without moving
362
+ * should remain a click.
363
+ * - Once the pointer has moved more than `activationDistance` pixels (default
364
+ * `4`), we transition to `dragging` and emit a `drag-start` event. From
365
+ * there, every `pointerMove` updates the live `(x, y)`.
366
+ * - `pointerUp` in `dragging` emits a `drop` event and returns to `idle`.
367
+ * `pointerUp` in `pending` (no drag happened) returns to `idle` silently.
368
+ * - `cancel()` at any time returns to `idle` and emits a `cancel` event if a
369
+ * drag or pending pick was in flight.
370
+ *
371
+ * Events other than `pointerDown` that arrive with the "wrong" `pointerId`
372
+ * are ignored — necessary on touch devices where multiple pointers may be
373
+ * live simultaneously.
374
+ *
375
+ * The controller is a pure reducer that returns its output events. It does
376
+ * **not** subscribe to the board model, and it performs zero DOM reads or
377
+ * writes. The React layer is responsible for wiring `PointerEvent`s to these
378
+ * methods and reacting to the returned events.
379
+ */
380
+
381
+ /** Emitted when the pointer crosses `activationDistance` from its origin. */
382
+ interface DragStartEvent {
383
+ readonly kind: "drag-start";
384
+ readonly from: SquareIndex;
385
+ }
386
+ /** Emitted while dragging, on every `pointerMove`. Coordinates are whatever
387
+ * the caller passed in (no DOM awareness — typically `clientX`/`clientY`). */
388
+ interface DragMoveEvent {
389
+ readonly kind: "drag-move";
390
+ readonly from: SquareIndex;
391
+ readonly x: number;
392
+ readonly y: number;
393
+ }
394
+ /** Emitted on `pointerUp` in `dragging`. `wasDrag` is always `true` here. */
395
+ interface DropEvent {
396
+ readonly kind: "drop";
397
+ readonly from: SquareIndex;
398
+ readonly x: number;
399
+ readonly y: number;
400
+ readonly wasDrag: true;
401
+ }
402
+ /** Emitted on `pointerUp` in `pending` — the user clicked without dragging. */
403
+ interface ClickEvent {
404
+ readonly kind: "click";
405
+ readonly from: SquareIndex;
406
+ }
407
+ /** Emitted by `cancel()` when a pending pick or an in-flight drag existed. */
408
+ interface CancelEvent {
409
+ readonly kind: "cancel";
410
+ readonly from: SquareIndex;
411
+ }
412
+ /** Any event emitted by the drag controller. */
413
+ type DragEvent = DragStartEvent | DragMoveEvent | DropEvent | ClickEvent | CancelEvent;
414
+ /** Controller options. */
415
+ interface DragControllerOptions {
416
+ /** Distance threshold (in CSS pixels) for `pending → dragging`. Default 4. */
417
+ readonly activationDistance?: number;
418
+ }
419
+ /** Public controller API. */
420
+ interface DragController {
421
+ /** The current drag state. Read-only. */
422
+ readonly state: DragState;
423
+ /**
424
+ * Handle a pointer-down on a source square. Returns `true` if the event was
425
+ * consumed (i.e. we were `idle` and are now `pending`); `false` otherwise.
426
+ */
427
+ pointerDown(from: SquareIndex, pointerId: number, x: number, y: number): boolean;
428
+ /**
429
+ * Handle a pointer-move. Returns the emitted event (`drag-start` on the
430
+ * first crossing of the threshold, `drag-move` afterwards) or `null` if
431
+ * the move did not produce one.
432
+ */
433
+ pointerMove(pointerId: number, x: number, y: number): DragStartEvent | DragMoveEvent | null;
434
+ /**
435
+ * Handle a pointer-up. Returns `drop` when a drag was in flight, `click`
436
+ * when the user released without crossing the threshold, or `null` if the
437
+ * event does not concern us.
438
+ */
439
+ pointerUp(pointerId: number, x: number, y: number): DropEvent | ClickEvent | null;
440
+ /** Abort any pending or in-flight drag. Returns the emitted event, or
441
+ * `null` if there was nothing to cancel. */
442
+ cancel(): CancelEvent | null;
443
+ }
444
+ /** Construct a fresh drag controller. */
445
+ declare function createDragController(options?: DragControllerOptions): DragController;
446
+
447
+ /**
448
+ * `hash()`-keyed LRU cache for `(position, from-square) → to-squares`.
449
+ *
450
+ * Every time the user picks up a piece we need the list of legal target squares
451
+ * to paint rings on the board. The engine's `legalMoves(from)` call is cheap
452
+ * but crosses the WASM boundary; caching on `engine.hash()` makes every repeat
453
+ * selection free.
454
+ *
455
+ * Keyed as `(hash << 6n) | BigInt(from)` — 70 bits total, carried as a single
456
+ * `bigint` key. LRU order is preserved by `Map` iteration order: on hit we
457
+ * `delete` + `set` to bump the entry to the most-recently-used end; on write
458
+ * past capacity we evict the oldest (the first key in iteration order).
459
+ */
460
+
461
+ /** Lookup outcome from {@link LegalMoveIndex.get}. */
462
+ type LegalMoveEntry = Readonly<Uint8Array>;
463
+ /** Position hash representation: zero-BigInt { lo, hi } pair or bigint. */
464
+ type PositionHash = bigint | ZobristKey;
465
+ /** The cache API. */
466
+ interface LegalMoveIndex {
467
+ /** Return cached target squares for `(hash, from)`, or `undefined` on miss. */
468
+ get(hash: PositionHash, from: SquareIndex): LegalMoveEntry | undefined;
469
+ /** Store target squares for `(hash, from)`. */
470
+ set(hash: PositionHash, from: SquareIndex, tos: Uint8Array): void;
471
+ /** Drop every entry. */
472
+ clear(): void;
473
+ /** Current number of entries. */
474
+ readonly size: number;
475
+ /** Configured maximum entry count. */
476
+ readonly capacity: number;
477
+ /** Cumulative hit count since construction (or last `resetStats`). */
478
+ readonly hits: number;
479
+ /** Cumulative miss count since construction (or last `resetStats`). */
480
+ readonly misses: number;
481
+ /** Reset `hits` / `misses` to zero. Does not affect stored entries. */
482
+ resetStats(): void;
483
+ }
484
+ /** Options for {@link createLegalMoveIndex}. */
485
+ interface LegalMoveIndexOptions {
486
+ /** Maximum number of entries retained. Must be ≥ 1. Defaults to `1024`. */
487
+ readonly capacity?: number;
488
+ }
489
+ /** Create an LRU cache. */
490
+ declare function createLegalMoveIndex(options?: LegalMoveIndexOptions): LegalMoveIndex;
491
+
492
+ /**
493
+ * `useSyncExternalStore`-compatible store with byte-level per-square diff.
494
+ *
495
+ * Global listeners fire on every commit. Per-square listeners fire **only** when
496
+ * their byte of `snapshot.board` changed — so a move that touches 2–4 squares
497
+ * wakes only 2–4 Square components instead of all 64.
498
+ */
499
+
500
+ /** Cleanup returned from a subscription. Idempotent. */
501
+ type Unsubscribe = () => void;
502
+ /** Internal listener type: a void-returning callback. */
503
+ type Listener = () => void;
504
+ /**
505
+ * The store API. Surface area is intentionally minimal; everything else lives
506
+ * in `board-model`.
507
+ */
508
+ interface BoardStore {
509
+ /** Return the current frozen snapshot. Same reference between commits. */
510
+ getSnapshot(): BoardSnapshot;
511
+ /** Subscribe to every commit. Returns an unsubscribe function. */
512
+ subscribe(listener: Listener): Unsubscribe;
513
+ /**
514
+ * Subscribe to commits in which `board[index]` changed. Useful from a
515
+ * per-square React component via `useSyncExternalStore`.
516
+ */
517
+ subscribeSquare(index: SquareIndex, listener: Listener): Unsubscribe;
518
+ /**
519
+ * Install a new snapshot. Diffs `board` bytes against the previous snapshot
520
+ * and fires only the per-square listeners whose byte actually changed, plus
521
+ * every global listener.
522
+ *
523
+ * @remarks
524
+ * Callers must build a fresh snapshot object — mutating the previous one in
525
+ * place would make `getSnapshot()` return `=== previous`, which React treats
526
+ * as "no change" and skips the render.
527
+ */
528
+ commit(next: BoardSnapshot): void;
529
+ }
530
+ /** Create a new board store initialised with `initial`. */
531
+ declare function createBoardStore(initial: BoardSnapshot): BoardStore;
532
+
533
+ /**
534
+ * Board model: the orchestrator.
535
+ *
536
+ * Owns the engine adapter, the subscribe store, the legal-move cache, the
537
+ * arrow set, the premove buffer, and the redo stack. Every public action
538
+ * funnels here: `tryMove`, `undo`, `redo`, `goto`, `load`, `reset`,
539
+ * `selectSquare`, and arrow / premove mutators. Each action produces **at
540
+ * most one** snapshot commit so that React subscribers receive a single,
541
+ * coherent update per user intent.
542
+ *
543
+ * The model is intentionally framework-agnostic: no React, no DOM, no
544
+ * `useState`. Consumers drive it imperatively and subscribe to the store
545
+ * for state.
546
+ */
547
+
548
+ /** Constructor options for {@link createBoardModel}. */
549
+ interface BoardModelOptions {
550
+ /** Options forwarded to the legal-move cache. */
551
+ readonly legalMoveIndex?: LegalMoveIndexOptions;
552
+ /** Options forwarded to the drag controller. */
553
+ readonly dragController?: DragControllerOptions;
554
+ /**
555
+ * In development, freeze every emitted `BoardSnapshot` to catch accidental
556
+ * mutation. Defaults to `true` when `NODE_ENV !== "production"`. Turning
557
+ * this off is reserved for profiling; leave it alone otherwise.
558
+ */
559
+ readonly freezeSnapshots?: boolean;
560
+ }
561
+ /** Options for one coherent controlled-position update. */
562
+ interface SyncPositionOptions {
563
+ /** FEN to load into the underlying engine. */
564
+ readonly fen: string;
565
+ /**
566
+ * Managed, application-owned arrows to install with the position. When
567
+ * omitted, managed arrows are left alone if the FEN is already current
568
+ * and cleared on a real position load, matching `load(fen)` semantics.
569
+ */
570
+ readonly managedArrows?: readonly Arrow[];
571
+ /**
572
+ * Preserve user-drawn arrows across a position load. Defaults to `false`
573
+ * because arrows usually describe the previous position.
574
+ */
575
+ readonly preserveUserArrows?: boolean;
576
+ }
577
+ /** The orchestrator API consumed by React. */
578
+ interface BoardModel {
579
+ /** Current snapshot. Stable between commits. */
580
+ getSnapshot(): BoardSnapshot;
581
+ /** Subscribe to every commit. */
582
+ subscribe(listener: () => void): Unsubscribe;
583
+ /** Subscribe to commits that changed `board[index]`. */
584
+ subscribeSquare(index: SquareIndex, listener: () => void): Unsubscribe;
585
+ /** Select a square. Passing `null` clears the selection. No-op if unchanged. */
586
+ selectSquare(index: SquareIndex | null): void;
587
+ /** Attempt a move. Returns the packed move on success, `null` on illegal. */
588
+ tryMove(from: SquareIndex, to: SquareIndex, promotion?: PieceType): PackedMove | null;
589
+ /** Undo the most recent move. */
590
+ undo(): PackedMove | null;
591
+ /** Redo the most recently undone move. */
592
+ redo(): PackedMove | null;
593
+ /** Jump to ply `n` in the history (0 = initial position). */
594
+ goto(ply: number): void;
595
+ /** Load a FEN; clears history, redo, arrows, and premoves. */
596
+ load(fen: string): void;
597
+ /**
598
+ * Controlled-position sync for analysis/replay viewers. Loads the FEN
599
+ * and replaces the managed arrow subset in the same snapshot commit.
600
+ */
601
+ syncPosition(options: SyncPositionOptions): void;
602
+ /** Reset to the starting position; clears history, redo, arrows, premoves. */
603
+ reset(): void;
604
+ /** `true` if a move `from → to` (optionally promoting) is legal right now. */
605
+ isLegal(from: SquareIndex, to: SquareIndex, promotion?: PieceType): boolean;
606
+ /** Legal target squares from `from`, cached by position hash. */
607
+ legalFrom(from: SquareIndex): ReadonlySet<SquareIndex>;
608
+ addArrow(arrow: Arrow): void;
609
+ removeArrow(arrow: Arrow): void;
610
+ toggleArrow(arrow: Arrow): void;
611
+ /** Drop every arrow, managed or not. Nuclear option. */
612
+ clearArrows(): void;
613
+ /**
614
+ * Drop only **user-drawn** arrows (anything without `managed: true`).
615
+ * The board uses this for its click-to-dismiss behaviour so engine /
616
+ * app-owned hints survive user interaction.
617
+ */
618
+ clearUserArrows(): void;
619
+ /** Drop only **managed** arrows. Leaves user drawings untouched. */
620
+ clearManagedArrows(): void;
621
+ /**
622
+ * Atomic replace of the **entire** arrow set (managed and user). Use
623
+ * this when the board is a pure programmatic surface with no human
624
+ * drawing — a review / replay viewer, a puzzle diagram, tests.
625
+ *
626
+ * For analysis-style boards that stream engine hints alongside human
627
+ * arrow drawings, prefer {@link setManagedArrows}: it replaces only
628
+ * the managed subset and preserves whatever the user has drawn by
629
+ * right-clicking.
630
+ *
631
+ * @remarks
632
+ * Arrows whose identity tuple already exists are preserved by
633
+ * reference across the call, so React subscribers that compare
634
+ * per-arrow references skip unchanged entries. A true no-op (same set
635
+ * in the same order) commits nothing.
636
+ */
637
+ setArrows(arrows: readonly Arrow[]): void;
638
+ /**
639
+ * Atomic replace of **only** the managed subset. User-drawn arrows
640
+ * are untouched; every incoming arrow is implicitly marked
641
+ * `managed: true`. Idiomatic for engine-annotation feeds (Stockfish
642
+ * best-moves, multi-PV fans): the arrow set turns over as a whole per
643
+ * position without racing the user's right-click gesture.
644
+ *
645
+ * @example
646
+ * ```ts
647
+ * game.setManagedArrows(bestLine ? [uciToArrow(bestLine[0])] : []);
648
+ * ```
649
+ */
650
+ setManagedArrows(arrows: readonly Arrow[]): void;
651
+ queuePremove(premove: Premove): void;
652
+ clearPremoves(): void;
653
+ /** The drag controller; React layer binds pointer events to it. */
654
+ readonly drag: DragController;
655
+ /** Statistics view of the legal-move cache (for benchmarks). */
656
+ readonly legalMoveCache: LegalMoveIndex;
657
+ /** The underlying engine adapter, for escape-hatch callers. */
658
+ readonly engine: EngineAdapter;
659
+ /**
660
+ * The animation descriptors produced by the most recent commit. Empty on
661
+ * the initial snapshot. Consumed by the React layer's `useAnimation` hook.
662
+ */
663
+ readonly lastAnimations: readonly AnimDescriptor[];
664
+ /** Release engine resources and drop all subscriptions. */
665
+ dispose(): void;
666
+ }
667
+ /**
668
+ * Construct a board model around an engine adapter.
669
+ *
670
+ * The model does **not** create the adapter — the caller does.
671
+ * See `createGigachessAdapter` for standard adapter construction.
672
+ */
673
+ declare function createBoardModel(engine: EngineAdapter, options?: BoardModelOptions): BoardModel;
674
+
675
+ export { createDragController as $, type AnimDescriptor as A, BOARD_CELL_BB as B, type CancelEvent as C, type DragController as D, type EngineAdapter as E, type DragControllerOptions as F, type DragEvent as G, type DragMoveEvent as H, type DragStartEvent as I, type DragState as J, type DropEvent as K, type LegalMoveEntry as L, type LegalMoveIndex as M, type LegalMoveIndexOptions as N, MOVE2_PROMO_BISHOP as O, type PackedMove as P, MOVE2_PROMO_KNIGHT as Q, MOVE2_PROMO_NONE as R, type SquareIndex as S, MOVE2_PROMO_QUEEN as T, MOVE2_PROMO_ROOK as U, type PositionHash as V, type SyncPositionOptions as W, type Unsubscribe as X, createBoardModel as Y, type ZobristKey as Z, createBoardStore as _, PieceType as a, createLegalMoveIndex as a0, encodeBoardCell as a1, isEmptyCell as a2, isSquareIndex as a3, packMove as a4, toSquareIndex as a5, unpackMove as a6, writeBoardCell as a7, type Arrow as b, colorOf as c, type Premove as d, type ArrowCustomSvg as e, type ArrowLabel as f, BOARD_CELL_BK as g, BOARD_CELL_BN as h, BOARD_CELL_BP as i, BOARD_CELL_BQ as j, BOARD_CELL_BR as k, BOARD_CELL_EMPTY as l, BOARD_CELL_WB as m, BOARD_CELL_WK as n, BOARD_CELL_WN as o, pieceTypeOf as p, BOARD_CELL_WP as q, BOARD_CELL_WQ as r, BOARD_CELL_WR as s, type BoardCell as t, type BoardModel as u, type BoardModelOptions as v, type BoardSnapshot as w, type BoardStore as x, type ClickEvent as y, Color as z };
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ // src/renderers/canvas.ts
4
+ var CANVAS_RENDERER_VERSION = "0.0.0";
5
+
6
+ exports.CANVAS_RENDERER_VERSION = CANVAS_RENDERER_VERSION;
7
+ //# sourceMappingURL=canvas.cjs.map
8
+ //# sourceMappingURL=canvas.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/renderers/canvas.ts"],"names":[],"mappings":";;;AAYO,IAAM,uBAAA,GAA0B","file":"canvas.cjs","sourcesContent":["/**\n * gigaboard/canvas — opt-in full-canvas renderer.\n *\n * For stress use cases: very large boards (fairy chess), many simultaneous arrows,\n * or low-end devices where per-square DOM nodes become a cost. Drops some DOM\n * superpowers (ARIA grid, CSS theming of individual squares, `renderSquare` escape\n * hatches). The default DOM renderer is recommended for almost all applications.\n *\n * @remarks\n * Lands in M8 (post-1.0). This is a scaffolding placeholder.\n */\n\nexport const CANVAS_RENDERER_VERSION = \"0.0.0\";\n"]}