Поставьте зависимости:
npm install react-native-reanimated react-native-svgpnpm add react-native-reanimated react-native-svgyarn add react-native-reanimated react-native-svgbun add react-native-reanimated react-native-svgСкопируйте эти файлы в src/shared/components/organisms/check-box/:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.
import React, { useCallback, useState } from "react";
import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
import Animated, {
useAnimatedStyle,
useSharedValue,
withSpring,
} from "react-native-reanimated";
import { SafeAreaView } from "react-native-safe-area-context";
import { Checkbox } from "@/shared/components/organisms/check-box";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";
const CUSTOMIZE = [
{ key: "checkmarkColor", label: "Цвет галочки", type: "color", default: "#ffffff" },
{ key: "boxColor", label: "Цвет поля", type: "color", default: "#242424" },
{ key: "boxSize", label: "Размер поля", type: "slider", min: 24, max: 96, step: 1, unit: "px", default: 45 },
{ key: "radius", label: "Скругление", type: "slider", min: 0, max: 48, step: 1, unit: "px", default: 8 },
{ key: "size", label: "Размер галочки", type: "slider", min: 16, max: 110, step: 1, unit: "px", default: 50 },
{ key: "stroke", label: "Толщина линии", type: "slider", min: 1, max: 10, step: 0.5, unit: "px", default: 4 },
{ key: "pressScale", label: "Сжатие", type: "slider", min: 0.5, max: 1, step: 0.01, default: 0.9 },
{ key: "background", label: "Фон", type: "color", default: "#0a0a0a" },
] as const;
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
export default function CheckBoxScreen() {
const custom = useCustomize(CUSTOMIZE);
const [checked, setChecked] = useState(false);
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
const onPressIn = useCallback(() => {
scale.value = withSpring(custom.pressScale, { damping: 15, stiffness: 300, mass: 0.5 });
}, [scale, custom.pressScale]);
const onPressOut = useCallback(() => {
scale.value = withSpring(1, { damping: 12, stiffness: 250, mass: 0.5 });
}, [scale]);
const onPress = useCallback(() => setChecked((prev) => !prev), []);
useAutoplay(async ({ wait }) => {
await wait(200);
for (const hold of [650, 450]) {
onPressIn();
try {
await wait(120);
} finally {
onPressOut();
}
onPress();
await wait(hold);
}
});
return (
<Showcase>
<View style={[styles.stage, { backgroundColor: custom.background }]}>
<View style={styles.demo}>
<AnimatedPressable
accessibilityRole="checkbox"
accessibilityState={{ checked }}
hitSlop={12}
onPress={onPress}
onPressIn={onPressIn}
onPressOut={onPressOut}
style={animatedStyle}
>
<View
style={[
styles.checkBoxContainer,
{
width: custom.boxSize,
height: custom.boxSize,
borderRadius: custom.radius,
backgroundColor: custom.boxColor,
},
]}
>
<Checkbox
checked={checked}
showBorder={false}
checkmarkColor={custom.checkmarkColor}
size={custom.size}
stroke={custom.stroke}
/>
</View>
</AnimatedPressable>
</View>
</View>
</Showcase>
);
}
const styles = StyleSheet.create({
stage: {
flex: 1,
backgroundColor: "#0a0a0a",
justifyContent: "center",
alignItems: "center",
},
checkBoxContainer: {
width: 45,
height: 45,
backgroundColor: "#242424",
borderRadius: 8,
justifyContent: "center",
alignItems: "center",
},
demo: { gap: 12, alignItems: "flex-start" },
});checkmarkColorТип string
checked?Тип boolean
stroke?Тип number
showBorder?Тип boolean
size?Тип number