@lichess-org/pgn-viewer 2.4.7 → 2.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.
Files changed (51) hide show
  1. package/README.md +11 -0
  2. package/demo/frame.html +1 -1
  3. package/demo/index.html +1 -1
  4. package/demo/lichess-pgn-viewer.css +61 -28
  5. package/demo/lichess-pgn-viewer.js +694 -379
  6. package/demo/one.html +6 -6
  7. package/demo/one.js +1 -1
  8. package/dist/interfaces.d.ts +2 -1
  9. package/dist/lichess-pgn-viewer.css +1 -1
  10. package/dist/lichess-pgn-viewer.min.js +4 -4
  11. package/dist/pgnViewer.d.ts +1 -0
  12. package/dist/pgnViewer.js +4 -0
  13. package/dist/pgnViewer.js.map +1 -1
  14. package/dist/translation.d.ts +2 -2
  15. package/dist/translation.js +48 -3
  16. package/dist/translation.js.map +1 -1
  17. package/dist/tsconfig.tsbuildinfo +1 -1
  18. package/dist/view/accessibleBoard.d.ts +3 -0
  19. package/dist/view/accessibleBoard.js +40 -0
  20. package/dist/view/accessibleBoard.js.map +1 -0
  21. package/dist/view/aria.d.ts +10 -0
  22. package/dist/view/aria.js +54 -0
  23. package/dist/view/aria.js.map +1 -0
  24. package/dist/view/glyph.d.ts +9 -0
  25. package/dist/view/glyph.js +1 -1
  26. package/dist/view/glyph.js.map +1 -1
  27. package/dist/view/main.js +9 -0
  28. package/dist/view/main.js.map +1 -1
  29. package/dist/view/menu.js +76 -11
  30. package/dist/view/menu.js.map +1 -1
  31. package/dist/view/player.js +15 -10
  32. package/dist/view/player.js.map +1 -1
  33. package/dist/view/side.js +29 -14
  34. package/dist/view/side.js.map +1 -1
  35. package/dist/view/util.d.ts +5 -0
  36. package/dist/view/util.js +63 -0
  37. package/dist/view/util.js.map +1 -1
  38. package/package.json +13 -14
  39. package/scss/_side.scss +19 -4
  40. package/scss/_util.scss +10 -0
  41. package/src/interfaces.ts +2 -2
  42. package/src/pgnViewer.ts +6 -0
  43. package/src/translation.ts +50 -4
  44. package/src/view/accessibleBoard.ts +61 -0
  45. package/src/view/aria.ts +68 -0
  46. package/src/view/glyph.ts +1 -1
  47. package/src/view/main.ts +13 -0
  48. package/src/view/menu.ts +138 -60
  49. package/src/view/player.ts +19 -13
  50. package/src/view/side.ts +40 -16
  51. package/src/view/util.ts +66 -0
@@ -1,4 +1,4 @@
1
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/types.js
1
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/types.js
2
2
  var FILE_NAMES = ["a", "b", "c", "d", "e", "f", "g", "h"];
3
3
  var RANK_NAMES = ["1", "2", "3", "4", "5", "6", "7", "8"];
4
4
  var COLORS = ["white", "black"];
@@ -6,7 +6,7 @@ var ROLES = ["pawn", "knight", "bishop", "rook", "queen", "king"];
6
6
  var CASTLING_SIDES = ["a", "h"];
7
7
  var isDrop = (v) => "role" in v;
8
8
 
9
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/util.js
9
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/util.js
10
10
  var defined = (v) => v !== void 0;
11
11
  var opposite = (color) => color === "white" ? "black" : "white";
12
12
  var squareRank = (square) => square >> 3;
