kokopu-react 1.0.1 → 1.3.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 (79) hide show
  1. package/.nycrc.yml +13 -0
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +3 -0
  4. package/dist/lib/ArrowMarkerIcon.js +1 -1
  5. package/dist/lib/Chessboard.js +267 -89
  6. package/dist/lib/{impl/ErrorBox.js → ErrorBox.js} +6 -7
  7. package/dist/lib/css/chessboard.css +4 -0
  8. package/dist/lib/i18n.js +35 -0
  9. package/dist/lib/index.js +8 -0
  10. package/doc_src/{demo/.eslintrc.yml → .eslintrc.yml} +0 -0
  11. package/doc_src/demo/PageChessboardBase.js +37 -42
  12. package/doc_src/demo/PageChessboardEdition.js +70 -70
  13. package/doc_src/demo/PageChessboardMove.js +20 -27
  14. package/doc_src/demo/PageChessboardSmallScreens.js +15 -16
  15. package/doc_src/examples/ErrorBox.md +3 -0
  16. package/doc_src/theming/LogoRenderer.js +50 -0
  17. package/doc_src/theming/kokopu-react-logo.png +0 -0
  18. package/doc_src/theming/theming.css +29 -0
  19. package/graphic_test_app/02_chessboard_simple.js +1 -0
  20. package/graphic_test_app/04_chessboard_annotations.js +1 -1
  21. package/graphic_test_app/05_chessboard_move.js +1 -0
  22. package/graphic_test_app/07_chessboard_click_squares.js +36 -0
  23. package/graphic_test_app/08_chessboard_move_pieces.js +36 -0
  24. package/graphic_test_app/09_chessboard_edit_arrows.js +36 -0
  25. package/graphic_test_app/10_chessboard_play_moves.js +39 -0
  26. package/graphic_test_app/11_chessboard_play_promotions.js +35 -0
  27. package/graphic_test_app/common/test_app.js +14 -0
  28. package/graphics/logo-small.svg +14 -0
  29. package/graphics/logo.svg +26 -0
  30. package/package.json +29 -22
  31. package/scripts/test_graphic/docker-compose.yml +1 -1
  32. package/scripts/test_graphic/webpack-config.js +6 -1
  33. package/scripts/test_headless.webpack-config.js +6 -1
  34. package/src/Chessboard.js +156 -40
  35. package/src/{impl/ErrorBox.js → ErrorBox.js} +4 -5
  36. package/src/css/chessboard.css +4 -0
  37. package/src/i18n.js +30 -0
  38. package/src/index.js +1 -0
  39. package/test/4_chessboard_graphic.js +2 -2
  40. package/test/5_chessboard_interaction.js +135 -0
  41. package/test/6_chessboard_play_moves.js +107 -0
  42. package/test/common/graphic.js +75 -15
  43. package/test/references/02_chessboard_simple/2.png +0 -0
  44. package/test/references/02_chessboard_simple/5.png +0 -0
  45. package/test/references/03_chessboard_flipped/2.png +0 -0
  46. package/test/references/05_chessboard_move/8.png +0 -0
  47. package/test/references/08_chessboard_move_pieces/after_move.png +0 -0
  48. package/test/references/08_chessboard_move_pieces/empty_square.png +0 -0
  49. package/test/references/08_chessboard_move_pieces/null_vector.png +0 -0
  50. package/test/references/08_chessboard_move_pieces/out_of_board.png +0 -0
  51. package/test/references/08_chessboard_move_pieces/over_arrow_marker.png +0 -0
  52. package/test/references/08_chessboard_move_pieces/over_empty.png +0 -0
  53. package/test/references/08_chessboard_move_pieces/over_non_empty_1.png +0 -0
  54. package/test/references/08_chessboard_move_pieces/over_non_empty_2.png +0 -0
  55. package/test/references/08_chessboard_move_pieces/over_square_marker.png +0 -0
  56. package/test/references/08_chessboard_move_pieces/over_text_marker.png +0 -0
  57. package/test/references/09_chessboard_edit_arrows/base_1.png +0 -0
  58. package/test/references/09_chessboard_edit_arrows/base_2.png +0 -0
  59. package/test/references/09_chessboard_edit_arrows/edit_color_not_set.png +0 -0
  60. package/test/references/09_chessboard_edit_arrows/null_vector.png +0 -0
  61. package/test/references/09_chessboard_edit_arrows/out_of_board.png +0 -0
  62. package/test/references/09_chessboard_edit_arrows/over_arrow_marker.png +0 -0
  63. package/test/references/09_chessboard_edit_arrows/over_square_marker.png +0 -0
  64. package/test/references/10_chessboard_play_moves/castling_move.png +0 -0
  65. package/test/references/10_chessboard_play_moves/chess960_ambiguous_king_move.png +0 -0
  66. package/test/references/10_chessboard_play_moves/chess960_castling_move_1.png +0 -0
  67. package/test/references/10_chessboard_play_moves/chess960_castling_move_2.png +0 -0
  68. package/test/references/10_chessboard_play_moves/chess960_non_kxr_castling.png +0 -0
  69. package/test/references/10_chessboard_play_moves/illegal_move.png +0 -0
  70. package/test/references/10_chessboard_play_moves/illegal_position.png +0 -0
  71. package/test/references/10_chessboard_play_moves/null_vector.png +0 -0
  72. package/test/references/10_chessboard_play_moves/out_of_board.png +0 -0
  73. package/test/references/10_chessboard_play_moves/regular_move_1.png +0 -0
  74. package/test/references/10_chessboard_play_moves/regular_move_2.png +0 -0
  75. package/test/references/10_chessboard_play_moves/wrong_color.png +0 -0
  76. package/test/references/11_chessboard_play_promotions/antichess_promotion.png +0 -0
  77. package/test/references/11_chessboard_play_promotions/cancel_promotion.png +0 -0
  78. package/test/references/11_chessboard_play_promotions/regular_promotion_1.png +0 -0
  79. package/test/references/11_chessboard_play_promotions/regular_promotion_2.png +0 -0
