diff --git a/README.md b/README.md index d5e7eaa..afa7ea7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ yarn add @react-chess/chessground ## Documentation -After installing, the component can be default imported and it has 4 optional props: +After installing, the component can be default imported and it has 5 optional props: - `width: number` defaults to `900`, determines width of the chessboard in pxs @@ -28,6 +28,8 @@ After installing, the component can be default imported and it has 4 optional pr - `contained: boolean` defaults to `false`, when enabled renders the chessboard in a `100%` width & height div. +- `ref: Api` returns an instance of the Chessground API for interacting with the chessboard. + Renders a simple `900 x 900` board, with pieces in their default position: ```jsx @@ -40,3 +42,51 @@ import "chessground/assets/chessground.cburnett.css"; ReactDOM.render(, document.getElementById("root")); ``` + +## Example: showing the moves of a game + +```tsx +import { useEffect, useRef } from "react"; +import Chessground, { Api, Config, Key } from "@react-chess/chessground"; + +// these styles must be imported somewhere +import "chessground/assets/chessground.base.css"; +import "chessground/assets/chessground.brown.css"; +import "chessground/assets/chessground.cburnett.css"; + +const CONFIG: Config = { + movable: { free: false }, +}; + +// Demo game moves in long algebraic form +const MOVES = ( + "e2e4 e7e5 g1f3 d7d6 d2d4 c8g4 d4e5 g4f3 d1f3 d6e5 " + + "f1c4 g8f6 f3b3 d8e7 b1c3 c7c6 c1g5 b7b5 c3b5 c6b5 " + + "c4b5 b8d7 e1c1 a8d8 d1d7 d8d7 h1d1 e7e6 b5d7 f6d7 " + + "b3b8 d7b8 d1d8" +).split(" "); + +export const DemoGameMoves = () => { + const apiRef = useRef(); + + useEffect(() => { + // Make a move every 2 seconds + const interval = setInterval(() => { + const move = MOVES.shift(); + if (move) { + apiRef.current!.move(move.substring(0,2) as Key, move.substring(2,4) as Key); + } else { + clearInterval(interval); + } + }, 2000); + return () => clearInterval(interval); + }); + + return ( + + ); +} +``` \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index 317e5f6..94246ff 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,44 +1,50 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Chessground as ChessgroundApi } from 'chessground'; +import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react'; -import { Api } from 'chessground/api'; +import { Chessground as ChessgroundApi } from 'chessground'; import { Config } from 'chessground/config'; +import { Api } from 'chessground/api'; +import { Key } from 'chessground/types'; + interface Props { - width?: number - height?: number + width?: number; + height?: number; contained?: boolean; - config?: Config -} - -function Chessground({ - width = 900, height = 900, config = {}, contained = false, -}: Props) { - const [api, setApi] = useState(null); - - const ref = useRef(null); - - useEffect(() => { - if (ref && ref.current && !api) { - const chessgroundApi = ChessgroundApi(ref.current, { - animation: { enabled: true, duration: 200 }, - ...config, - }); - setApi(chessgroundApi); - } else if (ref && ref.current && api) { - api.set(config); - } - }, [ref]); - - useEffect(() => { - api?.set(config); - }, [api, config]); - - return ( -
-
-
- ); -} - + config?: Config; +}; + +const Chessground = forwardRef( + ( + { width = 900, height = 900, config = {}, contained = false }: Props, + apiRef, + ) => { + const [api, setApi] = useState(); + const divRef = useRef(null); + + useImperativeHandle(apiRef, () => { + return api; + }, [api]); + + useEffect(() => { + if (divRef.current && !api) { + const chessgroundApi = ChessgroundApi(divRef.current, config); + setApi(chessgroundApi); + } + }, [divRef.current, api]); + + useEffect(() => { + if (api) { + api.set(config); + } + }, [config]); + + return ( +
+
+
+ ); + } +); + +export type { Api, Config, Key }; export default Chessground;