1- import { useEffect , useImperativeHandle } from "react"
1+ import { useImperativeHandle } from "react"
22import type { SwitchChangeEvent } from "react-native"
3- import { Pressable , StyleSheet } from "react-native"
4- import Animated , {
5- interpolate ,
6- interpolateColor ,
7- useAnimatedStyle ,
8- useSharedValue ,
9- withSpring ,
10- } from "react-native-reanimated"
3+ import { Platform , StyleSheet , Switch as NativeSwitch } from "react-native"
114
125import { accentColor , useColor } from "@/src/theme/colors"
136
@@ -26,6 +19,10 @@ export interface SwitchProps {
2619 value ?: boolean | undefined
2720
2821 size ?: "sm" | "default"
22+
23+ disabled ?: boolean | undefined
24+
25+ testID ?: string | undefined
2926}
3027
3128export type SwitchRef = {
@@ -37,100 +34,39 @@ export const Switch = ({
3734 onValueChange,
3835 onChange,
3936 size = "default" ,
37+ disabled = false ,
38+ testID,
4039} : SwitchProps & { ref ?: React . Ref < SwitchRef | null > } ) => {
41- const gray3 = useColor ( "gray3" )
42- const animatedValue = useSharedValue ( value ? 1 : 0 )
43-
44- const dimensions =
45- size === "sm"
46- ? { width : 40 , height : 24 , thumbSize : 20 }
47- : { width : 48 , height : 28 , thumbSize : 24 }
48-
49- useEffect ( ( ) => {
50- animatedValue . value = withSpring ( value ? 1 : 0 , {
51- damping : 15 ,
52- stiffness : 200 ,
53- } )
54- } , [ animatedValue , value ] )
55-
56- useImperativeHandle ( ref , ( ) => ( {
57- value : value || false ,
58- } ) )
59-
60- const handlePress = ( ) => {
61- const newValue = ! value
62- onValueChange ?.( newValue )
63- onChange ?.( {
64- nativeEvent : { value : newValue } ,
65- } as SwitchChangeEvent )
66- }
67-
68- const trackAnimatedStyle = useAnimatedStyle ( ( ) => {
69- const backgroundColor = interpolateColor ( animatedValue . value , [ 0 , 1 ] , [ gray3 , accentColor ] )
70-
71- return {
72- backgroundColor,
73- }
74- } )
75-
76- const thumbAnimatedStyle = useAnimatedStyle ( ( ) => {
77- const translateX = interpolate (
78- animatedValue . value ,
79- [ 0 , 1 ] ,
80- [ 2 , dimensions . width - dimensions . thumbSize - 2 ] ,
81- )
82-
83- return {
84- transform : [ { translateX } ] ,
85- }
86- } )
40+ const gray4 = useColor ( "gray4" )
41+
42+ useImperativeHandle (
43+ ref ,
44+ ( ) => ( {
45+ value,
46+ } ) ,
47+ [ value ] ,
48+ )
8749
8850 return (
89- < Pressable onPress = { handlePress } className = "opacity-100" style = { styles . container } >
90- < Animated . View
91- style = { [
92- styles . track ,
93- { width : dimensions . width , height : dimensions . height } ,
94- trackAnimatedStyle ,
95- ] }
96- >
97- < Animated . View
98- style = { [
99- styles . thumb ,
100- {
101- width : dimensions . thumbSize ,
102- height : dimensions . thumbSize ,
103- } ,
104- thumbAnimatedStyle ,
105- ] }
106- />
107- </ Animated . View >
108- </ Pressable >
51+ < NativeSwitch
52+ disabled = { disabled }
53+ ios_backgroundColor = { gray4 }
54+ onChange = { onChange ?? undefined }
55+ onValueChange = { onValueChange ?? undefined }
56+ style = { size === "sm" ? styles . small : styles . default }
57+ testID = { testID }
58+ thumbColor = { Platform . OS === "android" ? "#FFFFFF" : undefined }
59+ trackColor = { { false : gray4 , true : accentColor } }
60+ value = { value }
61+ />
10962 )
11063}
11164
11265const styles = StyleSheet . create ( {
113- container : {
114- justifyContent : "center" ,
115- alignItems : "center" ,
116- } ,
117- track : {
118- borderRadius : 999 ,
119- justifyContent : "center" ,
120- position : "relative" ,
66+ default : {
67+ transform : [ { scaleX : 0.94 } , { scaleY : 0.94 } ] ,
12168 } ,
122- thumb : {
123- borderRadius : 999 ,
124- backgroundColor : "#FFFFFF" ,
125- position : "absolute" ,
126- top : 2 ,
127- shadowColor : "#000" ,
128- shadowOffset : {
129- width : 0 ,
130- height : 1 ,
131- } ,
132- shadowOpacity : 0.2 ,
133- shadowRadius : 2 ,
134- elevation : 3 ,
69+ small : {
70+ transform : [ { scaleX : 0.8 } , { scaleY : 0.8 } ] ,
13571 } ,
13672} )
0 commit comments