@@ -56,21 +56,21 @@ var makeUci = (move3) => isDrop(move3) ? `${roleToChar(move3.role).toUpperCase()
56
56
  var kingCastlesTo = (color, side) => color === "white" ? side === "a" ? 2 : 6 : side === "a" ? 58 : 62;
57
57
  var rookCastlesTo = (color, side) => color === "white" ? side === "a" ? 3 : 5 : side === "a" ? 59 : 61;
58
58
 
59
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/squareSet.js
60
- var popcnt32 = (n2) => {
61
- n2 = n2 - (n2 >>> 1 & 1431655765);
62
- n2 = (n2 & 858993459) + (n2 >>> 2 & 858993459);
63
- return Math.imul(n2 + (n2 >>> 4) & 252645135, 16843009) >> 24;
59
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/squareSet.js
60
+ var popcnt32 = (n) => {
61
+ n = n - (n >>> 1 & 1431655765);
62
+ n = (n & 858993459) + (n >>> 2 & 858993459);
63
+ return Math.imul(n + (n >>> 4) & 252645135, 16843009) >> 24;
64
64
  };
65
- var bswap32 = (n2) => {
66
- n2 = n2 >>> 8 & 16711935 | (n2 & 16711935) << 8;
67
- return n2 >>> 16 & 65535 | (n2 & 65535) << 16;
65
+ var bswap32 = (n) => {
66
+ n = n >>> 8 & 16711935 | (n & 16711935) << 8;
67
+ return n >>> 16 & 65535 | (n & 65535) << 16;
68
68
  };
69
- var rbit32 = (n2) => {
70
- n2 = n2 >>> 1 & 1431655765 | (n2 & 1431655765) << 1;
71
- n2 = n2 >>> 2 & 858993459 | (n2 & 858993459) << 2;
72
- n2 = n2 >>> 4 & 252645135 | (n2 & 252645135) << 4;
73
- return bswap32(n2);
69
+ var rbit32 = (n) => {
70
+ n = n >>> 1 & 1431655765 | (n & 1431655765) << 1;
71
+ n = n >>> 2 & 858993459 | (n & 858993459) << 2;
72
+ n = n >>> 4 & 252645135 | (n & 252645135) << 4;
73
+ return bswap32(n);
74
74
  };
75
75
  var SquareSet = class _SquareSet {
76
76
  constructor(lo, hi) {
@@ -248,7 +248,7 @@ var SquareSet = class _SquareSet {
248
248
  }
249
249
  };
250
250
 
251
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/attacks.js
251
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/attacks.js
252
252
  var computeRange = (square, deltas) => {
253
253
  let range = SquareSet.empty();
254
254
  for (const delta of deltas) {
@@ -338,7 +338,7 @@ var ray = (a, b) => {
338
338
  };
339
339
  var between = (a, b) => ray(a, b).intersect(SquareSet.full().shl64(a).xor(SquareSet.full().shl64(b))).withoutFirst();
340
340
 
341
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/board.js
341
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/board.js
342
342
  var Board = class _Board {
343
343
  constructor() {
344
344
  }
@@ -451,6 +451,12 @@ var Board = class _Board {
451
451
  bishopsAndQueens() {
452
452
  return this.bishop.union(this.queen);
453
453
  }
454
+ steppers() {
455
+ return this.knight.union(this.pawn).union(this.king);
456
+ }
457
+ sliders() {
458
+ return this.bishop.union(this.rook).union(this.queen);
459
+ }
454
460
  /**
455
461
  * Finds the unique king of the given `color`, if any.
456
462
  */
@@ -459,7 +465,7 @@ var Board = class _Board {
459
465
  }
460
466
  };
461
467
 
462
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/setup.js
468
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/setup.js
463
469
  var MaterialSide = class _MaterialSide {
464
470
  constructor() {
465
471
  }
@@ -570,63 +576,81 @@ var RemainingChecks = class _RemainingChecks {
570
576
  }
571
577
  };
572
578
 
573
- // node_modules/.pnpm/@badrap+result@0.2.13/node_modules/@badrap/result/dist/index.modern.mjs
574
- var r = class {
575
- unwrap(r2, t2) {
576
- const e2 = this._chain((t3) => n.ok(r2 ? r2(t3) : t3), (r3) => t2 ? n.ok(t2(r3)) : n.err(r3));
577
- if (e2.isErr) throw e2.error;
578
- return e2.value;
579
+ // node_modules/.pnpm/@badrap+result@0.3.1/node_modules/@badrap/result/dist/mjs/index.mjs
580
+ var _Result = class {
581
+ unwrap(ok, err) {
582
+ const r = this._chain((value) => Result.ok(ok ? ok(value) : value), (error) => err ? Result.ok(err(error)) : Result.err(error));
583
+ if (r.isErr) {
584
+ throw r.error;
585
+ }
586
+ return r.value;
579
587
  }
580
- map(r2, t2) {
581
- return this._chain((t3) => n.ok(r2(t3)), (r3) => n.err(t2 ? t2(r3) : r3));
588
+ map(ok, err) {
589
+ return this._chain((value) => Result.ok(ok(value)), (error) => Result.err(err ? err(error) : error));
582
590
  }
583
- chain(r2, t2) {
584
- return this._chain(r2, t2 || ((r3) => n.err(r3)));
591
+ chain(ok, err) {
592
+ return this._chain(ok, err !== null && err !== void 0 ? err : ((error) => Result.err(error)));
585
593
  }
586
594
  };
587
- var t = class extends r {
588
- constructor(r2) {
589
- super(), this.value = void 0, this.isOk = true, this.isErr = false, this.value = r2;
595
+ var _Ok = class extends _Result {
596
+ constructor(value) {
597
+ super();
598
+ this.value = value;
599
+ this.isOk = true;
600
+ this.isErr = false;
590
601
  }
591
- _chain(r2, t2) {
592
- return r2(this.value);
602
+ _chain(ok, _err) {
603
+ return ok(this.value);
593
604
  }
594
605
  };
595
- var e = class extends r {
596
- constructor(r2) {
597
- super(), this.error = void 0, this.isOk = false, this.isErr = true, this.error = r2;
606
+ var _Err = class extends _Result {
607
+ constructor(error) {
608
+ super();
609
+ this.error = error;
610
+ this.isOk = false;
611
+ this.isErr = true;
598
612
  }
599
- _chain(r2, t2) {
600
- return t2(this.error);
613
+ _chain(_ok, err) {
614
+ return err(this.error);
601
615
  }
602
616
  };
603
- var n;
604
- !function(r2) {
605
- r2.ok = function(r3) {
606
- return new t(r3);
607
- }, r2.err = function(r3) {
608
- return new e(r3 || new Error());
609
- }, r2.all = function(t2) {
610
- if (Array.isArray(t2)) {
611
- const e3 = [];
612
- for (let r3 = 0; r3 < t2.length; r3++) {
613
- const n3 = t2[r3];
614
- if (n3.isErr) return n3;
615
- e3.push(n3.value);
617
+ var Result;
618
+ (function(Result2) {
619
+ function ok(value) {
620
+ return new _Ok(value);
621
+ }
622
+ Result2.ok = ok;
623
+ function err(error) {
624
+ return new _Err(error || new Error());
625
+ }
626
+ Result2.err = err;
627
+ function all(obj) {
628
+ if (Array.isArray(obj)) {
629
+ const res2 = [];
630
+ for (let i = 0; i < obj.length; i++) {
631
+ const item = obj[i];
632
+ if (item.isErr) {
633
+ return item;
634
+ }
635
+ res2.push(item.value);
616
636
  }
617
- return r2.ok(e3);
637
+ return Result2.ok(res2);
618
638
  }
619
- const e2 = {}, n2 = Object.keys(t2);
620
- for (let r3 = 0; r3 < n2.length; r3++) {
621
- const s = t2[n2[r3]];
622
- if (s.isErr) return s;
623
- e2[n2[r3]] = s.value;
639
+ const res = {};
640
+ const keys = Object.keys(obj);
641
+ for (let i = 0; i < keys.length; i++) {
642
+ const item = obj[keys[i]];
643
+ if (item.isErr) {
644
+ return item;
645
+ }
646
+ res[keys[i]] = item.value;
624
647
  }
625
- return r2.ok(e2);
626
- };
627
- }(n || (n = {}));
648
+ return Result2.ok(res);
649
+ }
650
+ Result2.all = all;
651
+ })(Result || (Result = {}));
628
652
 
629
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/chess.js
653
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/chess.js
630
654
  var IllegalSetup;
631
655
  (function(IllegalSetup2) {
632
656
  IllegalSetup2["Empty"] = "ERR_EMPTY";
@@ -805,21 +829,21 @@ var Position = class {
805
829
  }
806
830
  validate() {
807
831
  if (this.board.occupied.isEmpty())
808
- return n.err(new PositionError(IllegalSetup.Empty));
832
+ return Result.err(new PositionError(IllegalSetup.Empty));
809
833
  if (this.board.king.size() !== 2)
810
- return n.err(new PositionError(IllegalSetup.Kings));
834
+ return Result.err(new PositionError(IllegalSetup.Kings));
811
835
  if (!defined(this.board.kingOf(this.turn)))
812
- return n.err(new PositionError(IllegalSetup.Kings));
836
+ return Result.err(new PositionError(IllegalSetup.Kings));
813
837
  const otherKing = this.board.kingOf(opposite(this.turn));
814
838
  if (!defined(otherKing))
815
- return n.err(new PositionError(IllegalSetup.Kings));
839
+ return Result.err(new PositionError(IllegalSetup.Kings));
816
840
  if (this.kingAttackers(otherKing, this.turn, this.board.occupied).nonEmpty()) {
817
- return n.err(new PositionError(IllegalSetup.OppositeCheck));
841
+ return Result.err(new PositionError(IllegalSetup.OppositeCheck));
818
842
  }
819
843
  if (SquareSet.backranks().intersects(this.board.pawn)) {
820
- return n.err(new PositionError(IllegalSetup.PawnsOnBackrank));
844
+ return Result.err(new PositionError(IllegalSetup.PawnsOnBackrank));
821
845
  }
822
- return n.ok(void 0);
846
+ return Result.ok(void 0);
823
847
  }
824
848
  dropDests(_ctx) {
825
849
  return SquareSet.empty();
@@ -1167,10 +1191,10 @@ var normalizeMove = (pos, move3) => {
1167
1191
  };
1168
1192
  };
1169
1193
 
1170
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/compat.js
1194
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/compat.js
1171
1195
  var scalachessCharPair = (move3) => isDrop(move3) ? String.fromCharCode(35 + move3.to, 35 + 64 + 8 * 5 + ["queen", "rook", "bishop", "knight", "pawn"].indexOf(move3.role)) : String.fromCharCode(35 + move3.from, move3.promotion ? 35 + 64 + 8 * ["queen", "rook", "bishop", "knight", "king"].indexOf(move3.promotion) + squareFile(move3.to) : 35 + move3.to);
1172
1196
 
1173
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/fen.js
1197
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/fen.js
1174
1198
  var INITIAL_BOARD_FEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
1175
1199
  var INITIAL_EPD = INITIAL_BOARD_FEN + " w KQkq -";
1176
1200
  var INITIAL_FEN = INITIAL_EPD + " 0 1";
@@ -1191,9 +1215,9 @@ var InvalidFen;
1191
1215
  })(InvalidFen || (InvalidFen = {}));
1192
1216
  var FenError = class extends Error {
1193
1217
  };
1194
- var nthIndexOf = (haystack, needle, n2) => {
1218
+ var nthIndexOf = (haystack, needle, n) => {
1195
1219
  let index = haystack.indexOf(needle);
1196
- while (n2-- > 0) {
1220
+ while (n-- > 0) {
1197
1221
  if (index === -1)
1198
1222
  break;
1199
1223
  index = haystack.indexOf(needle, index + needle.length);
@@ -1220,11 +1244,11 @@ var parseBoardFen = (boardPart) => {
1220
1244
  file += step2;
1221
1245
  else {
1222
1246
  if (file >= 8 || rank < 0)
1223
- return n.err(new FenError(InvalidFen.Board));
1247
+ return Result.err(new FenError(InvalidFen.Board));
1224
1248
  const square = file + rank * 8;
1225
1249
  const piece = charToPiece(c);
1226
1250
  if (!piece)
1227
- return n.err(new FenError(InvalidFen.Board));
1251
+ return Result.err(new FenError(InvalidFen.Board));
1228
1252
  if (boardPart[i + 1] === "~") {
1229
1253
  piece.promoted = true;
1230
1254
  i++;
@@ -1235,25 +1259,25 @@ var parseBoardFen = (boardPart) => {
1235
1259
  }
1236
1260
  }
1237
1261
  if (rank !== 0 || file !== 8)
1238
- return n.err(new FenError(InvalidFen.Board));
1239
- return n.ok(board);
1262
+ return Result.err(new FenError(InvalidFen.Board));
1263
+ return Result.ok(board);
1240
1264
  };
1241
1265
  var parsePockets = (pocketPart) => {
1242
1266
  if (pocketPart.length > 64)
1243
- return n.err(new FenError(InvalidFen.Pockets));
1267
+ return Result.err(new FenError(InvalidFen.Pockets));
1244
1268
  const pockets = Material.empty();
1245
1269
  for (const c of pocketPart) {
1246
1270
  const piece = charToPiece(c);
1247
1271
  if (!piece)
1248
- return n.err(new FenError(InvalidFen.Pockets));
1272
+ return Result.err(new FenError(InvalidFen.Pockets));
1249
1273
  pockets[piece.color][piece.role]++;
1250
1274
  }
1251
- return n.ok(pockets);
1275
+ return Result.ok(pockets);
1252
1276
  };
1253
1277
  var parseCastlingFen = (board, castlingPart) => {
1254
1278
  let castlingRights = SquareSet.empty();
1255
1279
  if (castlingPart === "-")
1256
- return n.ok(castlingRights);
1280
+ return Result.ok(castlingRights);
1257
1281
  for (const c of castlingPart) {
1258
1282
  const lower = c.toLowerCase();
1259
1283
  const color = c === lower ? "black" : "white";
@@ -1265,12 +1289,12 @@ var parseCastlingFen = (board, castlingPart) => {
1265
1289
  const candidate = lower === "k" ? rooksAndKings.last() : rooksAndKings.first();
1266
1290
  castlingRights = castlingRights.with(defined(candidate) && board.rook.has(candidate) ? candidate : squareFromCoords(lower === "k" ? 7 : 0, rank));
1267
1291
  } else
1268
- return n.err(new FenError(InvalidFen.Castling));
1292
+ return Result.err(new FenError(InvalidFen.Castling));
1269
1293
  }
1270
1294
  if (COLORS.some((color) => SquareSet.backrank(color).intersect(castlingRights).size() > 2)) {
1271
- return n.err(new FenError(InvalidFen.Castling));
1295
+ return Result.err(new FenError(InvalidFen.Castling));
1272
1296
  }
1273
- return n.ok(castlingRights);
1297
+ return Result.ok(castlingRights);
1274
1298
  };
1275
1299
  var parseRemainingChecks = (part) => {
1276
1300
  const parts = part.split("+");
@@ -1278,28 +1302,28 @@ var parseRemainingChecks = (part) => {
1278
1302
  const white = parseSmallUint(parts[1]);
1279
1303
  const black = parseSmallUint(parts[2]);
1280
1304
  if (!defined(white) || white > 3 || !defined(black) || black > 3) {
1281
- return n.err(new FenError(InvalidFen.RemainingChecks));
1305
+ return Result.err(new FenError(InvalidFen.RemainingChecks));
1282
1306
  }
1283
- return n.ok(new RemainingChecks(3 - white, 3 - black));
1307
+ return Result.ok(new RemainingChecks(3 - white, 3 - black));
1284
1308
  } else if (parts.length === 2) {
1285
1309
  const white = parseSmallUint(parts[0]);
1286
1310
  const black = parseSmallUint(parts[1]);
1287
1311
  if (!defined(white) || white > 3 || !defined(black) || black > 3) {
1288
- return n.err(new FenError(InvalidFen.RemainingChecks));
1312
+ return Result.err(new FenError(InvalidFen.RemainingChecks));
1289
1313
  }
1290
- return n.ok(new RemainingChecks(white, black));
1314
+ return Result.ok(new RemainingChecks(white, black));
1291
1315
  } else
1292
- return n.err(new FenError(InvalidFen.RemainingChecks));
1316
+ return Result.err(new FenError(InvalidFen.RemainingChecks));
1293
1317
  };
1294
1318
  var parseFen = (fen) => {
1295
1319
  const parts = fen.split(/[\s_]+/);
1296
1320
  const boardPart = parts.shift();
1297
1321
  let board;
1298
- let pockets = n.ok(void 0);
1322
+ let pockets = Result.ok(void 0);
1299
1323
  if (boardPart.endsWith("]")) {
1300
1324
  const pocketStart = boardPart.indexOf("[");
1301
1325
  if (pocketStart === -1)
1302
- return n.err(new FenError(InvalidFen.Fen));
1326
+ return Result.err(new FenError(InvalidFen.Fen));
1303
1327
  board = parseBoardFen(boardPart.slice(0, pocketStart));
1304
1328
  pockets = parsePockets(boardPart.slice(pocketStart + 1, -1));
1305
1329
  } else {
@@ -1318,16 +1342,16 @@ var parseFen = (fen) => {
1318
1342
  else if (turnPart === "b")
1319
1343
  turn = "black";
1320
1344
  else
1321
- return n.err(new FenError(InvalidFen.Turn));
1345
+ return Result.err(new FenError(InvalidFen.Turn));
1322
1346
  return board.chain((board2) => {
1323
1347
  const castlingPart = parts.shift();
1324
- const castlingRights = defined(castlingPart) ? parseCastlingFen(board2, castlingPart) : n.ok(SquareSet.empty());
1348
+ const castlingRights = defined(castlingPart) ? parseCastlingFen(board2, castlingPart) : Result.ok(SquareSet.empty());
1325
1349
  const epPart = parts.shift();
1326
1350
  let epSquare;
1327
1351
  if (defined(epPart) && epPart !== "-") {
1328
1352
  epSquare = parseSquare(epPart);
1329
1353
  if (!defined(epSquare))
1330
- return n.err(new FenError(InvalidFen.EpSquare));
1354
+ return Result.err(new FenError(InvalidFen.EpSquare));
1331
1355
  }
1332
1356
  let halfmovePart = parts.shift();
1333
1357
  let earlyRemainingChecks;
@@ -1337,22 +1361,22 @@ var parseFen = (fen) => {
1337
1361
  }
1338
1362
  const halfmoves = defined(halfmovePart) ? parseSmallUint(halfmovePart) : 0;
1339
1363
  if (!defined(halfmoves))
1340
- return n.err(new FenError(InvalidFen.Halfmoves));
1364
+ return Result.err(new FenError(InvalidFen.Halfmoves));
1341
1365
  const fullmovesPart = parts.shift();
1342
1366
  const fullmoves = defined(fullmovesPart) ? parseSmallUint(fullmovesPart) : 1;
1343
1367
  if (!defined(fullmoves))
1344
- return n.err(new FenError(InvalidFen.Fullmoves));
1368
+ return Result.err(new FenError(InvalidFen.Fullmoves));
1345
1369
  const remainingChecksPart = parts.shift();
1346
- let remainingChecks = n.ok(void 0);
1370
+ let remainingChecks = Result.ok(void 0);
1347
1371
  if (defined(remainingChecksPart)) {
1348
1372
  if (defined(earlyRemainingChecks))
1349
- return n.err(new FenError(InvalidFen.RemainingChecks));
1373
+ return Result.err(new FenError(InvalidFen.RemainingChecks));
1350
1374
  remainingChecks = parseRemainingChecks(remainingChecksPart);
1351
1375
  } else if (defined(earlyRemainingChecks)) {
1352
1376
  remainingChecks = earlyRemainingChecks;
1353
1377
  }
1354
1378
  if (parts.length > 0)
1355
- return n.err(new FenError(InvalidFen.Fen));
1379
+ return Result.err(new FenError(InvalidFen.Fen));
1356
1380
  return pockets.chain((pockets2) => castlingRights.chain((castlingRights2) => remainingChecks.map((remainingChecks2) => {
1357
1381
  return {
1358
1382
  board: board2,
@@ -1368,12 +1392,12 @@ var parseFen = (fen) => {
1368
1392
  });
1369
1393
  };
1370
1394
  var makePiece = (piece) => {
1371
- let r2 = roleToChar(piece.role);
1395
+ let r = roleToChar(piece.role);
1372
1396
  if (piece.color === "white")
1373
- r2 = r2.toUpperCase();
1397
+ r = r.toUpperCase();
1374
1398
  if (piece.promoted)
1375
- r2 += "~";
1376
- return r2;
1399
+ r += "~";
1400
+ return r;
1377
1401
  };
1378
1402
  var makeBoardFen = (board) => {
1379
1403
  let fen = "";
@@ -1436,7 +1460,7 @@ var makeFen = (setup, opts) => [
1436
1460
  ...(opts === null || opts === void 0 ? void 0 : opts.epd) ? [] : [Math.max(0, Math.min(setup.halfmoves, 9999)), Math.max(1, Math.min(setup.fullmoves, 9999))]
1437
1461
  ].join(" ");
1438
1462
 
1439
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/san.js
1463
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/san.js
1440
1464
  var makeSanWithoutSuffix = (pos, move3) => {
1441
1465
  let san = "";
1442
1466
  if (isDrop(move3)) {
@@ -1565,7 +1589,7 @@ var parseSan = (pos, san) => {
1565
1589
  };
1566
1590
  };
1567
1591
 
1568
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/variant.js
1592
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/variant.js
1569
1593
  var Crazyhouse = class extends Position {
1570
1594
  constructor() {
1571
1595
  super("crazyhouse");
@@ -1596,12 +1620,12 @@ var Crazyhouse = class extends Position {
1596
1620
  return super.validate().chain((_) => {
1597
1621
  var _a, _b;
1598
1622
  if ((_a = this.pockets) === null || _a === void 0 ? void 0 : _a.count("king")) {
1599
- return n.err(new PositionError(IllegalSetup.Kings));
1623
+ return Result.err(new PositionError(IllegalSetup.Kings));
1600
1624
  }
1601
1625
  if ((((_b = this.pockets) === null || _b === void 0 ? void 0 : _b.size()) || 0) + this.board.occupied.size() > 64) {
1602
- return n.err(new PositionError(IllegalSetup.Variant));
1626
+ return Result.err(new PositionError(IllegalSetup.Variant));
1603
1627
  }
1604
- return n.ok(void 0);
1628
+ return Result.ok(void 0);
1605
1629
  });
1606
1630
  }
1607
1631
  hasInsufficientMaterial(color) {
@@ -1641,19 +1665,19 @@ var Atomic = class extends Position {
1641
1665
  }
1642
1666
  validate() {
1643
1667
  if (this.board.occupied.isEmpty())
1644
- return n.err(new PositionError(IllegalSetup.Empty));
1668
+ return Result.err(new PositionError(IllegalSetup.Empty));
1645
1669
  if (this.board.king.size() > 2)
1646
- return n.err(new PositionError(IllegalSetup.Kings));
1670
+ return Result.err(new PositionError(IllegalSetup.Kings));
1647
1671
  const otherKing = this.board.kingOf(opposite(this.turn));
1648
1672
  if (!defined(otherKing))
1649
- return n.err(new PositionError(IllegalSetup.Kings));
1673
+ return Result.err(new PositionError(IllegalSetup.Kings));
1650
1674
  if (this.kingAttackers(otherKing, this.turn, this.board.occupied).nonEmpty()) {
1651
- return n.err(new PositionError(IllegalSetup.OppositeCheck));
1675
+ return Result.err(new PositionError(IllegalSetup.OppositeCheck));
1652
1676
  }
1653
1677
  if (SquareSet.backranks().intersects(this.board.pawn)) {
1654
- return n.err(new PositionError(IllegalSetup.PawnsOnBackrank));
1678
+ return Result.err(new PositionError(IllegalSetup.PawnsOnBackrank));
1655
1679
  }
1656
- return n.ok(void 0);
1680
+ return Result.ok(void 0);
1657
1681
  }
1658
1682
  kingAttackers(square, attacker, occupied) {
1659
1683
  const attackerKings = this.board.pieces(attacker, "king");
@@ -1749,11 +1773,11 @@ var Antichess = class extends Position {
1749
1773
  }
1750
1774
  validate() {
1751
1775
  if (this.board.occupied.isEmpty())
1752
- return n.err(new PositionError(IllegalSetup.Empty));
1776
+ return Result.err(new PositionError(IllegalSetup.Empty));
1753
1777
  if (SquareSet.backranks().intersects(this.board.pawn)) {
1754
- return n.err(new PositionError(IllegalSetup.PawnsOnBackrank));
1778
+ return Result.err(new PositionError(IllegalSetup.PawnsOnBackrank));
1755
1779
  }
1756
- return n.ok(void 0);
1780
+ return Result.ok(void 0);
1757
1781
  }
1758
1782
  kingAttackers(_square, _attacker, _occupied) {
1759
1783
  return SquareSet.empty();
@@ -1927,7 +1951,7 @@ var RacingKings = class extends Position {
1927
1951
  }
1928
1952
  validate() {
1929
1953
  if (this.isCheck() || this.board.pawn.nonEmpty())
1930
- return n.err(new PositionError(IllegalSetup.Variant));
1954
+ return Result.err(new PositionError(IllegalSetup.Variant));
1931
1955
  return super.validate();
1932
1956
  }
1933
1957
  dests(square, ctx) {
@@ -2021,20 +2045,20 @@ var Horde = class extends Position {
2021
2045
  }
2022
2046
  validate() {
2023
2047
  if (this.board.occupied.isEmpty())
2024
- return n.err(new PositionError(IllegalSetup.Empty));
2048
+ return Result.err(new PositionError(IllegalSetup.Empty));
2025
2049
  if (this.board.king.size() !== 1)
2026
- return n.err(new PositionError(IllegalSetup.Kings));
2050
+ return Result.err(new PositionError(IllegalSetup.Kings));
2027
2051
  const otherKing = this.board.kingOf(opposite(this.turn));
2028
2052
  if (defined(otherKing) && this.kingAttackers(otherKing, this.turn, this.board.occupied).nonEmpty()) {
2029
- return n.err(new PositionError(IllegalSetup.OppositeCheck));
2053
+ return Result.err(new PositionError(IllegalSetup.OppositeCheck));
2030
2054
  }
2031
2055
  for (const color of COLORS) {
2032
2056
  const backranks = this.board.pieces(color, "king").isEmpty() ? SquareSet.backrank(opposite(color)) : SquareSet.backranks();
2033
2057
  if (this.board.pieces(color, "pawn").intersects(backranks)) {
2034
- return n.err(new PositionError(IllegalSetup.PawnsOnBackrank));
2058
+ return Result.err(new PositionError(IllegalSetup.PawnsOnBackrank));
2035
2059
  }
2036
2060
  }
2037
- return n.ok(void 0);
2061
+ return Result.ok(void 0);
2038
2062
  }
2039
2063
  hasInsufficientMaterial(color) {
2040
2064
  if (this.board.pieces(color, "king").nonEmpty())
@@ -2183,7 +2207,7 @@ var setupPosition = (rules, setup) => {
2183
2207
  }
2184
2208
  };
2185
2209
 
2186
- // node_modules/.pnpm/chessops@0.14.2/node_modules/chessops/dist/esm/pgn.js
2210
+ // node_modules/.pnpm/chessops@0.15.0/node_modules/chessops/dist/esm/pgn.js
2187
2211
  var defaultGame = (initHeaders = defaultHeaders) => ({
2188
2212
  headers: initHeaders(),
2189
2213
  moves: new Node()
@@ -2549,12 +2573,12 @@ var parseVariant = (variant) => {
2549
2573
  var startingPosition = (headers) => {
2550
2574
  const rules = parseVariant(headers.get("Variant"));
2551
2575
  if (!rules)
2552
- return n.err(new PositionError(IllegalSetup.Variant));
2576
+ return Result.err(new PositionError(IllegalSetup.Variant));
2553
2577
  const fen = headers.get("FEN");
2554
2578
  if (fen)
2555
2579
  return parseFen(fen).chain((setup) => setupPosition(rules, setup));
2556
2580
  else
2557
- return n.ok(defaultPosition(rules));
2581
+ return Result.ok(defaultPosition(rules));
2558
2582
  };
2559
2583
  function parseCommentShapeColor(str) {
2560
2584
  switch (str) {
@@ -2612,10 +2636,18 @@ var parseComment = (comment) => {
2612
2636
  };
2613
2637
 
2614
2638
  // src/translation.ts
2615
- function translate(translator) {
2616
- return (key) => translator && translator(key) || defaultTranslator(key);
2617
- }
2618
2639
  var defaultTranslator = (key) => defaultTranslations[key];
2640
+ function translate(translator = defaultTranslator) {
2641
+ return (key, ...args) => interpolate(translator(key) ?? key, args);
2642
+ }
2643
+ var interpolate = (str, args) => {
2644
+ let result = str;
2645
+ args.forEach((arg, index) => {
2646
+ result = result.replace(`%${index + 1}$s`, arg);
2647
+ result = result.replace("%s", arg);
2648
+ });
2649
+ return result;
2650
+ };
2619
2651
  var defaultTranslations = {
2620
2652
  flipTheBoard: "Flip the board",
2621
2653
  analysisBoard: "Analysis board",
@@ -2623,7 +2655,44 @@ var defaultTranslations = {
2623
2655
  getPgn: "Get PGN",
2624
2656
  download: "Download",
2625
2657
  viewOnLichess: "View on Lichess",
2626
- viewOnSite: "View on site"
2658
+ viewOnSite: "View on site",
2659
+ menu: "Menu",
2660
+ "aria.first": "Go to first move",
2661
+ "aria.prev": "Go to previous move",
2662
+ "aria.next": "Go to next move",
2663
+ "aria.last": "Go to last move",
2664
+ "aria.gameMoves": "Game moves",
2665
+ "aria.gameResult": "Game result",
2666
+ "aria.variation": "Variation",
2667
+ "aria.navigationControls": "Game navigation controls",
2668
+ "aria.viewProfileOnLichess": "View %s's profile on Lichess",
2669
+ "aria.chessGameBetween": "Chess game between %1$s, whites, and %2$s, blacks. %3$s",
2670
+ "aria.gameInProgress": "Game in progress",
2671
+ "aria.whitesWin": "Whites win",
2672
+ "aria.blacksWin": "Blacks win",
2673
+ "aria.draw": "Draw",
2674
+ "aria.unknownPlayer": "Unknown player",
2675
+ "aria.rated": "rated %s",
2676
+ "aria.move": "Move %1$s, %2$s, %3$s",
2677
+ "aria.white": "white",
2678
+ "aria.black": "black",
2679
+ "aria.remaining": "%s remaining",
2680
+ "aria.linkOpensInNewTab": "%s, link, opens in new tab",
2681
+ "aria.accessibleChessboard": "Accessible chessboard",
2682
+ "aria.piece.king": "king",
2683
+ "aria.piece.queen": "queen",
2684
+ "aria.piece.rook": "rook",
2685
+ "aria.piece.bishop": "bishop",
2686
+ "aria.piece.knight": "knight",
2687
+ "aria.piece.pawn": "pawn",
2688
+ "aria.empty": "empty",
2689
+ "san.takes": "takes",
2690
+ "san.check": "check",
2691
+ "san.checkmate": "checkmate",
2692
+ "san.promotesTo": "promotes to",
2693
+ "san.droppedOn": "dropped on",
2694
+ "san.longCastling": "long castling",
2695
+ "san.shortCastling": "short castling"
2627
2696
  };
2628
2697
 
2629
2698
  // node_modules/.pnpm/chessground@9.2.1/node_modules/chessground/dist/types.js
@@ -2633,7 +2702,7 @@ var ranks = ["1", "2", "3", "4", "5", "6", "7", "8"];
2633
2702
 
2634
2703
  // node_modules/.pnpm/chessground@9.2.1/node_modules/chessground/dist/util.js
2635
2704
  var invRanks = [...ranks].reverse();
2636
- var allKeys = Array.prototype.concat(...files.map((c) => ranks.map((r2) => c + r2)));
2705
+ var allKeys = Array.prototype.concat(...files.map((c) => ranks.map((r) => c + r)));
2637
2706
  var pos2key = (pos) => allKeys[8 * pos[0] + pos[1]];
2638
2707
  var key2pos = (k) => [k.charCodeAt(0) - 97, k.charCodeAt(1) - 49];
2639
2708
  var uciToMove = (uci) => {
@@ -2693,15 +2762,15 @@ var translateAndScale = (el, pos, scale = 1) => {
2693
2762
  var setVisible = (el, v) => {
2694
2763
  el.style.visibility = v ? "visible" : "hidden";
2695
2764
  };
2696
- var eventPosition = (e2) => {
2765
+ var eventPosition = (e) => {
2697
2766
  var _a;
2698
- if (e2.clientX || e2.clientX === 0)
2699
- return [e2.clientX, e2.clientY];
2700
- if ((_a = e2.targetTouches) === null || _a === void 0 ? void 0 : _a[0])
2701
- return [e2.targetTouches[0].clientX, e2.targetTouches[0].clientY];
2767
+ if (e.clientX || e.clientX === 0)
2768
+ return [e.clientX, e.clientY];
2769
+ if ((_a = e.targetTouches) === null || _a === void 0 ? void 0 : _a[0])
2770
+ return [e.targetTouches[0].clientX, e.targetTouches[0].clientY];
2702
2771
  return;
2703
2772
  };
2704
- var isRightButton = (e2) => e2.button === 2;
2773
+ var isRightButton = (e) => e.button === 2;
2705
2774
  var createEl = (tagName2, className) => {
2706
2775
  const el = document.createElement(tagName2);
2707
2776
  if (className)
@@ -2771,7 +2840,7 @@ var nodeAtPathFrom = (node, path) => {
2771
2840
  const child = childById(node, path.head());
2772
2841
  return child ? nodeAtPathFrom(child, path.tail()) : void 0;
2773
2842
  };
2774
- var isMoveNode = (n2) => "data" in n2;
2843
+ var isMoveNode = (n) => "data" in n;
2775
2844
  var isMoveData = (d) => "uci" in d;
2776
2845
 
2777
2846
  // src/pgn.ts
@@ -2787,7 +2856,7 @@ var parseComments = (strings) => {
2787
2856
  const comments = strings.map(parseComment);
2788
2857
  const reduceTimes = (times) => times.reduce((last, time) => typeof time == void 0 ? last : time, void 0);
2789
2858
  return {
2790
- texts: comments.map((c) => c.text).filter((t2) => !!t2),
2859
+ texts: comments.map((c) => c.text).filter((t) => !!t),
2791
2860
  shapes: comments.flatMap((c) => c.shapes),
2792
2861
  clock: reduceTimes(comments.map((c) => c.clock)),
2793
2862
  emt: reduceTimes(comments.map((c) => c.emt))
@@ -2917,6 +2986,9 @@ var PgnViewer = class {
2917
2986
  this.toggleMenu = () => {
2918
2987
  this.pane = this.pane == "board" ? "menu" : "board";
2919
2988
  this.redraw();
2989
+ if (this.pane == "board") {
2990
+ setTimeout(() => this.menuButton?.focus(), 0);
2991
+ }
2920
2992
  };
2921
2993
  this.togglePgn = () => {
2922
2994
  this.pane = this.pane == "pgn" ? "board" : "pgn";
@@ -3002,7 +3074,7 @@ function premove(pieces, key, canCastle) {
3002
3074
  const piece = pieces.get(key);
3003
3075
  if (!piece)
3004
3076
  return [];
3005
- const pos = key2pos(key), r2 = piece.role, mobility = r2 === "pawn" ? pawn(piece.color) : r2 === "knight" ? knight : r2 === "bishop" ? bishop : r2 === "rook" ? rook : r2 === "queen" ? queen : king(piece.color, rookFilesOf(pieces, piece.color), canCastle);
3077
+ const pos = key2pos(key), r = piece.role, mobility = r === "pawn" ? pawn(piece.color) : r === "knight" ? knight : r === "bishop" ? bishop : r === "rook" ? rook : r === "queen" ? queen : king(piece.color, rookFilesOf(pieces, piece.color), canCastle);
3006
3078
  return allPos.filter((pos2) => (pos[0] !== pos2[0] || pos[1] !== pos2[1]) && mobility(pos[0], pos[1], pos2[0], pos2[1])).map(pos2key);
3007
3079
  }
3008
3080
 
@@ -3517,23 +3589,23 @@ function animate(mutation, state) {
3517
3589
  }
3518
3590
  return result;
3519
3591
  }
3520
- var easing = (t2) => t2 < 0.5 ? 4 * t2 * t2 * t2 : (t2 - 1) * (2 * t2 - 2) * (2 * t2 - 2) + 1;
3592
+ var easing = (t) => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
3521
3593
 
3522
3594
  // node_modules/.pnpm/chessground@9.2.1/node_modules/chessground/dist/draw.js
3523
3595
  var brushes = ["green", "red", "blue", "yellow"];
3524
- function start(state, e2) {
3525
- if (e2.touches && e2.touches.length > 1)
3596
+ function start(state, e) {
3597
+ if (e.touches && e.touches.length > 1)
3526
3598
  return;
3527
- e2.stopPropagation();
3528
- e2.preventDefault();
3529
- e2.ctrlKey ? unselect(state) : cancelMove(state);
3530
- const pos = eventPosition(e2), orig = getKeyAtDomPos(pos, whitePov(state), state.dom.bounds());
3599
+ e.stopPropagation();
3600
+ e.preventDefault();
3601
+ e.ctrlKey ? unselect(state) : cancelMove(state);
3602
+ const pos = eventPosition(e), orig = getKeyAtDomPos(pos, whitePov(state), state.dom.bounds());
3531
3603
  if (!orig)
3532
3604
  return;
3533
3605
  state.drawable.current = {
3534
3606
  orig,
3535
3607
  pos,
3536
- brush: eventBrush(e2),
3608
+ brush: eventBrush(e),
3537
3609
  snapToValidMove: state.drawable.defaultSnapToValidMove
3538
3610
  };
3539
3611
  processDraw(state);
@@ -3556,9 +3628,9 @@ function processDraw(state) {
3556
3628
  }
3557
3629
  });
3558
3630
  }
3559
- function move(state, e2) {
3631
+ function move(state, e) {
3560
3632
  if (state.drawable.current)
3561
- state.drawable.current.pos = eventPosition(e2);
3633
+ state.drawable.current.pos = eventPosition(e);
3562
3634
  }
3563
3635
  function end(state) {
3564
3636
  const cur = state.drawable.current;
@@ -3581,10 +3653,10 @@ function clear(state) {
3581
3653
  onChange(state.drawable);
3582
3654
  }
3583
3655
  }
3584
- function eventBrush(e2) {
3656
+ function eventBrush(e) {
3585
3657
  var _a;
3586
- const modA = (e2.shiftKey || e2.ctrlKey) && isRightButton(e2);
3587
- const modB = e2.altKey || e2.metaKey || ((_a = e2.getModifierState) === null || _a === void 0 ? void 0 : _a.call(e2, "AltGraph"));
3658
+ const modA = (e.shiftKey || e.ctrlKey) && isRightButton(e);
3659
+ const modB = e.altKey || e.metaKey || ((_a = e.getModifierState) === null || _a === void 0 ? void 0 : _a.call(e, "AltGraph"));
3588
3660
  return brushes[(modA ? 1 : 0) + (modB ? 2 : 0)];
3589
3661
  }
3590
3662
  function addShape(drawable, cur) {
@@ -3606,27 +3678,27 @@ function onChange(drawable) {
3606
3678
  }
3607
3679
 
3608
3680
  // node_modules/.pnpm/chessground@9.2.1/node_modules/chessground/dist/drag.js
3609
- function start2(s, e2) {
3610
- if (!(s.trustAllEvents || e2.isTrusted))
3681
+ function start2(s, e) {
3682
+ if (!(s.trustAllEvents || e.isTrusted))
3611
3683
  return;
3612
- if (e2.buttons !== void 0 && e2.buttons > 1)
3684
+ if (e.buttons !== void 0 && e.buttons > 1)
3613
3685
  return;
3614
- if (e2.touches && e2.touches.length > 1)
3686
+ if (e.touches && e.touches.length > 1)
3615
3687
  return;
3616
- const bounds = s.dom.bounds(), position = eventPosition(e2), orig = getKeyAtDomPos(position, whitePov(s), bounds);
3688
+ const bounds = s.dom.bounds(), position = eventPosition(e), orig = getKeyAtDomPos(position, whitePov(s), bounds);
3617
3689
  if (!orig)
3618
3690
  return;
3619
3691
  const piece = s.pieces.get(orig);
3620
3692
  const previouslySelected = s.selected;
3621
3693
  if (!previouslySelected && s.drawable.enabled && (s.drawable.eraseOnClick || !piece || piece.color !== s.turnColor))
3622
3694
  clear(s);
3623
- if (e2.cancelable !== false && (!e2.touches || s.blockTouchScroll || piece || previouslySelected || pieceCloseTo(s, position)))
3624
- e2.preventDefault();
3625
- else if (e2.touches)
3695
+ if (e.cancelable !== false && (!e.touches || s.blockTouchScroll || piece || previouslySelected || pieceCloseTo(s, position)))
3696
+ e.preventDefault();
3697
+ else if (e.touches)
3626
3698
  return;
3627
3699
  const hadPremove = !!s.premovable.current;
3628
3700
  const hadPredrop = !!s.predroppable.current;
3629
- s.stats.ctrlKey = e2.ctrlKey;
3701
+ s.stats.ctrlKey = e.ctrlKey;
3630
3702
  if (s.selected && canMove(s, s.selected, orig)) {
3631
3703
  anim((state) => selectSquare(state, orig), s);
3632
3704
  } else {
@@ -3643,7 +3715,7 @@ function start2(s, e2) {
3643
3715
  started: s.draggable.autoDistance && s.stats.dragged,
3644
3716
  element,
3645
3717
  previouslySelected,
3646
- originTarget: e2.target,
3718
+ originTarget: e.target,
3647
3719
  keyHasChanged: false
3648
3720
  };
3649
3721
  element.cgDragging = true;
@@ -3672,11 +3744,11 @@ function pieceCloseTo(s, pos) {
3672
3744
  }
3673
3745
  return false;
3674
3746
  }
3675
- function dragNewPiece(s, piece, e2, force) {
3747
+ function dragNewPiece(s, piece, e, force) {
3676
3748
  const key = "a0";
3677
3749
  s.pieces.set(key, piece);
3678
3750
  s.dom.redraw();
3679
- const position = eventPosition(e2);
3751
+ const position = eventPosition(e);
3680
3752
  s.draggable.current = {
3681
3753
  orig: key,
3682
3754
  piece,
@@ -3684,7 +3756,7 @@ function dragNewPiece(s, piece, e2, force) {
3684
3756
  pos: position,
3685
3757
  started: true,
3686
3758
  element: () => pieceElementByKey(s, key),
3687
- originTarget: e2.target,
3759
+ originTarget: e.target,
3688
3760
  newPiece: true,
3689
3761
  force: !!force,
3690
3762
  keyHasChanged: false
@@ -3725,30 +3797,30 @@ function processDrag(s) {
3725
3797
  processDrag(s);
3726
3798
  });
3727
3799
  }
3728
- function move2(s, e2) {
3729
- if (s.draggable.current && (!e2.touches || e2.touches.length < 2)) {
3730
- s.draggable.current.pos = eventPosition(e2);
3800
+ function move2(s, e) {
3801
+ if (s.draggable.current && (!e.touches || e.touches.length < 2)) {
3802
+ s.draggable.current.pos = eventPosition(e);
3731
3803
  }
3732
3804
  }
3733
- function end2(s, e2) {
3805
+ function end2(s, e) {
3734
3806
  const cur = s.draggable.current;
3735
3807
  if (!cur)
3736
3808
  return;
3737
- if (e2.type === "touchend" && e2.cancelable !== false)
3738
- e2.preventDefault();
3739
- if (e2.type === "touchend" && cur.originTarget !== e2.target && !cur.newPiece) {
3809
+ if (e.type === "touchend" && e.cancelable !== false)
3810
+ e.preventDefault();
3811
+ if (e.type === "touchend" && cur.originTarget !== e.target && !cur.newPiece) {
3740
3812
  s.draggable.current = void 0;
3741
3813
  return;
3742
3814
  }
3743
3815
  unsetPremove(s);
3744
3816
  unsetPredrop(s);
3745
- const eventPos = eventPosition(e2) || cur.pos;
3817
+ const eventPos = eventPosition(e) || cur.pos;
3746
3818
  const dest = getKeyAtDomPos(eventPos, whitePov(s), s.dom.bounds());
3747
3819
  if (dest && cur.started && cur.orig !== dest) {
3748
3820
  if (cur.newPiece)
3749
3821
  dropNewPiece(s, cur.orig, dest, cur.force);
3750
3822
  else {
3751
- s.stats.ctrlKey = e2.ctrlKey;
3823
+ s.stats.ctrlKey = e.ctrlKey;
3752
3824
  if (userMove(s, cur.orig, dest))
3753
3825
  s.stats.dragged = true;
3754
3826
  }
@@ -3778,9 +3850,9 @@ function cancel2(s) {
3778
3850
  }
3779
3851
  }
3780
3852
  function removeDragElements(s) {
3781
- const e2 = s.dom.elements;
3782
- if (e2.ghost)
3783
- setVisible(e2.ghost, false);
3853
+ const e = s.dom.elements;
3854
+ if (e.ghost)
3855
+ setVisible(e.ghost, false);
3784
3856
  }
3785
3857
  function pieceElementByKey(s, key) {
3786
3858
  let el = s.dom.elements.board.firstChild;
@@ -4342,7 +4414,7 @@ function renderWrap(element, s) {
4342
4414
  const ranksPositionClass = s.ranksPosition === "left" ? " left" : "";
4343
4415
  if (s.coordinatesOnSquares) {
4344
4416
  const rankN = s.orientation === "white" ? (i) => i + 1 : (i) => 8 - i;
4345
- files.forEach((f, i) => container.appendChild(renderCoords(ranks.map((r2) => f + r2), "squares rank" + rankN(i) + orientClass + ranksPositionClass)));
4417
+ files.forEach((f, i) => container.appendChild(renderCoords(ranks.map((r) => f + r), "squares rank" + rankN(i) + orientClass + ranksPositionClass)));
4346
4418
  } else {
4347
4419
  container.appendChild(renderCoords(ranks, "ranks" + orientClass + ranksPositionClass));
4348
4420
  container.appendChild(renderCoords(files, "files" + orientClass));
@@ -4376,7 +4448,7 @@ function renderCoords(elems, className) {
4376
4448
  }
4377
4449
 
4378
4450
  // node_modules/.pnpm/chessground@9.2.1/node_modules/chessground/dist/drop.js
4379
- function drop(s, e2) {
4451
+ function drop(s, e) {
4380
4452
  if (!s.dropmode.active)
4381
4453
  return;
4382
4454
  unsetPremove(s);
@@ -4384,7 +4456,7 @@ function drop(s, e2) {
4384
4456
  const piece = s.dropmode.piece;
4385
4457
  if (piece) {
4386
4458
  s.pieces.set("a0", piece);
4387
- const position = eventPosition(e2);
4459
+ const position = eventPosition(e);
4388
4460
  const dest = position && getKeyAtDomPos(position, whitePov(s), s.dom.bounds());
4389
4461
  if (dest)
4390
4462
  dropNewPiece(s, "a0", dest);
@@ -4398,7 +4470,7 @@ function bindBoard(s, onResize) {
4398
4470
  if ("ResizeObserver" in window)
4399
4471
  new ResizeObserver(onResize).observe(s.dom.elements.wrap);
4400
4472
  if (s.disableContextMenu || s.drawable.enabled) {
4401
- boardEl.addEventListener("contextmenu", (e2) => e2.preventDefault());
4473
+ boardEl.addEventListener("contextmenu", (e) => e.preventDefault());
4402
4474
  }
4403
4475
  if (s.viewOnly)
4404
4476
  return;
@@ -4431,27 +4503,27 @@ function unbindable(el, eventName, callback, options) {
4431
4503
  el.addEventListener(eventName, callback, options);
4432
4504
  return () => el.removeEventListener(eventName, callback, options);
4433
4505
  }
4434
- var startDragOrDraw = (s) => (e2) => {
4506
+ var startDragOrDraw = (s) => (e) => {
4435
4507
  if (s.draggable.current)
4436
4508
  cancel2(s);
4437
4509
  else if (s.drawable.current)
4438
4510
  cancel(s);
4439
- else if (e2.shiftKey || isRightButton(e2)) {
4511
+ else if (e.shiftKey || isRightButton(e)) {
4440
4512
  if (s.drawable.enabled)
4441
- start(s, e2);
4513
+ start(s, e);
4442
4514
  } else if (!s.viewOnly) {
4443
4515
  if (s.dropmode.active)
4444
- drop(s, e2);
4516
+ drop(s, e);
4445
4517
  else
4446
- start2(s, e2);
4518
+ start2(s, e);
4447
4519
  }
4448
4520
  };
4449
- var dragOrDraw = (s, withDrag, withDraw) => (e2) => {
4521
+ var dragOrDraw = (s, withDrag, withDraw) => (e) => {
4450
4522
  if (s.drawable.current) {
4451
4523
  if (s.drawable.enabled)
4452
- withDraw(s, e2);
4524
+ withDraw(s, e);
4453
4525
  } else if (!s.viewOnly)
4454
- withDrag(s, e2);
4526
+ withDrag(s, e);
4455
4527
  };
4456
4528
 
4457
4529
  // node_modules/.pnpm/chessground@9.2.1/node_modules/chessground/dist/render.js
@@ -4772,7 +4844,7 @@ function debounceRedraw(redrawNow) {
4772
4844
  };
4773
4845
  }
4774
4846
 
4775
- // node_modules/.pnpm/snabbdom@3.6.2/node_modules/snabbdom/build/htmldomapi.js
4847
+ // node_modules/.pnpm/snabbdom@3.5.1/node_modules/snabbdom/build/htmldomapi.js
4776
4848
  function createElement2(tagName2, options) {
4777
4849
  return document.createElement(tagName2, options);
4778
4850
  }
@@ -4887,19 +4959,19 @@ var htmlDomApi = {
4887
4959
  isDocumentFragment
4888
4960
  };
4889
4961
 
4890
- // node_modules/.pnpm/snabbdom@3.6.2/node_modules/snabbdom/build/vnode.js
4962
+ // node_modules/.pnpm/snabbdom@3.5.1/node_modules/snabbdom/build/vnode.js
4891
4963
  function vnode(sel, data, children, text, elm) {
4892
4964
  const key = data === void 0 ? void 0 : data.key;
4893
4965
  return { sel, data, children, text, elm, key };
4894
4966
  }
4895
4967
 
4896
- // node_modules/.pnpm/snabbdom@3.6.2/node_modules/snabbdom/build/is.js
4968
+ // node_modules/.pnpm/snabbdom@3.5.1/node_modules/snabbdom/build/is.js
4897
4969
  var array = Array.isArray;
4898
4970
  function primitive(s) {
4899
4971
  return typeof s === "string" || typeof s === "number" || s instanceof String || s instanceof Number;
4900
4972
  }
4901
4973
 
4902
- // node_modules/.pnpm/snabbdom@3.6.2/node_modules/snabbdom/build/init.js
4974
+ // node_modules/.pnpm/snabbdom@3.5.1/node_modules/snabbdom/build/init.js
4903
4975
  function isUndef(s) {
4904
4976
  return s === void 0;
4905
4977
  }
@@ -4974,9 +5046,7 @@ function init(modules, domApi, options) {
4974
5046
  return function rmCb() {
4975
5047
  if (--listeners === 0) {
4976
5048
  const parent = api.parentNode(childElm);
4977
- if (parent !== null) {
4978
- api.removeChild(parent, childElm);
4979
- }
5049
+ api.removeChild(parent, childElm);
4980
5050
  }
4981
5051
  };
4982
5052
  }
@@ -4998,8 +5068,6 @@ function init(modules, domApi, options) {
4998
5068
  vnode2.text = "";
4999
5069
  }
5000
5070
  vnode2.elm = api.createComment(vnode2.text);
5001
- } else if (sel === "") {
5002
- vnode2.elm = api.createTextNode(vnode2.text);
5003
5071
  } else if (sel !== void 0) {
5004
5072
  const hashIdx = sel.indexOf("#");
5005
5073
  const dotIdx = sel.indexOf(".", hashIdx);
@@ -5013,9 +5081,6 @@ function init(modules, domApi, options) {
5013
5081
  elm.setAttribute("class", sel.slice(dot + 1).replace(/\./g, " "));
5014
5082
  for (i = 0; i < cbs.create.length; ++i)
5015
5083
  cbs.create[i](emptyNode, vnode2);
5016
- if (primitive(vnode2.text) && (!array(children) || children.length === 0)) {
5017
- api.appendChild(elm, api.createTextNode(vnode2.text));
5018
- }
5019
5084
  if (array(children)) {
5020
5085
  for (i = 0; i < children.length; ++i) {
5021
5086
  const ch = children[i];
@@ -5023,6 +5088,8 @@ function init(modules, domApi, options) {
5023
5088
  api.appendChild(elm, createElm(ch, insertedVnodeQueue));
5024
5089
  }
5025
5090
  }
5091
+ } else if (primitive(vnode2.text)) {
5092
+ api.appendChild(elm, api.createTextNode(vnode2.text));
5026
5093
  }
5027
5094
  const hook = vnode2.data.hook;
5028
5095
  if (isDef(hook)) {
@@ -5146,10 +5213,6 @@ function init(modules, domApi, options) {
5146
5213
  idxInOld = oldKeyToIdx[newStartVnode.key];
5147
5214
  if (isUndef(idxInOld)) {
5148
5215
  api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
5149
- newStartVnode = newCh[++newStartIdx];
5150
- } else if (isUndef(oldKeyToIdx[newEndVnode.key])) {
5151
- api.insertBefore(parentElm, createElm(newEndVnode, insertedVnodeQueue), api.nextSibling(oldEndVnode.elm));
5152
- newEndVnode = newCh[--newEndIdx];
5153
5216
  } else {
5154
5217
  elmToMove = oldCh[idxInOld];
5155
5218
  if (elmToMove.sel !== newStartVnode.sel) {
@@ -5159,8 +5222,8 @@ function init(modules, domApi, options) {
5159
5222
  oldCh[idxInOld] = void 0;
5160
5223
  api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);
5161
5224
  }
5162
- newStartVnode = newCh[++newStartIdx];
5163
5225
  }
5226
+ newStartVnode = newCh[++newStartIdx];
5164
5227
  }
5165
5228
  }
5166
5229
  if (newStartIdx <= newEndIdx) {
@@ -5238,7 +5301,7 @@ function init(modules, domApi, options) {
5238
5301
  };
5239
5302
  }
5240
5303
 
5241
- // node_modules/.pnpm/snabbdom@3.6.2/node_modules/snabbdom/build/h.js
5304
+ // node_modules/.pnpm/snabbdom@3.5.1/node_modules/snabbdom/build/h.js
5242
5305
  function addNS(data, children, sel) {
5243
5306
  data.ns = "http://www.w3.org/2000/svg";
5244
5307
  if (sel !== "foreignObject" && children !== void 0) {
@@ -5286,19 +5349,17 @@ function h(sel, b, c) {
5286
5349
  children[i] = vnode(void 0, void 0, void 0, children[i], void 0);
5287
5350
  }
5288
5351
  }
5289
- if (sel.startsWith("svg") && (sel.length === 3 || sel[3] === "." || sel[3] === "#")) {
5352
+ if (sel[0] === "s" && sel[1] === "v" && sel[2] === "g" && (sel.length === 3 || sel[3] === "." || sel[3] === "#")) {
5290
5353
  addNS(data, children, sel);
5291
5354
  }
5292
5355
  return vnode(sel, data, children, text, void 0);
5293
5356
  }
5294
5357
 
5295
- // node_modules/.pnpm/snabbdom@3.6.2/node_modules/snabbdom/build/modules/attributes.js
5358
+ // node_modules/.pnpm/snabbdom@3.5.1/node_modules/snabbdom/build/modules/attributes.js
5296
5359
  var xlinkNS = "http://www.w3.org/1999/xlink";
5297
- var xmlnsNS = "http://www.w3.org/2000/xmlns/";
5298
5360
  var xmlNS = "http://www.w3.org/XML/1998/namespace";
5299
5361
  var colonChar = 58;
5300
5362
  var xChar = 120;
5301
- var mChar = 109;
5302
5363
  function updateAttrs(oldVnode, vnode2) {
5303
5364
  let key;
5304
5365
  const elm = vnode2.elm;
@@ -5324,7 +5385,7 @@ function updateAttrs(oldVnode, vnode2) {
5324
5385
  } else if (key.charCodeAt(3) === colonChar) {
5325
5386
  elm.setAttributeNS(xmlNS, key, cur);
5326
5387
  } else if (key.charCodeAt(5) === colonChar) {
5327
- key.charCodeAt(1) === mChar ? elm.setAttributeNS(xmlnsNS, key, cur) : elm.setAttributeNS(xlinkNS, key, cur);
5388
+ elm.setAttributeNS(xlinkNS, key, cur);
5328
5389
  } else {
5329
5390
  elm.setAttribute(key, cur);
5330
5391
  }
@@ -5342,7 +5403,7 @@ var attributesModule = {
5342
5403
  update: updateAttrs
5343
5404
  };
5344
5405
 
5345
- // node_modules/.pnpm/snabbdom@3.6.2/node_modules/snabbdom/build/modules/class.js
5406
+ // node_modules/.pnpm/snabbdom@3.5.1/node_modules/snabbdom/build/modules/class.js
5346
5407
  function updateClass(oldVnode, vnode2) {
5347
5408
  let cur;
5348
5409
  let name;
@@ -5369,144 +5430,6 @@ function updateClass(oldVnode, vnode2) {
5369
5430
  }
5370
5431
  var classModule = { create: updateClass, update: updateClass };
5371
5432
 
5372
- // src/view/util.ts
5373
- function bindMobileMousedown(el, f, redraw) {
5374
- for (const mousedownEvent of ["touchstart", "mousedown"]) {
5375
- el.addEventListener(
5376
- mousedownEvent,
5377
- (e2) => {
5378
- f(e2);
5379
- e2.preventDefault();
5380
- if (redraw) redraw();
5381
- },
5382
- { passive: false }
5383
- );
5384
- }
5385
- }
5386
- var bind = (eventName, f, redraw, passive = true) => onInsert(
5387
- (el) => el.addEventListener(
5388
- eventName,
5389
- (e2) => {
5390
- const res = f(e2);
5391
- if (res === false) e2.preventDefault();
5392
- redraw?.();
5393
- return res;
5394
- },
5395
- { passive }
5396
- )
5397
- );
5398
- function onInsert(f) {
5399
- return {
5400
- insert: (vnode2) => f(vnode2.elm)
5401
- };
5402
- }
5403
-
5404
- // src/events.ts
5405
- function stepwiseScroll(inner) {
5406
- let scrollTotal = 0;
5407
- return (e2) => {
5408
- scrollTotal += e2.deltaY * (e2.deltaMode ? 40 : 1);
5409
- if (Math.abs(scrollTotal) >= 4) {
5410
- inner(e2, true);
5411
- scrollTotal = 0;
5412
- } else {
5413
- inner(e2, false);
5414
- }
5415
- };
5416
- }
5417
- function eventRepeater(action, e2) {
5418
- const repeat = () => {
5419
- action();
5420
- delay = Math.max(100, delay - delay / 15);
5421
- timeout = setTimeout(repeat, delay);
5422
- };
5423
- let delay = 350;
5424
- let timeout = setTimeout(repeat, 500);
5425
- action();
5426
- const eventName = e2.type == "touchstart" ? "touchend" : "mouseup";
5427
- document.addEventListener(eventName, () => clearTimeout(timeout), { once: true });
5428
- }
5429
- var suppressKeyNavOn = (e2) => e2.altKey || e2.ctrlKey || e2.shiftKey || e2.metaKey || document.activeElement instanceof HTMLInputElement || document.activeElement instanceof HTMLTextAreaElement;
5430
- var onKeyDown = (ctrl) => (e2) => {
5431
- if (suppressKeyNavOn(e2)) return;
5432
- else if (e2.key == "ArrowLeft") ctrl.goTo("prev");
5433
- else if (e2.key == "ArrowRight") ctrl.goTo("next");
5434
- else if (e2.key == "f") ctrl.flip();
5435
- };
5436
-
5437
- // src/view/menu.ts
5438
- var renderMenu = (ctrl) => h("div.lpv__menu.lpv__pane", [
5439
- h(
5440
- "button.lpv__menu__entry.lpv__menu__flip.lpv__fbt",
5441
- {
5442
- hook: bind("click", ctrl.flip)
5443
- },
5444
- ctrl.translate("flipTheBoard")
5445
- ),
5446
- ctrl.opts.menu.analysisBoard?.enabled ? h(
5447
- "a.lpv__menu__entry.lpv__menu__analysis.lpv__fbt",
5448
- {
5449
- attrs: {
5450
- href: ctrl.analysisUrl(),
5451
- target: "_blank"
5452
- }
5453
- },
5454
- ctrl.translate("analysisBoard")
5455
- ) : void 0,
5456
- ctrl.opts.menu.practiceWithComputer?.enabled ? h(
5457
- "a.lpv__menu__entry.lpv__menu__practice.lpv__fbt",
5458
- {
5459
- attrs: {
5460
- href: ctrl.practiceUrl(),
5461
- target: "_blank"
5462
- }
5463
- },
5464
- ctrl.translate("practiceWithComputer")
5465
- ) : void 0,
5466
- ctrl.opts.menu.getPgn.enabled ? h(
5467
- "button.lpv__menu__entry.lpv__menu__pgn.lpv__fbt",
5468
- {
5469
- hook: bind("click", ctrl.togglePgn)
5470
- },
5471
- ctrl.translate("getPgn")
5472
- ) : void 0,
5473
- renderExternalLink(ctrl)
5474
- ]);
5475
- var renderExternalLink = (ctrl) => {
5476
- const link = ctrl.game.metadata.externalLink;
5477
- return link && h(
5478
- "a.lpv__menu__entry.lpv__fbt",
5479
- {
5480
- attrs: {
5481
- href: link,
5482
- target: "_blank"
5483
- }
5484
- },
5485
- ctrl.translate(ctrl.game.metadata.isLichess ? "viewOnLichess" : "viewOnSite")
5486
- );
5487
- };
5488
- var renderControls = (ctrl) => h("div.lpv__controls", [
5489
- ctrl.pane == "board" ? void 0 : dirButton(ctrl, "first", "step-backward"),
5490
- dirButton(ctrl, "prev", "left-open"),
5491
- h(
5492
- "button.lpv__fbt.lpv__controls__menu.lpv__icon",
5493
- {
5494
- class: {
5495
- active: ctrl.pane != "board",
5496
- "lpv__icon-ellipsis-vert": ctrl.pane == "board"
5497
- },
5498
- hook: bind("click", ctrl.toggleMenu)
5499
- },
5500
- ctrl.pane == "board" ? void 0 : "X"
5501
- ),
5502
- dirButton(ctrl, "next", "right-open"),
5503
- ctrl.pane == "board" ? void 0 : dirButton(ctrl, "last", "step-forward")
5504
- ]);
5505
- var dirButton = (ctrl, to, icon) => h(`button.lpv__controls__goto.lpv__controls__goto--${to}.lpv__fbt.lpv__icon.lpv__icon-${icon}`, {
5506
- class: { disabled: ctrl.pane == "board" && !ctrl.canGoTo(to) },
5507
- hook: onInsert((el) => bindMobileMousedown(el, (e2) => eventRepeater(() => ctrl.goTo(to), e2)))
5508
- });
5509
-
5510
5433
  // src/view/glyph.ts
5511
5434
  var renderNag = (nag) => {
5512
5435
  const glyph = glyphs[nag];
@@ -5611,19 +5534,326 @@ var glyphs = {
5611
5534
  }
5612
5535
  };
5613
5536
 
5537
+ // src/view/util.ts
5538
+ function bindMobileMousedown(el, f, redraw) {
5539
+ for (const mousedownEvent of ["touchstart", "mousedown"]) {
5540
+ el.addEventListener(
5541
+ mousedownEvent,
5542
+ (e) => {
5543
+ f(e);
5544
+ e.preventDefault();
5545
+ if (redraw) redraw();
5546
+ },
5547
+ { passive: false }
5548
+ );
5549
+ }
5550
+ }
5551
+ var bind = (eventName, f, redraw, passive = true) => onInsert(
5552
+ (el) => el.addEventListener(
5553
+ eventName,
5554
+ (e) => {
5555
+ const res = f(e);
5556
+ if (res === false) e.preventDefault();
5557
+ redraw?.();
5558
+ return res;
5559
+ },
5560
+ { passive }
5561
+ )
5562
+ );
5563
+ function onInsert(f) {
5564
+ return {
5565
+ insert: (vnode2) => f(vnode2.elm)
5566
+ };
5567
+ }
5568
+ var clockContent = (seconds) => {
5569
+ if (!seconds && seconds !== 0) return ["-"];
5570
+ const date = new Date(seconds * 1e3), sep = ":", baseStr = pad2(date.getUTCMinutes()) + sep + pad2(date.getUTCSeconds());
5571
+ return seconds >= 3600 ? [Math.floor(seconds / 3600) + sep + baseStr] : [baseStr];
5572
+ };
5573
+ var pad2 = (num) => (num < 10 ? "0" : "") + num;
5574
+ var formatSquareForScreenReader = (translate3, file, rank, piece) => {
5575
+ const square = `${file.toUpperCase()}${rank}`;
5576
+ if (!piece) return `${square} ${translate3("aria.empty")}`;
5577
+ const pieceName = translate3(`aria.piece.${piece.role}`);
5578
+ return `${square} ${translate3(`aria.${piece.color}`)} ${pieceName}`;
5579
+ };
5580
+ var formatMoveForScreenReader = (san, nags, translate3) => {
5581
+ let formatted = translate3 ? transSanToWords(san, translate3) : san;
5582
+ if (nags && nags.length > 0) {
5583
+ const annotations = nags.map((nag) => glyphs[nag]?.name).filter((name) => name).join(", ");
5584
+ if (annotations) {
5585
+ formatted += `, ${annotations}`;
5586
+ }
5587
+ }
5588
+ return formatted;
5589
+ };
5590
+ var transSanToWords = (san, translate3) => san.split("").map((c) => {
5591
+ if (c === "x") return translate3("san.takes");
5592
+ if (c === "+") return translate3("san.check");
5593
+ if (c === "#") return translate3("san.checkmate");
5594
+ if (c === "=") return translate3("san.promotesTo");
5595
+ if (c === "@") return translate3("san.droppedOn");
5596
+ const code = c.charCodeAt(0);
5597
+ if (code > 48 && code < 58) return c;
5598
+ if (code > 96 && code < 105) return c.toUpperCase();
5599
+ if (c === "K") return translate3("aria.piece.king");
5600
+ if (c === "Q") return translate3("aria.piece.queen");
5601
+ if (c === "R") return translate3("aria.piece.rook");
5602
+ if (c === "B") return translate3("aria.piece.bishop");
5603
+ if (c === "N") return translate3("aria.piece.knight");
5604
+ if (c === "O") return "O";
5605
+ return c;
5606
+ }).join(" ").replace("O - O - O", translate3("san.longCastling")).replace("O - O", translate3("san.shortCastling"));
5607
+
5608
+ // src/events.ts
5609
+ function stepwiseScroll(inner) {
5610
+ let scrollTotal = 0;
5611
+ return (e) => {
5612
+ scrollTotal += e.deltaY * (e.deltaMode ? 40 : 1);
5613
+ if (Math.abs(scrollTotal) >= 4) {
5614
+ inner(e, true);
5615
+ scrollTotal = 0;
5616
+ } else {
5617
+ inner(e, false);
5618
+ }
5619
+ };
5620
+ }
5621
+ function eventRepeater(action, e) {
5622
+ const repeat = () => {
5623
+ action();
5624
+ delay = Math.max(100, delay - delay / 15);
5625
+ timeout = setTimeout(repeat, delay);
5626
+ };
5627
+ let delay = 350;
5628
+ let timeout = setTimeout(repeat, 500);
5629
+ action();
5630
+ const eventName = e.type == "touchstart" ? "touchend" : "mouseup";
5631
+ document.addEventListener(eventName, () => clearTimeout(timeout), { once: true });
5632
+ }
5633
+ var suppressKeyNavOn = (e) => e.altKey || e.ctrlKey || e.shiftKey || e.metaKey || document.activeElement instanceof HTMLInputElement || document.activeElement instanceof HTMLTextAreaElement;
5634
+ var onKeyDown = (ctrl) => (e) => {
5635
+ if (suppressKeyNavOn(e)) return;
5636
+ else if (e.key == "ArrowLeft") ctrl.goTo("prev");
5637
+ else if (e.key == "ArrowRight") ctrl.goTo("next");
5638
+ else if (e.key == "f") ctrl.flip();
5639
+ };
5640
+
5641
+ // src/view/menu.ts
5642
+ var renderMenu = (ctrl) => h(
5643
+ "div.lpv__menu.lpv__pane",
5644
+ {
5645
+ attrs: {
5646
+ role: "menu",
5647
+ "aria-label": ctrl.translate("menu") ?? "Menu"
5648
+ },
5649
+ hook: {
5650
+ insert: (vnode2) => {
5651
+ const menuEl = vnode2.elm;
5652
+ const firstItem = menuEl.querySelector('[role="menuitem"]');
5653
+ firstItem?.focus();
5654
+ setupMenuKeyboard(ctrl, menuEl);
5655
+ }
5656
+ }
5657
+ },
5658
+ [
5659
+ h(
5660
+ "button.lpv__menu__entry.lpv__menu__flip.lpv__fbt",
5661
+ {
5662
+ attrs: { role: "menuitem" },
5663
+ hook: bind("click", ctrl.flip)
5664
+ },
5665
+ ctrl.translate("flipTheBoard")
5666
+ ),
5667
+ ctrl.opts.menu.analysisBoard?.enabled ? h(
5668
+ "a.lpv__menu__entry.lpv__menu__analysis.lpv__fbt",
5669
+ {
5670
+ attrs: {
5671
+ role: "menuitem",
5672
+ href: ctrl.analysisUrl(),
5673
+ target: "_blank",
5674
+ "aria-label": ctrl.translate("aria.linkOpensInNewTab", ctrl.translate("analysisBoard"))
5675
+ }
5676
+ },
5677
+ ctrl.translate("analysisBoard")
5678
+ ) : void 0,
5679
+ ctrl.opts.menu.practiceWithComputer?.enabled ? h(
5680
+ "a.lpv__menu__entry.lpv__menu__practice.lpv__fbt",
5681
+ {
5682
+ attrs: {
5683
+ role: "menuitem",
5684
+ href: ctrl.practiceUrl(),
5685
+ target: "_blank",
5686
+ "aria-label": ctrl.translate(
5687
+ "aria.linkOpensInNewTab",
5688
+ ctrl.translate("practiceWithComputer")
5689
+ )
5690
+ }
5691
+ },
5692
+ ctrl.translate("practiceWithComputer")
5693
+ ) : void 0,
5694
+ ctrl.opts.menu.getPgn.enabled ? h(
5695
+ "button.lpv__menu__entry.lpv__menu__pgn.lpv__fbt",
5696
+ {
5697
+ attrs: { role: "menuitem" },
5698
+ hook: bind("click", ctrl.togglePgn)
5699
+ },
5700
+ ctrl.translate("getPgn")
5701
+ ) : void 0,
5702
+ renderExternalLink(ctrl)
5703
+ ]
5704
+ );
5705
+ var renderExternalLink = (ctrl) => {
5706
+ const link = ctrl.game.metadata.externalLink;
5707
+ const linkText = ctrl.translate(ctrl.game.metadata.isLichess ? "viewOnLichess" : "viewOnSite");
5708
+ return link && h(
5709
+ "a.lpv__menu__entry.lpv__fbt",
5710
+ {
5711
+ attrs: {
5712
+ role: "menuitem",
5713
+ href: link,
5714
+ target: "_blank",
5715
+ "aria-label": ctrl.translate("aria.linkOpensInNewTab", linkText)
5716
+ }
5717
+ },
5718
+ linkText
5719
+ );
5720
+ };
5721
+ var renderControls = (ctrl) => h(
5722
+ "div.lpv__controls",
5723
+ {
5724
+ attrs: {
5725
+ role: "navigation",
5726
+ "aria-label": ctrl.translate("aria.navigationControls")
5727
+ }
5728
+ },
5729
+ [
5730
+ ctrl.pane == "board" ? void 0 : dirButton(ctrl, "first", "step-backward"),
5731
+ dirButton(ctrl, "prev", "left-open"),
5732
+ h(
5733
+ "button.lpv__fbt.lpv__controls__menu.lpv__icon",
5734
+ {
5735
+ class: {
5736
+ active: ctrl.pane != "board",
5737
+ "lpv__icon-ellipsis-vert": ctrl.pane == "board"
5738
+ },
5739
+ hook: {
5740
+ insert: (vnode2) => {
5741
+ const el = vnode2.elm;
5742
+ el.addEventListener("click", ctrl.toggleMenu);
5743
+ ctrl.menuButton = el;
5744
+ }
5745
+ },
5746
+ attrs: {
5747
+ "aria-label": ctrl.translate("menu"),
5748
+ "aria-expanded": String(ctrl.pane === "menu"),
5749
+ "aria-haspopup": "menu"
5750
+ }
5751
+ },
5752
+ ctrl.pane == "board" ? void 0 : "X"
5753
+ ),
5754
+ dirButton(ctrl, "next", "right-open"),
5755
+ ctrl.pane == "board" ? void 0 : dirButton(ctrl, "last", "step-forward")
5756
+ ]
5757
+ );
5758
+ var dirButton = (ctrl, to, icon) => {
5759
+ const isDisabled = ctrl.pane == "board" && !ctrl.canGoTo(to);
5760
+ return h(`button.lpv__controls__goto.lpv__controls__goto--${to}.lpv__fbt.lpv__icon.lpv__icon-${icon}`, {
5761
+ class: { disabled: isDisabled },
5762
+ hook: onInsert((el) => bindMobileMousedown(el, (e) => eventRepeater(() => ctrl.goTo(to), e))),
5763
+ attrs: {
5764
+ "aria-label": ctrl.translate(`aria.${to}`),
5765
+ "aria-disabled": String(isDisabled),
5766
+ disabled: isDisabled
5767
+ }
5768
+ });
5769
+ };
5770
+ var setupMenuKeyboard = (ctrl, menuEl) => {
5771
+ const handleMenuKeydown = (e) => {
5772
+ switch (e.key) {
5773
+ case "Enter":
5774
+ case " ":
5775
+ e.preventDefault();
5776
+ document.activeElement?.click();
5777
+ break;
5778
+ case "Escape":
5779
+ e.preventDefault();
5780
+ ctrl.toggleMenu();
5781
+ break;
5782
+ }
5783
+ };
5784
+ menuEl.addEventListener("keydown", handleMenuKeydown);
5785
+ };
5786
+
5787
+ // src/view/aria.ts
5788
+ var ariaHidden = { "aria-hidden": true };
5789
+ var presentation = { role: "presentation", "aria-hidden": "true" };
5790
+ var renderAriaAnnouncement = (ctrl) => {
5791
+ const data = ctrl.curData();
5792
+ if (!isMoveData(data)) return "";
5793
+ const moveNumber = Math.ceil(data.ply / 2);
5794
+ const color = data.ply % 2 === 1 ? "white" : "black";
5795
+ const san = data.san;
5796
+ let announcement = ctrl.translate(
5797
+ "aria.move",
5798
+ moveNumber.toString(),
5799
+ ctrl.translate(`aria.${color}`),
5800
+ formatMoveForScreenReader(san, data.nags, ctrl.translate)
5801
+ );
5802
+ const clock = data.clocks && data.clocks[color === "white" ? "white" : "black"];
5803
+ if (clock !== void 0 && ctrl.opts.showClocks) {
5804
+ const clockTime = clockContent(clock).join("");
5805
+ if (clockTime !== "-") {
5806
+ announcement += ", " + ctrl.translate("aria.remaining", clockTime);
5807
+ }
5808
+ }
5809
+ const comments = data.comments.join(" ").trim();
5810
+ if (comments) {
5811
+ announcement += `. ${comments}`;
5812
+ }
5813
+ return announcement;
5814
+ };
5815
+ var renderRootAriaLabel = (ctrl) => {
5816
+ const game = ctrl.game;
5817
+ const formatPlayer = (player) => {
5818
+ let playerInfo = player.name || ctrl.translate("aria.unknownPlayer");
5819
+ if (player.title) {
5820
+ playerInfo = `${player.title} ${playerInfo}`;
5821
+ }
5822
+ if (player.rating) {
5823
+ playerInfo = `${playerInfo}, ${ctrl.translate("aria.rated", player.rating.toString())}`;
5824
+ }
5825
+ return playerInfo;
5826
+ };
5827
+ const formatResult = (result2) => {
5828
+ if (!result2 || result2 === "*") return ctrl.translate("aria.gameInProgress");
5829
+ if (result2 === "1-0") return ctrl.translate("aria.whitesWin");
5830
+ if (result2 === "0-1") return ctrl.translate("aria.blacksWin");
5831
+ if (result2 === "1/2-1/2") return ctrl.translate("aria.draw");
5832
+ return result2;
5833
+ };
5834
+ const whiteName = formatPlayer(game.players.white);
5835
+ const blackName = formatPlayer(game.players.black);
5836
+ const result = formatResult(game.metadata.result);
5837
+ return ctrl.translate("aria.chessGameBetween", whiteName, blackName, result);
5838
+ };
5839
+
5614
5840
  // src/view/side.ts
5615
5841
  var renderMoves = (ctrl) => h("div.lpv__side", [
5616
5842
  h(
5617
5843
  "div.lpv__moves",
5618
5844
  {
5845
+ attrs: {
5846
+ role: "complementary",
5847
+ "aria-label": ctrl.translate("aria.gameMoves")
5848
+ },
5619
5849
  hook: {
5620
5850
  insert: (vnode2) => {
5621
5851
  const el = vnode2.elm;
5622
5852
  if (!ctrl.path.empty()) autoScroll(ctrl, el);
5623
5853
  el.addEventListener(
5624
- "mousedown",
5625
- (e2) => {
5626
- const path = e2.target.getAttribute("p");
5854
+ "click",
5855
+ (e) => {
5856
+ const path = e.target.getAttribute("data-path");
5627
5857
  if (path) ctrl.toPath(new Path(path));
5628
5858
  },
5629
5859
  { passive: true }
@@ -5642,13 +5872,19 @@ var renderMoves = (ctrl) => h("div.lpv__side", [
5642
5872
  ]);
5643
5873
  var renderResultComment = (ctrl) => {
5644
5874
  const res = ctrl.game.metadata.result;
5645
- return res && res != "*" ? [h("comment.result", ctrl.game.metadata.result)] : [];
5875
+ return res && res != "*" ? [
5876
+ h(
5877
+ "comment.result",
5878
+ { attrs: { role: "note", "aria-label": ctrl.translate("aria.gameResult") } },
5879
+ ctrl.game.metadata.result
5880
+ )
5881
+ ] : [];
5646
5882
  };
5647
- var emptyMove = () => h("move.empty", "...");
5648
- var indexNode = (turn) => h("index", `${turn}.`);
5649
- var commentNode = (comment) => h("comment", comment);
5650
- var parenOpen = () => h("paren.open", "(");
5651
- var parenClose = () => h("paren.close", ")");
5883
+ var emptyMove = () => h("button.move.empty", { attrs: { "aria-hidden": "true", disabled: true } }, "...");
5884
+ var indexNode = (turn) => h("index", { attrs: presentation }, `${turn}.`);
5885
+ var commentNode = (comment) => h("comment", { attrs: { role: "note" } }, comment);
5886
+ var parenOpen = () => h("paren.open", { attrs: ariaHidden }, "(");
5887
+ var parenClose = () => h("paren.close", { attrs: ariaHidden }, ")");
5652
5888
  var moveTurn = (move3) => Math.floor((move3.ply - 1) / 2) + 1;
5653
5889
  var makeMoveNodes = (ctrl) => {
5654
5890
  const moveDom = renderMove(ctrl);
@@ -5664,20 +5900,23 @@ var makeMoveNodes = (ctrl) => {
5664
5900
  const addEmptyMove = oddMove && (variations.length || move3.comments.length) && node.children.length;
5665
5901
  if (addEmptyMove) elms.push(emptyMove());
5666
5902
  move3.comments.forEach((comment) => elms.push(commentNode(comment)));
5667
- variations.forEach((variation) => elms.push(makeMainVariation(moveDom, variation)));
5903
+ variations.forEach((variation) => elms.push(makeMainVariation(ctrl.translate, moveDom, variation)));
5668
5904
  if (addEmptyMove) elms.push(indexNode(moveTurn(move3)), emptyMove());
5669
5905
  variations = node.children.slice(1);
5670
5906
  }
5671
5907
  return elms;
5672
5908
  };
5673
- var makeMainVariation = (moveDom, node) => h("variation", [...node.data.startingComments.map(commentNode), ...makeVariationMoves(moveDom, node)]);
5909
+ var makeMainVariation = (translate3, moveDom, node) => h("variation", { attrs: { role: "group", "aria-label": translate3("aria.variation") } }, [
5910
+ ...node.data.startingComments.map(commentNode),
5911
+ ...makeVariationMoves(moveDom, node)
5912
+ ]);
5674
5913
  var makeVariationMoves = (moveDom, node) => {
5675
5914
  let elms = [];
5676
5915
  let variations = [];
5677
- if (node.data.ply % 2 == 0) elms.push(h("index", [moveTurn(node.data), "..."]));
5916
+ if (node.data.ply % 2 == 0) elms.push(h("index", { attrs: presentation }, [moveTurn(node.data), "..."]));
5678
5917
  do {
5679
5918
  const move3 = node.data;
5680
- if (move3.ply % 2 == 1) elms.push(h("index", [moveTurn(move3), "."]));
5919
+ if (move3.ply % 2 == 1) elms.push(h("index", { attrs: presentation }, [moveTurn(move3), "."]));
5681
5920
  elms.push(moveDom(move3));
5682
5921
  move3.comments.forEach((comment) => elms.push(commentNode(comment)));
5683
5922
  variations.forEach((variation) => {
@@ -5689,7 +5928,7 @@ var makeVariationMoves = (moveDom, node) => {
5689
5928
  return elms;
5690
5929
  };
5691
5930
  var renderMove = (ctrl) => (move3) => h(
5692
- "move",
5931
+ "button.move",
5693
5932
  {
5694
5933
  class: {
5695
5934
  current: ctrl.path.equals(move3.path),
@@ -5702,7 +5941,14 @@ var renderMove = (ctrl) => (move3) => h(
5702
5941
  inaccuracy: move3.nags.includes(6)
5703
5942
  },
5704
5943
  attrs: {
5705
- p: move3.path.path
5944
+ "data-path": move3.path.path,
5945
+ role: "button",
5946
+ "aria-label": ctrl.translate(
5947
+ "aria.move",
5948
+ Math.ceil(move3.ply / 2).toString(),
5949
+ ctrl.translate(`aria.${move3.ply % 2 === 1 ? "white" : "black"}`),
5950
+ formatMoveForScreenReader(move3.san, move3.nags, ctrl.translate)
5951
+ )
5706
5952
  }
5707
5953
  },
5708
5954
  [move3.san, ...move3.nags.map(renderNag)]
@@ -5726,9 +5972,14 @@ function renderPlayer(ctrl, side) {
5726
5972
  player.rating ? h("span.lpv__player__rating", ["(", player.rating, ")"]) : void 0
5727
5973
  ];
5728
5974
  return h(`div.lpv__player.lpv__player--${side}`, [
5729
- player.isLichessUser ? h(
5975
+ player.isLichessUser && player.name ? h(
5730
5976
  "a.lpv__player__person.ulpt.user-link",
5731
- { attrs: { href: `${ctrl.opts.lichess}/@/${player.name}` } },
5977
+ {
5978
+ attrs: {
5979
+ href: `${ctrl.opts.lichess}/@/${player.name}`,
5980
+ "aria-label": ctrl.translate("aria.viewProfileOnLichess", player.name)
5981
+ }
5982
+ },
5732
5983
  personEls
5733
5984
  ) : h("span.lpv__player__person", personEls),
5734
5985
  ctrl.opts.showClocks ? renderClock(ctrl, color) : void 0
@@ -5737,14 +5988,67 @@ function renderPlayer(ctrl, side) {
5737
5988
  var renderClock = (ctrl, color) => {
5738
5989
  const move3 = ctrl.curData();
5739
5990
  const clock = move3.clocks && move3.clocks[color];
5740
- return typeof clock == void 0 ? void 0 : h("div.lpv__player__clock", { class: { active: color == move3.turn } }, clockContent(clock));
5991
+ return typeof clock == void 0 ? void 0 : h(
5992
+ "div.lpv__player__clock",
5993
+ {
5994
+ class: { active: color == move3.turn },
5995
+ attrs: {
5996
+ role: "timer",
5997
+ "aria-label": clockContent(clock).join("")
5998
+ }
5999
+ },
6000
+ clockContent(clock)
6001
+ );
5741
6002
  };
5742
- var clockContent = (seconds) => {
5743
- if (!seconds && seconds !== 0) return ["-"];
5744
- const date = new Date(seconds * 1e3), sep = ":", baseStr = pad2(date.getUTCMinutes()) + sep + pad2(date.getUTCSeconds());
5745
- return seconds >= 3600 ? [Math.floor(seconds / 3600) + sep + baseStr] : [baseStr];
6003
+
6004
+ // src/view/accessibleBoard.ts
6005
+ var renderAccessibleBoard = (ctrl) => {
6006
+ const flipped = ctrl.flipped;
6007
+ return h(
6008
+ "div.lpv__sr-only",
6009
+ {
6010
+ attrs: {
6011
+ role: "grid",
6012
+ "aria-label": ctrl.translate("aria.accessibleChessboard"),
6013
+ "aria-hidden": "false"
6014
+ }
6015
+ },
6016
+ renderBoardRows(ctrl, flipped)
6017
+ );
6018
+ };
6019
+ var renderBoardRows = (ctrl, flipped) => {
6020
+ const pieces = ctrl.ground?.state.pieces || read(ctrl.curData().fen);
6021
+ const orderedRanks = flipped ? ranks : invRanks;
6022
+ const orderedFiles = flipped ? [...files].reverse() : files;
6023
+ return orderedRanks.map(
6024
+ (rank) => h(
6025
+ "div",
6026
+ {
6027
+ attrs: {
6028
+ role: "row"
6029
+ }
6030
+ },
6031
+ orderedFiles.map((file) => {
6032
+ const squareKey = `${file}${rank}`;
6033
+ const piece = pieces.get(squareKey);
6034
+ return renderSquare(ctrl.translate, file, rank, piece);
6035
+ })
6036
+ )
6037
+ );
6038
+ };
6039
+ var renderSquare = (translate3, file, rank, piece) => {
6040
+ const ariaLabel = formatSquareForScreenReader(translate3, file, rank, piece);
6041
+ return h(
6042
+ "span",
6043
+ {
6044
+ attrs: {
6045
+ role: "gridcell",
6046
+ "aria-label": ariaLabel
6047
+ }
6048
+ },
6049
+ ariaLabel
6050
+ );
5746
6051
  };
5747
- var pad2 = (num) => (num < 10 ? "0" : "") + num;
5748
6052
 
5749
6053
  // src/view/main.ts
5750
6054
  function view(ctrl) {
@@ -5758,7 +6062,9 @@ function view(ctrl) {
5758
6062
  "lpv--players": showPlayers
5759
6063
  },
5760
6064
  attrs: {
5761
- tabindex: 0
6065
+ role: "region",
6066
+ tabindex: 0,
6067
+ "aria-label": renderRootAriaLabel(ctrl)
5762
6068
  },
5763
6069
  hook: onInsert((el) => {
5764
6070
  ctrl.setGround(Chessground(el.querySelector(".cg-wrap"), makeConfig(ctrl, el)));
@@ -5766,6 +6072,14 @@ function view(ctrl) {
5766
6072
  })
5767
6073
  },
5768
6074
  [
6075
+ h(
6076
+ "div.lpv__sr-only",
6077
+ {
6078
+ attrs: { "aria-live": "polite", "aria-atomic": "true" }
6079
+ },
6080
+ renderAriaAnnouncement(ctrl)
6081
+ ),
6082
+ renderAccessibleBoard(ctrl),
5769
6083
  showPlayers ? renderPlayer(ctrl, "top") : void 0,
5770
6084
  renderBoard(ctrl),
5771
6085
  showPlayers ? renderPlayer(ctrl, "bottom") : void 0,
@@ -5778,15 +6092,16 @@ function view(ctrl) {
5778
6092
  var renderBoard = (ctrl) => h(
5779
6093
  "div.lpv__board",
5780
6094
  {
6095
+ attrs: ariaHidden,
5781
6096
  hook: onInsert((el) => {
5782
6097
  el.addEventListener("click", ctrl.focus);
5783
6098
  if (ctrl.opts.scrollToMove && !("ontouchstart" in window))
5784
6099
  el.addEventListener(
5785
6100
  "wheel",
5786
- stepwiseScroll((e2, scroll) => {
5787
- e2.preventDefault();
5788
- if (e2.deltaY > 0 && scroll) ctrl.goTo("next", false);
5789
- else if (e2.deltaY < 0 && scroll) ctrl.goTo("prev", false);
6101
+ stepwiseScroll((e, scroll) => {
6102
+ e.preventDefault();
6103
+ if (e.deltaY > 0 && scroll) ctrl.goTo("next", false);
6104
+ else if (e.deltaY < 0 && scroll) ctrl.goTo("prev", false);
5790
6105
  })
5791
6106
  );
5792
6107
  })