package/.nycrc.yml ADDED
@@ -0,0 +1,13 @@
1
+ temp-dir: ./build/.nyc_output
2
+ report-dir: ./build/coverage
3
+
4
+ reporter:
5
+ - text
6
+ - html
7
+
8
+ check-coverage: true
9
+
10
+ exclude:
11
+ - build/**
12
+ - graphic_test_app/**
13
+ - test/**
package/CHANGELOG.md CHANGED
@@ -1,6 +1,24 @@
1
1
  ChangeLog
2
2
  =========
3
3
 
4
+ 1.3.0 (September 26, 2021)
5
+ --------------------------
6
+ * Expose component `ErrorBox`.
7
+ * Minor fixes in documentation.
8
+
9
+ 1.2.0 (September 13, 2021)
10
+ --------------------------
11
+ * Fix ambiguous castling move issue at Chess960.
12
+
13
+ 1.1.0 (August 15, 2021)
14
+ -----------------------
15
+ * Provide interaction mode `playMoves`.
16
+ * Add code coverage.
17
+
18
+ 1.0.2 (August 10, 2021)
19
+ -----------------------
20
+ * No need for ReactDOM in dependencies (dev-dependencies only).
21
+
4
22
  1.0.1 (July 30, 2021)
5
23
  ---------------------
6
24
  * Wrong config in `package.json`.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  Kokopu-React
2
2
  ============
3
3
 
4
+ <img align="right" width="96" height="96" src="graphics/logo.svg" />
5
+
4
6
  Kokopu-React is a [React](https://reactjs.org/)-based library to create and display chessboard components.
5
7
  Kokopu-React is built on top of [Kokopu](https://www.npmjs.com/package/kokopu), a headless library that
6
8
  implements all the chess logic (game rules, parsing of [FEN](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation)
@@ -9,6 +11,7 @@ and [PGN](https://en.wikipedia.org/wiki/Portable_Game_Notation) formats...).
9
11
  https://www.npmjs.com/package/kokopu-react
10
12
 
11
13
  [![Build Status](https://travis-ci.com/yo35/kokopu-react.svg?branch=master)](https://travis-ci.com/yo35/kokopu-react)
14
+ [![Coverage Status](https://coveralls.io/repos/github/yo35/kokopu-react/badge.svg?branch=master)](https://coveralls.io/github/yo35/kokopu-react?branch=master)
12
15
 
13
16
 
14
17
 
@@ -31,7 +31,7 @@ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || func
31
31
 
32
32
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
33
33
 
34
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
34
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
35
35
 
36
36
  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
37
37
 
@@ -21,7 +21,9 @@ var _piecesets2 = _interopRequireDefault(require("./impl/piecesets"));
21
21
 
22
22
  var _ArrowTip = _interopRequireDefault(require("./impl/ArrowTip"));
23
23
 
24
- var _ErrorBox = _interopRequireDefault(require("./impl/ErrorBox"));
24
+ var _ErrorBox = _interopRequireDefault(require("./ErrorBox"));
25
+
26
+ var _i18n = _interopRequireDefault(require("./i18n"));
25
27
 
26
28
  var _markers = require("./markers");
27
29
 
@@ -61,7 +63,7 @@ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || func
61
63
 
62
64
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
63
65
 
64
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
66
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
65
67
 
66
68
  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
67
69
 
@@ -98,8 +100,10 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
98
100
 
99
101
  _this = _super.call(this, props);
100
102
  _this.state = {
103
+ inhibitedSquare: '-',
101
104
  draggedSquare: '-',
102
105
  hoveredSquare: '-',
106
+ promotionDrawer: false,
103
107
  windowWidth: window.innerWidth
104
108
  };
105
109
  _this.arrowTipIdSuffix = (0, _util.generateRandomId)();
@@ -127,35 +131,23 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
127
131
  var _this2 = this;
128
132
 
129
133
  // Compute the current position.
130
- var parseInfo = parsePosition(this.props.position);
134
+ var info = this.getPositionAndMoveInfo();
131
135
 
132
- if (parseInfo.error) {
136
+ if (info.positionError) {
137
+ return /*#__PURE__*/_react["default"].createElement(_ErrorBox["default"], {
138
+ title: _i18n["default"].INVALID_FEN_ERROR_TITLE,
139
+ message: info.message
140
+ });
141
+ } else if (info.moveError) {
133
142
  return /*#__PURE__*/_react["default"].createElement(_ErrorBox["default"], {
134
- title: "Error while analysing a FEN string.",
135
- message: parseInfo.message
143
+ title: _i18n["default"].INVALID_NOTATION_ERROR_TITLE,
144
+ message: info.message
136
145
  });
137
146
  }
