@dxos/react-ui-gameboard 0.8.4-main.84f28bd → 0.8.4-main.8baae0fced
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/README.md +2 -0
- package/dist/lib/browser/index.mjs +691 -812
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +691 -812
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Chessboard/Chessboard.d.ts +20 -0
- package/dist/types/src/components/Chessboard/Chessboard.d.ts.map +1 -0
- package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts +31 -0
- package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts.map +1 -0
- package/dist/types/src/components/Chessboard/chess.d.ts +60 -0
- package/dist/types/src/components/Chessboard/chess.d.ts.map +1 -0
- package/dist/types/src/components/Chessboard/chess.test.d.ts +2 -0
- package/dist/types/src/components/Chessboard/chess.test.d.ts.map +1 -0
- package/dist/types/src/components/Chessboard/index.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/Gameboard.d.ts +41 -0
- package/dist/types/src/components/Gameboard/Gameboard.d.ts.map +1 -0
- package/dist/types/src/{Board → components/Gameboard}/Piece.d.ts +3 -2
- package/dist/types/src/components/Gameboard/Piece.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/Square.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/index.d.ts +4 -0
- package/dist/types/src/components/Gameboard/index.d.ts.map +1 -0
- package/dist/types/src/{Board → components/Gameboard}/types.d.ts +4 -3
- package/dist/types/src/components/Gameboard/types.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/util.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +3 -0
- package/dist/types/src/components/index.d.ts.map +1 -0
- package/dist/types/src/gen/pieces/chess/alpha/bB.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/bK.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/bN.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/bP.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/bQ.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/bR.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/wB.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/wK.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/wN.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/wP.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/wQ.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/alpha/wR.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/bB.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/bK.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/bN.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/bP.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/bQ.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/bR.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/wB.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/wK.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/wN.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/wP.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/wQ.d.ts.map +1 -1
- package/dist/types/src/gen/pieces/chess/cburnett/wR.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +30 -28
- package/src/components/Chessboard/Chessboard.stories.tsx +113 -0
- package/src/components/Chessboard/Chessboard.tsx +205 -0
- package/src/components/Chessboard/chess.test.ts +19 -0
- package/src/components/Chessboard/chess.ts +325 -0
- package/src/components/Gameboard/Gameboard.tsx +138 -0
- package/src/{Board → components/Gameboard}/Piece.tsx +27 -23
- package/src/{Board → components/Gameboard}/Square.tsx +8 -6
- package/src/components/Gameboard/index.ts +8 -0
- package/src/{Board → components/Gameboard}/types.ts +5 -3
- package/src/components/index.ts +6 -0
- package/src/index.ts +1 -2
- package/dist/types/src/Board/Board.d.ts +0 -15
- package/dist/types/src/Board/Board.d.ts.map +0 -1
- package/dist/types/src/Board/Container.d.ts +0 -14
- package/dist/types/src/Board/Container.d.ts.map +0 -1
- package/dist/types/src/Board/Piece.d.ts.map +0 -1
- package/dist/types/src/Board/Square.d.ts.map +0 -1
- package/dist/types/src/Board/context.d.ts +0 -10
- package/dist/types/src/Board/context.d.ts.map +0 -1
- package/dist/types/src/Board/index.d.ts +0 -8
- package/dist/types/src/Board/index.d.ts.map +0 -1
- package/dist/types/src/Board/types.d.ts.map +0 -1
- package/dist/types/src/Board/util.d.ts.map +0 -1
- package/dist/types/src/Chessboard/Chessboard.d.ts +0 -14
- package/dist/types/src/Chessboard/Chessboard.d.ts.map +0 -1
- package/dist/types/src/Chessboard/Chessboard.stories.d.ts +0 -16
- package/dist/types/src/Chessboard/Chessboard.stories.d.ts.map +0 -1
- package/dist/types/src/Chessboard/chess.d.ts +0 -40
- package/dist/types/src/Chessboard/chess.d.ts.map +0 -1
- package/dist/types/src/Chessboard/index.d.ts.map +0 -1
- package/src/Board/Board.tsx +0 -86
- package/src/Board/Container.tsx +0 -25
- package/src/Board/context.ts +0 -22
- package/src/Board/index.ts +0 -12
- package/src/Chessboard/Chessboard.stories.tsx +0 -108
- package/src/Chessboard/Chessboard.tsx +0 -190
- package/src/Chessboard/chess.ts +0 -213
- /package/dist/types/src/{Chessboard → components/Chessboard}/index.d.ts +0 -0
- /package/dist/types/src/{Board → components/Gameboard}/Square.d.ts +0 -0
- /package/dist/types/src/{Board → components/Gameboard}/util.d.ts +0 -0
- /package/src/{Chessboard → components/Chessboard}/index.ts +0 -0
- /package/src/{Board → components/Gameboard}/util.ts +0 -0
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React, { type CSSProperties, type PropsWithChildren } from 'react';
|
|
2
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
|
-
export type ContainerProps = ThemedClassName<PropsWithChildren<{
|
|
4
|
-
style?: CSSProperties;
|
|
5
|
-
}>>;
|
|
6
|
-
/**
|
|
7
|
-
* Container centers the board.
|
|
8
|
-
*/
|
|
9
|
-
export declare const Container: React.ForwardRefExoticComponent<Omit<React.PropsWithChildren<{
|
|
10
|
-
style?: CSSProperties;
|
|
11
|
-
}>, "className"> & {
|
|
12
|
-
classNames?: import("@dxos/react-ui-types").ClassNameValue;
|
|
13
|
-
} & React.RefAttributes<HTMLDivElement>>;
|
|
14
|
-
//# sourceMappingURL=Container.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Container.d.ts","sourceRoot":"","sources":["../../../../src/Board/Container.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,aAAa,EAAc,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAEtF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,MAAM,MAAM,cAAc,GAAG,eAAe,CAC1C,iBAAiB,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC,CACH,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;YAPV,aAAa;;;wCAavB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Piece.d.ts","sourceRoot":"","sources":["../../../../src/Board/Piece.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAA+B,KAAK,EAAE,EAAE,KAAK,QAAQ,EAAQ,MAAM,OAAO,CAAC;AAKzF,OAAO,EAAgC,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIpF,OAAO,EAA8C,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG,eAAe,CAAC;IACvC,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;CACxC,CAAC,CAAC;AAEH,eAAO,MAAM,KAAK,2FAAuE,UAAU,uBAwGjG,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Square.d.ts","sourceRoot":"","sources":["../../../../src/Board/Square.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA4C,MAAM,OAAO,CAAC;AAIjE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAI5C,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC;IACxC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,eAAO,MAAM,MAAM,sEAAkD,WAAW,uBA+C9E,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type PieceRecord, type BoardModel, type Move } from './types';
|
|
2
|
-
export type BoardContextType = {
|
|
3
|
-
model?: BoardModel;
|
|
4
|
-
dragging?: boolean;
|
|
5
|
-
promoting?: PieceRecord;
|
|
6
|
-
onPromotion: (move: Move) => void;
|
|
7
|
-
};
|
|
8
|
-
export declare const BoardContext: import("react").Context<BoardContextType | undefined>;
|
|
9
|
-
export declare const useBoardContext: () => BoardContextType;
|
|
10
|
-
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/Board/context.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,YAAY,uDAAyD,CAAC;AAEnF,eAAO,MAAM,eAAe,wBAE3B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Board/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AAEvB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/Board/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI;IACzD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvF,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,UAAU,QAAQ,KAAG,MAA4B,CAAC;AACnF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,QAAkD,CAAC;AAGlG,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,WAMtB,CAAC;AAG7B,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,QACwC,CAAC;AAE9F,eAAO,MAAM,eAAe,GAAI,IAAI,QAAQ,EAAE,IAAI,QAAQ,KAAG,OAA6C,CAAC;AAE3G;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IACrC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;CACtC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../src/Board/util.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAC;AAE/E,eAAO,MAAM,iBAAiB,GAAI,WAAW,WAAW,EAAE,SAAS,WAAW,KAAG,aAShF,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React, { type PropsWithChildren } from 'react';
|
|
2
|
-
import { type Player } from '../Board';
|
|
3
|
-
export type ChessboardProps = PropsWithChildren<{
|
|
4
|
-
orientation?: Player;
|
|
5
|
-
showLabels?: boolean;
|
|
6
|
-
debug?: boolean;
|
|
7
|
-
rows?: number;
|
|
8
|
-
cols?: number;
|
|
9
|
-
}>;
|
|
10
|
-
/**
|
|
11
|
-
* Chessboard layout.
|
|
12
|
-
*/
|
|
13
|
-
export declare const Chessboard: React.MemoExoticComponent<({ orientation, showLabels, debug, rows, cols }: ChessboardProps) => React.JSX.Element>;
|
|
14
|
-
//# sourceMappingURL=Chessboard.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Chessboard.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/Chessboard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAA8C,MAAM,OAAO,CAAC;AAQlG,OAAO,EAIL,KAAK,MAAM,EAKZ,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,eAAe,GAAG,iBAAiB,CAAC;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU,6EAAiE,eAAe,uBAyGrG,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import '@dxos-theme';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { type ChessboardProps } from './Chessboard';
|
|
5
|
-
type RenderProps = Pick<ChessboardProps, 'orientation' | 'showLabels' | 'debug'> & {
|
|
6
|
-
fen: string;
|
|
7
|
-
};
|
|
8
|
-
declare const DefaultStory: ({ fen, orientation: _orientation, ...props }: RenderProps) => React.JSX.Element;
|
|
9
|
-
declare const meta: Meta<typeof DefaultStory>;
|
|
10
|
-
export default meta;
|
|
11
|
-
type Story = StoryObj<typeof DefaultStory>;
|
|
12
|
-
export declare const Default: Story;
|
|
13
|
-
export declare const Promotion: Story;
|
|
14
|
-
export declare const Debug: Story;
|
|
15
|
-
export declare const Nine: Story;
|
|
16
|
-
//# sourceMappingURL=Chessboard.stories.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Chessboard.stories.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/Chessboard.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAoD,MAAM,OAAO,CAAC;AAMzE,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAIhE,KAAK,WAAW,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,GAAG,YAAY,GAAG,OAAO,CAAC,GAAG;IACjF,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,QAAA,MAAM,YAAY,GAAI,8CAA8C,WAAW,sBA6B9E,CAAC;AA2BF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAKnC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,SAAS,EAAE,KAIvB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAOnB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { type ReadonlySignal } from '@preact/signals-core';
|
|
2
|
-
import { Chess } from 'chess.js';
|
|
3
|
-
import { type FC, type SVGProps } from 'react';
|
|
4
|
-
import { type Move, type Location, type PieceMap, type PieceType, type BoardModel, type Player } from '../Board';
|
|
5
|
-
export type ChessPiece = 'BK' | 'BQ' | 'BR' | 'BB' | 'BN' | 'BP' | 'WK' | 'WQ' | 'WR' | 'WB' | 'WN' | 'WP';
|
|
6
|
-
export declare const ChessPieces: Record<ChessPiece, FC<SVGProps<SVGSVGElement>>>;
|
|
7
|
-
export declare const posToLocation: (pos: string) => Location;
|
|
8
|
-
export declare const locationToPos: ([row, col]: Location) => string;
|
|
9
|
-
export declare const boardStyles: {
|
|
10
|
-
black: string;
|
|
11
|
-
white: string;
|
|
12
|
-
promotion: string;
|
|
13
|
-
};
|
|
14
|
-
export declare const getSquareColor: ([row, col]: Location) => string;
|
|
15
|
-
/**
|
|
16
|
-
* Chess model.
|
|
17
|
-
*/
|
|
18
|
-
export declare class ChessModel implements BoardModel<ChessPiece> {
|
|
19
|
-
private _game;
|
|
20
|
-
private readonly _pieces;
|
|
21
|
-
constructor(fen?: string);
|
|
22
|
-
get turn(): Player;
|
|
23
|
-
get pieces(): ReadonlySignal<PieceMap<ChessPiece>>;
|
|
24
|
-
get game(): Chess;
|
|
25
|
-
get fen(): string;
|
|
26
|
-
initialize(fen?: string): void;
|
|
27
|
-
isValidMove(move: Move): boolean;
|
|
28
|
-
canPromote(move: Move): boolean;
|
|
29
|
-
makeMove(move: Move): boolean;
|
|
30
|
-
makeRandomMove(): boolean;
|
|
31
|
-
/**
|
|
32
|
-
* Update pieces preserving identity.
|
|
33
|
-
*/
|
|
34
|
-
private _update;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Preserve the original piece objects (and IDs).
|
|
38
|
-
*/
|
|
39
|
-
export declare const mapPieces: <T extends PieceType>(before: PieceMap<T>, after: PieceMap<T>) => PieceMap<T>;
|
|
40
|
-
//# sourceMappingURL=chess.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chess.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/chess.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,cAAc,EAAU,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,KAAK,EAAe,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAI/C,OAAO,EACL,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,KAAK,QAAQ,EAEb,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3G,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAS,CAAC;AAElF,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,QAI3C,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,YAAY,QAAQ,KAAG,MAEpD,CAAC;AAyBF,eAAO,MAAM,WAAW;;;;CAAkB,CAAC;AAE3C,eAAO,MAAM,cAAc,GAAI,YAAY,QAAQ,WAElD,CAAC;AAmBF;;GAEG;AACH,qBAAa,UAAW,YAAW,UAAU,CAAC,UAAU,CAAC;IACvD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;gBAEhD,GAAG,CAAC,EAAE,MAAM;IAIxB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,MAAM,IAAI,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAEjD;IAED,IAAI,IAAI,IAAI,KAAK,CAEhB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAM9B,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAIhC,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAM/B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAW7B,cAAc,IAAI,OAAO;IAYzB;;OAEG;IACH,OAAO,CAAC,OAAO;CAsBhB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,SAAS,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAG,QAAQ,CAAC,CAAC,CAmClG,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AAExB,cAAc,cAAc,CAAC"}
|
package/src/Board/Board.tsx
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
|
-
import React, { type PropsWithChildren, useCallback, useEffect, useState } from 'react';
|
|
7
|
-
|
|
8
|
-
import { log } from '@dxos/log';
|
|
9
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
10
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
11
|
-
|
|
12
|
-
import { Container } from './Container';
|
|
13
|
-
import { BoardContext, type BoardContextType } from './context';
|
|
14
|
-
import { type BoardModel, isLocation, isPiece, type Move, type PieceRecord } from './types';
|
|
15
|
-
|
|
16
|
-
type RootProps = ThemedClassName<
|
|
17
|
-
PropsWithChildren<{
|
|
18
|
-
model?: BoardModel;
|
|
19
|
-
onDrop?: (move: Move) => boolean;
|
|
20
|
-
}>
|
|
21
|
-
>;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Generic board container.
|
|
25
|
-
*/
|
|
26
|
-
const Root = ({ children, classNames, model, onDrop }: RootProps) => {
|
|
27
|
-
const [dragging, setDragging] = useState(false);
|
|
28
|
-
const [promoting, setPromoting] = useState<PieceRecord | undefined>();
|
|
29
|
-
|
|
30
|
-
// Handle promotion.
|
|
31
|
-
const onPromotion = useCallback<BoardContextType['onPromotion']>((move) => {
|
|
32
|
-
log('onPromotion', { move });
|
|
33
|
-
setPromoting(undefined);
|
|
34
|
-
onDrop?.(move);
|
|
35
|
-
}, []);
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (!model) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// TODO(burdon): Should target specific container.
|
|
43
|
-
return monitorForElements({
|
|
44
|
-
onDragStart: ({ source }) => {
|
|
45
|
-
log('onDragStart', { source });
|
|
46
|
-
setDragging(true);
|
|
47
|
-
},
|
|
48
|
-
onDrop: ({ source, location }) => {
|
|
49
|
-
log('onDrop', { source, location });
|
|
50
|
-
const target = location.current.dropTargets[0];
|
|
51
|
-
if (!target) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const targetLocation = target.data.location;
|
|
56
|
-
const piece = source.data.piece;
|
|
57
|
-
if (!isLocation(targetLocation) || !isPiece(piece)) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const move: Move = { from: piece.location, to: targetLocation, piece: piece.type };
|
|
62
|
-
if (model.canPromote?.(move)) {
|
|
63
|
-
setPromoting({ ...piece, location: targetLocation });
|
|
64
|
-
} else {
|
|
65
|
-
onDrop?.(move);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
setDragging(false);
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
}, [model]);
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<BoardContext.Provider value={{ model, dragging, promoting, onPromotion }}>
|
|
75
|
-
<Container classNames={mx('aspect-square', classNames)}>{children}</Container>
|
|
76
|
-
</BoardContext.Provider>
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
Root.displayName = 'Board.Root';
|
|
81
|
-
|
|
82
|
-
export const Board = {
|
|
83
|
-
Root,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export type { RootProps as BoardRootProps };
|
package/src/Board/Container.tsx
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { type CSSProperties, forwardRef, type PropsWithChildren } from 'react';
|
|
6
|
-
|
|
7
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
8
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
9
|
-
|
|
10
|
-
export type ContainerProps = ThemedClassName<
|
|
11
|
-
PropsWithChildren<{
|
|
12
|
-
style?: CSSProperties;
|
|
13
|
-
}>
|
|
14
|
-
>;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Container centers the board.
|
|
18
|
-
*/
|
|
19
|
-
export const Container = forwardRef<HTMLDivElement, ContainerProps>(({ children, classNames, style }, forwardedRef) => {
|
|
20
|
-
return (
|
|
21
|
-
<div ref={forwardedRef} style={style} className='flex w-full h-full justify-center overflow-hidden'>
|
|
22
|
-
<div className={mx('max-w-full max-h-full content-center', classNames)}>{children}</div>
|
|
23
|
-
</div>
|
|
24
|
-
);
|
|
25
|
-
});
|
package/src/Board/context.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { createContext, useContext } from 'react';
|
|
6
|
-
|
|
7
|
-
import { raise } from '@dxos/debug';
|
|
8
|
-
|
|
9
|
-
import { type PieceRecord, type BoardModel, type Move } from './types';
|
|
10
|
-
|
|
11
|
-
export type BoardContextType = {
|
|
12
|
-
model?: BoardModel;
|
|
13
|
-
dragging?: boolean; // TODO(burdon): Change to PieceRecord.
|
|
14
|
-
promoting?: PieceRecord;
|
|
15
|
-
onPromotion: (move: Move) => void;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const BoardContext = createContext<BoardContextType | undefined>(undefined);
|
|
19
|
-
|
|
20
|
-
export const useBoardContext = () => {
|
|
21
|
-
return useContext(BoardContext) ?? raise(new Error('Missing BoardContext'));
|
|
22
|
-
};
|
package/src/Board/index.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
8
|
-
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
|
-
|
|
10
|
-
import { log } from '@dxos/log';
|
|
11
|
-
import { Button, Toolbar } from '@dxos/react-ui';
|
|
12
|
-
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
13
|
-
|
|
14
|
-
import { Chessboard, type ChessboardProps } from './Chessboard';
|
|
15
|
-
import { ChessModel } from './chess';
|
|
16
|
-
import { Board, type BoardRootProps, type Player, type Move } from '../Board';
|
|
17
|
-
|
|
18
|
-
type RenderProps = Pick<ChessboardProps, 'orientation' | 'showLabels' | 'debug'> & {
|
|
19
|
-
fen: string;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const DefaultStory = ({ fen, orientation: _orientation, ...props }: RenderProps) => {
|
|
23
|
-
const model = useMemo(() => new ChessModel(fen), [fen]);
|
|
24
|
-
const [orientation, setOrientation] = useState<Player | undefined>(_orientation);
|
|
25
|
-
|
|
26
|
-
const handleDrop = useCallback<NonNullable<BoardRootProps['onDrop']>>(
|
|
27
|
-
(move: Move) => {
|
|
28
|
-
log.info('handleDrop', { move });
|
|
29
|
-
return model.makeMove(move);
|
|
30
|
-
},
|
|
31
|
-
[model],
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<div className='flex flex-col grow gap-2 overflow-hidden'>
|
|
36
|
-
<Toolbar.Root>
|
|
37
|
-
<Button onClick={() => model.initialize()}>Reset</Button>
|
|
38
|
-
<Button onClick={() => model.makeRandomMove()}>Move</Button>
|
|
39
|
-
<div className='grow'></div>
|
|
40
|
-
<Button
|
|
41
|
-
onClick={() => setOrientation((orientation) => (!orientation || orientation === 'white' ? 'black' : 'white'))}
|
|
42
|
-
>
|
|
43
|
-
Toggle
|
|
44
|
-
</Button>
|
|
45
|
-
</Toolbar.Root>
|
|
46
|
-
<Board.Root model={model} onDrop={handleDrop}>
|
|
47
|
-
<Chessboard orientation={orientation} {...props} />
|
|
48
|
-
</Board.Root>
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const Grid = (props: RenderProps) => {
|
|
54
|
-
const models = useMemo(() => Array.from({ length: 9 }).map(() => new ChessModel()), []);
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
const i = setInterval(() => {
|
|
57
|
-
const model = models[Math.floor(Math.random() * models.length)];
|
|
58
|
-
model.makeRandomMove();
|
|
59
|
-
}, 100);
|
|
60
|
-
return () => clearInterval(i);
|
|
61
|
-
}, []);
|
|
62
|
-
|
|
63
|
-
return (
|
|
64
|
-
<div className='h-full aspect-square mx-auto'>
|
|
65
|
-
<div className='grid grid-cols-3 gap-2'>
|
|
66
|
-
{models.map((model, i) => (
|
|
67
|
-
<div key={i} className='aspect-square'>
|
|
68
|
-
<Board.Root model={model}>
|
|
69
|
-
<Chessboard />
|
|
70
|
-
</Board.Root>
|
|
71
|
-
</div>
|
|
72
|
-
))}
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const meta: Meta<typeof DefaultStory> = {
|
|
79
|
-
title: 'ui/react-ui-gameboard/Chessboard',
|
|
80
|
-
component: Chessboard,
|
|
81
|
-
render: DefaultStory,
|
|
82
|
-
decorators: [withTheme, withLayout({ fullscreen: true, classNames: '' })],
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export default meta;
|
|
86
|
-
|
|
87
|
-
type Story = StoryObj<typeof DefaultStory>;
|
|
88
|
-
|
|
89
|
-
export const Default: Story = {};
|
|
90
|
-
|
|
91
|
-
export const Promotion: Story = {
|
|
92
|
-
args: {
|
|
93
|
-
fen: '4k3/7P/8/8/8/8/1p6/4K3 w - - 0 1',
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export const Debug: Story = {
|
|
98
|
-
args: {
|
|
99
|
-
debug: true,
|
|
100
|
-
showLabels: true,
|
|
101
|
-
orientation: 'black',
|
|
102
|
-
fen: 'q3k1nr/1pp1nQpp/3p4/1P2p3/4P3/B1PP1b2/B5PP/5K2 b k - 0 17',
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
export const Nine: Story = {
|
|
107
|
-
render: Grid,
|
|
108
|
-
};
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { type PropsWithChildren, useRef, useMemo, useEffect, useState, memo } from 'react';
|
|
6
|
-
import { useResizeDetector } from 'react-resize-detector';
|
|
7
|
-
|
|
8
|
-
import { useTrackProps } from '@dxos/react-ui';
|
|
9
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
10
|
-
import { isNotFalsy } from '@dxos/util';
|
|
11
|
-
|
|
12
|
-
import { boardStyles, type ChessPiece, ChessPieces, getSquareColor, locationToPos } from './chess';
|
|
13
|
-
import {
|
|
14
|
-
type DOMRectBounds,
|
|
15
|
-
type Location,
|
|
16
|
-
type PieceRecord,
|
|
17
|
-
type Player,
|
|
18
|
-
Piece,
|
|
19
|
-
Square,
|
|
20
|
-
getRelativeBounds,
|
|
21
|
-
locationToString,
|
|
22
|
-
} from '../Board';
|
|
23
|
-
import { useBoardContext } from '../Board';
|
|
24
|
-
|
|
25
|
-
export type ChessboardProps = PropsWithChildren<{
|
|
26
|
-
orientation?: Player;
|
|
27
|
-
showLabels?: boolean;
|
|
28
|
-
debug?: boolean;
|
|
29
|
-
rows?: number;
|
|
30
|
-
cols?: number;
|
|
31
|
-
}>;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Chessboard layout.
|
|
35
|
-
*/
|
|
36
|
-
export const Chessboard = memo(({ orientation, showLabels, debug, rows = 8, cols = 8 }: ChessboardProps) => {
|
|
37
|
-
useTrackProps({ orientation, showLabels, debug }, Chessboard.displayName, false);
|
|
38
|
-
const { ref: containerRef, width, height } = useResizeDetector({ refreshRate: 200 });
|
|
39
|
-
const { model, promoting, onPromotion } = useBoardContext();
|
|
40
|
-
|
|
41
|
-
const locations = useMemo<Location[]>(() => {
|
|
42
|
-
return Array.from({ length: rows }, (_, i) => (orientation === 'black' ? i : rows - 1 - i)).flatMap((row) =>
|
|
43
|
-
Array.from({ length: cols }).map((_, col) => [row, col] as Location),
|
|
44
|
-
);
|
|
45
|
-
}, [orientation, rows, cols]);
|
|
46
|
-
|
|
47
|
-
// Use DOM grid layout to position squares.
|
|
48
|
-
const layout = useMemo(() => {
|
|
49
|
-
return locations.map((location) => {
|
|
50
|
-
return (
|
|
51
|
-
<div
|
|
52
|
-
key={locationToString(location)}
|
|
53
|
-
{...{
|
|
54
|
-
['data-location' as const]: locationToString(location),
|
|
55
|
-
}}
|
|
56
|
-
/>
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
}, [locations]);
|
|
60
|
-
|
|
61
|
-
// Build map of square locations to bounds.
|
|
62
|
-
const [grid, setGrid] = useState<Record<string, DOMRectBounds>>({});
|
|
63
|
-
const gridRef = useRef<HTMLDivElement>(null);
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
setGrid(
|
|
66
|
-
locations.reduce(
|
|
67
|
-
(acc, location) => {
|
|
68
|
-
const square = getSquareLocation(gridRef.current!, location)!;
|
|
69
|
-
const bounds = getRelativeBounds(gridRef.current!, square);
|
|
70
|
-
return { ...acc, [locationToString(location)]: bounds };
|
|
71
|
-
},
|
|
72
|
-
{} as Record<string, DOMRectBounds>,
|
|
73
|
-
),
|
|
74
|
-
);
|
|
75
|
-
}, [locations, width, height]);
|
|
76
|
-
|
|
77
|
-
// Get the bounds of each square and piece.
|
|
78
|
-
const positions = useMemo<{ piece: PieceRecord; bounds: DOMRectBounds }[]>(() => {
|
|
79
|
-
if (!gridRef.current) {
|
|
80
|
-
return [];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return Object.values(model?.pieces.value ?? {})
|
|
84
|
-
.map((piece) => {
|
|
85
|
-
if (piece.id === promoting?.id) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const bounds = grid[locationToString(piece.location)];
|
|
90
|
-
return { piece, bounds };
|
|
91
|
-
})
|
|
92
|
-
.filter(isNotFalsy);
|
|
93
|
-
}, [grid, model?.pieces.value, promoting]);
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<div ref={containerRef} className='relative'>
|
|
97
|
-
<div ref={gridRef} className='grid grid-rows-8 grid-cols-8 aspect-square select-none'>
|
|
98
|
-
{layout}
|
|
99
|
-
</div>
|
|
100
|
-
<div>
|
|
101
|
-
{locations.map((location) => (
|
|
102
|
-
<Square
|
|
103
|
-
key={locationToString(location)}
|
|
104
|
-
location={location}
|
|
105
|
-
label={showLabels ? locationToPos(location) : undefined}
|
|
106
|
-
bounds={grid[locationToString(location)]}
|
|
107
|
-
classNames={getSquareColor(location)}
|
|
108
|
-
/>
|
|
109
|
-
))}
|
|
110
|
-
</div>
|
|
111
|
-
<div className={mx(promoting && 'opacity-50')}>
|
|
112
|
-
{positions.map(({ bounds, piece }) => (
|
|
113
|
-
<Piece
|
|
114
|
-
key={piece.id}
|
|
115
|
-
piece={piece}
|
|
116
|
-
bounds={bounds}
|
|
117
|
-
label={debug ? piece.id : undefined}
|
|
118
|
-
orientation={orientation}
|
|
119
|
-
Component={ChessPieces[piece.type as ChessPiece]}
|
|
120
|
-
/>
|
|
121
|
-
))}
|
|
122
|
-
</div>
|
|
123
|
-
<div>
|
|
124
|
-
{promoting && (
|
|
125
|
-
<PromotionSelector
|
|
126
|
-
grid={grid}
|
|
127
|
-
piece={promoting}
|
|
128
|
-
onSelect={(piece) => {
|
|
129
|
-
onPromotion({
|
|
130
|
-
from: Object.values(model!.pieces.value).find((p) => p.id === promoting.id)!.location,
|
|
131
|
-
to: piece.location,
|
|
132
|
-
piece: promoting.type,
|
|
133
|
-
promotion: piece.type,
|
|
134
|
-
});
|
|
135
|
-
}}
|
|
136
|
-
/>
|
|
137
|
-
)}
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
Chessboard.displayName = 'Chessboard';
|
|
144
|
-
|
|
145
|
-
const getSquareLocation = (container: HTMLElement, location: Location): HTMLElement | null => {
|
|
146
|
-
return container.querySelector(`[data-location="${locationToString(location)}"]`);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const PromotionSelector = ({
|
|
150
|
-
grid,
|
|
151
|
-
piece,
|
|
152
|
-
onSelect,
|
|
153
|
-
}: {
|
|
154
|
-
grid: Record<string, DOMRectBounds>;
|
|
155
|
-
piece: PieceRecord;
|
|
156
|
-
onSelect: (piece: PieceRecord) => void;
|
|
157
|
-
}) => {
|
|
158
|
-
const positions = ['Q', 'N', 'R', 'B'].map((pieceType, i) => {
|
|
159
|
-
const location = [piece.location[0] + (piece.location[0] === 0 ? i : -i), piece.location[1]] as Location;
|
|
160
|
-
return {
|
|
161
|
-
piece: {
|
|
162
|
-
id: `promotion-${pieceType}`,
|
|
163
|
-
type: (piece.side === 'black' ? 'B' : 'W') + pieceType,
|
|
164
|
-
side: piece.side,
|
|
165
|
-
location,
|
|
166
|
-
},
|
|
167
|
-
bounds: grid[locationToString(location)],
|
|
168
|
-
};
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const handleSelect = (selected: PieceRecord) => {
|
|
172
|
-
onSelect({ ...piece, type: selected.type });
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
// TODO(burdon): Circle.
|
|
176
|
-
return (
|
|
177
|
-
<div>
|
|
178
|
-
{positions.map(({ piece, bounds }) => (
|
|
179
|
-
<div key={piece.id} style={bounds} onClick={() => handleSelect(piece)}>
|
|
180
|
-
<Piece
|
|
181
|
-
piece={piece}
|
|
182
|
-
bounds={bounds}
|
|
183
|
-
Component={ChessPieces[piece.type as ChessPiece]}
|
|
184
|
-
classNames={mx('border-2 border-neutral-700 rounded-full', boardStyles.promotion)}
|
|
185
|
-
/>
|
|
186
|
-
</div>
|
|
187
|
-
))}
|
|
188
|
-
</div>
|
|
189
|
-
);
|
|
190
|
-
};
|