@dxos/react-ui-gameboard 0.8.4-main.f9ba587 → 0.8.4-main.fffef41

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 (72) hide show
  1. package/dist/lib/browser/index.mjs +496 -435
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +496 -435
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/Chessboard/Chessboard.d.ts +20 -0
  8. package/dist/types/src/components/Chessboard/Chessboard.d.ts.map +1 -0
  9. package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts +30 -0
  10. package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts.map +1 -0
  11. package/dist/types/src/components/Chessboard/chess.d.ts +59 -0
  12. package/dist/types/src/components/Chessboard/chess.d.ts.map +1 -0
  13. package/dist/types/src/components/Chessboard/chess.test.d.ts +2 -0
  14. package/dist/types/src/components/Chessboard/chess.test.d.ts.map +1 -0
  15. package/dist/types/src/components/Chessboard/index.d.ts.map +1 -0
  16. package/dist/types/src/components/Gameboard/Gameboard.d.ts +38 -0
  17. package/dist/types/src/components/Gameboard/Gameboard.d.ts.map +1 -0
  18. package/dist/types/src/{Board → components/Gameboard}/Piece.d.ts +3 -2
  19. package/dist/types/src/components/Gameboard/Piece.d.ts.map +1 -0
  20. package/dist/types/src/components/Gameboard/Square.d.ts.map +1 -0
  21. package/dist/types/src/components/Gameboard/index.d.ts +4 -0
  22. package/dist/types/src/components/Gameboard/index.d.ts.map +1 -0
  23. package/dist/types/src/{Board → components/Gameboard}/types.d.ts +3 -1
  24. package/dist/types/src/components/Gameboard/types.d.ts.map +1 -0
  25. package/dist/types/src/components/Gameboard/util.d.ts.map +1 -0
  26. package/dist/types/src/components/index.d.ts +3 -0
  27. package/dist/types/src/components/index.d.ts.map +1 -0
  28. package/dist/types/src/index.d.ts +1 -2
  29. package/dist/types/src/index.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +24 -22
  32. package/src/{Chessboard → components/Chessboard}/Chessboard.stories.tsx +33 -32
  33. package/src/components/Chessboard/Chessboard.tsx +198 -0
  34. package/src/components/Chessboard/chess.test.ts +19 -0
  35. package/src/components/Chessboard/chess.ts +322 -0
  36. package/src/components/Gameboard/Gameboard.tsx +140 -0
  37. package/src/{Board → components/Gameboard}/Piece.tsx +24 -22
  38. package/src/{Board → components/Gameboard}/Square.tsx +4 -4
  39. package/src/components/Gameboard/index.ts +8 -0
  40. package/src/{Board → components/Gameboard}/types.ts +4 -1
  41. package/src/components/index.ts +6 -0
  42. package/src/index.ts +1 -2
  43. package/dist/types/src/Board/Board.d.ts +0 -15
  44. package/dist/types/src/Board/Board.d.ts.map +0 -1
  45. package/dist/types/src/Board/Container.d.ts +0 -14
  46. package/dist/types/src/Board/Container.d.ts.map +0 -1
  47. package/dist/types/src/Board/Piece.d.ts.map +0 -1
  48. package/dist/types/src/Board/Square.d.ts.map +0 -1
  49. package/dist/types/src/Board/context.d.ts +0 -10
  50. package/dist/types/src/Board/context.d.ts.map +0 -1
  51. package/dist/types/src/Board/index.d.ts +0 -8
  52. package/dist/types/src/Board/index.d.ts.map +0 -1
  53. package/dist/types/src/Board/types.d.ts.map +0 -1
  54. package/dist/types/src/Board/util.d.ts.map +0 -1
  55. package/dist/types/src/Chessboard/Chessboard.d.ts +0 -14
  56. package/dist/types/src/Chessboard/Chessboard.d.ts.map +0 -1
  57. package/dist/types/src/Chessboard/Chessboard.stories.d.ts +0 -16
  58. package/dist/types/src/Chessboard/Chessboard.stories.d.ts.map +0 -1
  59. package/dist/types/src/Chessboard/chess.d.ts +0 -40
  60. package/dist/types/src/Chessboard/chess.d.ts.map +0 -1
  61. package/dist/types/src/Chessboard/index.d.ts.map +0 -1
  62. package/src/Board/Board.tsx +0 -86
  63. package/src/Board/Container.tsx +0 -25
  64. package/src/Board/context.ts +0 -22
  65. package/src/Board/index.ts +0 -12
  66. package/src/Chessboard/Chessboard.tsx +0 -190
  67. package/src/Chessboard/chess.ts +0 -213
  68. /package/dist/types/src/{Chessboard → components/Chessboard}/index.d.ts +0 -0
  69. /package/dist/types/src/{Board → components/Gameboard}/Square.d.ts +0 -0
  70. /package/dist/types/src/{Board → components/Gameboard}/util.d.ts +0 -0
  71. /package/src/{Chessboard → components/Chessboard}/index.ts +0 -0
  72. /package/src/{Board → components/Gameboard}/util.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-gameboard",
