react-native-chess-kit 0.4.2 → 0.5.1
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 +21 -21
- package/README.md +168 -168
- package/lib/commonjs/board-annotations.js +8 -8
- package/lib/commonjs/board-arrows.js +7 -7
- package/lib/commonjs/board-background.js +5 -5
- package/lib/commonjs/board-coordinates.js +78 -11
- package/lib/commonjs/board-coordinates.js.map +1 -1
- package/lib/commonjs/board-drag-ghost.js +10 -10
- package/lib/commonjs/board-highlights.js +15 -15
- package/lib/commonjs/board-legal-dots.js +5 -5
- package/lib/commonjs/board-piece.js +25 -25
- package/lib/commonjs/board-pieces.js +6 -6
- package/lib/commonjs/board.js +76 -35
- package/lib/commonjs/board.js.map +1 -1
- package/lib/commonjs/constants.js +4 -1
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/promotion-picker.js +8 -8
- package/lib/commonjs/static-board.js +51 -16
- package/lib/commonjs/static-board.js.map +1 -1
- package/lib/commonjs/use-board-gesture.js +52 -33
- package/lib/commonjs/use-board-gesture.js.map +1 -1
- package/lib/commonjs/use-board-pieces.js +15 -15
- package/lib/commonjs/use-board-state.js +8 -8
- package/lib/commonjs/use-premove.js +12 -12
- package/lib/module/board-annotations.js +8 -8
- package/lib/module/board-arrows.js +7 -7
- package/lib/module/board-background.js +5 -5
- package/lib/module/board-coordinates.js +79 -12
- package/lib/module/board-coordinates.js.map +1 -1
- package/lib/module/board-drag-ghost.js +10 -10
- package/lib/module/board-highlights.js +15 -15
- package/lib/module/board-legal-dots.js +5 -5
- package/lib/module/board-piece.js +25 -25
- package/lib/module/board-pieces.js +6 -6
- package/lib/module/board.js +77 -36
- package/lib/module/board.js.map +1 -1
- package/lib/module/constants.js +3 -0
- package/lib/module/constants.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/promotion-picker.js +8 -8
- package/lib/module/static-board.js +52 -17
- package/lib/module/static-board.js.map +1 -1
- package/lib/module/use-board-gesture.js +52 -33
- package/lib/module/use-board-gesture.js.map +1 -1
- package/lib/module/use-board-pieces.js +15 -15
- package/lib/module/use-board-state.js +8 -8
- package/lib/module/use-premove.js +12 -12
- package/lib/typescript/board-coordinates.d.ts +10 -4
- package/lib/typescript/board-coordinates.d.ts.map +1 -1
- package/lib/typescript/board.d.ts.map +1 -1
- package/lib/typescript/constants.d.ts +2 -0
- package/lib/typescript/constants.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/static-board.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +23 -3
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/use-board-gesture.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/board-annotations.tsx +147 -147
- package/src/board-arrows.tsx +197 -197
- package/src/board-background.tsx +46 -46
- package/src/board-coordinates.tsx +192 -98
- package/src/board-drag-ghost.tsx +132 -132
- package/src/board-highlights.tsx +226 -226
- package/src/board-legal-dots.tsx +73 -73
- package/src/board-piece.tsx +160 -160
- package/src/board-pieces.tsx +63 -63
- package/src/board.tsx +685 -641
- package/src/constants.ts +103 -100
- package/src/index.ts +101 -100
- package/src/pieces/default-pieces.tsx +383 -383
- package/src/pieces/index.ts +1 -1
- package/src/promotion-picker.tsx +147 -147
- package/src/static-board.tsx +187 -150
- package/src/themes.ts +129 -129
- package/src/types.ts +373 -352
- package/src/use-board-gesture.ts +429 -412
- package/src/use-board-pieces.ts +158 -158
- package/src/use-board-state.ts +111 -111
- package/src/use-premove.ts +59 -59
package/src/board-highlights.tsx
CHANGED
|
@@ -1,226 +1,226 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
import Animated, {
|
|
4
|
-
useAnimatedStyle,
|
|
5
|
-
type SharedValue,
|
|
6
|
-
} from 'react-native-reanimated';
|
|
7
|
-
|
|
8
|
-
import type { ChessColor, HighlightData } from './types';
|
|
9
|
-
import { squareToXY } from './use-board-pieces';
|
|
10
|
-
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
// Props
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
|
|
15
|
-
type BoardHighlightsProps = {
|
|
16
|
-
boardSize: number;
|
|
17
|
-
orientation: ChessColor;
|
|
18
|
-
squareSize: number;
|
|
19
|
-
/** Last move squares to highlight */
|
|
20
|
-
lastMove?: { from: string; to: string } | null;
|
|
21
|
-
lastMoveColor: string;
|
|
22
|
-
/** Check highlight on king square (auto-detected) */
|
|
23
|
-
checkSquare?: string | null;
|
|
24
|
-
checkColor: string;
|
|
25
|
-
/** Selected piece square */
|
|
26
|
-
selectedSquare?: string | null;
|
|
27
|
-
selectedColor: string;
|
|
28
|
-
/** Premove squares */
|
|
29
|
-
premoveSquares?: { from: string; to: string } | null;
|
|
30
|
-
premoveColor: string;
|
|
31
|
-
/** Custom highlights from consumer */
|
|
32
|
-
highlights?: HighlightData[];
|
|
33
|
-
/** Imperative highlights (from ref.highlight()) */
|
|
34
|
-
imperativeHighlights?: HighlightData[];
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
type DragTargetHighlightProps = {
|
|
38
|
-
squareSize: number;
|
|
39
|
-
orientation: ChessColor;
|
|
40
|
-
dragTargetSquare: SharedValue<string | null>;
|
|
41
|
-
color: string;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
// Static highlights (View-based, no animation needed)
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Renders all board square highlights as a single layer.
|
|
50
|
-
*
|
|
51
|
-
* Combines multiple highlight sources (last move, check, selected piece,
|
|
52
|
-
* premoves, custom, and imperative) into one flat list of colored rectangles.
|
|
53
|
-
* Rendered between the background and pieces layers.
|
|
54
|
-
*
|
|
55
|
-
* Uses plain Views (not Animated) because highlights change discretely
|
|
56
|
-
* on move events, not during animation frames.
|
|
57
|
-
*/
|
|
58
|
-
export const BoardHighlights = React.memo(function BoardHighlights({
|
|
59
|
-
boardSize,
|
|
60
|
-
orientation,
|
|
61
|
-
squareSize,
|
|
62
|
-
lastMove,
|
|
63
|
-
lastMoveColor,
|
|
64
|
-
checkSquare,
|
|
65
|
-
checkColor,
|
|
66
|
-
selectedSquare,
|
|
67
|
-
selectedColor,
|
|
68
|
-
premoveSquares,
|
|
69
|
-
premoveColor,
|
|
70
|
-
highlights,
|
|
71
|
-
imperativeHighlights,
|
|
72
|
-
}: BoardHighlightsProps) {
|
|
73
|
-
// Collect all highlights into a flat array (ordered by visual priority: bottom to top)
|
|
74
|
-
const allHighlights: HighlightData[] = [];
|
|
75
|
-
|
|
76
|
-
// Last move (lowest priority -- drawn first, underneath everything)
|
|
77
|
-
if (lastMove) {
|
|
78
|
-
allHighlights.push({ square: lastMove.from, color: lastMoveColor });
|
|
79
|
-
allHighlights.push({ square: lastMove.to, color: lastMoveColor });
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Premove highlights
|
|
83
|
-
if (premoveSquares) {
|
|
84
|
-
allHighlights.push({ square: premoveSquares.from, color: premoveColor });
|
|
85
|
-
allHighlights.push({ square: premoveSquares.to, color: premoveColor });
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Selected piece square
|
|
89
|
-
if (selectedSquare) {
|
|
90
|
-
allHighlights.push({ square: selectedSquare, color: selectedColor });
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Check indicator (king square)
|
|
94
|
-
if (checkSquare) {
|
|
95
|
-
allHighlights.push({ square: checkSquare, color: checkColor });
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Consumer-provided custom highlights
|
|
99
|
-
if (highlights) {
|
|
100
|
-
for (const h of highlights) {
|
|
101
|
-
allHighlights.push(h);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Imperative highlights (from ref.highlight() calls)
|
|
106
|
-
if (imperativeHighlights) {
|
|
107
|
-
for (const h of imperativeHighlights) {
|
|
108
|
-
allHighlights.push(h);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (allHighlights.length === 0) return null;
|
|
113
|
-
|
|
114
|
-
return (
|
|
115
|
-
<View
|
|
116
|
-
style={{ position: 'absolute', width: boardSize, height: boardSize }}
|
|
117
|
-
pointerEvents="none"
|
|
118
|
-
>
|
|
119
|
-
{allHighlights.map((h, i) => {
|
|
120
|
-
const { x, y } = squareToXY(h.square, squareSize, orientation);
|
|
121
|
-
return (
|
|
122
|
-
<View
|
|
123
|
-
key={`${h.square}-${h.color}-${i}`}
|
|
124
|
-
style={{
|
|
125
|
-
position: 'absolute',
|
|
126
|
-
left: x,
|
|
127
|
-
top: y,
|
|
128
|
-
width: squareSize,
|
|
129
|
-
height: squareSize,
|
|
130
|
-
backgroundColor: h.color,
|
|
131
|
-
}}
|
|
132
|
-
/>
|
|
133
|
-
);
|
|
134
|
-
})}
|
|
135
|
-
</View>
|
|
136
|
-
);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// ---------------------------------------------------------------------------
|
|
140
|
-
// Drag target highlight (Animated, updates on UI thread during drag)
|
|
141
|
-
// ---------------------------------------------------------------------------
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Highlight on the square currently under the dragged piece.
|
|
145
|
-
* Uses Reanimated shared values for zero-JS-bridge updates during drag.
|
|
146
|
-
*/
|
|
147
|
-
export const DragTargetHighlight = React.memo(function DragTargetHighlight({
|
|
148
|
-
squareSize,
|
|
149
|
-
orientation,
|
|
150
|
-
dragTargetSquare,
|
|
151
|
-
color,
|
|
152
|
-
}: DragTargetHighlightProps) {
|
|
153
|
-
const animatedStyle = useAnimatedStyle(() => {
|
|
154
|
-
const square = dragTargetSquare.value;
|
|
155
|
-
if (!square) {
|
|
156
|
-
return { opacity: 0, transform: [{ translateX: 0 }, { translateY: 0 }] };
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Inline coordinate calculation (worklet-safe, no function call)
|
|
160
|
-
const fileIdx = square.charCodeAt(0) - 97;
|
|
161
|
-
const rankIdx = parseInt(square[1], 10) - 1;
|
|
162
|
-
const col = orientation === 'white' ? fileIdx : 7 - fileIdx;
|
|
163
|
-
const row = orientation === 'white' ? 7 - rankIdx : rankIdx;
|
|
164
|
-
|
|
165
|
-
return {
|
|
166
|
-
opacity: 1,
|
|
167
|
-
transform: [
|
|
168
|
-
{ translateX: col * squareSize },
|
|
169
|
-
{ translateY: row * squareSize },
|
|
170
|
-
],
|
|
171
|
-
};
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
return (
|
|
175
|
-
<Animated.View
|
|
176
|
-
style={[
|
|
177
|
-
{
|
|
178
|
-
position: 'absolute',
|
|
179
|
-
width: squareSize,
|
|
180
|
-
height: squareSize,
|
|
181
|
-
backgroundColor: color,
|
|
182
|
-
},
|
|
183
|
-
animatedStyle,
|
|
184
|
-
]}
|
|
185
|
-
pointerEvents="none"
|
|
186
|
-
/>
|
|
187
|
-
);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// ---------------------------------------------------------------------------
|
|
191
|
-
// Standalone SquareHighlight (exported for advanced consumers)
|
|
192
|
-
// ---------------------------------------------------------------------------
|
|
193
|
-
|
|
194
|
-
type SquareHighlightProps = {
|
|
195
|
-
square: string;
|
|
196
|
-
color: string;
|
|
197
|
-
squareSize: number;
|
|
198
|
-
orientation: ChessColor;
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Single square highlight component.
|
|
203
|
-
* Exported for consumers who build their own overlay layers.
|
|
204
|
-
*/
|
|
205
|
-
export const SquareHighlight = React.memo(function SquareHighlight({
|
|
206
|
-
square,
|
|
207
|
-
color,
|
|
208
|
-
squareSize,
|
|
209
|
-
orientation,
|
|
210
|
-
}: SquareHighlightProps) {
|
|
211
|
-
const { x, y } = squareToXY(square, squareSize, orientation);
|
|
212
|
-
|
|
213
|
-
return (
|
|
214
|
-
<View
|
|
215
|
-
style={{
|
|
216
|
-
position: 'absolute',
|
|
217
|
-
left: x,
|
|
218
|
-
top: y,
|
|
219
|
-
width: squareSize,
|
|
220
|
-
height: squareSize,
|
|
221
|
-
backgroundColor: color,
|
|
222
|
-
}}
|
|
223
|
-
pointerEvents="none"
|
|
224
|
-
/>
|
|
225
|
-
);
|
|
226
|
-
});
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import Animated, {
|
|
4
|
+
useAnimatedStyle,
|
|
5
|
+
type SharedValue,
|
|
6
|
+
} from 'react-native-reanimated';
|
|
7
|
+
|
|
8
|
+
import type { ChessColor, HighlightData } from './types';
|
|
9
|
+
import { squareToXY } from './use-board-pieces';
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Props
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
type BoardHighlightsProps = {
|
|
16
|
+
boardSize: number;
|
|
17
|
+
orientation: ChessColor;
|
|
18
|
+
squareSize: number;
|
|
19
|
+
/** Last move squares to highlight */
|
|
20
|
+
lastMove?: { from: string; to: string } | null;
|
|
21
|
+
lastMoveColor: string;
|
|
22
|
+
/** Check highlight on king square (auto-detected) */
|
|
23
|
+
checkSquare?: string | null;
|
|
24
|
+
checkColor: string;
|
|
25
|
+
/** Selected piece square */
|
|
26
|
+
selectedSquare?: string | null;
|
|
27
|
+
selectedColor: string;
|
|
28
|
+
/** Premove squares */
|
|
29
|
+
premoveSquares?: { from: string; to: string } | null;
|
|
30
|
+
premoveColor: string;
|
|
31
|
+
/** Custom highlights from consumer */
|
|
32
|
+
highlights?: HighlightData[];
|
|
33
|
+
/** Imperative highlights (from ref.highlight()) */
|
|
34
|
+
imperativeHighlights?: HighlightData[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type DragTargetHighlightProps = {
|
|
38
|
+
squareSize: number;
|
|
39
|
+
orientation: ChessColor;
|
|
40
|
+
dragTargetSquare: SharedValue<string | null>;
|
|
41
|
+
color: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Static highlights (View-based, no animation needed)
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Renders all board square highlights as a single layer.
|
|
50
|
+
*
|
|
51
|
+
* Combines multiple highlight sources (last move, check, selected piece,
|
|
52
|
+
* premoves, custom, and imperative) into one flat list of colored rectangles.
|
|
53
|
+
* Rendered between the background and pieces layers.
|
|
54
|
+
*
|
|
55
|
+
* Uses plain Views (not Animated) because highlights change discretely
|
|
56
|
+
* on move events, not during animation frames.
|
|
57
|
+
*/
|
|
58
|
+
export const BoardHighlights = React.memo(function BoardHighlights({
|
|
59
|
+
boardSize,
|
|
60
|
+
orientation,
|
|
61
|
+
squareSize,
|
|
62
|
+
lastMove,
|
|
63
|
+
lastMoveColor,
|
|
64
|
+
checkSquare,
|
|
65
|
+
checkColor,
|
|
66
|
+
selectedSquare,
|
|
67
|
+
selectedColor,
|
|
68
|
+
premoveSquares,
|
|
69
|
+
premoveColor,
|
|
70
|
+
highlights,
|
|
71
|
+
imperativeHighlights,
|
|
72
|
+
}: BoardHighlightsProps) {
|
|
73
|
+
// Collect all highlights into a flat array (ordered by visual priority: bottom to top)
|
|
74
|
+
const allHighlights: HighlightData[] = [];
|
|
75
|
+
|
|
76
|
+
// Last move (lowest priority -- drawn first, underneath everything)
|
|
77
|
+
if (lastMove) {
|
|
78
|
+
allHighlights.push({ square: lastMove.from, color: lastMoveColor });
|
|
79
|
+
allHighlights.push({ square: lastMove.to, color: lastMoveColor });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Premove highlights
|
|
83
|
+
if (premoveSquares) {
|
|
84
|
+
allHighlights.push({ square: premoveSquares.from, color: premoveColor });
|
|
85
|
+
allHighlights.push({ square: premoveSquares.to, color: premoveColor });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Selected piece square
|
|
89
|
+
if (selectedSquare) {
|
|
90
|
+
allHighlights.push({ square: selectedSquare, color: selectedColor });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check indicator (king square)
|
|
94
|
+
if (checkSquare) {
|
|
95
|
+
allHighlights.push({ square: checkSquare, color: checkColor });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Consumer-provided custom highlights
|
|
99
|
+
if (highlights) {
|
|
100
|
+
for (const h of highlights) {
|
|
101
|
+
allHighlights.push(h);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Imperative highlights (from ref.highlight() calls)
|
|
106
|
+
if (imperativeHighlights) {
|
|
107
|
+
for (const h of imperativeHighlights) {
|
|
108
|
+
allHighlights.push(h);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (allHighlights.length === 0) return null;
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<View
|
|
116
|
+
style={{ position: 'absolute', width: boardSize, height: boardSize }}
|
|
117
|
+
pointerEvents="none"
|
|
118
|
+
>
|
|
119
|
+
{allHighlights.map((h, i) => {
|
|
120
|
+
const { x, y } = squareToXY(h.square, squareSize, orientation);
|
|
121
|
+
return (
|
|
122
|
+
<View
|
|
123
|
+
key={`${h.square}-${h.color}-${i}`}
|
|
124
|
+
style={{
|
|
125
|
+
position: 'absolute',
|
|
126
|
+
left: x,
|
|
127
|
+
top: y,
|
|
128
|
+
width: squareSize,
|
|
129
|
+
height: squareSize,
|
|
130
|
+
backgroundColor: h.color,
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
})}
|
|
135
|
+
</View>
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// Drag target highlight (Animated, updates on UI thread during drag)
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Highlight on the square currently under the dragged piece.
|
|
145
|
+
* Uses Reanimated shared values for zero-JS-bridge updates during drag.
|
|
146
|
+
*/
|
|
147
|
+
export const DragTargetHighlight = React.memo(function DragTargetHighlight({
|
|
148
|
+
squareSize,
|
|
149
|
+
orientation,
|
|
150
|
+
dragTargetSquare,
|
|
151
|
+
color,
|
|
152
|
+
}: DragTargetHighlightProps) {
|
|
153
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
154
|
+
const square = dragTargetSquare.value;
|
|
155
|
+
if (!square) {
|
|
156
|
+
return { opacity: 0, transform: [{ translateX: 0 }, { translateY: 0 }] };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Inline coordinate calculation (worklet-safe, no function call)
|
|
160
|
+
const fileIdx = square.charCodeAt(0) - 97;
|
|
161
|
+
const rankIdx = parseInt(square[1], 10) - 1;
|
|
162
|
+
const col = orientation === 'white' ? fileIdx : 7 - fileIdx;
|
|
163
|
+
const row = orientation === 'white' ? 7 - rankIdx : rankIdx;
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
opacity: 1,
|
|
167
|
+
transform: [
|
|
168
|
+
{ translateX: col * squareSize },
|
|
169
|
+
{ translateY: row * squareSize },
|
|
170
|
+
],
|
|
171
|
+
};
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<Animated.View
|
|
176
|
+
style={[
|
|
177
|
+
{
|
|
178
|
+
position: 'absolute',
|
|
179
|
+
width: squareSize,
|
|
180
|
+
height: squareSize,
|
|
181
|
+
backgroundColor: color,
|
|
182
|
+
},
|
|
183
|
+
animatedStyle,
|
|
184
|
+
]}
|
|
185
|
+
pointerEvents="none"
|
|
186
|
+
/>
|
|
187
|
+
);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
// Standalone SquareHighlight (exported for advanced consumers)
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
|
|
194
|
+
type SquareHighlightProps = {
|
|
195
|
+
square: string;
|
|
196
|
+
color: string;
|
|
197
|
+
squareSize: number;
|
|
198
|
+
orientation: ChessColor;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Single square highlight component.
|
|
203
|
+
* Exported for consumers who build their own overlay layers.
|
|
204
|
+
*/
|
|
205
|
+
export const SquareHighlight = React.memo(function SquareHighlight({
|
|
206
|
+
square,
|
|
207
|
+
color,
|
|
208
|
+
squareSize,
|
|
209
|
+
orientation,
|
|
210
|
+
}: SquareHighlightProps) {
|
|
211
|
+
const { x, y } = squareToXY(square, squareSize, orientation);
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<View
|
|
215
|
+
style={{
|
|
216
|
+
position: 'absolute',
|
|
217
|
+
left: x,
|
|
218
|
+
top: y,
|
|
219
|
+
width: squareSize,
|
|
220
|
+
height: squareSize,
|
|
221
|
+
backgroundColor: color,
|
|
222
|
+
}}
|
|
223
|
+
pointerEvents="none"
|
|
224
|
+
/>
|
|
225
|
+
);
|
|
226
|
+
});
|
package/src/board-legal-dots.tsx
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import type { ChessColor, LegalMoveTarget } from './types';
|
|
5
|
-
import { squareToXY } from './use-board-pieces';
|
|
6
|
-
|
|
7
|
-
type BoardLegalDotsProps = {
|
|
8
|
-
legalMoves: LegalMoveTarget[];
|
|
9
|
-
squareSize: number;
|
|
10
|
-
orientation: ChessColor;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Legal move indicator dots, rendered only when a piece is selected.
|
|
15
|
-
*
|
|
16
|
-
* Dots are CONDITIONALLY rendered (only for actual legal move squares,
|
|
17
|
-
* typically 5-15) instead of always mounting 64 invisible dot views.
|
|
18
|
-
*/
|
|
19
|
-
export const BoardLegalDots = React.memo(function BoardLegalDots({
|
|
20
|
-
legalMoves,
|
|
21
|
-
squareSize,
|
|
22
|
-
orientation,
|
|
23
|
-
}: BoardLegalDotsProps) {
|
|
24
|
-
if (legalMoves.length === 0) return null;
|
|
25
|
-
|
|
26
|
-
const dotSize = squareSize * 0.28;
|
|
27
|
-
const ringSize = squareSize * 0.85;
|
|
28
|
-
const borderWidth = squareSize * 0.08;
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<View
|
|
32
|
-
style={{ position: 'absolute', width: squareSize * 8, height: squareSize * 8 }}
|
|
33
|
-
pointerEvents="none"
|
|
34
|
-
>
|
|
35
|
-
{legalMoves.map((move) => {
|
|
36
|
-
const { x, y } = squareToXY(move.square, squareSize, orientation);
|
|
37
|
-
|
|
38
|
-
if (move.isCapture) {
|
|
39
|
-
return (
|
|
40
|
-
<View
|
|
41
|
-
key={move.square}
|
|
42
|
-
style={{
|
|
43
|
-
position: 'absolute',
|
|
44
|
-
left: x + (squareSize - ringSize) / 2,
|
|
45
|
-
top: y + (squareSize - ringSize) / 2,
|
|
46
|
-
width: ringSize,
|
|
47
|
-
height: ringSize,
|
|
48
|
-
borderRadius: ringSize / 2,
|
|
49
|
-
borderWidth,
|
|
50
|
-
borderColor: 'rgba(0, 0, 0, 0.25)',
|
|
51
|
-
}}
|
|
52
|
-
/>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<View
|
|
58
|
-
key={move.square}
|
|
59
|
-
style={{
|
|
60
|
-
position: 'absolute',
|
|
61
|
-
left: x + (squareSize - dotSize) / 2,
|
|
62
|
-
top: y + (squareSize - dotSize) / 2,
|
|
63
|
-
width: dotSize,
|
|
64
|
-
height: dotSize,
|
|
65
|
-
borderRadius: dotSize / 2,
|
|
66
|
-
backgroundColor: 'rgba(0, 0, 0, 0.25)',
|
|
67
|
-
}}
|
|
68
|
-
/>
|
|
69
|
-
);
|
|
70
|
-
})}
|
|
71
|
-
</View>
|
|
72
|
-
);
|
|
73
|
-
});
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { ChessColor, LegalMoveTarget } from './types';
|
|
5
|
+
import { squareToXY } from './use-board-pieces';
|
|
6
|
+
|
|
7
|
+
type BoardLegalDotsProps = {
|
|
8
|
+
legalMoves: LegalMoveTarget[];
|
|
9
|
+
squareSize: number;
|
|
10
|
+
orientation: ChessColor;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Legal move indicator dots, rendered only when a piece is selected.
|
|
15
|
+
*
|
|
16
|
+
* Dots are CONDITIONALLY rendered (only for actual legal move squares,
|
|
17
|
+
* typically 5-15) instead of always mounting 64 invisible dot views.
|
|
18
|
+
*/
|
|
19
|
+
export const BoardLegalDots = React.memo(function BoardLegalDots({
|
|
20
|
+
legalMoves,
|
|
21
|
+
squareSize,
|
|
22
|
+
orientation,
|
|
23
|
+
}: BoardLegalDotsProps) {
|
|
24
|
+
if (legalMoves.length === 0) return null;
|
|
25
|
+
|
|
26
|
+
const dotSize = squareSize * 0.28;
|
|
27
|
+
const ringSize = squareSize * 0.85;
|
|
28
|
+
const borderWidth = squareSize * 0.08;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<View
|
|
32
|
+
style={{ position: 'absolute', width: squareSize * 8, height: squareSize * 8 }}
|
|
33
|
+
pointerEvents="none"
|
|
34
|
+
>
|
|
35
|
+
{legalMoves.map((move) => {
|
|
36
|
+
const { x, y } = squareToXY(move.square, squareSize, orientation);
|
|
37
|
+
|
|
38
|
+
if (move.isCapture) {
|
|
39
|
+
return (
|
|
40
|
+
<View
|
|
41
|
+
key={move.square}
|
|
42
|
+
style={{
|
|
43
|
+
position: 'absolute',
|
|
44
|
+
left: x + (squareSize - ringSize) / 2,
|
|
45
|
+
top: y + (squareSize - ringSize) / 2,
|
|
46
|
+
width: ringSize,
|
|
47
|
+
height: ringSize,
|
|
48
|
+
borderRadius: ringSize / 2,
|
|
49
|
+
borderWidth,
|
|
50
|
+
borderColor: 'rgba(0, 0, 0, 0.25)',
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<View
|
|
58
|
+
key={move.square}
|
|
59
|
+
style={{
|
|
60
|
+
position: 'absolute',
|
|
61
|
+
left: x + (squareSize - dotSize) / 2,
|
|
62
|
+
top: y + (squareSize - dotSize) / 2,
|
|
63
|
+
width: dotSize,
|
|
64
|
+
height: dotSize,
|
|
65
|
+
borderRadius: dotSize / 2,
|
|
66
|
+
backgroundColor: 'rgba(0, 0, 0, 0.25)',
|
|
67
|
+
}}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
})}
|
|
71
|
+
</View>
|
|
72
|
+
);
|
|
73
|
+
});
|