138
147
 
139
- var position = parseInfo.position;
140
- var move = null;
141
- var positionBefore = null;
142
-
143
- if (this.props.move) {
144
- parseInfo = parseMove(position, this.props.move);
145
-
146
- if (parseInfo.error) {
147
- return /*#__PURE__*/_react["default"].createElement(_ErrorBox["default"], {
148
- title: "Invalid move notation.",
149
- message: parseInfo.message
150
- });
151
- }
152
-
153
- move = parseInfo.move;
154
- positionBefore = position;
155
- position = new _kokopu["default"].Position(position);
156
- position.play(move);
157
- } // Compute the attributes.
158
-
148
+ var position = info.position,
149
+ move = info.move,
150
+ positionBefore = info.positionBefore; // Compute the attributes.
159
151
 
160
152
  var squareSize = this.getSquareSize();
161
153
  var coordinateVisible = this.isCoordinateVisible();
@@ -263,7 +255,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
263
255
  }
264
256
  });
265
257
 
266
- return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, this.renderSquareMarkers(sqm, squareSize, colorset), this.renderHoveredSquare(squareSize, colorset), pieces, this.renderTextMarkers(txtm, squareSize, colorset), this.renderArrowMarkers(arm, squareSize, colorset), this.renderMoveArrow(move, 1, squareSize, colorset), handles, this.renderDraggedPiece(position, squareSize, pieceset), this.renderDraggedArrow(squareSize, colorset), this.renderTurnFlag(position.turn(), squareSize, pieceset));
258
+ return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, this.renderSquareMarkers(sqm, squareSize, colorset), this.renderHoveredSquare(squareSize, colorset), pieces, this.renderTextMarkers(txtm, squareSize, colorset), this.renderArrowMarkers(arm, squareSize, colorset), this.renderMoveArrow(move, 1, squareSize, colorset), handles, this.renderPromotionDrawer(position, squareSize, colorset, pieceset), this.renderDraggedPiece(position, squareSize, pieceset), this.renderDraggedArrow(squareSize, colorset), this.renderTurnFlag(position.turn(), squareSize, pieceset));
267
259
  }
