// components/ui/switch.tsx import * as React from 'react'; import { Pressable, type ViewProps } from 'react-native'; import Animated, { useSharedValue, useAnimatedStyle, withSpring, interpolateColor, } from 'react-native-reanimated'; import { cn } from '@/lib/utils'; import { useThemeColors } from '@/hooks/useThemeColors'; export interface SwitchProps extends Omit { checked?: boolean; defaultChecked?: boolean; onCheckedChange?: (checked: boolean) => void; disabled?: boolean; className?: string; thumbClassName?: string; } export function Switch({ checked: controlledChecked, defaultChecked = false, onCheckedChange, disabled = false, className, thumbClassName, ...props }: SwitchProps) { const { colors } = useThemeColors(); const [internalChecked, setInternalChecked] = React.useState(defaultChecked); const isChecked = controlledChecked !== undefined ? controlledChecked : internalChecked; const progress = useSharedValue(isChecked ? 1 : 0); React.useEffect(() => { progress.value = withSpring(isChecked ? 1 : 0, { damping: 30, stiffness: 200, overshootClamping: true, }); }, [isChecked]); const handlePress = () => { if (disabled) return; const nextChecked = !isChecked; if (controlledChecked === undefined) { setInternalChecked(nextChecked); } onCheckedChange?.(nextChecked); }; const thumbStyle = useAnimatedStyle(() => ({ transform: [{ translateX: progress.value * 20 }], })); const trackStyle = useAnimatedStyle(() => { return { backgroundColor: interpolateColor( progress.value, [0, 1], [colors.input, colors.primary] ), }; }); return ( ); }