@@ -3,17 +3,22 @@ import {
33 StyleSheet ,
44 TouchableWithoutFeedback ,
55 I18nManager ,
6- View ,
76} from 'react-native' ;
87import Reanimated , {
8+ AnimationCallback ,
99 useAnimatedStyle ,
1010 useSharedValue ,
1111 withSpring ,
12+ runOnJS ,
1213} from 'react-native-reanimated' ;
1314import type { SwitchProps } from '../types' ;
1415
15- const spring = ( _value : any , config : any = { damping : 20 , stiffness : 120 } ) =>
16- withSpring ( _value , config ) ;
16+ const spring = (
17+ _value : any ,
18+ config : any = { damping : 20 , stiffness : 120 } ,
19+ callback ?: AnimationCallback
20+ ) =>
21+ withSpring ( _value , config , callback ) ;
1722
1823const PADDINGHORIZONTAL = 2 ;
1924
@@ -45,6 +50,7 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
4550 switchStyle,
4651 circleChildrenActive,
4752 circleChildrenInActive,
53+ onAnimationEnd,
4854 } = IProps ;
4955
5056 const { isRTL } = I18nManager ;
@@ -142,7 +148,6 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
142148 ( defaultCircleSize +
143149 ( defaultPadding . paddingLeft + defaultPadding . paddingRight ) ) ) ;
144150 if ( value ) {
145- circleTranslateX . value = spring ( size , { damping : 15 , stiffness : 120 } ) ;
146151 textTranslateXActive . value = spring ( 0 ) ;
147152 textTranslateXInActive . value = spring ( factory * defaultWidth ) ;
148153 if ( circleActiveColor ) {
@@ -153,8 +158,17 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
153158 }
154159 circleChildrenActiveOpacity . value = spring ( 1 ) ;
155160 circleChildrenInActiveOpacity . value = spring ( 0 ) ;
161+ circleTranslateX . value = spring (
162+ size ,
163+ { damping : 15 , stiffness : 120 } ,
164+ ( finished ?: boolean ) => {
165+ 'worklet' ;
166+ if ( finished && onAnimationEnd ) {
167+ runOnJS ( onAnimationEnd ) ( true ) ;
168+ }
169+ }
170+ ) ;
156171 } else {
157- circleTranslateX . value = spring ( 0 , { damping : 15 , stiffness : 120 } ) ;
158172 textTranslateXActive . value = spring ( - ( defaultWidth * factory ) ) ;
159173 textTranslateXInActive . value = spring ( 0 ) ;
160174 if ( circleInActiveColor ) {
@@ -165,6 +179,16 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
165179 }
166180 circleChildrenActiveOpacity . value = spring ( 0 ) ;
167181 circleChildrenInActiveOpacity . value = spring ( 1 ) ;
182+ circleTranslateX . value = spring (
183+ 0 ,
184+ { damping : 15 , stiffness : 120 } ,
185+ ( finished ?: boolean ) => {
186+ 'worklet' ;
187+ if ( finished && onAnimationEnd ) {
188+ runOnJS ( onAnimationEnd ) ( false ) ;
189+ }
190+ }
191+ ) ;
168192 }
169193 } , [ value , defaultWidth , defaultCircleSize , defaultPadding , isRTL ] ) ;
170194
@@ -176,20 +200,14 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
176200 }
177201 } , [ disabled ] ) ;
178202
179- const Button = ( props : any ) => {
180- if ( typeof onValueChange === 'function' && ! disabled ) {
181- return (
182- < TouchableWithoutFeedback
183- { ...props }
184- onPress = { ( ) => onValueChange ( ! value ) }
185- />
186- ) ;
187- }
188- return < View { ...props } /> ;
189- } ;
190-
191203 return (
192- < Button >
204+ < TouchableWithoutFeedback
205+ onPress = { ( ) => {
206+ if ( ! disabled ) {
207+ onValueChange ?.( ! value ) ;
208+ }
209+ } }
210+ >
193211 < Reanimated . View
194212 style = { [
195213 styles . switch ,
@@ -277,14 +295,15 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
277295 </ Reanimated . View >
278296 </ Reanimated . View >
279297 </ Reanimated . View >
280- </ Button >
298+ </ TouchableWithoutFeedback >
281299 ) ;
282300} ;
283301
284302Switch . defaultProps = {
285303 disabled : false ,
286304 value : false ,
287305 onValueChange : undefined ,
306+ onAnimationEnd : undefined ,
288307 activeText : 'ON' ,
289308 inActiveText : 'OFF' ,
290309 backgroundActive : '#249c00' ,
0 commit comments