react-native-chess-kit 0.5.2 → 0.5.3
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 +187 -168
- package/lib/commonjs/board-annotations.js +8 -8
- package/lib/commonjs/board-annotations.js.map +1 -1
- package/lib/commonjs/board-arrows.js.map +1 -1
- package/lib/commonjs/board-background.js +5 -5
- package/lib/commonjs/board-background.js.map +1 -1
- package/lib/commonjs/board-coordinates.js +8 -8
- package/lib/commonjs/board-coordinates.js.map +1 -1
- package/lib/commonjs/board-drag-ghost.js +10 -10
- package/lib/commonjs/board-drag-ghost.js.map +1 -1
- package/lib/commonjs/board-highlights.js +15 -15
- package/lib/commonjs/board-highlights.js.map +1 -1
- package/lib/commonjs/board-legal-dots.js +5 -5
- package/lib/commonjs/board-legal-dots.js.map +1 -1
- package/lib/commonjs/board-piece.js +25 -25
- package/lib/commonjs/board-piece.js.map +1 -1
- package/lib/commonjs/board-pieces.js +6 -6
- package/lib/commonjs/board-pieces.js.map +1 -1
- package/lib/commonjs/board.js +68 -63
- package/lib/commonjs/board.js.map +1 -1
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/pieces/default-pieces.js.map +1 -1
- package/lib/commonjs/pieces/index.js.map +1 -1
- package/lib/commonjs/promotion-picker.js +9 -9
- package/lib/commonjs/promotion-picker.js.map +1 -1
- package/lib/commonjs/static-board.js +7 -7
- package/lib/commonjs/static-board.js.map +1 -1
- package/lib/commonjs/themes.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/use-board-gesture.js +26 -26
- package/lib/commonjs/use-board-gesture.js.map +1 -1
- package/lib/commonjs/use-board-pieces.js +15 -15
- package/lib/commonjs/use-board-pieces.js.map +1 -1
- package/lib/commonjs/use-board-state.js +21 -12
- package/lib/commonjs/use-board-state.js.map +1 -1
- package/lib/commonjs/use-premove.js +12 -12
- package/lib/commonjs/use-premove.js.map +1 -1
- package/lib/module/board-annotations.js +8 -8
- package/lib/module/board-annotations.js.map +1 -1
- package/lib/module/board-arrows.js.map +1 -1
- package/lib/module/board-background.js +5 -5
- package/lib/module/board-background.js.map +1 -1
- package/lib/module/board-coordinates.js +8 -8
- package/lib/module/board-coordinates.js.map +1 -1
- package/lib/module/board-drag-ghost.js +10 -10
- package/lib/module/board-drag-ghost.js.map +1 -1
- package/lib/module/board-highlights.js +15 -15
- package/lib/module/board-highlights.js.map +1 -1
- package/lib/module/board-legal-dots.js +5 -5
- package/lib/module/board-legal-dots.js.map +1 -1
- package/lib/module/board-piece.js +25 -25
- package/lib/module/board-piece.js.map +1 -1
- package/lib/module/board-pieces.js +6 -6
- package/lib/module/board-pieces.js.map +1 -1
- package/lib/module/board.js +68 -63
- package/lib/module/board.js.map +1 -1
- package/lib/module/constants.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/pieces/default-pieces.js.map +1 -1
- package/lib/module/pieces/index.js.map +1 -1
- package/lib/module/promotion-picker.js +9 -9
- package/lib/module/promotion-picker.js.map +1 -1
- package/lib/module/static-board.js +7 -7
- package/lib/module/static-board.js.map +1 -1
- package/lib/module/themes.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/use-board-gesture.js +26 -26
- package/lib/module/use-board-gesture.js.map +1 -1
- package/lib/module/use-board-pieces.js +15 -15
- package/lib/module/use-board-pieces.js.map +1 -1
- package/lib/module/use-board-state.js +21 -12
- package/lib/module/use-board-state.js.map +1 -1
- package/lib/module/use-premove.js +12 -12
- package/lib/module/use-premove.js.map +1 -1
- package/lib/typescript/board-coordinates.d.ts.map +1 -1
- package/lib/typescript/board.d.ts.map +1 -1
- package/lib/typescript/promotion-picker.d.ts.map +1 -1
- package/lib/typescript/static-board.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +12 -2
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/use-board-gesture.d.ts.map +1 -1
- package/lib/typescript/use-board-state.d.ts.map +1 -1
- package/package.json +23 -3
- package/src/board-annotations.tsx +147 -147
- package/src/board-background.tsx +46 -46
- package/src/board-coordinates.tsx +192 -192
- 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 +688 -685
- package/src/constants.ts +103 -103
- package/src/index.ts +101 -101
- 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 +186 -187
- package/src/themes.ts +129 -129
- package/src/types.ts +394 -373
- package/src/use-board-gesture.ts +459 -429
- package/src/use-board-pieces.ts +158 -158
- package/src/use-board-state.ts +120 -111
- package/src/use-premove.ts +59 -59
package/src/board-piece.tsx
CHANGED
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
2
|
-
import Animated, {
|
|
3
|
-
useAnimatedStyle,
|
|
4
|
-
useSharedValue,
|
|
5
|
-
withTiming,
|
|
6
|
-
withSpring,
|
|
7
|
-
type SharedValue,
|
|
8
|
-
type BaseAnimationBuilder,
|
|
9
|
-
} from 'react-native-reanimated';
|
|
10
|
-
|
|
11
|
-
import type { AnimationConfig } from './types';
|
|
12
|
-
import { DEFAULT_MOVE_DURATION } from './constants';
|
|
13
|
-
|
|
14
|
-
type BoardPieceProps = {
|
|
15
|
-
/** Target pixel position (top-left of destination square) */
|
|
16
|
-
targetX: number;
|
|
17
|
-
targetY: number;
|
|
18
|
-
/** Square size in pixels */
|
|
19
|
-
squareSize: number;
|
|
20
|
-
/** Animation config for piece movement (timing or spring) */
|
|
21
|
-
animationConfig?: AnimationConfig;
|
|
22
|
-
/** Fallback move duration if animationConfig not provided */
|
|
23
|
-
moveDuration?: number;
|
|
24
|
-
/** The piece visual (rendered by parent via renderPiece) */
|
|
25
|
-
children: React.ReactElement;
|
|
26
|
-
/** Gesture state: is this piece currently being dragged? */
|
|
27
|
-
activeSquare: SharedValue<string | null>;
|
|
28
|
-
isDragging: SharedValue<boolean>;
|
|
29
|
-
/** This piece's current square */
|
|
30
|
-
square: string;
|
|
31
|
-
/**
|
|
32
|
-
* Exiting animation played when this piece unmounts (e.g. captured).
|
|
33
|
-
* Pass `undefined` to disable (piece disappears instantly on unmount).
|
|
34
|
-
*/
|
|
35
|
-
exitingAnimation?: BaseAnimationBuilder | typeof BaseAnimationBuilder;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Animate a shared value using the provided AnimationConfig.
|
|
40
|
-
* Falls back to withTiming with moveDuration for backwards compatibility.
|
|
41
|
-
*/
|
|
42
|
-
function animateValue(
|
|
43
|
-
target: number,
|
|
44
|
-
config?: AnimationConfig,
|
|
45
|
-
moveDuration?: number,
|
|
46
|
-
): number {
|
|
47
|
-
if (config) {
|
|
48
|
-
if (config.type === 'spring') {
|
|
49
|
-
return withSpring(target, {
|
|
50
|
-
damping: config.damping ?? 15,
|
|
51
|
-
stiffness: config.stiffness ?? 200,
|
|
52
|
-
mass: config.mass ?? 1,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
// timing
|
|
56
|
-
return withTiming(target, {
|
|
57
|
-
duration: config.duration ?? DEFAULT_MOVE_DURATION,
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const duration = moveDuration ?? DEFAULT_MOVE_DURATION;
|
|
62
|
-
if (duration <= 0) return target;
|
|
63
|
-
return withTiming(target, { duration });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* A single animated chess piece.
|
|
68
|
-
*
|
|
69
|
-
* Uses two nested Animated.Views to avoid the Reanimated warning
|
|
70
|
-
* "Property opacity may be overwritten by a layout animation":
|
|
71
|
-
*
|
|
72
|
-
* Outer view: position (transform) + exiting layout animation (FadeOut)
|
|
73
|
-
* Inner view: drag-hide opacity
|
|
74
|
-
*
|
|
75
|
-
* Only `transform` and `opacity` are animated — Reanimated's fast path
|
|
76
|
-
* on Android. No layout properties (top/left/width/height), avoiding
|
|
77
|
-
* costly layout recalculations on low-end devices.
|
|
78
|
-
*
|
|
79
|
-
* During drag:
|
|
80
|
-
* - Inner view hides (opacity: 0) — the drag ghost shows instead
|
|
81
|
-
*
|
|
82
|
-
* After a move:
|
|
83
|
-
* - Outer view snaps to new position via withTiming/withSpring
|
|
84
|
-
*
|
|
85
|
-
* On capture (unmount):
|
|
86
|
-
* - Outer view plays the exitingAnimation (default: FadeOut, no conflict with inner opacity)
|
|
87
|
-
* - Pass exitingAnimation={undefined} to disable (instant disappear on full board remount)
|
|
88
|
-
*/
|
|
89
|
-
export const BoardPieceView = React.memo(
|
|
90
|
-
function BoardPieceView({
|
|
91
|
-
targetX,
|
|
92
|
-
targetY,
|
|
93
|
-
squareSize,
|
|
94
|
-
animationConfig,
|
|
95
|
-
moveDuration,
|
|
96
|
-
children,
|
|
97
|
-
activeSquare,
|
|
98
|
-
isDragging,
|
|
99
|
-
square,
|
|
100
|
-
exitingAnimation,
|
|
101
|
-
}: BoardPieceProps) {
|
|
102
|
-
// Shared values for smooth animated position — written from JS, read on UI thread
|
|
103
|
-
const currentX = useSharedValue(targetX);
|
|
104
|
-
const currentY = useSharedValue(targetY);
|
|
105
|
-
|
|
106
|
-
// When target position changes (piece moved), animate to the new square.
|
|
107
|
-
// useEffect is the correct pattern for reacting to JS prop changes —
|
|
108
|
-
// useDerivedValue is meant for shared-value-to-shared-value derivation.
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
currentX.value = animateValue(targetX, animationConfig, moveDuration);
|
|
111
|
-
currentY.value = animateValue(targetY, animationConfig, moveDuration);
|
|
112
|
-
}, [targetX, targetY, animationConfig, moveDuration, currentX, currentY]);
|
|
113
|
-
|
|
114
|
-
// Position style on outer view — no opacity here to avoid conflict
|
|
115
|
-
// with the FadeOut exiting layout animation
|
|
116
|
-
const positionStyle = useAnimatedStyle(() => ({
|
|
117
|
-
transform: [
|
|
118
|
-
{ translateX: currentX.value },
|
|
119
|
-
{ translateY: currentY.value },
|
|
120
|
-
],
|
|
121
|
-
}));
|
|
122
|
-
|
|
123
|
-
// Drag-hide opacity on inner view — separate from the exiting animation
|
|
124
|
-
const opacityStyle = useAnimatedStyle(() => {
|
|
125
|
-
const isBeingDragged = isDragging.value && activeSquare.value === square;
|
|
126
|
-
return { opacity: isBeingDragged ? 0 : 1 };
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
return (
|
|
130
|
-
<Animated.View
|
|
131
|
-
style={[
|
|
132
|
-
{
|
|
133
|
-
position: 'absolute',
|
|
134
|
-
width: squareSize,
|
|
135
|
-
height: squareSize,
|
|
136
|
-
},
|
|
137
|
-
positionStyle,
|
|
138
|
-
]}
|
|
139
|
-
// Exiting animation when this piece is captured (removed from the piece list).
|
|
140
|
-
// Lives on the outer view so it doesn't conflict with the
|
|
141
|
-
// drag-hide opacity on the inner view.
|
|
142
|
-
// Pass undefined to disable (e.g. during full board remount via key change).
|
|
143
|
-
exiting={exitingAnimation}
|
|
144
|
-
>
|
|
145
|
-
<Animated.View style={[{ flex: 1 }, opacityStyle]}>
|
|
146
|
-
{children}
|
|
147
|
-
</Animated.View>
|
|
148
|
-
</Animated.View>
|
|
149
|
-
);
|
|
150
|
-
},
|
|
151
|
-
// Custom comparator: only re-render when position, square, or animation config changes
|
|
152
|
-
(prev, next) =>
|
|
153
|
-
prev.targetX === next.targetX &&
|
|
154
|
-
prev.targetY === next.targetY &&
|
|
155
|
-
prev.square === next.square &&
|
|
156
|
-
prev.squareSize === next.squareSize &&
|
|
157
|
-
prev.moveDuration === next.moveDuration &&
|
|
158
|
-
prev.animationConfig === next.animationConfig &&
|
|
159
|
-
prev.children === next.children,
|
|
160
|
-
);
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import Animated, {
|
|
3
|
+
useAnimatedStyle,
|
|
4
|
+
useSharedValue,
|
|
5
|
+
withTiming,
|
|
6
|
+
withSpring,
|
|
7
|
+
type SharedValue,
|
|
8
|
+
type BaseAnimationBuilder,
|
|
9
|
+
} from 'react-native-reanimated';
|
|
10
|
+
|
|
11
|
+
import type { AnimationConfig } from './types';
|
|
12
|
+
import { DEFAULT_MOVE_DURATION } from './constants';
|
|
13
|
+
|
|
14
|
+
type BoardPieceProps = {
|
|
15
|
+
/** Target pixel position (top-left of destination square) */
|
|
16
|
+
targetX: number;
|
|
17
|
+
targetY: number;
|
|
18
|
+
/** Square size in pixels */
|
|
19
|
+
squareSize: number;
|
|
20
|
+
/** Animation config for piece movement (timing or spring) */
|
|
21
|
+
animationConfig?: AnimationConfig;
|
|
22
|
+
/** Fallback move duration if animationConfig not provided */
|
|
23
|
+
moveDuration?: number;
|
|
24
|
+
/** The piece visual (rendered by parent via renderPiece) */
|
|
25
|
+
children: React.ReactElement;
|
|
26
|
+
/** Gesture state: is this piece currently being dragged? */
|
|
27
|
+
activeSquare: SharedValue<string | null>;
|
|
28
|
+
isDragging: SharedValue<boolean>;
|
|
29
|
+
/** This piece's current square */
|
|
30
|
+
square: string;
|
|
31
|
+
/**
|
|
32
|
+
* Exiting animation played when this piece unmounts (e.g. captured).
|
|
33
|
+
* Pass `undefined` to disable (piece disappears instantly on unmount).
|
|
34
|
+
*/
|
|
35
|
+
exitingAnimation?: BaseAnimationBuilder | typeof BaseAnimationBuilder;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Animate a shared value using the provided AnimationConfig.
|
|
40
|
+
* Falls back to withTiming with moveDuration for backwards compatibility.
|
|
41
|
+
*/
|
|
42
|
+
function animateValue(
|
|
43
|
+
target: number,
|
|
44
|
+
config?: AnimationConfig,
|
|
45
|
+
moveDuration?: number,
|
|
46
|
+
): number {
|
|
47
|
+
if (config) {
|
|
48
|
+
if (config.type === 'spring') {
|
|
49
|
+
return withSpring(target, {
|
|
50
|
+
damping: config.damping ?? 15,
|
|
51
|
+
stiffness: config.stiffness ?? 200,
|
|
52
|
+
mass: config.mass ?? 1,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// timing
|
|
56
|
+
return withTiming(target, {
|
|
57
|
+
duration: config.duration ?? DEFAULT_MOVE_DURATION,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const duration = moveDuration ?? DEFAULT_MOVE_DURATION;
|
|
62
|
+
if (duration <= 0) return target;
|
|
63
|
+
return withTiming(target, { duration });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A single animated chess piece.
|
|
68
|
+
*
|
|
69
|
+
* Uses two nested Animated.Views to avoid the Reanimated warning
|
|
70
|
+
* "Property opacity may be overwritten by a layout animation":
|
|
71
|
+
*
|
|
72
|
+
* Outer view: position (transform) + exiting layout animation (FadeOut)
|
|
73
|
+
* Inner view: drag-hide opacity
|
|
74
|
+
*
|
|
75
|
+
* Only `transform` and `opacity` are animated — Reanimated's fast path
|
|
76
|
+
* on Android. No layout properties (top/left/width/height), avoiding
|
|
77
|
+
* costly layout recalculations on low-end devices.
|
|
78
|
+
*
|
|
79
|
+
* During drag:
|
|
80
|
+
* - Inner view hides (opacity: 0) — the drag ghost shows instead
|
|
81
|
+
*
|
|
82
|
+
* After a move:
|
|
83
|
+
* - Outer view snaps to new position via withTiming/withSpring
|
|
84
|
+
*
|
|
85
|
+
* On capture (unmount):
|
|
86
|
+
* - Outer view plays the exitingAnimation (default: FadeOut, no conflict with inner opacity)
|
|
87
|
+
* - Pass exitingAnimation={undefined} to disable (instant disappear on full board remount)
|
|
88
|
+
*/
|
|
89
|
+
export const BoardPieceView = React.memo(
|
|
90
|
+
function BoardPieceView({
|
|
91
|
+
targetX,
|
|
92
|
+
targetY,
|
|
93
|
+
squareSize,
|
|
94
|
+
animationConfig,
|
|
95
|
+
moveDuration,
|
|
96
|
+
children,
|
|
97
|
+
activeSquare,
|
|
98
|
+
isDragging,
|
|
99
|
+
square,
|
|
100
|
+
exitingAnimation,
|
|
101
|
+
}: BoardPieceProps) {
|
|
102
|
+
// Shared values for smooth animated position — written from JS, read on UI thread
|
|
103
|
+
const currentX = useSharedValue(targetX);
|
|
104
|
+
const currentY = useSharedValue(targetY);
|
|
105
|
+
|
|
106
|
+
// When target position changes (piece moved), animate to the new square.
|
|
107
|
+
// useEffect is the correct pattern for reacting to JS prop changes —
|
|
108
|
+
// useDerivedValue is meant for shared-value-to-shared-value derivation.
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
currentX.value = animateValue(targetX, animationConfig, moveDuration);
|
|
111
|
+
currentY.value = animateValue(targetY, animationConfig, moveDuration);
|
|
112
|
+
}, [targetX, targetY, animationConfig, moveDuration, currentX, currentY]);
|
|
113
|
+
|
|
114
|
+
// Position style on outer view — no opacity here to avoid conflict
|
|
115
|
+
// with the FadeOut exiting layout animation
|
|
116
|
+
const positionStyle = useAnimatedStyle(() => ({
|
|
117
|
+
transform: [
|
|
118
|
+
{ translateX: currentX.value },
|
|
119
|
+
{ translateY: currentY.value },
|
|
120
|
+
],
|
|
121
|
+
}));
|
|
122
|
+
|
|
123
|
+
// Drag-hide opacity on inner view — separate from the exiting animation
|
|
124
|
+
const opacityStyle = useAnimatedStyle(() => {
|
|
125
|
+
const isBeingDragged = isDragging.value && activeSquare.value === square;
|
|
126
|
+
return { opacity: isBeingDragged ? 0 : 1 };
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Animated.View
|
|
131
|
+
style={[
|
|
132
|
+
{
|
|
133
|
+
position: 'absolute',
|
|
134
|
+
width: squareSize,
|
|
135
|
+
height: squareSize,
|
|
136
|
+
},
|
|
137
|
+
positionStyle,
|
|
138
|
+
]}
|
|
139
|
+
// Exiting animation when this piece is captured (removed from the piece list).
|
|
140
|
+
// Lives on the outer view so it doesn't conflict with the
|
|
141
|
+
// drag-hide opacity on the inner view.
|
|
142
|
+
// Pass undefined to disable (e.g. during full board remount via key change).
|
|
143
|
+
exiting={exitingAnimation}
|
|
144
|
+
>
|
|
145
|
+
<Animated.View style={[{ flex: 1 }, opacityStyle]}>
|
|
146
|
+
{children}
|
|
147
|
+
</Animated.View>
|
|
148
|
+
</Animated.View>
|
|
149
|
+
);
|
|
150
|
+
},
|
|
151
|
+
// Custom comparator: only re-render when position, square, or animation config changes
|
|
152
|
+
(prev, next) =>
|
|
153
|
+
prev.targetX === next.targetX &&
|
|
154
|
+
prev.targetY === next.targetY &&
|
|
155
|
+
prev.square === next.square &&
|
|
156
|
+
prev.squareSize === next.squareSize &&
|
|
157
|
+
prev.moveDuration === next.moveDuration &&
|
|
158
|
+
prev.animationConfig === next.animationConfig &&
|
|
159
|
+
prev.children === next.children,
|
|
160
|
+
);
|
package/src/board-pieces.tsx
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { SharedValue, BaseAnimationBuilder } from 'react-native-reanimated';
|
|
3
|
-
|
|
4
|
-
import type { ChessColor, BoardPiece, AnimationConfig } from './types';
|
|
5
|
-
import { BoardPieceView } from './board-piece';
|
|
6
|
-
import { squareToXY } from './use-board-pieces';
|
|
7
|
-
|
|
8
|
-
type BoardPiecesProps = {
|
|
9
|
-
pieces: BoardPiece[];
|
|
10
|
-
squareSize: number;
|
|
11
|
-
orientation: ChessColor;
|
|
12
|
-
moveDuration: number;
|
|
13
|
-
animationConfig?: AnimationConfig;
|
|
14
|
-
renderPiece: (code: string, size: number) => React.ReactElement;
|
|
15
|
-
activeSquare: SharedValue<string | null>;
|
|
16
|
-
isDragging: SharedValue<boolean>;
|
|
17
|
-
/** Exiting animation for pieces. Passed through to each BoardPieceView. */
|
|
18
|
-
exitingAnimation?: BaseAnimationBuilder | typeof BaseAnimationBuilder;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Renders all pieces on the board.
|
|
23
|
-
*
|
|
24
|
-
* Each piece gets a stable key (from useBoardPieces) so React doesn't
|
|
25
|
-
* unmount/remount pieces that moved — it updates their position props
|
|
26
|
-
* and the BoardPieceView animates the transition.
|
|
27
|
-
*/
|
|
28
|
-
export const BoardPiecesLayer = React.memo(function BoardPiecesLayer({
|
|
29
|
-
pieces,
|
|
30
|
-
squareSize,
|
|
31
|
-
orientation,
|
|
32
|
-
moveDuration,
|
|
33
|
-
animationConfig,
|
|
34
|
-
renderPiece,
|
|
35
|
-
activeSquare,
|
|
36
|
-
isDragging,
|
|
37
|
-
exitingAnimation,
|
|
38
|
-
}: BoardPiecesProps) {
|
|
39
|
-
return (
|
|
40
|
-
<>
|
|
41
|
-
{pieces.map((piece) => {
|
|
42
|
-
const { x, y } = squareToXY(piece.square, squareSize, orientation);
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<BoardPieceView
|
|
46
|
-
key={piece.id}
|
|
47
|
-
targetX={x}
|
|
48
|
-
targetY={y}
|
|
49
|
-
squareSize={squareSize}
|
|
50
|
-
moveDuration={moveDuration}
|
|
51
|
-
animationConfig={animationConfig}
|
|
52
|
-
activeSquare={activeSquare}
|
|
53
|
-
isDragging={isDragging}
|
|
54
|
-
square={piece.square}
|
|
55
|
-
exitingAnimation={exitingAnimation}
|
|
56
|
-
>
|
|
57
|
-
{renderPiece(piece.code, squareSize)}
|
|
58
|
-
</BoardPieceView>
|
|
59
|
-
);
|
|
60
|
-
})}
|
|
61
|
-
</>
|
|
62
|
-
);
|
|
63
|
-
});
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SharedValue, BaseAnimationBuilder } from 'react-native-reanimated';
|
|
3
|
+
|
|
4
|
+
import type { ChessColor, BoardPiece, AnimationConfig } from './types';
|
|
5
|
+
import { BoardPieceView } from './board-piece';
|
|
6
|
+
import { squareToXY } from './use-board-pieces';
|
|
7
|
+
|
|
8
|
+
type BoardPiecesProps = {
|
|
9
|
+
pieces: BoardPiece[];
|
|
10
|
+
squareSize: number;
|
|
11
|
+
orientation: ChessColor;
|
|
12
|
+
moveDuration: number;
|
|
13
|
+
animationConfig?: AnimationConfig;
|
|
14
|
+
renderPiece: (code: string, size: number) => React.ReactElement;
|
|
15
|
+
activeSquare: SharedValue<string | null>;
|
|
16
|
+
isDragging: SharedValue<boolean>;
|
|
17
|
+
/** Exiting animation for pieces. Passed through to each BoardPieceView. */
|
|
18
|
+
exitingAnimation?: BaseAnimationBuilder | typeof BaseAnimationBuilder;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Renders all pieces on the board.
|
|
23
|
+
*
|
|
24
|
+
* Each piece gets a stable key (from useBoardPieces) so React doesn't
|
|
25
|
+
* unmount/remount pieces that moved — it updates their position props
|
|
26
|
+
* and the BoardPieceView animates the transition.
|
|
27
|
+
*/
|
|
28
|
+
export const BoardPiecesLayer = React.memo(function BoardPiecesLayer({
|
|
29
|
+
pieces,
|
|
30
|
+
squareSize,
|
|
31
|
+
orientation,
|
|
32
|
+
moveDuration,
|
|
33
|
+
animationConfig,
|
|
34
|
+
renderPiece,
|
|
35
|
+
activeSquare,
|
|
36
|
+
isDragging,
|
|
37
|
+
exitingAnimation,
|
|
38
|
+
}: BoardPiecesProps) {
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
{pieces.map((piece) => {
|
|
42
|
+
const { x, y } = squareToXY(piece.square, squareSize, orientation);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<BoardPieceView
|
|
46
|
+
key={piece.id}
|
|
47
|
+
targetX={x}
|
|
48
|
+
targetY={y}
|
|
49
|
+
squareSize={squareSize}
|
|
50
|
+
moveDuration={moveDuration}
|
|
51
|
+
animationConfig={animationConfig}
|
|
52
|
+
activeSquare={activeSquare}
|
|
53
|
+
isDragging={isDragging}
|
|
54
|
+
square={piece.square}
|
|
55
|
+
exitingAnimation={exitingAnimation}
|
|
56
|
+
>
|
|
57
|
+
{renderPiece(piece.code, squareSize)}
|
|
58
|
+
</BoardPieceView>
|
|
59
|
+
);
|
|
60
|
+
})}
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
});
|