@dxos/react-ui-gameboard 0.8.3 → 0.8.4-main.28f8d3d

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 (70) hide show
  1. package/dist/lib/browser/index.mjs +407 -381
  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 +407 -381
  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 +15 -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 +28 -0
  10. package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts.map +1 -0
  11. package/dist/types/src/{Chessboard → components/Chessboard}/chess.d.ts +20 -7
  12. package/dist/types/src/components/Chessboard/chess.d.ts.map +1 -0
  13. package/dist/types/src/components/Chessboard/index.d.ts.map +1 -0
  14. package/dist/types/src/components/Gameboard/Gameboard.d.ts +37 -0
  15. package/dist/types/src/components/Gameboard/Gameboard.d.ts.map +1 -0
  16. package/dist/types/src/{Board → components/Gameboard}/Piece.d.ts +3 -2
  17. package/dist/types/src/components/Gameboard/Piece.d.ts.map +1 -0
  18. package/dist/types/src/components/Gameboard/Square.d.ts.map +1 -0
  19. package/dist/types/src/components/Gameboard/index.d.ts +4 -0
  20. package/dist/types/src/components/Gameboard/index.d.ts.map +1 -0
  21. package/dist/types/src/{Board → components/Gameboard}/types.d.ts +2 -1
  22. package/dist/types/src/components/Gameboard/types.d.ts.map +1 -0
  23. package/dist/types/src/components/Gameboard/util.d.ts.map +1 -0
  24. package/dist/types/src/components/index.d.ts +3 -0
  25. package/dist/types/src/components/index.d.ts.map +1 -0
  26. package/dist/types/src/index.d.ts +1 -2
  27. package/dist/types/src/index.d.ts.map +1 -1
  28. package/dist/types/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +19 -14
  30. package/src/{Chessboard → components/Chessboard}/Chessboard.stories.tsx +33 -30
  31. package/src/components/Chessboard/Chessboard.tsx +191 -0
  32. package/src/{Chessboard → components/Chessboard}/chess.ts +88 -28
  33. package/src/components/Gameboard/Gameboard.tsx +139 -0
  34. package/src/{Board → components/Gameboard}/Piece.tsx +19 -20
  35. package/src/{Board → components/Gameboard}/Square.tsx +4 -4
  36. package/src/components/Gameboard/index.ts +8 -0
  37. package/src/{Board → components/Gameboard}/types.ts +3 -1
  38. package/src/components/index.ts +6 -0
  39. package/src/index.ts +1 -2
  40. package/dist/lib/node/index.cjs +0 -1039
  41. package/dist/lib/node/index.cjs.map +0 -7
  42. package/dist/lib/node/meta.json +0 -1
  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.map +0 -1
  60. package/dist/types/src/Chessboard/index.d.ts.map +0 -1
  61. package/src/Board/Board.tsx +0 -86
  62. package/src/Board/Container.tsx +0 -25
  63. package/src/Board/context.ts +0 -22
  64. package/src/Board/index.ts +0 -12
  65. package/src/Chessboard/Chessboard.tsx +0 -190
  66. /package/dist/types/src/{Chessboard → components/Chessboard}/index.d.ts +0 -0
  67. /package/dist/types/src/{Board → components/Gameboard}/Square.d.ts +0 -0
  68. /package/dist/types/src/{Board → components/Gameboard}/util.d.ts +0 -0
  69. /package/src/{Chessboard → components/Chessboard}/index.ts +0 -0
  70. /package/src/{Board → components/Gameboard}/util.ts +0 -0
@@ -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
- };
File without changes