3
- "version": "0.8.4-main.f9ba587",
3
+ "version": "0.8.4-main.fffef41",
4
4
  "description": "Game board.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -9,6 +9,7 @@
9
9
  "type": "module",
10
10
  "exports": {
11
11
  ".": {
12
+ "source": "./src/index.ts",
12
13
  "types": "./dist/types/src/index.d.ts",
13
14
  "browser": "./dist/lib/browser/index.mjs",
14
15
  "node": "./dist/lib/node-esm/index.mjs"
@@ -26,33 +27,34 @@
26
27
  "@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
27
28
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
28
29
  "@preact-signals/safe-react": "^0.9.0",
29
- "@preact/signals-core": "^1.9.0",
30
- "chess.js": "^1.0.0",
30
+ "@preact/signals-core": "^1.12.1",
31
+ "@radix-ui/react-context": "1.1.1",
32
+ "chess.js": "^1.4.0",
31
33
  "react-resize-detector": "^11.0.1",
32
- "@dxos/debug": "0.8.4-main.f9ba587",
33
- "@dxos/invariant": "0.8.4-main.f9ba587",
34
- "@dxos/node-std": "0.8.4-main.f9ba587",
35
- "@dxos/log": "0.8.4-main.f9ba587",
36
- "@dxos/util": "0.8.4-main.f9ba587"
34
+ "@dxos/invariant": "0.8.4-main.fffef41",
35
+ "@dxos/debug": "0.8.4-main.fffef41",
36
+ "@dxos/log": "0.8.4-main.fffef41",
37
+ "@dxos/node-std": "0.8.4-main.fffef41",
38
+ "@dxos/util": "0.8.4-main.fffef41"
37
39
  },
38
40
  "devDependencies": {
39
41
  "@svgr/cli": "^8.1.0",
40
42
  "@types/lodash.defaultsdeep": "^4.6.6",
41
- "@types/react": "~18.2.0",
42
- "@types/react-dom": "~18.2.0",
43
+ "@types/react": "~19.2.2",
44
+ "@types/react-dom": "~19.2.2",
43
45
  "lodash.defaultsdeep": "^4.6.1",
44
- "react": "~18.2.0",
45
- "react-dom": "~18.2.0",
46
- "vite": "5.4.7",
47
- "@dxos/react-ui": "0.8.4-main.f9ba587",
48
- "@dxos/react-ui-theme": "0.8.4-main.f9ba587",
49
- "@dxos/storybook-utils": "0.8.4-main.f9ba587"
46
+ "react": "~19.2.0",
47
+ "react-dom": "~19.2.0",
48
+ "vite": "7.1.9",
49
+ "@dxos/react-ui-theme": "0.8.4-main.fffef41",
50
+ "@dxos/react-ui": "0.8.4-main.fffef41",
51
+ "@dxos/storybook-utils": "0.8.4-main.fffef41"
50
52
  },
51
53
  "peerDependencies": {
52
- "react": "~18.2.0",
53
- "react-dom": "~18.2.0",
54
- "@dxos/react-ui": "0.8.4-main.f9ba587",
55
- "@dxos/react-ui-theme": "0.8.4-main.f9ba587"
54
+ "react": "^19.0.0",
55
+ "react-dom": "^19.0.0",
56
+ "@dxos/react-ui": "0.8.4-main.fffef41",
57
+ "@dxos/react-ui-theme": "0.8.4-main.fffef41"
56
58
  },
57
59
  "publishConfig": {
58
60
  "access": "public"
@@ -60,7 +62,7 @@
60
62
  "scripts": {
61
63
  "gen:pieces": "pnpm gen:pieces:chess",
62
64
  "gen:pieces:chess": "pnpm gen:pieces:chess:alpha && pnpm gen:pieces:chess:cburnett",
63
- "gen:pieces:chess:alpha": "pnpm svgr --typescript --filename-case=camel --out-dir ./src/gen/pieces/chess/alpha ./assets/pieces/chess/alpha",
64
- "gen:pieces:chess:cburnett": "pnpm svgr --typescript --filename-case=camel --out-dir ./src/gen/pieces/chess/cburnett ./assets/pieces/chess/cburnett"
65
+ "gen:pieces:chess:alpha": "pnpm svgr --typescript --filename-case=camel --out-dir ./src/gen/pieces/chess/alpha ./assets/pieces/chess/alpha > /dev/null",
66
+ "gen:pieces:chess:cburnett": "pnpm svgr --typescript --filename-case=camel --out-dir ./src/gen/pieces/chess/cburnett ./assets/pieces/chess/cburnett > /dev/null"
65
67
  }
66
68
  }
@@ -2,31 +2,30 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
- import type { Meta, StoryObj } from '@storybook/react-vite';
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
9
7
 
10
- import { log } from '@dxos/log';
11
8
  import { Button, Toolbar } from '@dxos/react-ui';
12
- import { withLayout, withTheme } from '@dxos/storybook-utils';
9
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
10
+
11
+ import { Gameboard, type GameboardRootProps, type Move, type Player } from '../Gameboard';
13
12
 
14
- import { Chessboard, type ChessboardProps } from './Chessboard';
15
13
  import { ChessModel } from './chess';
16
- import { Board, type BoardRootProps, type Player, type Move } from '../Board';
14
+ import { Chessboard, type ChessboardProps } from './Chessboard';
17
15
 
18
- type RenderProps = Pick<ChessboardProps, 'orientation' | 'showLabels' | 'debug'> & {
19
- fen: string;
16
+ type DefaultStoryProps = Pick<ChessboardProps, 'orientation' | 'showLabels' | 'debug'> & {
17
+ pgn?: string;
20
18
  };
21
19
 
22
- const DefaultStory = ({ fen, orientation: _orientation, ...props }: RenderProps) => {
23
- const model = useMemo(() => new ChessModel(fen), [fen]);
20
+ const DefaultStory = ({ orientation: _orientation, pgn, ...props }: DefaultStoryProps) => {
21
+ const model = useMemo(() => new ChessModel(pgn), [pgn]);
24
22
  const [orientation, setOrientation] = useState<Player | undefined>(_orientation);
25
23
 
26
- const handleDrop = useCallback<NonNullable<BoardRootProps['onDrop']>>(
24
+ const handleDrop = useCallback<NonNullable<GameboardRootProps<ChessModel>['onDrop']>>(
27
25
  (move: Move) => {
28
- log.info('handleDrop', { move });
29
- return model.makeMove(move);
26
+ const result = model.makeMove(move);
27
+ console.log(model.pgn);
28
+ return result;
30
29
  },
31
30
  [model],
32
31
  );
@@ -34,7 +33,7 @@ const DefaultStory = ({ fen, orientation: _orientation, ...props }: RenderProps)
34
33
  return (
35
34
  <div className='flex flex-col grow gap-2 overflow-hidden'>
36
35
  <Toolbar.Root>
37
- <Button onClick={() => model.initialize()}>Reset</Button>
36
+ <Button onClick={() => model.update()}>Reset</Button>
38
37
  <Button onClick={() => model.makeRandomMove()}>Move</Button>
39
38
  <div className='grow'></div>
40
39
  <Button
@@ -43,14 +42,16 @@ const DefaultStory = ({ fen, orientation: _orientation, ...props }: RenderProps)
43
42
  Toggle
44
43
  </Button>
45
44
  </Toolbar.Root>
46
- <Board.Root model={model} onDrop={handleDrop}>
47
- <Chessboard orientation={orientation} {...props} />
48
- </Board.Root>
45
+ <Gameboard.Root model={model} onDrop={handleDrop}>
46
+ <Gameboard.Content grow contain>
47
+ <Chessboard orientation={orientation} {...props} />
48
+ </Gameboard.Content>
49
+ </Gameboard.Root>
49
50
  </div>
50
51
  );
51
52
  };
52
53
 
53
- const Grid = (props: RenderProps) => {
54
+ const GridStory = () => {
54
55
  const models = useMemo(() => Array.from({ length: 9 }).map(() => new ChessModel()), []);
55
56
  useEffect(() => {
56
57
  const i = setInterval(() => {
@@ -61,13 +62,13 @@ const Grid = (props: RenderProps) => {
61
62
  }, []);
62
63
 
63
64
  return (
64
- <div className='h-full aspect-square mx-auto'>
65
+ <div className='bs-full aspect-square mx-auto'>
65
66
  <div className='grid grid-cols-3 gap-2'>
66
67
  {models.map((model, i) => (
67
68
  <div key={i} className='aspect-square'>
68
- <Board.Root model={model}>
69
+ <Gameboard.Root model={model}>
69
70
  <Chessboard />
70
- </Board.Root>
71
+ </Gameboard.Root>
71
72
  </div>
72
73
  ))}
73
74
  </div>
@@ -75,34 +76,34 @@ const Grid = (props: RenderProps) => {
75
76
  );
76
77
  };
77
78
 
78
- const meta: Meta<typeof DefaultStory> = {
79
+ const meta = {
79
80
  title: 'ui/react-ui-gameboard/Chessboard',
80
81
  component: Chessboard,
81
82
  render: DefaultStory,
82
- decorators: [withTheme, withLayout({ fullscreen: true, classNames: '' })],
83
- };
83
+ decorators: [withTheme, withLayout({ container: 'column' })],
84
+ } satisfies Meta<typeof Chessboard>;
84
85
 
85
86
  export default meta;
86
87
 
87
- type Story = StoryObj<typeof DefaultStory>;
88
+ type Story = StoryObj<typeof meta>;
88
89
 
89
90
  export const Default: Story = {};
90
91
 
91
92
  export const Promotion: Story = {
92
93
  args: {
93
- fen: '4k3/7P/8/8/8/8/1p6/4K3 w - - 0 1',
94
+ pgn: '1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 d5 8. exd5 Nxd5 9. O-O Be6 10. Qb3 Na5 11. Qa4+ c6 12. Bxd5 Bxc3 13. Bxe6 fxe6 14. d5 Qg5 15. dxe6 Kf8 16. e7+ Kg8 *',
94
95
  },
95
96
  };
96
97
 
97
98
  export const Debug: Story = {
98
99
  args: {
99
- debug: true,
100
- showLabels: true,
100
+ pgn: '1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 d5 8. exd5 Nxd5 9. O-O Be6 10. Qb3 Na5 11. Qa4+ c6 12. Bxd5 Bxc3 13. Bxe6 fxe6 *',
101
101
  orientation: 'black',
102
- fen: 'q3k1nr/1pp1nQpp/3p4/1P2p3/4P3/B1PP1b2/B5PP/5K2 b k - 0 17',
102
+ showLabels: true,
103
+ debug: true,
103
104
  },
104
105
  };
105
106
 
106
- export const Nine: Story = {
107
- render: Grid,
107
+ export const Grid = {
108
+ render: GridStory,
108
109
  };
@@ -0,0 +1,198 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { type PropsWithChildren, forwardRef, memo, useEffect, useMemo, useRef, useState } from 'react';
6
+ import { useResizeDetector } from 'react-resize-detector';
7
+
8
+ import { type ThemedClassName, useForwardedRef } from '@dxos/react-ui';
9
+ import { mx } from '@dxos/react-ui-theme';
10
+ import { isNonNullable } from '@dxos/util';
11
+
12
+ import {
13
+ type DOMRectBounds,
14
+ Gameboard,
15
+ type Location,
16
+ type PieceRecord,
17
+ type Player,
18
+ getRelativeBounds,
19
+ locationToString,
20
+ useGameboardContext,
21
+ } from '../Gameboard';
22
+
23
+ import { type ChessModel, type ChessPiece, ChessPieces, boardStyles, getSquareColor, locationToPos } from './chess';
24
+
25
+ export type ChessboardProps = ThemedClassName<
26
+ PropsWithChildren<{
27
+ orientation?: Player;
28
+ showLabels?: boolean;
29
+ debug?: boolean;
30
+ rows?: number;
31
+ cols?: number;
32
+ }>
33
+ >;
34
+
35
+ /**
36
+ * Chessboard layout.
37
+ */
38
+ const ChessboardComponent = forwardRef<HTMLDivElement, ChessboardProps>(
39
+ ({ classNames, orientation, showLabels, debug, rows = 8, cols = 8 }, forwardedRef) => {
40
+ const targetRef = useForwardedRef(forwardedRef);
41
+ const { width, height } = useResizeDetector({ targetRef, refreshRate: 200 });
42
+ const { model, promoting, onPromotion } = useGameboardContext<ChessModel>(Chessboard.displayName!);
43
+
44
+ // Board squares.
45
+ const squares = useMemo<Location[]>(() => {
46
+ return Array.from({ length: rows }, (_, i) => (orientation === 'black' ? i : rows - 1 - i)).flatMap((row) =>
47
+ Array.from({ length: cols }).map((_, col) => [row, col] as Location),
48
+ );
49
+ }, [orientation, rows, cols]);
50
+
51
+ // Use DOM grid layout to position squares.
52
+ const layout = useMemo(() => {
53
+ return squares.map((location) => {
54
+ return (
55
+ <div
56
+ key={locationToString(location)}
57
+ {...{
58
+ ['data-location' as const]: locationToString(location),
59
+ }}
60
+ />
61
+ );
62
+ });
63
+ }, [squares]);
64
+
65
+ // Build map of square locations to bounds.
66
+ const [grid, setGrid] = useState<Record<string, DOMRectBounds>>({});
67
+ const gridRef = useRef<HTMLDivElement>(null);
68
+ useEffect(() => {
69
+ setGrid(
70
+ squares.reduce(
71
+ (acc, location) => {
72
+ const square = getSquareLocation(gridRef.current!, location)!;
73
+ const bounds = getRelativeBounds(gridRef.current!, square);
74
+ return { ...acc, [locationToString(location)]: bounds };
75
+ },
76
+ {} as Record<string, DOMRectBounds>,
77
+ ),
78
+ );
79
+ }, [squares, width, height]);
80
+
81
+ // Get the bounds of each square and piece.
82
+ const positions = useMemo<{ piece: PieceRecord; bounds: DOMRectBounds }[]>(() => {
83
+ if (!gridRef.current) {
84
+ return [];
85
+ }
86
+
87
+ return Object.values(model?.pieces.value ?? {})
88
+ .map((piece) => {
89
+ if (piece.id === promoting?.id) {
90
+ return null;
91
+ }
92
+
93
+ const bounds = grid[locationToString(piece.location)];
94
+ return { piece, bounds };
95
+ })
96
+ .filter(isNonNullable);
97
+ }, [grid, model?.pieces.value, promoting]);
98
+
99
+ return (
100
+ <div ref={targetRef} tabIndex={0} className={mx('relative outline-none', classNames)}>
101
+ {/* DOM Layout. */}
102
+ <div ref={gridRef} className='grid grid-rows-8 grid-cols-8 aspect-square select-none'>
103
+ {layout}
104
+ </div>
105
+ {/* Squares. */}
106
+ <div>
107
+ {squares.map((location) => (
108
+ <Gameboard.Square
109
+ key={locationToString(location)}
110
+ location={location}
111
+ label={showLabels ? locationToPos(location) : undefined}
112
+ bounds={grid[locationToString(location)]}
113
+ classNames={getSquareColor(location)}
114
+ />
115
+ ))}
116
+ </div>
117
+ {/* Pieces. */}
118
+ <div className={mx(promoting && 'opacity-50')}>
119
+ {positions.map(({ bounds, piece }) => (
120
+ <Gameboard.Piece
121
+ key={piece.id}
122
+ piece={piece}
123
+ bounds={bounds}
124
+ label={debug ? piece.id : undefined}
125
+ orientation={orientation}
126
+ Component={ChessPieces[piece.type as ChessPiece]}
127
+ />
128
+ ))}
129
+ </div>
130
+ {/* Promotion selector. */}
131
+ {promoting && (
132
+ <PromotionSelector
133
+ grid={grid}
134
+ piece={promoting}
135
+ onSelect={(piece) => {
136
+ onPromotion({
137
+ from: Object.values(model.pieces.value).find((p) => p.id === promoting.id)!.location,
138
+ to: piece.location,
139
+ piece: promoting.type,
140
+ promotion: piece.type,
141
+ });
142
+ }}
143
+ />
144
+ )}
145
+ </div>
146
+ );
147
+ },
148
+ );
149
+
150
+ ChessboardComponent.displayName = 'Chessboard';
151
+
152
+ export const Chessboard = memo(ChessboardComponent);
153
+
154
+ const PromotionSelector = ({
155
+ grid,
156
+ piece,
157
+ onSelect,
158
+ }: {
159
+ grid: Record<string, DOMRectBounds>;
160
+ piece: PieceRecord;
161
+ onSelect: (piece: PieceRecord) => void;
162
+ }) => {
163
+ const positions = ['Q', 'N', 'R', 'B'].map((pieceType, i) => {
164
+ const location = [piece.location[0] + (piece.location[0] === 0 ? i : -i), piece.location[1]] as Location;
165
+ return {
166
+ piece: {
167
+ id: `promotion-${pieceType}`,
168
+ type: (piece.side === 'black' ? 'B' : 'W') + pieceType,
169
+ side: piece.side,
170
+ location,
171
+ },
172
+ bounds: grid[locationToString(location)],
173
+ };
174
+ });
175
+
176
+ const handleSelect = (selected: PieceRecord) => {
177
+ onSelect({ ...piece, type: selected.type });
178
+ };
179
+
180
+ return (
181
+ <>
182
+ {positions.map(({ piece, bounds }) => (
183
+ <Gameboard.Piece
184
+ key={piece.id}
185
+ classNames={mx('border-2 border-neutral-700 rounded-full', boardStyles.promotion)}
186
+ piece={piece}
187
+ bounds={bounds}
188
+ Component={ChessPieces[piece.type as ChessPiece]}
189
+ onClick={() => handleSelect(piece)}
190
+ />
191
+ ))}
192
+ </>
193
+ );
194
+ };
195
+
196
+ const getSquareLocation = (container: HTMLElement, location: Location): HTMLElement | null => {
197
+ return container.querySelector(`[data-location="${locationToString(location)}"]`);
198
+ };
@@ -0,0 +1,19 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Chess as ChessJS } from 'chess.js';
6
+ import { describe, it } from 'vitest';
7
+
8
+ import { createPieceMap } from './chess';
9
+
10
+ describe('ChessModel', () => {
11
+ it('should update pieces', ({ expect }) => {
12
+ const chess = new ChessJS();
13
+ chess.loadPgn(
14
+ '1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 d5 8. exd5 Nxd5 9. O-O Be6 10. Qb3 Na5 11. Qa4+ c6 12. Bxd5 Bxc3 13. Bxe6 fxe6 *',
15
+ );
16
+ const pieces = createPieceMap(chess);
17
+ expect(pieces).to.exist;
18
+ });
19
+ });