UNPKG

react-chess

Version:

Renders a chess board using React

297 lines (250 loc) 9.84 kB
'use strict'; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var React = require('react'); var PropTypes = require('prop-types'); var Draggable = require('react-draggable'); var resizeAware = require('react-resize-aware'); var defaultLineup = require('./defaultLineup'); var pieceComponents = require('./pieces'); var decode = require('./decode'); var ResizeAware = resizeAware.default || resizeAware; var getDefaultLineup = function getDefaultLineup() { return defaultLineup.slice(); }; var noop = function noop() { /* intentional noop */ }; var square = 100 / 8; var squareSize = square + '%'; var squareStyles = { width: squareSize, paddingBottom: squareSize, float: 'left', position: 'relative', pointerEvents: 'none' }; var labelStyles = { fontSize: 'calc(7px + .5vw)', position: 'absolute', userSelect: 'none' }; var yLabelStyles = Object.assign({ top: '5%', left: '5%' }, labelStyles); var xLabelStyles = Object.assign({ bottom: '5%', right: '5%' }, labelStyles); var Chess = function (_React$Component) { _inherits(Chess, _React$Component); function Chess() { var _ref; _classCallCheck(this, Chess); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var _this = _possibleConstructorReturn(this, (_ref = Chess.__proto__ || Object.getPrototypeOf(Chess)).call.apply(_ref, [this].concat(args))); _this.els = {}; _this.state = {}; _this.setBoardRef = function (el) { return _this.els.board = el; }; _this.handleDragStart = _this.handleDragStart.bind(_this); _this.handleDragStop = _this.handleDragStop.bind(_this); _this.handleDrag = _this.handleDrag.bind(_this); _this.handleResize = _this.handleResize.bind(_this); return _this; } _createClass(Chess, [{ key: 'getSquareColor', value: function getSquareColor(x, y) { var _props = this.props, lightSquareColor = _props.lightSquareColor, darkSquareColor = _props.darkSquareColor; var odd = x % 2; if (y % 2) { return odd ? lightSquareColor : darkSquareColor; } return odd ? darkSquareColor : lightSquareColor; } }, { key: 'componentDidMount', value: function componentDidMount() { var boardSize = this.els.board.clientWidth; var tileSize = boardSize / 8; this.setState({ boardSize: boardSize, tileSize: tileSize }); } }, { key: 'handleResize', value: function handleResize(size) { var tileSize = size.width / 8; this.setState({ boardSize: size.width, tileSize: tileSize }); } }, { key: 'coordsToPosition', value: function coordsToPosition(coords) { var x = Math.round(coords.x / this.state.tileSize); var y = Math.round(coords.y / this.state.tileSize); return { x: x, y: y, pos: '' + String.fromCharCode(decode.charCodeOffset + x) + (8 - y) }; } }, { key: 'handleDrag', value: function handleDrag(evt, drag) { if (!this.props.highlightTarget) { return; } var targetTile = this.state.targetTile; var _coordsToPosition = this.coordsToPosition({ x: drag.node.offsetLeft + drag.x, y: drag.node.offsetTop + drag.y }), x = _coordsToPosition.x, y = _coordsToPosition.y; if (!targetTile || targetTile.x !== x || targetTile.y !== y) { this.setState({ targetTile: { x: x, y: y } }); } } }, { key: 'handleDragStart', value: function handleDragStart(evt, drag) { evt.preventDefault(); if (!this.props.allowMoves) { return false; } var node = drag.node; var dragFrom = this.coordsToPosition({ x: node.offsetLeft, y: node.offsetTop }); var draggingPiece = this.findPieceAtPosition(dragFrom.pos); if (this.props.onDragStart(draggingPiece, dragFrom.pos) === false) { return false; } this.setState({ dragFrom: dragFrom, draggingPiece: draggingPiece }); return evt; } }, { key: 'handleDragStop', value: function handleDragStop(evt, drag) { var node = drag.node; var _state = this.state, dragFrom = _state.dragFrom, draggingPiece = _state.draggingPiece; var dragTo = this.coordsToPosition({ x: node.offsetLeft + drag.x, y: node.offsetTop + drag.y }); this.setState({ dragFrom: null, targetTile: null, draggingPiece: null }); if (dragFrom.pos !== dragTo.pos) { this.props.onMovePiece(draggingPiece, dragFrom.pos, dragTo.pos); return false; } return true; } }, { key: 'findPieceAtPosition', value: function findPieceAtPosition(pos) { for (var i = 0; i < this.props.pieces.length; i++) { var piece = this.props.pieces[i]; if (piece.indexOf(pos) === 2) { return { notation: piece, name: piece.slice(0, 1), index: i, position: pos }; } } return null; } }, { key: 'renderLabelText', value: function renderLabelText(x, y) { var isLeftColumn = x === 0; var isBottomRow = y === 7; if (!this.props.drawLabels || !isLeftColumn && !isBottomRow) { return null; } if (isLeftColumn && isBottomRow) { return [React.createElement( 'span', { key: 'blx', style: xLabelStyles }, 'a' ), React.createElement( 'span', { key: 'bly', style: yLabelStyles }, '1' )]; } var label = isLeftColumn ? 8 - y : String.fromCharCode(decode.charCodeOffset + x); return React.createElement( 'span', { style: isLeftColumn ? yLabelStyles : xLabelStyles }, label ); } }, { key: 'render', value: function render() { var _this2 = this; var _state2 = this.state, targetTile = _state2.targetTile, draggingPiece = _state2.draggingPiece, boardSize = _state2.boardSize; var tiles = []; for (var y = 0; y < 8; y++) { for (var x = 0; x < 8; x++) { var isTarget = targetTile && targetTile.x === x && targetTile.y === y; var background = this.getSquareColor(x, y); var boxShadow = isTarget ? 'inset 0px 0px 0px 0.4vmin yellow' : undefined; var styles = Object.assign({ background: background, boxShadow: boxShadow }, squareStyles); tiles.push(React.createElement( 'div', { key: 'rect-' + x + '-' + y, style: styles }, this.renderLabelText(x, y) )); } } var pieces = this.props.pieces.map(function (decl, i) { var isMoving = draggingPiece && i === draggingPiece.index; var _decode$fromPieceDecl = decode.fromPieceDecl(decl), x = _decode$fromPieceDecl.x, y = _decode$fromPieceDecl.y, piece = _decode$fromPieceDecl.piece; var Piece = pieceComponents[piece]; return React.createElement( Draggable, { bounds: 'parent', position: { x: 0, y: 0 }, onStart: _this2.handleDragStart, onDrag: _this2.handleDrag, onStop: _this2.handleDragStop, key: piece + '-' + x + '-' + y }, React.createElement(Piece, { isMoving: isMoving, x: x, y: y }) ); }); var children = tiles.concat(pieces); var boardStyles = { position: 'relative', overflow: 'hidden', width: '100%', height: boardSize }; return React.createElement( ResizeAware, { ref: this.setBoardRef, onlyEvent: true, onResize: this.handleResize, style: boardStyles }, children ); } }]); return Chess; }(React.Component); Chess.propTypes = { allowMoves: PropTypes.bool, highlightTarget: PropTypes.bool, drawLabels: PropTypes.bool, lightSquareColor: PropTypes.string, darkSquareColor: PropTypes.string, onMovePiece: PropTypes.func, onDragStart: PropTypes.func, pieces: PropTypes.arrayOf(PropTypes.string) }; Chess.defaultProps = { allowMoves: true, highlightTarget: true, drawLabels: true, onMovePiece: noop, onDragStart: noop, lightSquareColor: '#f0d9b5', darkSquareColor: '#b58863', pieces: getDefaultLineup() }; Chess.getDefaultLineup = getDefaultLineup; module.exports = Chess;