@dxos/react-ui-gameboard 0.8.4-main.f9ba587 → 0.8.4-main.fd6878d
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/dist/lib/browser/index.mjs +400 -374
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +400 -374
- 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 +15 -0
- package/dist/types/src/components/Chessboard/Chessboard.d.ts.map +1 -0
- package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts +28 -0
- package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts.map +1 -0
- package/dist/types/src/{Chessboard → components/Chessboard}/chess.d.ts +20 -7
- package/dist/types/src/components/Chessboard/chess.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 +37 -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 +2 -1
- 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/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 +16 -14
- package/src/{Chessboard → components/Chessboard}/Chessboard.stories.tsx +32 -29
- package/src/components/Chessboard/Chessboard.tsx +191 -0
- package/src/{Chessboard → components/Chessboard}/chess.ts +88 -28
- package/src/components/Gameboard/Gameboard.tsx +139 -0
- package/src/{Board → components/Gameboard}/Piece.tsx +19 -20
- package/src/{Board → components/Gameboard}/Square.tsx +4 -4
- package/src/components/Gameboard/index.ts +8 -0
- package/src/{Board → components/Gameboard}/types.ts +3 -1
- 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.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.tsx +0 -190
- /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,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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|