268
260
  }, {
269
261
  key: "renderSquare",
@@ -309,7 +301,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
309
301
  value: function renderPiece(position, squareSize, pieceset, sq) {
310
302
  var cp = position.square(sq);
311
303
 
312
- if (cp === '-' || this.isPieceDragModeEnabled() && this.state.draggedSquare === sq) {
304
+ if (cp === '-' || this.state.inhibitedSquare === sq) {
313
305
  return undefined;
314
306
  }
315
307
 
@@ -371,7 +363,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
371
363
  }, {
372
364
  key: "renderDraggedPiece",
373
365
  value: function renderDraggedPiece(position, squareSize, pieceset) {
374
- if (!this.isPieceDragModeEnabled() || this.state.draggedSquare === '-') {
366
+ if (!(this.isMovePieceModeEnabled() || this.isPlayMoveModeEnabled()) || this.state.draggedSquare === '-') {
375
367
  return undefined;
376
368
  }
377
369
 
@@ -379,11 +371,13 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
379
371
  x = _this$getSquareCoordi7.x,
380
372
  y = _this$getSquareCoordi7.y;
381
373
 
374
+ x = Math.min(Math.max(x + this.state.dragPosition.x, 0), 7 * squareSize);
375
+ y = Math.min(Math.max(y + this.state.dragPosition.y, 0), 7 * squareSize);
382
376
  var cp = position.square(this.state.draggedSquare);
383
377
  return /*#__PURE__*/_react["default"].createElement("image", {
384
378
  className: "kokopu-pieceDraggable kokopu-dragging",
385
- x: x + this.state.dragPosition.x,
386
- y: y + this.state.dragPosition.y,
379
+ x: x,
380
+ y: y,
387
381
  width: squareSize,
388
382
  height: squareSize,
389
383
  href: pieceset[cp]
@@ -392,7 +386,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
392
386
  }, {
393
387
  key: "renderDraggedArrow",
394
388
  value: function renderDraggedArrow(squareSize, colorset) {
395
- if (!this.isArrowDragModeEnabled() || this.state.draggedSquare === '-') {
389
+ if (!this.isEditArrowModeEnabled() || this.state.draggedSquare === '-') {
396
390
  return undefined;
397
391
  }
398
392
 
@@ -421,38 +415,90 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
421
415
  });
422
416
  }
423
417
  }, {
424
- key: "renderSquareHandle",
425
- value: function renderSquareHandle(position, squareSize, sq) {
418
+ key: "renderPromotionDrawer",
419
+ value: function renderPromotionDrawer(position, squareSize, colorset, pieceset) {
426
420
  var _this6 = this;
427
421
 
428
- var _this$getSquareCoordi9 = this.getSquareCoordinates(squareSize, sq),
422
+ if (!this.state.promotionDrawer) {
423
+ return undefined;
424
+ }
425
+
426
+ var _this$getSquareCoordi9 = this.getSquareCoordinates(squareSize, this.state.promotionDrawer.origin),
429
427
  x = _this$getSquareCoordi9.x,
430
428
  y = _this$getSquareCoordi9.y;
431
429
 
432
- if (this.isPieceDragModeEnabled() && position.square(sq) !== '-' || this.isArrowDragModeEnabled()) {
430
+ var inverted = position.turn() === (this.props.flipped ? 'w' : 'b'); // false==top-to-bottom true==bottom-to-top
431
+
432
+ var y0 = inverted ? y - squareSize * (this.state.promotionDrawer.buttons.length - 1) : y;
433
+ var buttons = this.state.promotionDrawer.buttons.map(function (p, i) {
434
+ var cp = position.turn() + p;
435
+ return /*#__PURE__*/_react["default"].createElement("image", {
436
+ key: 'drawer-piece-' + p,
437
+ className: "kokopu-clickable",
438
+ x: x,
439
+ y: y + i * (inverted ? -squareSize : squareSize),
440
+ width: squareSize,
441
+ height: squareSize,
442
+ href: pieceset[cp],
443
+ onClick: function onClick() {
444
+ return _this6.handleDrawerButtonClicked(p);
445
+ }
446
+ });
447
+ });
448
+ return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("rect", {
449
+ className: "kokopu-handle",
450
+ x: 0,
451
+ y: 0,
452
+ width: squareSize * 8,
453
+ height: squareSize * 8,
454
+ onClick: function onClick() {
455
+ return _this6.handleDrawerCancelButtonClicked();
456
+ }
457
+ }), /*#__PURE__*/_react["default"].createElement("rect", {
458
+ x: x,
459
+ y: y0,
460
+ width: squareSize,
461
+ height: squareSize * this.state.promotionDrawer.buttons.length,
462
+ fill: colorset.b
463
+ }), /*#__PURE__*/_react["default"].createElement("rect", {
464
+ x: x,
465
+ y: y0,
466
+ width: squareSize,
467
+ height: squareSize * this.state.promotionDrawer.buttons.length,
468
+ className: "kokopu-drawerMask",
469
+ fill: colorset.w
470
+ }), buttons);
471
+ }
472
+ }, {
473
+ key: "renderSquareHandle",
474
+ value: function renderSquareHandle(position, squareSize, sq) {
475
+ var _this7 = this;
476
+
477
+ var _this$getSquareCoordi10 = this.getSquareCoordinates(squareSize, sq),
478
+ x = _this$getSquareCoordi10.x,
479
+ y = _this$getSquareCoordi10.y;
480
+
481
+ var dragEnabledForMovePieces = this.isMovePieceModeEnabled() && position.square(sq) !== '-';
482
+ var dragEnabledForEditArrows = this.isEditArrowModeEnabled();
483
+ var dragEnabledForPlayMoves = this.isPlayMoveModeEnabled() && position.isLegal() && position.square(sq).startsWith(position.turn()) && !this.state.promotionDrawer;
484
+
485
+ if (dragEnabledForMovePieces || dragEnabledForEditArrows || dragEnabledForPlayMoves) {
433
486
  var dragPosition = this.state.draggedSquare === sq ? this.state.dragPosition : {
434
487
  x: 0,
435
488
  y: 0
436
489
  };
437
- var bounds = this.isPieceDragModeEnabled() ? {
438
- left: -x,
439
- top: -y,
440
- right: 7 * squareSize - x,
441
- bottom: 7 * squareSize - y
442
- } : undefined;
443
- var classNames = ['kokopu-handle', this.isPieceDragModeEnabled() ? 'kokopu-pieceDraggable' : 'kokopu-arrowDraggable'];
490
+ var classNames = ['kokopu-handle', this.isEditArrowModeEnabled() ? 'kokopu-arrowDraggable' : 'kokopu-pieceDraggable'];
444
491
  return /*#__PURE__*/_react["default"].createElement(_reactDraggable["default"], {
445
492
  key: 'handle-' + sq,
446
493
  position: dragPosition,
447
- bounds: bounds,
448
494
  onStart: function onStart(evt) {
449
- return _this6.handleDragStart(sq, evt);
495
+ return _this7.handleDragStart(sq, evt);
450
496
  },
451
497
  onDrag: function onDrag(_, dragData) {
452
- return _this6.handleDrag(sq, dragData);
498
+ return _this7.handleDrag(sq, dragData);
453
499
  },
454
500
  onStop: function onStop(_, dragData) {
455
- return _this6.handleDragStop(sq, dragData);
501
+ return _this7.handleDragStop(sq, dragData);
456
502
  }
457
503
  }, /*#__PURE__*/_react["default"].createElement("rect", {
458
504
  className: classNames.join(' '),
@@ -470,7 +516,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
470
516
  width: squareSize,
471
517
  height: squareSize,
472
518
  onClick: function onClick() {
473
- return _this6.handleSquareClicked(sq);
519
+ return _this7.handleSquareClicked(sq);
474
520
  }
475
521
  });
476
522
  } else {
@@ -480,7 +526,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
480
526
  }, {
481
527
  key: "renderSquareMarkers",
482
528
  value: function renderSquareMarkers(sqm, squareSize, colorset) {
483
- var _this7 = this;
529
+ var _this8 = this;
484
530
 
485
531
  var result = [];
486
532
  Object.entries(sqm).forEach(function (_ref) {
@@ -488,9 +534,9 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
488
534
  sq = _ref2[0],
489
535
  color = _ref2[1];
490
536
 
491
- var _this7$getSquareCoord = _this7.getSquareCoordinates(squareSize, sq),
492
- x = _this7$getSquareCoord.x,
493
- y = _this7$getSquareCoord.y;
537
+ var _this8$getSquareCoord = _this8.getSquareCoordinates(squareSize, sq),
538
+ x = _this8$getSquareCoord.x,
539
+ y = _this8$getSquareCoord.y;
494
540
 
495
541
  result.push( /*#__PURE__*/_react["default"].createElement("rect", {
496
542
  key: 'sqm-' + sq,
@@ -507,7 +553,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
507
553
  }, {
508
554
  key: "renderTextMarkers",
509
555
  value: function renderTextMarkers(txtm, squareSize, colorset) {
510
- var _this8 = this;
556
+ var _this9 = this;
511
557
 
512
558
  var result = [];
513
559
  Object.entries(txtm).forEach(function (_ref3) {
@@ -515,9 +561,9 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
515
561
  sq = _ref4[0],
516
562
  value = _ref4[1];
517
563
 
518
- var _this8$getSquareCoord = _this8.getSquareCoordinates(squareSize, sq),
519
- x = _this8$getSquareCoord.x,
520
- y = _this8$getSquareCoord.y;
564
+ var _this9$getSquareCoord = _this9.getSquareCoordinates(squareSize, sq),
565
+ x = _this9$getSquareCoord.x,
566
+ y = _this9$getSquareCoord.y;
521
567
 
522
568
  x += squareSize / 2;
523
569
  y += squareSize / 2;
@@ -537,7 +583,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
537
583
  }, {
538
584
  key: "renderArrowMarkers",
539
585
  value: function renderArrowMarkers(arm, squareSize, colorset) {
540
- var _this9 = this;
586
+ var _this10 = this;
541
587
 
542
588
  var result = [];
543
589
  var strokeWidth = squareSize * STROKE_THICKNESS_FACTOR;
@@ -553,13 +599,13 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
553
599
  return;
554
600
  }
555
601
 
556
- var _this9$getSquareCoord = _this9.getSquareCoordinates(squareSize, from),
557
- xFrom = _this9$getSquareCoord.x,
558
- yFrom = _this9$getSquareCoord.y;
602
+ var _this10$getSquareCoor = _this10.getSquareCoordinates(squareSize, from),
603
+ xFrom = _this10$getSquareCoor.x,
604
+ yFrom = _this10$getSquareCoor.y;
559
605
 
560
- var _this9$getSquareCoord2 = _this9.getSquareCoordinates(squareSize, to),
561
- xTo = _this9$getSquareCoord2.x,
562
- yTo = _this9$getSquareCoord2.y;
606
+ var _this10$getSquareCoor2 = _this10.getSquareCoordinates(squareSize, to),
607
+ xTo = _this10$getSquareCoor2.x,
608
+ yTo = _this10$getSquareCoor2.y;
563
609
 
564
610
  xFrom += squareSize / 2;
565
611
  yFrom += squareSize / 2;
@@ -568,7 +614,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
568
614
  xTo += Math.sign(xFrom - xTo) * ARROW_TIP_OFFSET_FACTOR * squareSize;
569
615
  yTo += Math.sign(yFrom - yTo) * ARROW_TIP_OFFSET_FACTOR * squareSize;
570
616
 
571
- var arrowTipId = _this9.getArrowTipId(color);
617
+ var arrowTipId = _this10.getArrowTipId(color);
572
618
 
573
619
  result.push( /*#__PURE__*/_react["default"].createElement("line", {
574
620
  key: 'arm-' + vect,
@@ -593,16 +639,16 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
593
639
  return undefined;
594
640
  }
595
641
 
596
- var _this$getSquareCoordi10 = this.getSquareCoordinates(squareSize, move.from()),
597
- xFrom = _this$getSquareCoordi10.x,
598
- yFrom = _this$getSquareCoordi10.y;
642
+ var _this$getSquareCoordi11 = this.getSquareCoordinates(squareSize, move.from()),
643
+ xFrom = _this$getSquareCoordi11.x,
644
+ yFrom = _this$getSquareCoordi11.y;
599
645
 
600
646
  xFrom += squareSize / 2;
601
647
  yFrom += squareSize / 2;
602
648
 
603
- var _this$getSquareCoordi11 = this.getSquareCoordinates(squareSize, move.to()),
604
- xTo = _this$getSquareCoordi11.x,
605
- yTo = _this$getSquareCoordi11.y;
649
+ var _this$getSquareCoordi12 = this.getSquareCoordinates(squareSize, move.to()),
650
+ xTo = _this$getSquareCoordi12.x,
651
+ yTo = _this$getSquareCoordi12.y;
606
652
 
607
653
  xTo += squareSize / 2;
608
654
  yTo += squareSize / 2;
@@ -689,6 +735,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
689
735
  value: function handleDragStart(sq, evt) {
690
736
  var squareBoundary = evt.target.getBoundingClientRect();
691
737
  this.setState({
738
+ inhibitedSquare: this.isMovePieceModeEnabled() || this.isPlayMoveModeEnabled() ? sq : '-',
692
739
  draggedSquare: sq,
693
740
  hoveredSquare: sq,
694
741
  cursorOffset: {
@@ -706,15 +753,13 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
706
753
  value: function handleDrag(sq, dragData) {
707
754
  var squareSize = this.getSquareSize();
708
755
 
709
- var _this$getSquareCoordi12 = this.getSquareCoordinates(squareSize, sq),
710
- x = _this$getSquareCoordi12.x,
711
- y = _this$getSquareCoordi12.y;
756
+ var _this$getSquareCoordi13 = this.getSquareCoordinates(squareSize, sq),
757
+ x = _this$getSquareCoordi13.x,
758
+ y = _this$getSquareCoordi13.y;
712
759
 
713
760
  var targetSq = this.getSquareAt(squareSize, x + dragData.x + this.state.cursorOffset.x, y + dragData.y + this.state.cursorOffset.y);
714
761
  this.setState({
715
- draggedSquare: sq,
716
762
  hoveredSquare: targetSq,
717
- cursorOffset: this.state.cursorOffset,
718
763
  dragPosition: {
719
764
  x: dragData.x,
720
765
  y: dragData.y
@@ -726,24 +771,84 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
726
771
  value: function handleDragStop(sq, dragData) {
727
772
  var squareSize = this.getSquareSize();
728
773
 
729
- var _this$getSquareCoordi13 = this.getSquareCoordinates(squareSize, sq),
730
- x = _this$getSquareCoordi13.x,
731
- y = _this$getSquareCoordi13.y;
774
+ var _this$getSquareCoordi14 = this.getSquareCoordinates(squareSize, sq),
775
+ x = _this$getSquareCoordi14.x,
776
+ y = _this$getSquareCoordi14.y;
732
777
 
733
778
  var targetSq = this.getSquareAt(squareSize, x + dragData.x + this.state.cursorOffset.x, y + dragData.y + this.state.cursorOffset.y);
734
779
  this.setState({
780
+ inhibitedSquare: '-',
735
781
  draggedSquare: '-',
736
782
  hoveredSquare: '-'
737
783
  });
738
784
 
739
- if (sq === targetSq) {
785
+ if (sq === targetSq || targetSq === '-') {
740
786
  return;
741
787
  }
742
788
 
743
- if (this.isPieceDragModeEnabled() && this.props.onPieceMoved) {
789
+ if (this.isMovePieceModeEnabled() && this.props.onPieceMoved) {
744
790
  this.props.onPieceMoved(sq, targetSq);
745
- } else if (this.isArrowDragModeEnabled() && this.props.onArrowEdited) {
791
+ } else if (this.isEditArrowModeEnabled() && this.props.onArrowEdited) {
746
792
  this.props.onArrowEdited(sq, targetSq);
793
+ } else if (this.isPlayMoveModeEnabled()) {
794
+ var _this$getPositionAndM = this.getPositionAndMoveInfo(),
795
+ position = _this$getPositionAndM.position;
796
+
797
+ var info = position.isMoveLegal(sq, targetSq);
798
+
799
+ if (!info) {
800
+ return;
801
+ }
802
+
803
+ switch (info.status) {
804
+ // Regular move.
805
+ case 'regular':
806
+ if (this.props.onMovePlayed) {
807
+ this.props.onMovePlayed(position.notation(info()));
808
+ }
809
+
810
+ break;
811
+ // Promotion move.
812
+
813
+ case 'promotion':
814
+ this.setState({
815
+ inhibitedSquare: sq,
816
+ promotionDrawer: {
817
+ origin: targetSq,
818
+ buttons: position.variant() === 'antichess' ? ['q', 'r', 'b', 'n', 'k'] : ['q', 'r', 'b', 'n'],
819
+ builder: function builder(piece) {
820
+ return position.notation(info(piece));
821
+ }
822
+ }
823
+ });
824
+ break;
825
+ // Other cases are not supposed to happen.
826
+ // istanbul ignore next
827
+
828
+ default:
829
+ break;
830
+ }
831
+ }
832
+ }
833
+ }, {
834
+ key: "handleDrawerCancelButtonClicked",
835
+ value: function handleDrawerCancelButtonClicked() {
836
+ this.setState({
837
+ inhibitedSquare: '-',
838
+ promotionDrawer: false
839
+ });
840
+ }
841
+ }, {
842
+ key: "handleDrawerButtonClicked",
843
+ value: function handleDrawerButtonClicked(piece) {
844
+ var builder = this.state.promotionDrawer.builder;
845
+ this.setState({
846
+ inhibitedSquare: '-',
847
+ promotionDrawer: false
848
+ });
849
+
850
+ if (this.props.onMovePlayed) {
851
+ this.props.onMovePlayed(builder(piece));
747
852
  }
748
853
  }
749
854
  }, {
@@ -758,17 +863,26 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
758
863
  */
759
864
 
760
865
  }, {
761
- key: "isPieceDragModeEnabled",
762
- value: function isPieceDragModeEnabled() {
866
+ key: "isMovePieceModeEnabled",
867
+ value: function isMovePieceModeEnabled() {
763
868
  return this.props.interactionMode === 'movePieces';
764
869
  }
870
+ /**
871
+ * Whether the "play move" mode is enabled or not.
872
+ */
873
+
874
+ }, {
875
+ key: "isPlayMoveModeEnabled",
876
+ value: function isPlayMoveModeEnabled() {
877
+ return this.props.interactionMode === 'playMoves';
878
+ }
765
879
  /**
766
880
  * Whether the "edit arrow" mode is enabled or not.
767
881
  */
768
882
 
769
883
  }, {
770
- key: "isArrowDragModeEnabled",
771
- value: function isArrowDragModeEnabled() {
884
+ key: "isEditArrowModeEnabled",
885
+ value: function isEditArrowModeEnabled() {
772
886
  return this.props.interactionMode === 'editArrows' && (0, _util.isValidColor)(this.props.editedArrowColor);
773
887
  }
774
888
  /**
@@ -810,6 +924,56 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
810
924
  y: y
811
925
  };
812
926
  }
927
+ /**
928
+ * Return information regarding the current displayed position and move, or parsing error message if something went wrong.
929
+ */
930
+
931
+ }, {
932
+ key: "getPositionAndMoveInfo",
933
+ value: function getPositionAndMoveInfo() {
934
+ // Parse the position.
935
+ var positionInfo = parsePosition(this.props.position);
936
+
937
+ if (positionInfo.error) {
938
+ return {
939
+ positionError: true,
940
+ moveError: true,
941
+ message: positionInfo.message
942
+ };
943
+ } // Nothing else to do if no move is defined.
944
+
945
+
946
+ if (!this.props.move) {
947
+ return {
948
+ positionError: false,
949
+ moveError: false,
950
+ position: positionInfo.position
951
+ };
952
+ } // Parse the move.
953
+
954
+
955
+ var moveInfo = parseMove(positionInfo.position, this.props.move);
956
+
957
+ if (moveInfo.error) {
958
+ return {
959
+ positionError: false,
960
+ moveError: true,
961
+ message: moveInfo.message,
962
+ positionBefore: positionInfo.position
963
+ };
964
+ } // Compute the position after the move and return the result.
965
+
966
+
967
+ var positionAfter = new _kokopu["default"].Position(positionInfo.position);
968
+ positionAfter.play(moveInfo.move);
969
+ return {
970
+ positionError: false,
971
+ moveError: false,
972
+ positionBefore: positionInfo.position,
973
+ move: moveInfo.move,
974
+ position: positionAfter
975
+ };
976
+ }
813
977
  /**
814
978
  * Return the square at the given location.
815
979
  */
@@ -1047,8 +1211,13 @@ Chessboard.propTypes = {
1047
1211
 
1048
1212
  /**
1049
1213
  * Type of action allowed with the mouse on the chessboard. If undefined, then the user cannot interact with the component.
1214
+ *
1215
+ * - `'movePieces'` allows the user to drag & drop the chess pieces from one square to another (regardless of the chess rules),
1216
+ * - `'clickSquares'` allows the user to click on squares,
1217
+ * - `'editArrows'` allows the user to draw arrow markers from one square to another (warning: attribute `editedArrowColor` must be set),
1218
+ * - `'playMoves'` allows the user to play legal chess moves (thus no interaction is possible if the displayed position is not legal).
1050
1219
  */
1051
- interactionMode: _propTypes["default"].oneOf(['movePieces', 'clickSquares', 'editArrows']),
1220
+ interactionMode: _propTypes["default"].oneOf(['movePieces', 'clickSquares', 'editArrows', 'playMoves']),
1052
1221
 
1053
1222
  /**
1054
1223
  * Color of the edited arrow (only used if `interactionMode` is set to `'editArrows'`).
@@ -1076,7 +1245,14 @@ Chessboard.propTypes = {
1076
1245
  * @param {string} from Origin square (e.g. `'g1'`).
1077
1246
  * @param {string} to Target square (e.g. `'f3'`).
1078
1247
  */
1079
- onArrowEdited: _propTypes["default"].func
1248
+ onArrowEdited: _propTypes["default"].func,
1249
+
1250
+ /**
1251
+ * Callback invoked when a move is played (only if `interactionMode` is set to `'playMoves'`).
1252
+ *
1253
+ * @param {string} move SAN notation representing the played move (e.g. `Nxe5`).
1254
+ */
1255
+ onMovePlayed: _propTypes["default"].func
1080
1256
  };
1081
1257
  Chessboard.defaultProps = {
1082
1258
  position: 'start',
@@ -1130,6 +1306,7 @@ function parsePosition(position) {
1130
1306
  position: new _kokopu["default"].Position(position)
1131
1307
  };
1132
1308
  } catch (e) {
1309
+ // istanbul ignore else
1133
1310
  if (e instanceof _kokopu["default"].exception.InvalidFEN) {
1134
1311
  return {
1135
1312
  error: true,
@@ -1142,7 +1319,7 @@ function parsePosition(position) {
1142
1319
  } else {
1143
1320
  return {
1144
1321
  error: true,
1145
- message: 'Invalid "position" attribute.'
1322
+ message: _i18n["default"].INVALID_POSITION_ATTRIBUTE_ERROR_MESSAGE
1146
1323
  };
1147
1324
  }
1148
1325
  }
@@ -1164,6 +1341,7 @@ function parseMove(position, move) {
1164
1341
  move: position.notation(move)
1165
1342
  };
1166
1343
  } catch (e) {
1344
+ // istanbul ignore else
1167
1345
  if (e instanceof _kokopu["default"].exception.InvalidNotation) {
1168
1346
  return {
1169
1347
  error: true,
@@ -1176,7 +1354,7 @@ function parseMove(position, move) {
1176
1354
  } else {
1177
1355
  return {
1178
1356
  error: true,
1179
- message: 'Invalid "move" attribute.'
1357
+ message: _i18n["default"].INVALID_MOVE_ATTRIBUTE_ERROR_MESSAGE
1180
1358
  };
1181
1359
  }
1182
1360
  }