gigaboard 1.4.2 → 1.5.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.
- package/dist/{board-model-BMtkLQvL.d.cts → board-model-BIVxSCWC.d.cts} +73 -2
- package/dist/{board-model-BMtkLQvL.d.ts → board-model-BIVxSCWC.d.ts} +73 -2
- package/dist/{chunk-EJUGH25P.js → chunk-53XWDREK.js} +4 -3
- package/dist/chunk-53XWDREK.js.map +1 -0
- package/dist/{chunk-SO6AOEFF.js → chunk-6F3FZAG7.js} +116 -18
- package/dist/chunk-6F3FZAG7.js.map +1 -0
- package/dist/{chunk-UBD62NOI.cjs → chunk-FUP2LDMO.cjs} +121 -16
- package/dist/chunk-FUP2LDMO.cjs.map +1 -0
- package/dist/{chunk-D45G3J5E.cjs → chunk-N4WTPXFC.cjs} +4 -2
- package/dist/chunk-N4WTPXFC.cjs.map +1 -0
- package/dist/core.cjs +72 -44
- package/dist/core.d.cts +17 -12
- package/dist/core.d.ts +17 -12
- package/dist/core.js +1 -1
- package/dist/{gigachess-C08uAeFw.d.ts → gigachess-DN-ncmAU.d.ts} +1 -1
- package/dist/{gigachess-Dr5gCN68.d.cts → gigachess-XpNGPM2m.d.cts} +1 -1
- package/dist/index.cjs +868 -250
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -8
- package/dist/index.d.ts +55 -8
- package/dist/index.js +775 -189
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +11 -11
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1 -1
- package/dist/{types-CcOgT5ov.d.ts → types-4W8ULiE2.d.ts} +1 -1
- package/dist/{types-DfqRXtbD.d.cts → types-Dox7oLof.d.cts} +1 -1
- package/package.json +2 -2
- package/dist/chunk-D45G3J5E.cjs.map +0 -1
- package/dist/chunk-EJUGH25P.js.map +0 -1
- package/dist/chunk-SO6AOEFF.js.map +0 -1
- package/dist/chunk-UBD62NOI.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkFUP2LDMO_cjs = require('./chunk-FUP2LDMO.cjs');
|
|
4
|
+
var chunkN4WTPXFC_cjs = require('./chunk-N4WTPXFC.cjs');
|
|
5
5
|
require('./chunk-G6ZFOJZR.cjs');
|
|
6
6
|
require('./chunk-AYVQCHSG.cjs');
|
|
7
7
|
require('./chunk-FNRS6YJI.cjs');
|
|
@@ -9,6 +9,64 @@ var react = require('react');
|
|
|
9
9
|
var jsxRuntime = require('react/jsx-runtime');
|
|
10
10
|
|
|
11
11
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
12
|
+
var FILE_LETTERS = ["a", "b", "c", "d", "e", "f", "g", "h"];
|
|
13
|
+
function Coordinates({ orientation, ranksPosition = "left" }) {
|
|
14
|
+
const ranksOnRight = ranksPosition === "right";
|
|
15
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
"aria-hidden": "true",
|
|
19
|
+
style: {
|
|
20
|
+
position: "absolute",
|
|
21
|
+
inset: 0,
|
|
22
|
+
pointerEvents: "none",
|
|
23
|
+
fontSize: "min(1.6vmin, 11px)",
|
|
24
|
+
fontWeight: 600,
|
|
25
|
+
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
26
|
+
},
|
|
27
|
+
children: [
|
|
28
|
+
FILE_LETTERS.map((letter, idx) => {
|
|
29
|
+
const col = orientation === "white" ? idx : 7 - idx;
|
|
30
|
+
const bottomRank = orientation === "white" ? 0 : 7;
|
|
31
|
+
const isLightSquare = (col + bottomRank) % 2 === 1;
|
|
32
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
33
|
+
"span",
|
|
34
|
+
{
|
|
35
|
+
style: {
|
|
36
|
+
position: "absolute",
|
|
37
|
+
left: `${col * 12.5 + 10}%`,
|
|
38
|
+
bottom: "1%",
|
|
39
|
+
color: `var(${isLightSquare ? chunkN4WTPXFC_cjs.CSS_VARS.COORDINATE_LIGHT : chunkN4WTPXFC_cjs.CSS_VARS.COORDINATE_DARK})`
|
|
40
|
+
},
|
|
41
|
+
children: letter
|
|
42
|
+
},
|
|
43
|
+
`file-${letter}`
|
|
44
|
+
);
|
|
45
|
+
}),
|
|
46
|
+
FILE_LETTERS.map((_, idx) => {
|
|
47
|
+
const rank = idx;
|
|
48
|
+
const row = orientation === "white" ? 7 - rank : rank;
|
|
49
|
+
const edgeFile = ranksOnRight ? orientation === "white" ? 7 : 0 : orientation === "white" ? 0 : 7;
|
|
50
|
+
const isLightSquare = (edgeFile + rank) % 2 === 1;
|
|
51
|
+
const sideStyle = ranksOnRight ? { right: "1%" } : { left: "1%" };
|
|
52
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
53
|
+
"span",
|
|
54
|
+
{
|
|
55
|
+
style: {
|
|
56
|
+
position: "absolute",
|
|
57
|
+
top: `${row * 12.5 + 1}%`,
|
|
58
|
+
...sideStyle,
|
|
59
|
+
color: `var(${isLightSquare ? chunkN4WTPXFC_cjs.CSS_VARS.COORDINATE_LIGHT : chunkN4WTPXFC_cjs.CSS_VARS.COORDINATE_DARK})`
|
|
60
|
+
},
|
|
61
|
+
children: rank + 1
|
|
62
|
+
},
|
|
63
|
+
`rank-${rank}`
|
|
64
|
+
);
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
12
70
|
function useBoardSnapshot(model) {
|
|
13
71
|
return react.useSyncExternalStore(model.subscribe, model.getSnapshot, model.getSnapshot);
|
|
14
72
|
}
|
|
@@ -22,12 +80,695 @@ function useSquareCell(model, index) {
|
|
|
22
80
|
},
|
|
23
81
|
[model, index]
|
|
24
82
|
);
|
|
25
|
-
const getSnapshot = react.useCallback(() => {
|
|
26
|
-
if (!model) return 0;
|
|
27
|
-
const snap = model.getSnapshot();
|
|
28
|
-
return snap.board[index] ?? 0;
|
|
29
|
-
}, [model, index]);
|
|
30
|
-
return react.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
83
|
+
const getSnapshot = react.useCallback(() => {
|
|
84
|
+
if (!model) return 0;
|
|
85
|
+
const snap = model.getSnapshot();
|
|
86
|
+
return snap.board[index] ?? 0;
|
|
87
|
+
}, [model, index]);
|
|
88
|
+
return react.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
89
|
+
}
|
|
90
|
+
function gridCoord(index, orientation) {
|
|
91
|
+
const file = index & 7;
|
|
92
|
+
const rank = index >> 3;
|
|
93
|
+
const col = orientation === "white" ? file + 1 : 8 - file;
|
|
94
|
+
const row = orientation === "white" ? 8 - rank : rank + 1;
|
|
95
|
+
return { col, row };
|
|
96
|
+
}
|
|
97
|
+
function algebraicOf(index) {
|
|
98
|
+
const file = index & 7;
|
|
99
|
+
const rank = index >> 3;
|
|
100
|
+
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
101
|
+
}
|
|
102
|
+
var SLOT_BASE_STYLE = Object.freeze({
|
|
103
|
+
display: "flex",
|
|
104
|
+
alignItems: "center",
|
|
105
|
+
justifyContent: "center",
|
|
106
|
+
pointerEvents: "none",
|
|
107
|
+
containerType: "size"
|
|
108
|
+
});
|
|
109
|
+
function PieceSlotImpl({ index, model, orientation, pieces }) {
|
|
110
|
+
const cell = useSquareCell(model, index);
|
|
111
|
+
if (cell === 0) return null;
|
|
112
|
+
const { col, row } = gridCoord(index, orientation);
|
|
113
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
114
|
+
"div",
|
|
115
|
+
{
|
|
116
|
+
"data-piece-square": algebraicOf(index),
|
|
117
|
+
"data-piece-cell": cell,
|
|
118
|
+
style: {
|
|
119
|
+
...SLOT_BASE_STYLE,
|
|
120
|
+
gridColumnStart: col,
|
|
121
|
+
gridRowStart: row,
|
|
122
|
+
filter: `var(${cell <= 6 ? chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_WHITE : chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_BLACK}, none)`
|
|
123
|
+
},
|
|
124
|
+
children: pieces({ cell, square: index })
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
var PieceSlot = react.memo(PieceSlotImpl);
|
|
129
|
+
PieceSlot.displayName = "PieceSlot";
|
|
130
|
+
var CONTAINER_STYLE = Object.freeze({
|
|
131
|
+
position: "absolute",
|
|
132
|
+
inset: 0,
|
|
133
|
+
display: "grid",
|
|
134
|
+
gridTemplateColumns: "repeat(8, 1fr)",
|
|
135
|
+
gridTemplateRows: "repeat(8, 1fr)",
|
|
136
|
+
pointerEvents: "none"
|
|
137
|
+
});
|
|
138
|
+
var PieceLayer = react.memo(function PieceLayer2({
|
|
139
|
+
model,
|
|
140
|
+
orientation,
|
|
141
|
+
pieces
|
|
142
|
+
}) {
|
|
143
|
+
const slots = [];
|
|
144
|
+
for (let i = 0; i < 64; i++) {
|
|
145
|
+
slots.push(
|
|
146
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
147
|
+
PieceSlot,
|
|
148
|
+
{
|
|
149
|
+
index: i,
|
|
150
|
+
model,
|
|
151
|
+
orientation,
|
|
152
|
+
pieces
|
|
153
|
+
},
|
|
154
|
+
i
|
|
155
|
+
)
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: CONTAINER_STYLE, children: slots });
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// src/lib/geometry.ts
|
|
162
|
+
function getSquareAtPoint(container, clientX, clientY, orientation) {
|
|
163
|
+
const rect = container.getBoundingClientRect();
|
|
164
|
+
const relX = clientX - rect.left;
|
|
165
|
+
const relY = clientY - rect.top;
|
|
166
|
+
if (relX < 0 || relY < 0 || relX >= rect.width || relY >= rect.height) return null;
|
|
167
|
+
const col = Math.floor(relX / rect.width * 8);
|
|
168
|
+
const row = Math.floor(relY / rect.height * 8);
|
|
169
|
+
const file = orientation === "white" ? col : 7 - col;
|
|
170
|
+
const rank = orientation === "white" ? 7 - row : row;
|
|
171
|
+
return rank * 8 + file;
|
|
172
|
+
}
|
|
173
|
+
function getPointAtSquareCentre(container, square, orientation) {
|
|
174
|
+
const rect = container.getBoundingClientRect();
|
|
175
|
+
const sqW = rect.width / 8;
|
|
176
|
+
const sqH = rect.height / 8;
|
|
177
|
+
const file = square & 7;
|
|
178
|
+
const rank = square >> 3;
|
|
179
|
+
const col = orientation === "white" ? file : 7 - file;
|
|
180
|
+
const row = orientation === "white" ? 7 - rank : rank;
|
|
181
|
+
return {
|
|
182
|
+
x: rect.left + sqW * col + sqW / 2,
|
|
183
|
+
y: rect.top + sqH * row + sqH / 2
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function algebraicOf2(square) {
|
|
187
|
+
const file = square & 7;
|
|
188
|
+
const rank = square >> 3;
|
|
189
|
+
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
190
|
+
}
|
|
191
|
+
function squareOf(algebraic) {
|
|
192
|
+
if (algebraic.length !== 2) return null;
|
|
193
|
+
const file = algebraic.charCodeAt(0) - 97;
|
|
194
|
+
const rank = algebraic.charCodeAt(1) - 49;
|
|
195
|
+
if (file < 0 || file > 7 || rank < 0 || rank > 7) return null;
|
|
196
|
+
return rank << 3 | file;
|
|
197
|
+
}
|
|
198
|
+
var PIECE_CHARS = ["", "P", "N", "B", "R", "Q", "K", "p", "n", "b", "r", "q", "k"];
|
|
199
|
+
function formatFenPlacement(board) {
|
|
200
|
+
const rows = [];
|
|
201
|
+
for (let r = 7; r >= 0; r--) {
|
|
202
|
+
let empty = 0;
|
|
203
|
+
let row = "";
|
|
204
|
+
for (let f = 0; f < 8; f++) {
|
|
205
|
+
const cell = board[r * 8 + f] ?? 0;
|
|
206
|
+
if (cell === 0) {
|
|
207
|
+
empty++;
|
|
208
|
+
} else {
|
|
209
|
+
if (empty > 0) {
|
|
210
|
+
row += String(empty);
|
|
211
|
+
empty = 0;
|
|
212
|
+
}
|
|
213
|
+
row += PIECE_CHARS[cell] ?? "";
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (empty > 0) {
|
|
217
|
+
row += String(empty);
|
|
218
|
+
}
|
|
219
|
+
rows.push(row);
|
|
220
|
+
}
|
|
221
|
+
return rows.join("/");
|
|
222
|
+
}
|
|
223
|
+
function updateFenPlacement(originalFen, newPlacement) {
|
|
224
|
+
const tokens = originalFen.trim().split(/\s+/);
|
|
225
|
+
if (tokens.length <= 1) {
|
|
226
|
+
return newPlacement;
|
|
227
|
+
}
|
|
228
|
+
tokens[0] = newPlacement;
|
|
229
|
+
return tokens.join(" ");
|
|
230
|
+
}
|
|
231
|
+
function pieceNameFromCell(cell) {
|
|
232
|
+
if (cell === 0) return "empty";
|
|
233
|
+
const color = cell > 6 ? "black" : "white";
|
|
234
|
+
const type = (cell - 1) % 6;
|
|
235
|
+
const names = ["pawn", "knight", "bishop", "rook", "queen", "king"];
|
|
236
|
+
return `${color} ${names[type] ?? "piece"}`;
|
|
237
|
+
}
|
|
238
|
+
function defaultSquareLabel(square, cell) {
|
|
239
|
+
const sq = algebraicOf2(square);
|
|
240
|
+
if (cell === 0) {
|
|
241
|
+
return `${sq}, empty`;
|
|
242
|
+
}
|
|
243
|
+
return `${sq}, ${pieceNameFromCell(cell)}`;
|
|
244
|
+
}
|
|
245
|
+
function cellFromKey(key) {
|
|
246
|
+
switch (key) {
|
|
247
|
+
case "P":
|
|
248
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_WP;
|
|
249
|
+
case "N":
|
|
250
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_WN;
|
|
251
|
+
case "B":
|
|
252
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_WB;
|
|
253
|
+
case "R":
|
|
254
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_WR;
|
|
255
|
+
case "Q":
|
|
256
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_WQ;
|
|
257
|
+
case "K":
|
|
258
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_WK;
|
|
259
|
+
case "p":
|
|
260
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_BP;
|
|
261
|
+
case "n":
|
|
262
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_BN;
|
|
263
|
+
case "b":
|
|
264
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_BB;
|
|
265
|
+
case "r":
|
|
266
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_BR;
|
|
267
|
+
case "q":
|
|
268
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_BQ;
|
|
269
|
+
case "k":
|
|
270
|
+
return chunkFUP2LDMO_cjs.BOARD_CELL_BK;
|
|
271
|
+
default:
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function cellFromPieceString(piece) {
|
|
276
|
+
if (!piece || piece === "erase") return 0;
|
|
277
|
+
if (piece.length === 2) {
|
|
278
|
+
const c0 = piece[0];
|
|
279
|
+
const c1 = piece[1];
|
|
280
|
+
if (c0 && c1) {
|
|
281
|
+
const color = c0.toLowerCase();
|
|
282
|
+
const type = c1.toUpperCase();
|
|
283
|
+
if (color === "w") return cellFromKey(type);
|
|
284
|
+
if (color === "b") return cellFromKey(type.toLowerCase());
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return cellFromKey(piece);
|
|
288
|
+
}
|
|
289
|
+
function getOppositePieceString(piece) {
|
|
290
|
+
if (!piece || piece === "erase") return null;
|
|
291
|
+
if (piece.length === 2) {
|
|
292
|
+
const c0 = piece[0];
|
|
293
|
+
const c1 = piece[1];
|
|
294
|
+
if (c0 && c1) {
|
|
295
|
+
const color = c0 === "w" ? "b" : "w";
|
|
296
|
+
return `${color}${c1}`;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return piece === piece.toUpperCase() ? piece.toLowerCase() : piece.toUpperCase();
|
|
300
|
+
}
|
|
301
|
+
function moveSquare(current, direction, orientation) {
|
|
302
|
+
const file = current & 7;
|
|
303
|
+
const rank = current >> 3;
|
|
304
|
+
const col = orientation === "white" ? file : 7 - file;
|
|
305
|
+
const row = orientation === "white" ? 7 - rank : rank;
|
|
306
|
+
let newCol = col;
|
|
307
|
+
let newRow = row;
|
|
308
|
+
switch (direction) {
|
|
309
|
+
case "up":
|
|
310
|
+
newRow = Math.max(0, row - 1);
|
|
311
|
+
break;
|
|
312
|
+
case "down":
|
|
313
|
+
newRow = Math.min(7, row + 1);
|
|
314
|
+
break;
|
|
315
|
+
case "left":
|
|
316
|
+
newCol = Math.max(0, col - 1);
|
|
317
|
+
break;
|
|
318
|
+
case "right":
|
|
319
|
+
newCol = Math.min(7, col + 1);
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
const newFile = orientation === "white" ? newCol : 7 - newCol;
|
|
323
|
+
const newRank = orientation === "white" ? 7 - newRow : newRow;
|
|
324
|
+
return newRank * 8 + newFile & 63;
|
|
325
|
+
}
|
|
326
|
+
function rankEndSquare(current, which, orientation) {
|
|
327
|
+
const rank = current >> 3;
|
|
328
|
+
if (orientation === "white") {
|
|
329
|
+
return rank << 3 | (which === "home" ? 0 : 7);
|
|
330
|
+
}
|
|
331
|
+
return rank << 3 | (which === "home" ? 7 : 0);
|
|
332
|
+
}
|
|
333
|
+
function BoardEditor({
|
|
334
|
+
fen = "8/8/8/8/8/8/8/8 w - - 0 1",
|
|
335
|
+
onChange,
|
|
336
|
+
onPieceChange,
|
|
337
|
+
selectedPiece,
|
|
338
|
+
onSelectPiece,
|
|
339
|
+
orientation = "white",
|
|
340
|
+
theme = chunkN4WTPXFC_cjs.defaultTheme,
|
|
341
|
+
pieces = chunkN4WTPXFC_cjs.defaultPieces,
|
|
342
|
+
showCoordinates = false,
|
|
343
|
+
style,
|
|
344
|
+
className,
|
|
345
|
+
ariaLabel = "Board editor",
|
|
346
|
+
onAnnounce,
|
|
347
|
+
getSquareAriaLabel,
|
|
348
|
+
focusedSquare: propFocusedSquare,
|
|
349
|
+
onSquareFocus,
|
|
350
|
+
onClear,
|
|
351
|
+
onSetStartingPosition,
|
|
352
|
+
onToggleSideToMove
|
|
353
|
+
}) {
|
|
354
|
+
const containerRef = react.useRef(null);
|
|
355
|
+
const liveRegionRef = react.useRef(null);
|
|
356
|
+
const liveCounter = react.useRef(0);
|
|
357
|
+
const [board, setBoard] = react.useState(() => {
|
|
358
|
+
try {
|
|
359
|
+
return chunkN4WTPXFC_cjs.parseFenPlacement(fen);
|
|
360
|
+
} catch {
|
|
361
|
+
return new Uint8Array(64);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
const [internalFocusedSquare, setInternalFocusedSquare] = react.useState(
|
|
365
|
+
() => orientation === "white" ? 28 : 36
|
|
366
|
+
// e4 or e5
|
|
367
|
+
);
|
|
368
|
+
const focusedSquare = propFocusedSquare ?? internalFocusedSquare;
|
|
369
|
+
const setFocusedSquare = setInternalFocusedSquare;
|
|
370
|
+
const [hasKeyboardFocus, setHasKeyboardFocus] = react.useState(false);
|
|
371
|
+
const [dragging, setDragging] = react.useState(null);
|
|
372
|
+
react.useEffect(() => {
|
|
373
|
+
try {
|
|
374
|
+
const nextBoard = chunkN4WTPXFC_cjs.parseFenPlacement(fen);
|
|
375
|
+
setBoard(nextBoard);
|
|
376
|
+
} catch {
|
|
377
|
+
}
|
|
378
|
+
}, [fen]);
|
|
379
|
+
const announce = react.useCallback(
|
|
380
|
+
(message) => {
|
|
381
|
+
onAnnounce?.(message);
|
|
382
|
+
const region = liveRegionRef.current;
|
|
383
|
+
if (region) {
|
|
384
|
+
liveCounter.current++;
|
|
385
|
+
region.setAttribute("data-live-id", String(liveCounter.current));
|
|
386
|
+
region.textContent = "";
|
|
387
|
+
void region.offsetHeight;
|
|
388
|
+
region.textContent = message;
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
[onAnnounce]
|
|
392
|
+
);
|
|
393
|
+
const getSquareDescription = react.useCallback(
|
|
394
|
+
(square, cell) => {
|
|
395
|
+
const sq = algebraicOf2(square);
|
|
396
|
+
if (getSquareAriaLabel) {
|
|
397
|
+
return getSquareAriaLabel(square, cell, sq);
|
|
398
|
+
}
|
|
399
|
+
return defaultSquareLabel(square, cell);
|
|
400
|
+
},
|
|
401
|
+
[getSquareAriaLabel]
|
|
402
|
+
);
|
|
403
|
+
const announceSquare = react.useCallback(
|
|
404
|
+
(square) => {
|
|
405
|
+
const cell = board[square] ?? 0;
|
|
406
|
+
const desc = getSquareDescription(square, cell);
|
|
407
|
+
announce(desc);
|
|
408
|
+
onSquareFocus?.(square, cell, algebraicOf2(square));
|
|
409
|
+
},
|
|
410
|
+
[announce, board, getSquareDescription, onSquareFocus]
|
|
411
|
+
);
|
|
412
|
+
const commitBoard = react.useCallback(
|
|
413
|
+
(nextBoard) => {
|
|
414
|
+
setBoard(nextBoard);
|
|
415
|
+
const newPlacement = formatFenPlacement(nextBoard);
|
|
416
|
+
const updatedFen = updateFenPlacement(fen, newPlacement);
|
|
417
|
+
onChange?.(updatedFen);
|
|
418
|
+
},
|
|
419
|
+
[fen, onChange]
|
|
420
|
+
);
|
|
421
|
+
const placePieceAt = react.useCallback(
|
|
422
|
+
(square, cellOrCode) => {
|
|
423
|
+
const targetCell = typeof cellOrCode === "string" ? cellFromPieceString(cellOrCode) : cellOrCode;
|
|
424
|
+
const currentCell = board[square] ?? 0;
|
|
425
|
+
const nextBoard = new Uint8Array(board);
|
|
426
|
+
if (targetCell !== 0 && currentCell === targetCell) {
|
|
427
|
+
nextBoard[square] = 0;
|
|
428
|
+
commitBoard(nextBoard);
|
|
429
|
+
onPieceChange?.(square, 0, algebraicOf2(square));
|
|
430
|
+
announce(`Piece removed from ${algebraicOf2(square)}`);
|
|
431
|
+
} else if (targetCell !== 0) {
|
|
432
|
+
nextBoard[square] = targetCell;
|
|
433
|
+
commitBoard(nextBoard);
|
|
434
|
+
onPieceChange?.(square, targetCell, algebraicOf2(square));
|
|
435
|
+
const name = pieceNameFromCell(targetCell);
|
|
436
|
+
announce(`${name} placed on ${algebraicOf2(square)}`);
|
|
437
|
+
const char = PIECE_CHARS[targetCell] ?? "";
|
|
438
|
+
const code = targetCell <= 6 ? `w${char}` : `b${char.toUpperCase()}`;
|
|
439
|
+
onSelectPiece?.(code);
|
|
440
|
+
} else {
|
|
441
|
+
nextBoard[square] = 0;
|
|
442
|
+
commitBoard(nextBoard);
|
|
443
|
+
onPieceChange?.(square, 0, algebraicOf2(square));
|
|
444
|
+
announce(`Piece removed from ${algebraicOf2(square)}`);
|
|
445
|
+
}
|
|
446
|
+
},
|
|
447
|
+
[announce, board, commitBoard, onPieceChange, onSelectPiece]
|
|
448
|
+
);
|
|
449
|
+
const removePieceAt = react.useCallback(
|
|
450
|
+
(square) => {
|
|
451
|
+
const current = board[square] ?? 0;
|
|
452
|
+
if (current === 0) {
|
|
453
|
+
announce(`${algebraicOf2(square)} is empty`);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const nextBoard = new Uint8Array(board);
|
|
457
|
+
nextBoard[square] = 0;
|
|
458
|
+
commitBoard(nextBoard);
|
|
459
|
+
onPieceChange?.(square, 0, algebraicOf2(square));
|
|
460
|
+
announce(`Piece removed from ${algebraicOf2(square)}`);
|
|
461
|
+
},
|
|
462
|
+
[announce, board, commitBoard, onPieceChange]
|
|
463
|
+
);
|
|
464
|
+
const handleKeyDown = react.useCallback(
|
|
465
|
+
(e) => {
|
|
466
|
+
if (e.altKey || e.ctrlKey || e.metaKey) return;
|
|
467
|
+
if (e.key.startsWith("Arrow")) {
|
|
468
|
+
if (e.shiftKey) return;
|
|
469
|
+
e.preventDefault();
|
|
470
|
+
const dir = e.key === "ArrowUp" ? "up" : e.key === "ArrowDown" ? "down" : e.key === "ArrowLeft" ? "left" : "right";
|
|
471
|
+
const next = moveSquare(focusedSquare, dir, orientation);
|
|
472
|
+
setFocusedSquare(next);
|
|
473
|
+
announceSquare(next);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
if (e.key === "Home" || e.key === "End") {
|
|
477
|
+
e.preventDefault();
|
|
478
|
+
const next = rankEndSquare(focusedSquare, e.key === "Home" ? "home" : "end", orientation);
|
|
479
|
+
setFocusedSquare(next);
|
|
480
|
+
announceSquare(next);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
if (e.key === "Backspace" || e.key === "Delete" || e.key === "x" || e.key === "X") {
|
|
484
|
+
e.preventDefault();
|
|
485
|
+
removePieceAt(focusedSquare);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
if (e.key === "c" || e.key === "C") {
|
|
489
|
+
e.preventDefault();
|
|
490
|
+
if (onClear) {
|
|
491
|
+
onClear();
|
|
492
|
+
} else {
|
|
493
|
+
commitBoard(new Uint8Array(64));
|
|
494
|
+
announce("Board cleared");
|
|
495
|
+
}
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (e.key === "s" || e.key === "S") {
|
|
499
|
+
e.preventDefault();
|
|
500
|
+
if (onSetStartingPosition) {
|
|
501
|
+
onSetStartingPosition();
|
|
502
|
+
} else {
|
|
503
|
+
commitBoard(chunkN4WTPXFC_cjs.parseFenPlacement(chunkN4WTPXFC_cjs.STARTING_FEN));
|
|
504
|
+
announce("Starting position");
|
|
505
|
+
}
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (e.key === "t" || e.key === "T") {
|
|
509
|
+
e.preventDefault();
|
|
510
|
+
onToggleSideToMove?.();
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
514
|
+
e.preventDefault();
|
|
515
|
+
if (selectedPiece) {
|
|
516
|
+
const piece = e.shiftKey ? getOppositePieceString(selectedPiece) : selectedPiece;
|
|
517
|
+
if (piece) placePieceAt(focusedSquare, piece);
|
|
518
|
+
}
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
const pieceCell = cellFromKey(e.key);
|
|
522
|
+
if (pieceCell !== 0) {
|
|
523
|
+
e.preventDefault();
|
|
524
|
+
placePieceAt(focusedSquare, pieceCell);
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
[
|
|
528
|
+
announce,
|
|
529
|
+
announceSquare,
|
|
530
|
+
commitBoard,
|
|
531
|
+
focusedSquare,
|
|
532
|
+
onClear,
|
|
533
|
+
onSetStartingPosition,
|
|
534
|
+
onToggleSideToMove,
|
|
535
|
+
orientation,
|
|
536
|
+
placePieceAt,
|
|
537
|
+
removePieceAt,
|
|
538
|
+
selectedPiece
|
|
539
|
+
]
|
|
540
|
+
);
|
|
541
|
+
const handlePointerDown = (e) => {
|
|
542
|
+
if (e.button !== 0) return;
|
|
543
|
+
const container = containerRef.current;
|
|
544
|
+
if (!container) return;
|
|
545
|
+
const sq = getSquareAtPoint(container, e.clientX, e.clientY, orientation);
|
|
546
|
+
if (sq === null) return;
|
|
547
|
+
container.focus();
|
|
548
|
+
setFocusedSquare(sq);
|
|
549
|
+
onSquareFocus?.(sq, board[sq] ?? 0, algebraicOf2(sq));
|
|
550
|
+
const cell = board[sq] ?? 0;
|
|
551
|
+
if (cell === 0) {
|
|
552
|
+
if (selectedPiece) {
|
|
553
|
+
placePieceAt(sq, selectedPiece);
|
|
554
|
+
}
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
558
|
+
setDragging({
|
|
559
|
+
origin: sq,
|
|
560
|
+
cell,
|
|
561
|
+
x: e.clientX,
|
|
562
|
+
y: e.clientY
|
|
563
|
+
});
|
|
564
|
+
};
|
|
565
|
+
const handlePointerMove = (e) => {
|
|
566
|
+
if (!dragging) return;
|
|
567
|
+
setDragging((prev) => prev ? { ...prev, x: e.clientX, y: e.clientY } : null);
|
|
568
|
+
};
|
|
569
|
+
const handlePointerUp = (e) => {
|
|
570
|
+
if (!dragging) return;
|
|
571
|
+
const container = containerRef.current;
|
|
572
|
+
const originSq = dragging.origin;
|
|
573
|
+
const movedCell = dragging.cell;
|
|
574
|
+
setDragging(null);
|
|
575
|
+
if (!container) return;
|
|
576
|
+
const targetSq = getSquareAtPoint(container, e.clientX, e.clientY, orientation);
|
|
577
|
+
if (targetSq === null) {
|
|
578
|
+
removePieceAt(originSq);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (targetSq === originSq) {
|
|
582
|
+
if (selectedPiece) {
|
|
583
|
+
placePieceAt(originSq, selectedPiece);
|
|
584
|
+
}
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const nextBoard = new Uint8Array(board);
|
|
588
|
+
nextBoard[originSq] = 0;
|
|
589
|
+
nextBoard[targetSq] = movedCell;
|
|
590
|
+
commitBoard(nextBoard);
|
|
591
|
+
announce(`${pieceNameFromCell(movedCell)} moved to ${algebraicOf2(targetSq)}`);
|
|
592
|
+
setFocusedSquare(targetSq);
|
|
593
|
+
};
|
|
594
|
+
const handleContextMenu = (e) => {
|
|
595
|
+
e.preventDefault();
|
|
596
|
+
const container = containerRef.current;
|
|
597
|
+
if (!container) return;
|
|
598
|
+
const sq = getSquareAtPoint(container, e.clientX, e.clientY, orientation);
|
|
599
|
+
if (sq === null) return;
|
|
600
|
+
setFocusedSquare(sq);
|
|
601
|
+
if (selectedPiece) {
|
|
602
|
+
const opp = getOppositePieceString(selectedPiece);
|
|
603
|
+
if (opp) placePieceAt(sq, opp);
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
const squareOrder = react.useMemo(() => {
|
|
607
|
+
const squares = [];
|
|
608
|
+
if (orientation === "white") {
|
|
609
|
+
for (let rank = 7; rank >= 0; rank--) {
|
|
610
|
+
for (let file = 0; file < 8; file++) {
|
|
611
|
+
squares.push(rank * 8 + file);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
} else {
|
|
615
|
+
for (let rank = 0; rank < 8; rank++) {
|
|
616
|
+
for (let file = 7; file >= 0; file--) {
|
|
617
|
+
squares.push(rank * 8 + file);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return squares;
|
|
622
|
+
}, [orientation]);
|
|
623
|
+
const containerStyle = {
|
|
624
|
+
position: "relative",
|
|
625
|
+
aspectRatio: "1 / 1",
|
|
626
|
+
width: "100%",
|
|
627
|
+
touchAction: "none",
|
|
628
|
+
outline: hasKeyboardFocus ? "3px solid var(--gb-editor-focus, #d97706)" : "none",
|
|
629
|
+
outlineOffset: "2px",
|
|
630
|
+
borderRadius: "8px",
|
|
631
|
+
...theme,
|
|
632
|
+
...style
|
|
633
|
+
};
|
|
634
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
635
|
+
"div",
|
|
636
|
+
{
|
|
637
|
+
ref: containerRef,
|
|
638
|
+
role: "application",
|
|
639
|
+
tabIndex: 0,
|
|
640
|
+
"aria-label": ariaLabel,
|
|
641
|
+
"aria-keyshortcuts": "ArrowUp ArrowDown ArrowLeft ArrowRight Enter Space Backspace Delete p P n N b B r R q Q k K c C s S t T",
|
|
642
|
+
onKeyDown: handleKeyDown,
|
|
643
|
+
onFocus: (e) => {
|
|
644
|
+
if (e.target === e.currentTarget) {
|
|
645
|
+
setHasKeyboardFocus(true);
|
|
646
|
+
announceSquare(focusedSquare);
|
|
647
|
+
}
|
|
648
|
+
},
|
|
649
|
+
onBlur: () => setHasKeyboardFocus(false),
|
|
650
|
+
onPointerDown: handlePointerDown,
|
|
651
|
+
onPointerMove: handlePointerMove,
|
|
652
|
+
onPointerUp: handlePointerUp,
|
|
653
|
+
onPointerCancel: () => setDragging(null),
|
|
654
|
+
onContextMenu: handleContextMenu,
|
|
655
|
+
className,
|
|
656
|
+
style: containerStyle,
|
|
657
|
+
"data-gb-editor": "true",
|
|
658
|
+
"data-gb-orientation": orientation,
|
|
659
|
+
children: [
|
|
660
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
661
|
+
"div",
|
|
662
|
+
{
|
|
663
|
+
"aria-hidden": "true",
|
|
664
|
+
style: {
|
|
665
|
+
position: "absolute",
|
|
666
|
+
inset: 0,
|
|
667
|
+
display: "grid",
|
|
668
|
+
gridTemplateColumns: "repeat(8, 1fr)",
|
|
669
|
+
gridTemplateRows: "repeat(8, 1fr)",
|
|
670
|
+
pointerEvents: "none"
|
|
671
|
+
},
|
|
672
|
+
children: squareOrder.map((sq) => {
|
|
673
|
+
const file = sq & 7;
|
|
674
|
+
const rank = sq >> 3;
|
|
675
|
+
const isLight = (file + rank & 1) !== 0;
|
|
676
|
+
const isFocused = hasKeyboardFocus && focusedSquare === sq;
|
|
677
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
678
|
+
"div",
|
|
679
|
+
{
|
|
680
|
+
"data-square": algebraicOf2(sq),
|
|
681
|
+
style: {
|
|
682
|
+
position: "relative",
|
|
683
|
+
backgroundColor: `var(${isLight ? chunkN4WTPXFC_cjs.CSS_VARS.SQ_LIGHT : chunkN4WTPXFC_cjs.CSS_VARS.SQ_DARK})`,
|
|
684
|
+
backgroundImage: `var(${isLight ? chunkN4WTPXFC_cjs.CSS_VARS.SQ_LIGHT_IMAGE : chunkN4WTPXFC_cjs.CSS_VARS.SQ_DARK_IMAGE},none)`,
|
|
685
|
+
backgroundSize: `var(${chunkN4WTPXFC_cjs.CSS_VARS.SQ_IMAGE_SIZE},cover)`,
|
|
686
|
+
boxShadow: isFocused ? "inset 0 0 0 3px rgba(255, 206, 76, 0.95)" : void 0,
|
|
687
|
+
userSelect: "none"
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
sq
|
|
691
|
+
);
|
|
692
|
+
})
|
|
693
|
+
}
|
|
694
|
+
),
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
696
|
+
"div",
|
|
697
|
+
{
|
|
698
|
+
"aria-hidden": "true",
|
|
699
|
+
style: {
|
|
700
|
+
position: "absolute",
|
|
701
|
+
inset: 0,
|
|
702
|
+
display: "grid",
|
|
703
|
+
gridTemplateColumns: "repeat(8, 1fr)",
|
|
704
|
+
gridTemplateRows: "repeat(8, 1fr)",
|
|
705
|
+
pointerEvents: "none"
|
|
706
|
+
},
|
|
707
|
+
children: squareOrder.map((sq) => {
|
|
708
|
+
const cell = board[sq] ?? 0;
|
|
709
|
+
if (cell === 0) return null;
|
|
710
|
+
const isOrigin = dragging?.origin === sq;
|
|
711
|
+
const { col, row } = gridCoord(sq, orientation);
|
|
712
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
713
|
+
"div",
|
|
714
|
+
{
|
|
715
|
+
"data-piece-square": algebraicOf2(sq),
|
|
716
|
+
style: {
|
|
717
|
+
...SLOT_BASE_STYLE,
|
|
718
|
+
gridColumnStart: col,
|
|
719
|
+
gridRowStart: row,
|
|
720
|
+
opacity: isOrigin ? 0.25 : 1,
|
|
721
|
+
filter: `var(${cell <= 6 ? chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_WHITE : chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_BLACK}, none)`,
|
|
722
|
+
pointerEvents: "none"
|
|
723
|
+
},
|
|
724
|
+
children: pieces({ cell, square: sq })
|
|
725
|
+
},
|
|
726
|
+
sq
|
|
727
|
+
);
|
|
728
|
+
})
|
|
729
|
+
}
|
|
730
|
+
),
|
|
731
|
+
dragging && containerRef.current ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
732
|
+
"div",
|
|
733
|
+
{
|
|
734
|
+
"aria-hidden": "true",
|
|
735
|
+
style: {
|
|
736
|
+
position: "fixed",
|
|
737
|
+
left: dragging.x - 30,
|
|
738
|
+
top: dragging.y - 30,
|
|
739
|
+
width: 60,
|
|
740
|
+
height: 60,
|
|
741
|
+
pointerEvents: "none",
|
|
742
|
+
zIndex: 100,
|
|
743
|
+
filter: `var(${dragging.cell <= 6 ? chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_WHITE : chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_BLACK}, none)`
|
|
744
|
+
},
|
|
745
|
+
children: pieces({ cell: dragging.cell, square: dragging.origin })
|
|
746
|
+
}
|
|
747
|
+
) : null,
|
|
748
|
+
showCoordinates ? /* @__PURE__ */ jsxRuntime.jsx(Coordinates, { orientation }) : null,
|
|
749
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
750
|
+
"div",
|
|
751
|
+
{
|
|
752
|
+
ref: liveRegionRef,
|
|
753
|
+
role: "status",
|
|
754
|
+
"aria-live": "assertive",
|
|
755
|
+
"aria-atomic": "true",
|
|
756
|
+
style: {
|
|
757
|
+
position: "absolute",
|
|
758
|
+
width: 1,
|
|
759
|
+
height: 1,
|
|
760
|
+
padding: 0,
|
|
761
|
+
margin: -1,
|
|
762
|
+
overflow: "hidden",
|
|
763
|
+
clip: "rect(0, 0, 0, 0)",
|
|
764
|
+
whiteSpace: "nowrap",
|
|
765
|
+
border: 0
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
)
|
|
769
|
+
]
|
|
770
|
+
}
|
|
771
|
+
);
|
|
31
772
|
}
|
|
32
773
|
function squareCentrePct(index, orientation) {
|
|
33
774
|
const file = index & 7;
|
|
@@ -608,7 +1349,7 @@ function injectFocusRingStyles() {
|
|
|
608
1349
|
`;
|
|
609
1350
|
document.head.appendChild(style);
|
|
610
1351
|
}
|
|
611
|
-
function
|
|
1352
|
+
function algebraicOf3(index) {
|
|
612
1353
|
const file = index & 7;
|
|
613
1354
|
const rank = index >> 3;
|
|
614
1355
|
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
@@ -627,7 +1368,7 @@ function SquareImpl({
|
|
|
627
1368
|
const rank = index >> 3;
|
|
628
1369
|
const isLight = (file + rank) % 2 === 1;
|
|
629
1370
|
const cell = useSquareCell(model, index);
|
|
630
|
-
const label = getSquareAriaLabel ? getSquareAriaLabel(index, cell) :
|
|
1371
|
+
const label = getSquareAriaLabel ? getSquareAriaLabel(index, cell) : algebraicOf3(index);
|
|
631
1372
|
const internalRef = react.useRef(null);
|
|
632
1373
|
const lastReportedFocusRef = react.useRef(false);
|
|
633
1374
|
const setRef = react.useCallback(
|
|
@@ -670,7 +1411,7 @@ function SquareImpl({
|
|
|
670
1411
|
"aria-rowindex": rank + 1,
|
|
671
1412
|
"aria-colindex": file + 1,
|
|
672
1413
|
tabIndex: isFocused ? 0 : -1,
|
|
673
|
-
"data-square":
|
|
1414
|
+
"data-square": algebraicOf3(index),
|
|
674
1415
|
"data-gb-square": "",
|
|
675
1416
|
"data-light": isLight ? "true" : "false",
|
|
676
1417
|
onClick: handleClick,
|
|
@@ -680,10 +1421,10 @@ function SquareImpl({
|
|
|
680
1421
|
// `backgroundColor` (not the `background` shorthand) so the
|
|
681
1422
|
// CSS `background-image` set by `useSelectionController` (or pseudo-elements)
|
|
682
1423
|
// can layer on top without clobbering this base colour.
|
|
683
|
-
backgroundColor: `var(${isLight ?
|
|
684
|
-
backgroundImage: `var(${isLight ?
|
|
685
|
-
backgroundSize: `var(${
|
|
686
|
-
backgroundBlendMode: `var(${
|
|
1424
|
+
backgroundColor: `var(${isLight ? chunkN4WTPXFC_cjs.CSS_VARS.SQ_LIGHT : chunkN4WTPXFC_cjs.CSS_VARS.SQ_DARK})`,
|
|
1425
|
+
backgroundImage: `var(${isLight ? chunkN4WTPXFC_cjs.CSS_VARS.SQ_LIGHT_IMAGE : chunkN4WTPXFC_cjs.CSS_VARS.SQ_DARK_IMAGE},none)`,
|
|
1426
|
+
backgroundSize: `var(${chunkN4WTPXFC_cjs.CSS_VARS.SQ_IMAGE_SIZE},cover)`,
|
|
1427
|
+
backgroundBlendMode: `var(${chunkN4WTPXFC_cjs.CSS_VARS.SQ_BLEND_MODE},normal)`,
|
|
687
1428
|
// Cursor is managed by `useCursorController` via injected CSS so
|
|
688
1429
|
// it can flip between `pointer` / `grab` / `grabbing` without a
|
|
689
1430
|
// React re-render per hover.
|
|
@@ -801,71 +1542,13 @@ function CheckLayerInner({ model, orientation }) {
|
|
|
801
1542
|
top: `${y}%`,
|
|
802
1543
|
width: "12.5%",
|
|
803
1544
|
height: "12.5%",
|
|
804
|
-
background: `var(${
|
|
1545
|
+
background: `var(${chunkN4WTPXFC_cjs.CSS_VARS.CHECK})`,
|
|
805
1546
|
pointerEvents: "none",
|
|
806
1547
|
zIndex: 2
|
|
807
1548
|
}
|
|
808
1549
|
}
|
|
809
1550
|
);
|
|
810
1551
|
}
|
|
811
|
-
var FILE_LETTERS = ["a", "b", "c", "d", "e", "f", "g", "h"];
|
|
812
|
-
function Coordinates({ orientation, ranksPosition = "left" }) {
|
|
813
|
-
const ranksOnRight = ranksPosition === "right";
|
|
814
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
815
|
-
"div",
|
|
816
|
-
{
|
|
817
|
-
"aria-hidden": "true",
|
|
818
|
-
style: {
|
|
819
|
-
position: "absolute",
|
|
820
|
-
inset: 0,
|
|
821
|
-
pointerEvents: "none",
|
|
822
|
-
fontSize: "min(1.6vmin, 11px)",
|
|
823
|
-
fontWeight: 600,
|
|
824
|
-
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
825
|
-
},
|
|
826
|
-
children: [
|
|
827
|
-
FILE_LETTERS.map((letter, idx) => {
|
|
828
|
-
const col = orientation === "white" ? idx : 7 - idx;
|
|
829
|
-
const bottomRank = orientation === "white" ? 0 : 7;
|
|
830
|
-
const isLightSquare = (col + bottomRank) % 2 === 1;
|
|
831
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
832
|
-
"span",
|
|
833
|
-
{
|
|
834
|
-
style: {
|
|
835
|
-
position: "absolute",
|
|
836
|
-
left: `${col * 12.5 + 10}%`,
|
|
837
|
-
bottom: "1%",
|
|
838
|
-
color: `var(${isLightSquare ? chunkD45G3J5E_cjs.CSS_VARS.COORDINATE_LIGHT : chunkD45G3J5E_cjs.CSS_VARS.COORDINATE_DARK})`
|
|
839
|
-
},
|
|
840
|
-
children: letter
|
|
841
|
-
},
|
|
842
|
-
`file-${letter}`
|
|
843
|
-
);
|
|
844
|
-
}),
|
|
845
|
-
FILE_LETTERS.map((_, idx) => {
|
|
846
|
-
const rank = idx;
|
|
847
|
-
const row = orientation === "white" ? 7 - rank : rank;
|
|
848
|
-
const edgeFile = ranksOnRight ? orientation === "white" ? 7 : 0 : orientation === "white" ? 0 : 7;
|
|
849
|
-
const isLightSquare = (edgeFile + rank) % 2 === 1;
|
|
850
|
-
const sideStyle = ranksOnRight ? { right: "1%" } : { left: "1%" };
|
|
851
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
852
|
-
"span",
|
|
853
|
-
{
|
|
854
|
-
style: {
|
|
855
|
-
position: "absolute",
|
|
856
|
-
top: `${row * 12.5 + 1}%`,
|
|
857
|
-
...sideStyle,
|
|
858
|
-
color: `var(${isLightSquare ? chunkD45G3J5E_cjs.CSS_VARS.COORDINATE_LIGHT : chunkD45G3J5E_cjs.CSS_VARS.COORDINATE_DARK})`
|
|
859
|
-
},
|
|
860
|
-
children: rank + 1
|
|
861
|
-
},
|
|
862
|
-
`rank-${rank}`
|
|
863
|
-
);
|
|
864
|
-
})
|
|
865
|
-
]
|
|
866
|
-
}
|
|
867
|
-
);
|
|
868
|
-
}
|
|
869
1552
|
var WRAPPER_STYLE = Object.freeze({
|
|
870
1553
|
position: "absolute",
|
|
871
1554
|
top: 0,
|
|
@@ -902,7 +1585,7 @@ var DragLayer = react.forwardRef(function DragLayer2({ pieces }, ref) {
|
|
|
902
1585
|
"data-drag-cell": cell,
|
|
903
1586
|
style: {
|
|
904
1587
|
...SLOT_STYLE,
|
|
905
|
-
filter: `var(${cell <= 6 ?
|
|
1588
|
+
filter: `var(${cell <= 6 ? chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_WHITE : chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_BLACK}, none)`
|
|
906
1589
|
},
|
|
907
1590
|
children: child
|
|
908
1591
|
},
|
|
@@ -1000,7 +1683,7 @@ function IllegalFlashLayer({ at, orientation }) {
|
|
|
1000
1683
|
top: `${y}%`,
|
|
1001
1684
|
width: "12.5%",
|
|
1002
1685
|
height: "12.5%",
|
|
1003
|
-
background:
|
|
1686
|
+
background: chunkN4WTPXFC_cjs.DEFAULT_ILLEGAL_FLASH_TINT,
|
|
1004
1687
|
opacity: 0,
|
|
1005
1688
|
pointerEvents: "none",
|
|
1006
1689
|
zIndex: 5
|
|
@@ -1008,7 +1691,7 @@ function IllegalFlashLayer({ at, orientation }) {
|
|
|
1008
1691
|
}
|
|
1009
1692
|
);
|
|
1010
1693
|
}
|
|
1011
|
-
function
|
|
1694
|
+
function algebraicOf4(index) {
|
|
1012
1695
|
const file = index & 7;
|
|
1013
1696
|
const rank = index >> 3;
|
|
1014
1697
|
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
@@ -1035,15 +1718,16 @@ function pieceName(cell) {
|
|
|
1035
1718
|
}
|
|
1036
1719
|
}
|
|
1037
1720
|
function announcementFor(lastMove, board, wasCapture) {
|
|
1038
|
-
const { from, to, kind, promotion } =
|
|
1721
|
+
const { from, to, kind, promotion } = chunkFUP2LDMO_cjs.decodePackedMove(lastMove);
|
|
1722
|
+
if (kind === "pass") return "Passes.";
|
|
1039
1723
|
if (kind === "castle") {
|
|
1040
1724
|
const isKingside = (to & 7) > (from & 7);
|
|
1041
1725
|
return isKingside ? "Castles kingside." : "Castles queenside.";
|
|
1042
1726
|
}
|
|
1043
1727
|
const landed = board[to] ?? 0;
|
|
1044
1728
|
const name = pieceName(landed);
|
|
1045
|
-
const fromSq =
|
|
1046
|
-
const toSq =
|
|
1729
|
+
const fromSq = algebraicOf4(from);
|
|
1730
|
+
const toSq = algebraicOf4(to);
|
|
1047
1731
|
if (kind === "promotion" && promotion !== null) {
|
|
1048
1732
|
const promoted = promotion === 1 ? "knight" : promotion === 2 ? "bishop" : promotion === 3 ? "rook" : "queen";
|
|
1049
1733
|
const action = wasCapture ? "captures and promotes" : "promotes";
|
|
@@ -1092,76 +1776,6 @@ function LiveRegion({ model }) {
|
|
|
1092
1776
|
}
|
|
1093
1777
|
);
|
|
1094
1778
|
}
|
|
1095
|
-
function gridCoord(index, orientation) {
|
|
1096
|
-
const file = index & 7;
|
|
1097
|
-
const rank = index >> 3;
|
|
1098
|
-
const col = orientation === "white" ? file + 1 : 8 - file;
|
|
1099
|
-
const row = orientation === "white" ? 8 - rank : rank + 1;
|
|
1100
|
-
return { col, row };
|
|
1101
|
-
}
|
|
1102
|
-
function algebraicOf3(index) {
|
|
1103
|
-
const file = index & 7;
|
|
1104
|
-
const rank = index >> 3;
|
|
1105
|
-
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
1106
|
-
}
|
|
1107
|
-
var SLOT_BASE_STYLE = Object.freeze({
|
|
1108
|
-
display: "flex",
|
|
1109
|
-
alignItems: "center",
|
|
1110
|
-
justifyContent: "center",
|
|
1111
|
-
pointerEvents: "none",
|
|
1112
|
-
containerType: "size"
|
|
1113
|
-
});
|
|
1114
|
-
function PieceSlotImpl({ index, model, orientation, pieces }) {
|
|
1115
|
-
const cell = useSquareCell(model, index);
|
|
1116
|
-
if (cell === 0) return null;
|
|
1117
|
-
const { col, row } = gridCoord(index, orientation);
|
|
1118
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1119
|
-
"div",
|
|
1120
|
-
{
|
|
1121
|
-
"data-piece-square": algebraicOf3(index),
|
|
1122
|
-
"data-piece-cell": cell,
|
|
1123
|
-
style: {
|
|
1124
|
-
...SLOT_BASE_STYLE,
|
|
1125
|
-
gridColumnStart: col,
|
|
1126
|
-
gridRowStart: row,
|
|
1127
|
-
filter: `var(${cell <= 6 ? chunkD45G3J5E_cjs.CSS_VARS.PIECE_FILTER_WHITE : chunkD45G3J5E_cjs.CSS_VARS.PIECE_FILTER_BLACK}, none)`
|
|
1128
|
-
},
|
|
1129
|
-
children: pieces({ cell, square: index })
|
|
1130
|
-
}
|
|
1131
|
-
);
|
|
1132
|
-
}
|
|
1133
|
-
var PieceSlot = react.memo(PieceSlotImpl);
|
|
1134
|
-
PieceSlot.displayName = "PieceSlot";
|
|
1135
|
-
var CONTAINER_STYLE = Object.freeze({
|
|
1136
|
-
position: "absolute",
|
|
1137
|
-
inset: 0,
|
|
1138
|
-
display: "grid",
|
|
1139
|
-
gridTemplateColumns: "repeat(8, 1fr)",
|
|
1140
|
-
gridTemplateRows: "repeat(8, 1fr)",
|
|
1141
|
-
pointerEvents: "none"
|
|
1142
|
-
});
|
|
1143
|
-
var PieceLayer = react.memo(function PieceLayer2({
|
|
1144
|
-
model,
|
|
1145
|
-
orientation,
|
|
1146
|
-
pieces
|
|
1147
|
-
}) {
|
|
1148
|
-
const slots = [];
|
|
1149
|
-
for (let i = 0; i < 64; i++) {
|
|
1150
|
-
slots.push(
|
|
1151
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1152
|
-
PieceSlot,
|
|
1153
|
-
{
|
|
1154
|
-
index: i,
|
|
1155
|
-
model,
|
|
1156
|
-
orientation,
|
|
1157
|
-
pieces
|
|
1158
|
-
},
|
|
1159
|
-
i
|
|
1160
|
-
)
|
|
1161
|
-
);
|
|
1162
|
-
}
|
|
1163
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: CONTAINER_STYLE, children: slots });
|
|
1164
|
-
});
|
|
1165
1779
|
function positionOf3(index, orientation) {
|
|
1166
1780
|
const file = index & 7;
|
|
1167
1781
|
const rank = index >> 3;
|
|
@@ -1211,7 +1825,7 @@ function PremoveLayerInner({ model, orientation, pieces, from, to }) {
|
|
|
1211
1825
|
top: `${origin.y}%`,
|
|
1212
1826
|
width: "12.5%",
|
|
1213
1827
|
height: "12.5%",
|
|
1214
|
-
background:
|
|
1828
|
+
background: chunkN4WTPXFC_cjs.DEFAULT_PREMOVE_TINT,
|
|
1215
1829
|
opacity: 0.5
|
|
1216
1830
|
}
|
|
1217
1831
|
}
|
|
@@ -1225,7 +1839,7 @@ function PremoveLayerInner({ model, orientation, pieces, from, to }) {
|
|
|
1225
1839
|
top: `${target.y}%`,
|
|
1226
1840
|
width: "12.5%",
|
|
1227
1841
|
height: "12.5%",
|
|
1228
|
-
background:
|
|
1842
|
+
background: chunkN4WTPXFC_cjs.DEFAULT_PREMOVE_TINT
|
|
1229
1843
|
}
|
|
1230
1844
|
}
|
|
1231
1845
|
),
|
|
@@ -1260,20 +1874,20 @@ function positionOf4(index, orientation) {
|
|
|
1260
1874
|
return { x: col * 12.5, y: row * 12.5 };
|
|
1261
1875
|
}
|
|
1262
1876
|
var CHOICE_ORDER = [
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1877
|
+
chunkFUP2LDMO_cjs.PieceType.Queen,
|
|
1878
|
+
chunkFUP2LDMO_cjs.PieceType.Knight,
|
|
1879
|
+
chunkFUP2LDMO_cjs.PieceType.Rook,
|
|
1880
|
+
chunkFUP2LDMO_cjs.PieceType.Bishop
|
|
1267
1881
|
];
|
|
1268
1882
|
var SHORTCUTS = {
|
|
1269
|
-
q:
|
|
1270
|
-
r:
|
|
1271
|
-
b:
|
|
1272
|
-
n:
|
|
1273
|
-
Q:
|
|
1274
|
-
R:
|
|
1275
|
-
B:
|
|
1276
|
-
N:
|
|
1883
|
+
q: chunkFUP2LDMO_cjs.PieceType.Queen,
|
|
1884
|
+
r: chunkFUP2LDMO_cjs.PieceType.Rook,
|
|
1885
|
+
b: chunkFUP2LDMO_cjs.PieceType.Bishop,
|
|
1886
|
+
n: chunkFUP2LDMO_cjs.PieceType.Knight,
|
|
1887
|
+
Q: chunkFUP2LDMO_cjs.PieceType.Queen,
|
|
1888
|
+
R: chunkFUP2LDMO_cjs.PieceType.Rook,
|
|
1889
|
+
B: chunkFUP2LDMO_cjs.PieceType.Bishop,
|
|
1890
|
+
N: chunkFUP2LDMO_cjs.PieceType.Knight
|
|
1277
1891
|
};
|
|
1278
1892
|
function PromotionOverlay({
|
|
1279
1893
|
from: _from,
|
|
@@ -1291,7 +1905,7 @@ function PromotionOverlay({
|
|
|
1291
1905
|
[getPromotionPieceAriaLabel, color]
|
|
1292
1906
|
);
|
|
1293
1907
|
const [activeAnnouncement, setActiveAnnouncement] = react.useState(
|
|
1294
|
-
() => getLabel(CHOICE_ORDER[0] ??
|
|
1908
|
+
() => getLabel(CHOICE_ORDER[0] ?? chunkFUP2LDMO_cjs.PieceType.Queen)
|
|
1295
1909
|
);
|
|
1296
1910
|
react.useEffect(() => {
|
|
1297
1911
|
buttonRefs.current[0]?.focus();
|
|
@@ -1373,7 +1987,7 @@ function PromotionOverlay({
|
|
|
1373
1987
|
{
|
|
1374
1988
|
role: "dialog",
|
|
1375
1989
|
"aria-modal": "true",
|
|
1376
|
-
"aria-label": `Choose promotion piece at ${
|
|
1990
|
+
"aria-label": `Choose promotion piece at ${algebraicOf5(to)}`,
|
|
1377
1991
|
onClick: (e) => e.stopPropagation(),
|
|
1378
1992
|
style: {
|
|
1379
1993
|
position: "absolute",
|
|
@@ -1389,7 +2003,7 @@ function PromotionOverlay({
|
|
|
1389
2003
|
overflow: "hidden"
|
|
1390
2004
|
},
|
|
1391
2005
|
children: CHOICE_ORDER.map((piece, index) => {
|
|
1392
|
-
const cell =
|
|
2006
|
+
const cell = chunkFUP2LDMO_cjs.encodeBoardCell(color, piece);
|
|
1393
2007
|
const label = getLabel(piece);
|
|
1394
2008
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1395
2009
|
"button",
|
|
@@ -1441,19 +2055,19 @@ var srOnlyStyle2 = {
|
|
|
1441
2055
|
};
|
|
1442
2056
|
function pieceName2(t) {
|
|
1443
2057
|
switch (t) {
|
|
1444
|
-
case
|
|
2058
|
+
case chunkFUP2LDMO_cjs.PieceType.Queen:
|
|
1445
2059
|
return "Queen";
|
|
1446
|
-
case
|
|
2060
|
+
case chunkFUP2LDMO_cjs.PieceType.Rook:
|
|
1447
2061
|
return "Rook";
|
|
1448
|
-
case
|
|
2062
|
+
case chunkFUP2LDMO_cjs.PieceType.Bishop:
|
|
1449
2063
|
return "Bishop";
|
|
1450
|
-
case
|
|
2064
|
+
case chunkFUP2LDMO_cjs.PieceType.Knight:
|
|
1451
2065
|
return "Knight";
|
|
1452
2066
|
default:
|
|
1453
2067
|
return "Piece";
|
|
1454
2068
|
}
|
|
1455
2069
|
}
|
|
1456
|
-
function
|
|
2070
|
+
function algebraicOf5(index) {
|
|
1457
2071
|
const file = index & 7;
|
|
1458
2072
|
const rank = index >> 3;
|
|
1459
2073
|
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
@@ -1469,13 +2083,13 @@ function StaticPieceLayer({ board, orientation, pieces }) {
|
|
|
1469
2083
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1470
2084
|
"div",
|
|
1471
2085
|
{
|
|
1472
|
-
"data-piece-square":
|
|
2086
|
+
"data-piece-square": algebraicOf(index),
|
|
1473
2087
|
"data-piece-cell": cell,
|
|
1474
2088
|
style: {
|
|
1475
2089
|
...SLOT_BASE_STYLE,
|
|
1476
2090
|
gridColumnStart: col,
|
|
1477
2091
|
gridRowStart: row,
|
|
1478
|
-
filter: `var(${cell <= 6 ?
|
|
2092
|
+
filter: `var(${cell <= 6 ? chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_WHITE : chunkN4WTPXFC_cjs.CSS_VARS.PIECE_FILTER_BLACK}, none)`
|
|
1479
2093
|
},
|
|
1480
2094
|
children: pieces({ cell, square: index })
|
|
1481
2095
|
},
|
|
@@ -1487,7 +2101,7 @@ function StaticPieceLayer({ board, orientation, pieces }) {
|
|
|
1487
2101
|
}
|
|
1488
2102
|
var DEFAULT_DURATION_MS = 60;
|
|
1489
2103
|
var DEFAULT_EASING = "cubic-bezier(0.22, 0.61, 0.36, 1)";
|
|
1490
|
-
function
|
|
2104
|
+
function algebraicOf6(index) {
|
|
1491
2105
|
const file = index & 7;
|
|
1492
2106
|
const rank = index >> 3;
|
|
1493
2107
|
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
@@ -1535,7 +2149,7 @@ function runAnimations(descriptors, container, orientation, duration, easing) {
|
|
|
1535
2149
|
case "en-passant":
|
|
1536
2150
|
case "promotion": {
|
|
1537
2151
|
const toEl = container.querySelector(
|
|
1538
|
-
`[data-piece-square="${
|
|
2152
|
+
`[data-piece-square="${algebraicOf6(d.to)}"]`
|
|
1539
2153
|
);
|
|
1540
2154
|
if (toEl === null) break;
|
|
1541
2155
|
const { dx, dy } = deltaFromTo(d.from, d.to, sqSize, orientation);
|
|
@@ -1544,10 +2158,10 @@ function runAnimations(descriptors, container, orientation, duration, easing) {
|
|
|
1544
2158
|
}
|
|
1545
2159
|
case "castle": {
|
|
1546
2160
|
const kingEl = container.querySelector(
|
|
1547
|
-
`[data-piece-square="${
|
|
2161
|
+
`[data-piece-square="${algebraicOf6(d.kingTo)}"]`
|
|
1548
2162
|
);
|
|
1549
2163
|
const rookEl = container.querySelector(
|
|
1550
|
-
`[data-piece-square="${
|
|
2164
|
+
`[data-piece-square="${algebraicOf6(d.rookTo)}"]`
|
|
1551
2165
|
);
|
|
1552
2166
|
if (kingEl !== null) {
|
|
1553
2167
|
const { dx, dy } = deltaFromTo(d.kingFrom, d.kingTo, sqSize, orientation);
|
|
@@ -1591,39 +2205,6 @@ function AnimationRunner({
|
|
|
1591
2205
|
}, [historyPly, model, containerRef, orientation, duration, easing, skipNextRef]);
|
|
1592
2206
|
return null;
|
|
1593
2207
|
}
|
|
1594
|
-
|
|
1595
|
-
// src/lib/geometry.ts
|
|
1596
|
-
function getSquareAtPoint(container, clientX, clientY, orientation) {
|
|
1597
|
-
const rect = container.getBoundingClientRect();
|
|
1598
|
-
const relX = clientX - rect.left;
|
|
1599
|
-
const relY = clientY - rect.top;
|
|
1600
|
-
if (relX < 0 || relY < 0 || relX >= rect.width || relY >= rect.height) return null;
|
|
1601
|
-
const col = Math.floor(relX / rect.width * 8);
|
|
1602
|
-
const row = Math.floor(relY / rect.height * 8);
|
|
1603
|
-
const file = orientation === "white" ? col : 7 - col;
|
|
1604
|
-
const rank = orientation === "white" ? 7 - row : row;
|
|
1605
|
-
return rank * 8 + file;
|
|
1606
|
-
}
|
|
1607
|
-
function getPointAtSquareCentre(container, square, orientation) {
|
|
1608
|
-
const rect = container.getBoundingClientRect();
|
|
1609
|
-
const sqW = rect.width / 8;
|
|
1610
|
-
const sqH = rect.height / 8;
|
|
1611
|
-
const file = square & 7;
|
|
1612
|
-
const rank = square >> 3;
|
|
1613
|
-
const col = orientation === "white" ? file : 7 - file;
|
|
1614
|
-
const row = orientation === "white" ? 7 - rank : rank;
|
|
1615
|
-
return {
|
|
1616
|
-
x: rect.left + sqW * col + sqW / 2,
|
|
1617
|
-
y: rect.top + sqH * row + sqH / 2
|
|
1618
|
-
};
|
|
1619
|
-
}
|
|
1620
|
-
function algebraicOf6(square) {
|
|
1621
|
-
const file = square & 7;
|
|
1622
|
-
const rank = square >> 3;
|
|
1623
|
-
return `${String.fromCharCode(97 + file)}${rank + 1}`;
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
// src/hooks/use-arrow-gesture.ts
|
|
1627
2208
|
function colorForModifiers(e, palette) {
|
|
1628
2209
|
if (e.shiftKey) return palette.shift;
|
|
1629
2210
|
if (e.altKey) return palette.alt;
|
|
@@ -1727,7 +2308,7 @@ function useArrowGesture(options) {
|
|
|
1727
2308
|
function wouldPromote(fromCell, toIndex) {
|
|
1728
2309
|
if (fromCell === 0) return false;
|
|
1729
2310
|
const pieceType = (fromCell - 1) % 6;
|
|
1730
|
-
if (pieceType !==
|
|
2311
|
+
if (pieceType !== chunkFUP2LDMO_cjs.PieceType.Pawn) return false;
|
|
1731
2312
|
const toRank = toIndex >> 3;
|
|
1732
2313
|
return toRank === 0 || toRank === 7;
|
|
1733
2314
|
}
|
|
@@ -1738,7 +2319,7 @@ function useClickToMove(model, onMove, onPromotionNeeded, enabled = true) {
|
|
|
1738
2319
|
if (model === null) return;
|
|
1739
2320
|
const snap = model.getSnapshot();
|
|
1740
2321
|
const cell = snap.board[index] ?? 0;
|
|
1741
|
-
const pieceColour = cell === 0 ? -1 : cell > 6 ?
|
|
2322
|
+
const pieceColour = cell === 0 ? -1 : cell > 6 ? chunkFUP2LDMO_cjs.Color.Black : chunkFUP2LDMO_cjs.Color.White;
|
|
1742
2323
|
if (snap.selected === null) {
|
|
1743
2324
|
if (pieceColour === snap.turn) model.selectSquare(index);
|
|
1744
2325
|
return;
|
|
@@ -1754,7 +2335,7 @@ function useClickToMove(model, onMove, onPromotionNeeded, enabled = true) {
|
|
|
1754
2335
|
onPromotionNeeded(snap.selected, index);
|
|
1755
2336
|
return;
|
|
1756
2337
|
}
|
|
1757
|
-
const played2 = model.tryMove(snap.selected, index,
|
|
2338
|
+
const played2 = model.tryMove(snap.selected, index, chunkFUP2LDMO_cjs.PieceType.Queen);
|
|
1758
2339
|
if (played2 !== null && onMove !== void 0) onMove(played2);
|
|
1759
2340
|
return;
|
|
1760
2341
|
}
|
|
@@ -1866,7 +2447,7 @@ function useCursorController(model, containerRef, allowDrag, allowPremove) {
|
|
|
1866
2447
|
};
|
|
1867
2448
|
}, [model, containerRef, allowDrag, allowPremove]);
|
|
1868
2449
|
}
|
|
1869
|
-
var GHOST_OPACITY_VAR =
|
|
2450
|
+
var GHOST_OPACITY_VAR = chunkN4WTPXFC_cjs.CSS_VARS.DRAG_GHOST_OPACITY;
|
|
1870
2451
|
function useDrag(options) {
|
|
1871
2452
|
const {
|
|
1872
2453
|
game,
|
|
@@ -1888,7 +2469,7 @@ function useDrag(options) {
|
|
|
1888
2469
|
if (!enabled) return;
|
|
1889
2470
|
const container = containerRef.current;
|
|
1890
2471
|
if (container === null || game === null) return;
|
|
1891
|
-
const controller =
|
|
2472
|
+
const controller = chunkFUP2LDMO_cjs.createDragController(
|
|
1892
2473
|
activationDistance === void 0 ? {} : { activationDistance }
|
|
1893
2474
|
);
|
|
1894
2475
|
let originEl = null;
|
|
@@ -1938,7 +2519,7 @@ function useDrag(options) {
|
|
|
1938
2519
|
controller.cancel();
|
|
1939
2520
|
return;
|
|
1940
2521
|
}
|
|
1941
|
-
const originLabel =
|
|
2522
|
+
const originLabel = algebraicOf2(evt.from);
|
|
1942
2523
|
originEl = container.querySelector(`[data-piece-square="${originLabel}"]`);
|
|
1943
2524
|
if (originEl !== null) {
|
|
1944
2525
|
originEl.style.opacity = `var(${GHOST_OPACITY_VAR}, 0.35)`;
|
|
@@ -2187,7 +2768,7 @@ function useLastMoveController(model, squareRefs, enabled) {
|
|
|
2187
2768
|
const lastMove = snap.lastMove;
|
|
2188
2769
|
let from = null;
|
|
2189
2770
|
let to = null;
|
|
2190
|
-
if (lastMove !== null) {
|
|
2771
|
+
if (lastMove !== null && !chunkFUP2LDMO_cjs.isNullMove(lastMove)) {
|
|
2191
2772
|
from = lastMove & 63;
|
|
2192
2773
|
to = lastMove >> 6 & 63;
|
|
2193
2774
|
}
|
|
@@ -2597,6 +3178,9 @@ var ILLEGAL_FLASH_HOLD_MS = 320;
|
|
|
2597
3178
|
var DEFAULT_POSITION_SYNC_DURATION_MS = 60;
|
|
2598
3179
|
var DEFAULT_POSITION_SYNC_EASING = "cubic-bezier(0.22, 0.61, 0.36, 1)";
|
|
2599
3180
|
var UCI_TRANSITION_RE = /^([a-h][1-8])([a-h][1-8])([nbrq])?$/i;
|
|
3181
|
+
function isNullTransition(transition) {
|
|
3182
|
+
return chunkFUP2LDMO_cjs.isNullMoveUci(transition.uci);
|
|
3183
|
+
}
|
|
2600
3184
|
function prefersReducedMotion3() {
|
|
2601
3185
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
2602
3186
|
return false;
|
|
@@ -2644,6 +3228,7 @@ function castleRookTransition(from, to) {
|
|
|
2644
3228
|
};
|
|
2645
3229
|
}
|
|
2646
3230
|
function transitionSquares(transition) {
|
|
3231
|
+
if (isNullTransition(transition)) return [];
|
|
2647
3232
|
const parsed = UCI_TRANSITION_RE.exec(transition.uci.trim().toLowerCase());
|
|
2648
3233
|
if (parsed === null) return [];
|
|
2649
3234
|
const moveFrom = parsed[1] ?? "";
|
|
@@ -2654,6 +3239,7 @@ function transitionSquares(transition) {
|
|
|
2654
3239
|
return transition.direction === "forward" ? forward : forward.map((item) => ({ from: item.to, to: item.from }));
|
|
2655
3240
|
}
|
|
2656
3241
|
function parseTransitionMove(transition) {
|
|
3242
|
+
if (isNullTransition(transition)) return null;
|
|
2657
3243
|
const parsed = UCI_TRANSITION_RE.exec(transition.uci.trim().toLowerCase());
|
|
2658
3244
|
if (parsed === null) return null;
|
|
2659
3245
|
const from = parsed[1];
|
|
@@ -2666,7 +3252,7 @@ function parseTransitionMove(transition) {
|
|
|
2666
3252
|
};
|
|
2667
3253
|
}
|
|
2668
3254
|
function isPawn(cell) {
|
|
2669
|
-
return !
|
|
3255
|
+
return !chunkFUP2LDMO_cjs.isEmptyCell(cell) && chunkFUP2LDMO_cjs.pieceTypeOf(cell) === 0;
|
|
2670
3256
|
}
|
|
2671
3257
|
function controlledFeedbackDescriptors(transition, previousBoard, nextBoard) {
|
|
2672
3258
|
if (transition === null || transition === void 0) return null;
|
|
@@ -2675,25 +3261,25 @@ function controlledFeedbackDescriptors(transition, previousBoard, nextBoard) {
|
|
|
2675
3261
|
const before = transition.direction === "forward" ? previousBoard : nextBoard;
|
|
2676
3262
|
const after = transition.direction === "forward" ? nextBoard : previousBoard;
|
|
2677
3263
|
const movingPiece = before[parsed.from] ?? 0;
|
|
2678
|
-
if (
|
|
3264
|
+
if (chunkFUP2LDMO_cjs.isEmptyCell(movingPiece)) return null;
|
|
2679
3265
|
const fromFile = parsed.from & 7;
|
|
2680
3266
|
const toFile = parsed.to & 7;
|
|
2681
3267
|
const targetBefore = before[parsed.to] ?? 0;
|
|
2682
3268
|
const targetAfter = after[parsed.to] ?? 0;
|
|
2683
|
-
if (
|
|
3269
|
+
if (chunkFUP2LDMO_cjs.pieceTypeOf(movingPiece) === 5 && Math.abs(toFile - fromFile) === 2) {
|
|
2684
3270
|
return [{ kind: "castle" }];
|
|
2685
3271
|
}
|
|
2686
|
-
if (parsed.promotion !== null || isPawn(movingPiece) && (parsed.to >> 3 === 0 || parsed.to >> 3 === 7) && !
|
|
3272
|
+
if (parsed.promotion !== null || isPawn(movingPiece) && (parsed.to >> 3 === 0 || parsed.to >> 3 === 7) && !chunkFUP2LDMO_cjs.isEmptyCell(targetAfter) && chunkFUP2LDMO_cjs.pieceTypeOf(targetAfter) !== 0) {
|
|
2687
3273
|
return [{ kind: "promotion" }];
|
|
2688
3274
|
}
|
|
2689
|
-
if (!
|
|
3275
|
+
if (!chunkFUP2LDMO_cjs.isEmptyCell(targetBefore) && chunkFUP2LDMO_cjs.colorOf(targetBefore) !== chunkFUP2LDMO_cjs.colorOf(movingPiece)) {
|
|
2690
3276
|
return [{ kind: "capture" }];
|
|
2691
3277
|
}
|
|
2692
|
-
if (isPawn(movingPiece) && fromFile !== toFile &&
|
|
3278
|
+
if (isPawn(movingPiece) && fromFile !== toFile && chunkFUP2LDMO_cjs.isEmptyCell(targetBefore)) {
|
|
2693
3279
|
const capturedSquare = parsed.from & -8 | toFile;
|
|
2694
3280
|
const capturedBefore = before[capturedSquare] ?? 0;
|
|
2695
3281
|
const capturedAfter = after[capturedSquare] ?? 0;
|
|
2696
|
-
if (!
|
|
3282
|
+
if (!chunkFUP2LDMO_cjs.isEmptyCell(capturedBefore) && chunkFUP2LDMO_cjs.colorOf(capturedBefore) !== chunkFUP2LDMO_cjs.colorOf(movingPiece) && chunkFUP2LDMO_cjs.isEmptyCell(capturedAfter)) {
|
|
2697
3283
|
return [{ kind: "en-passant" }];
|
|
2698
3284
|
}
|
|
2699
3285
|
}
|
|
@@ -2761,8 +3347,8 @@ function Chessboard(props) {
|
|
|
2761
3347
|
managedArrows,
|
|
2762
3348
|
preserveUserArrowsOnPositionSync,
|
|
2763
3349
|
orientation = "white",
|
|
2764
|
-
theme =
|
|
2765
|
-
pieces =
|
|
3350
|
+
theme = chunkN4WTPXFC_cjs.defaultTheme,
|
|
3351
|
+
pieces = chunkN4WTPXFC_cjs.defaultPieces,
|
|
2766
3352
|
showCoordinates = true,
|
|
2767
3353
|
ranksPosition = "left",
|
|
2768
3354
|
showLegalTargets = "rings",
|
|
@@ -2801,7 +3387,7 @@ function Chessboard(props) {
|
|
|
2801
3387
|
const fallbackBoard = react.useMemo(() => {
|
|
2802
3388
|
if (fallbackFen === void 0 || fallbackFen === "") return null;
|
|
2803
3389
|
try {
|
|
2804
|
-
return
|
|
3390
|
+
return chunkN4WTPXFC_cjs.parseFenPlacement(fallbackFen);
|
|
2805
3391
|
} catch {
|
|
2806
3392
|
return null;
|
|
2807
3393
|
}
|
|
@@ -2879,10 +3465,10 @@ function Chessboard(props) {
|
|
|
2879
3465
|
]);
|
|
2880
3466
|
const palette = react.useMemo(() => {
|
|
2881
3467
|
const merged = {
|
|
2882
|
-
default:
|
|
2883
|
-
shift:
|
|
2884
|
-
alt:
|
|
2885
|
-
ctrl:
|
|
3468
|
+
default: chunkN4WTPXFC_cjs.defaultArrowColors.default,
|
|
3469
|
+
shift: chunkN4WTPXFC_cjs.defaultArrowColors.shift,
|
|
3470
|
+
alt: chunkN4WTPXFC_cjs.defaultArrowColors.alt,
|
|
3471
|
+
ctrl: chunkN4WTPXFC_cjs.defaultArrowColors.ctrl
|
|
2886
3472
|
};
|
|
2887
3473
|
if (arrowColors !== void 0) {
|
|
2888
3474
|
for (const k in arrowColors) {
|
|
@@ -3200,15 +3786,15 @@ function useChessGame(options = {}) {
|
|
|
3200
3786
|
const { fen, ...modelOptions } = options;
|
|
3201
3787
|
const [initialModelOptions] = react.useState(() => modelOptions);
|
|
3202
3788
|
const [model, setModel] = react.useState(() => {
|
|
3203
|
-
const adapter =
|
|
3204
|
-
return
|
|
3789
|
+
const adapter = chunkFUP2LDMO_cjs.createGigachessAdapter(fen);
|
|
3790
|
+
return chunkFUP2LDMO_cjs.createBoardModel(adapter, modelOptions);
|
|
3205
3791
|
});
|
|
3206
3792
|
const prevFenRef = react.useRef(fen);
|
|
3207
3793
|
react.useEffect(() => {
|
|
3208
3794
|
if (prevFenRef.current !== fen) {
|
|
3209
3795
|
prevFenRef.current = fen;
|
|
3210
|
-
const adapter =
|
|
3211
|
-
const nextModel =
|
|
3796
|
+
const adapter = chunkFUP2LDMO_cjs.createGigachessAdapter(fen);
|
|
3797
|
+
const nextModel = chunkFUP2LDMO_cjs.createBoardModel(adapter, initialModelOptions);
|
|
3212
3798
|
setModel((prev) => {
|
|
3213
3799
|
prev.dispose();
|
|
3214
3800
|
return nextModel;
|
|
@@ -3224,68 +3810,100 @@ function useChessGame(options = {}) {
|
|
|
3224
3810
|
}
|
|
3225
3811
|
|
|
3226
3812
|
// src/index.ts
|
|
3227
|
-
var PACKAGE_VERSION = "1.
|
|
3813
|
+
var PACKAGE_VERSION = "1.5.0";
|
|
3228
3814
|
|
|
3229
3815
|
Object.defineProperty(exports, "Color", {
|
|
3230
3816
|
enumerable: true,
|
|
3231
|
-
get: function () { return
|
|
3817
|
+
get: function () { return chunkFUP2LDMO_cjs.Color; }
|
|
3818
|
+
});
|
|
3819
|
+
Object.defineProperty(exports, "NULL_MOVE_SAN", {
|
|
3820
|
+
enumerable: true,
|
|
3821
|
+
get: function () { return chunkFUP2LDMO_cjs.NULL_MOVE_SAN; }
|
|
3822
|
+
});
|
|
3823
|
+
Object.defineProperty(exports, "NULL_MOVE_SANS", {
|
|
3824
|
+
enumerable: true,
|
|
3825
|
+
get: function () { return chunkFUP2LDMO_cjs.NULL_MOVE_SANS; }
|
|
3826
|
+
});
|
|
3827
|
+
Object.defineProperty(exports, "NULL_MOVE_UCI", {
|
|
3828
|
+
enumerable: true,
|
|
3829
|
+
get: function () { return chunkFUP2LDMO_cjs.NULL_MOVE_UCI; }
|
|
3830
|
+
});
|
|
3831
|
+
Object.defineProperty(exports, "NULL_MOVE_WORD", {
|
|
3832
|
+
enumerable: true,
|
|
3833
|
+
get: function () { return chunkFUP2LDMO_cjs.NULL_MOVE_WORD; }
|
|
3232
3834
|
});
|
|
3233
3835
|
Object.defineProperty(exports, "PieceType", {
|
|
3234
3836
|
enumerable: true,
|
|
3235
|
-
get: function () { return
|
|
3837
|
+
get: function () { return chunkFUP2LDMO_cjs.PieceType; }
|
|
3236
3838
|
});
|
|
3237
3839
|
Object.defineProperty(exports, "createBoardModel", {
|
|
3238
3840
|
enumerable: true,
|
|
3239
|
-
get: function () { return
|
|
3841
|
+
get: function () { return chunkFUP2LDMO_cjs.createBoardModel; }
|
|
3240
3842
|
});
|
|
3241
3843
|
Object.defineProperty(exports, "createGigachessAdapter", {
|
|
3242
3844
|
enumerable: true,
|
|
3243
|
-
get: function () { return
|
|
3845
|
+
get: function () { return chunkFUP2LDMO_cjs.createGigachessAdapter; }
|
|
3846
|
+
});
|
|
3847
|
+
Object.defineProperty(exports, "isNullMove", {
|
|
3848
|
+
enumerable: true,
|
|
3849
|
+
get: function () { return chunkFUP2LDMO_cjs.isNullMove; }
|
|
3850
|
+
});
|
|
3851
|
+
Object.defineProperty(exports, "isNullMoveSan", {
|
|
3852
|
+
enumerable: true,
|
|
3853
|
+
get: function () { return chunkFUP2LDMO_cjs.isNullMoveSan; }
|
|
3854
|
+
});
|
|
3855
|
+
Object.defineProperty(exports, "isNullMoveUci", {
|
|
3856
|
+
enumerable: true,
|
|
3857
|
+
get: function () { return chunkFUP2LDMO_cjs.isNullMoveUci; }
|
|
3244
3858
|
});
|
|
3245
3859
|
Object.defineProperty(exports, "packMove", {
|
|
3246
3860
|
enumerable: true,
|
|
3247
|
-
get: function () { return
|
|
3861
|
+
get: function () { return chunkFUP2LDMO_cjs.packMove; }
|
|
3248
3862
|
});
|
|
3249
3863
|
Object.defineProperty(exports, "preloadGigachessAdapter", {
|
|
3250
3864
|
enumerable: true,
|
|
3251
|
-
get: function () { return
|
|
3865
|
+
get: function () { return chunkFUP2LDMO_cjs.preloadGigachessAdapter; }
|
|
3252
3866
|
});
|
|
3253
3867
|
Object.defineProperty(exports, "unpackMove", {
|
|
3254
3868
|
enumerable: true,
|
|
3255
|
-
get: function () { return
|
|
3869
|
+
get: function () { return chunkFUP2LDMO_cjs.unpackMove; }
|
|
3256
3870
|
});
|
|
3257
3871
|
Object.defineProperty(exports, "CSS_VARS", {
|
|
3258
3872
|
enumerable: true,
|
|
3259
|
-
get: function () { return
|
|
3873
|
+
get: function () { return chunkN4WTPXFC_cjs.CSS_VARS; }
|
|
3260
3874
|
});
|
|
3261
3875
|
Object.defineProperty(exports, "DEFAULT_ILLEGAL_FLASH_TINT", {
|
|
3262
3876
|
enumerable: true,
|
|
3263
|
-
get: function () { return
|
|
3877
|
+
get: function () { return chunkN4WTPXFC_cjs.DEFAULT_ILLEGAL_FLASH_TINT; }
|
|
3264
3878
|
});
|
|
3265
3879
|
Object.defineProperty(exports, "DEFAULT_PREMOVE_TINT", {
|
|
3266
3880
|
enumerable: true,
|
|
3267
|
-
get: function () { return
|
|
3881
|
+
get: function () { return chunkN4WTPXFC_cjs.DEFAULT_PREMOVE_TINT; }
|
|
3268
3882
|
});
|
|
3269
3883
|
Object.defineProperty(exports, "defaultArrowColors", {
|
|
3270
3884
|
enumerable: true,
|
|
3271
|
-
get: function () { return
|
|
3885
|
+
get: function () { return chunkN4WTPXFC_cjs.defaultArrowColors; }
|
|
3272
3886
|
});
|
|
3273
3887
|
Object.defineProperty(exports, "defaultPieces", {
|
|
3274
3888
|
enumerable: true,
|
|
3275
|
-
get: function () { return
|
|
3889
|
+
get: function () { return chunkN4WTPXFC_cjs.defaultPieces; }
|
|
3276
3890
|
});
|
|
3277
3891
|
Object.defineProperty(exports, "defaultTheme", {
|
|
3278
3892
|
enumerable: true,
|
|
3279
|
-
get: function () { return
|
|
3893
|
+
get: function () { return chunkN4WTPXFC_cjs.defaultTheme; }
|
|
3280
3894
|
});
|
|
3281
3895
|
exports.AnimationRunner = AnimationRunner;
|
|
3896
|
+
exports.BoardEditor = BoardEditor;
|
|
3282
3897
|
exports.Chessboard = Chessboard;
|
|
3283
3898
|
exports.DEFAULT_MOVE_HAPTIC_PATTERNS = DEFAULT_MOVE_HAPTIC_PATTERNS;
|
|
3284
3899
|
exports.DEFAULT_MOVE_SOUND_SOURCES = DEFAULT_MOVE_SOUND_SOURCES;
|
|
3285
3900
|
exports.PACKAGE_VERSION = PACKAGE_VERSION;
|
|
3901
|
+
exports.algebraicOf = algebraicOf2;
|
|
3286
3902
|
exports.classifyMoveFeedback = classifyMoveFeedback;
|
|
3903
|
+
exports.formatFenPlacement = formatFenPlacement;
|
|
3287
3904
|
exports.getPointAtSquareCentre = getPointAtSquareCentre;
|
|
3288
3905
|
exports.getSquareAtPoint = getSquareAtPoint;
|
|
3906
|
+
exports.squareOf = squareOf;
|
|
3289
3907
|
exports.triggerHaptic = triggerHaptic;
|
|
3290
3908
|
exports.triggerMoveHaptic = triggerMoveHaptic;
|
|
3291
3909
|
exports.useArrowGesture = useArrowGesture;
|