69 lines
1.5 KiB
TypeScript
69 lines
1.5 KiB
TypeScript
import React from "react";
|
|
import { TouchableOpacity, View, Animated } from "react-native";
|
|
|
|
interface ToggleProps {
|
|
value: boolean;
|
|
onValueChange: (value: boolean) => void;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
export default function Toggle({
|
|
value,
|
|
onValueChange,
|
|
disabled = false,
|
|
}: ToggleProps) {
|
|
const animatedValue = React.useRef(new Animated.Value(value ? 1 : 0)).current;
|
|
|
|
React.useEffect(() => {
|
|
Animated.spring(animatedValue, {
|
|
toValue: value ? 1 : 0,
|
|
useNativeDriver: true,
|
|
friction: 6,
|
|
tension: 40,
|
|
}).start();
|
|
}, [value]);
|
|
|
|
const translateX = animatedValue.interpolate({
|
|
inputRange: [0, 1],
|
|
outputRange: [2, 20],
|
|
});
|
|
|
|
const handlePress = () => {
|
|
if (!disabled) {
|
|
onValueChange(!value);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<TouchableOpacity
|
|
activeOpacity={0.8}
|
|
onPress={handlePress}
|
|
disabled={disabled}
|
|
style={{
|
|
width: 40,
|
|
height: 24,
|
|
borderRadius: 16,
|
|
backgroundColor: value ? "#105D38" : "#E5E7EB",
|
|
justifyContent: "center",
|
|
paddingLeft: 2,
|
|
}}
|
|
>
|
|
<Animated.View
|
|
style={{
|
|
width: 16,
|
|
height: 16,
|
|
borderRadius: 14,
|
|
right: 2,
|
|
backgroundColor: "#FFFFFF",
|
|
transform: [{ translateX }],
|
|
shadowColor: "#000",
|
|
shadowOffset: { width: 0, height: 2 },
|
|
shadowOpacity: 0.1,
|
|
shadowRadius: 3,
|
|
elevation: 3,
|
|
}}
|
|
/>
|
|
</TouchableOpacity>
|
|
);
|
|
}
|