@@ -18,15 +18,18 @@ import {
18
18
import type { PanGestureHandlerProps } from '../handlers/PanGestureHandler' ;
19
19
import type { PanGestureHandlerEventPayload } from '../handlers/GestureHandlerEventPayload' ;
20
20
import Animated , {
21
+ ReduceMotion ,
21
22
SharedValue ,
22
23
interpolate ,
24
+ measure ,
23
25
runOnJS ,
26
+ runOnUI ,
27
+ useAnimatedRef ,
24
28
useAnimatedStyle ,
25
29
useSharedValue ,
26
30
withSpring ,
27
31
} from 'react-native-reanimated' ;
28
32
import {
29
- Dimensions ,
30
33
I18nManager ,
31
34
LayoutChangeEvent ,
32
35
StyleProp ,
@@ -257,20 +260,9 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
257
260
const leftWidth = useSharedValue < number > ( 0 ) ;
258
261
const rightWidth = useSharedValue < number > ( 0 ) ;
259
262
260
- // used for synchronizing layout measurements between JS and UI
261
- const rightOffset = useSharedValue < number | null > ( null ) ;
262
-
263
263
const showLeftProgress = useSharedValue < number > ( 0 ) ;
264
264
const showRightProgress = useSharedValue < number > ( 0 ) ;
265
265
266
- const updateRightElementWidth = useCallback ( ( ) => {
267
- 'worklet' ;
268
- if ( rightOffset . value === null ) {
269
- rightOffset . value = rowWidth . value ;
270
- }
271
- rightWidth . value = Math . max ( 0 , rowWidth . value - rightOffset . value ) ;
272
- } , [ rightOffset , rightWidth , rowWidth ] ) ;
273
-
274
266
const updateAnimatedEvent = useCallback ( ( ) => {
275
267
'worklet' ;
276
268
@@ -372,11 +364,12 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
372
364
'worklet' ;
373
365
374
366
const translationSpringConfig = {
375
- duration : 1000 ,
376
- dampingRatio : 0.9 ,
377
- stiffness : 500 ,
367
+ mass : 2 ,
368
+ damping : 1000 ,
369
+ stiffness : 700 ,
378
370
velocity : velocityX ,
379
371
overshootClamping : true ,
372
+ reduceMotion : ReduceMotion . System ,
380
373
...animationOptions ,
381
374
} ;
382
375
@@ -412,16 +405,17 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
412
405
}
413
406
) ;
414
407
415
- const progressTarget = toValue === 0 ? 0 : 1 ;
408
+ const progressTarget = toValue === 0 ? 0 : 1 * Math . sign ( toValue ) ;
416
409
417
- showLeftProgress . value =
418
- showLeftProgress . value > 0
419
- ? withSpring ( progressTarget , progressSpringConfig )
420
- : 0 ;
421
- showRightProgress . value =
422
- showRightProgress . value > 0
423
- ? withSpring ( progressTarget , progressSpringConfig )
424
- : 0 ;
410
+ showLeftProgress . value = withSpring (
411
+ Math . max ( progressTarget , 0 ) ,
412
+ progressSpringConfig
413
+ ) ;
414
+
415
+ showRightProgress . value = withSpring (
416
+ Math . max ( - progressTarget , 0 ) ,
417
+ progressSpringConfig
418
+ ) ;
425
419
426
420
dispatchImmediateEvents ( frozenRowState , toValue ) ;
427
421
@@ -440,20 +434,66 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
440
434
]
441
435
) ;
442
436
437
+ const leftLayoutRef = useAnimatedRef ( ) ;
438
+ const leftWrapperLayoutRef = useAnimatedRef ( ) ;
439
+ const rightLayoutRef = useAnimatedRef ( ) ;
440
+
441
+ const updateElementWidths = useCallback ( ( ) => {
442
+ 'worklet' ;
443
+ const leftLayout = measure ( leftLayoutRef ) ;
444
+ const leftWrapperLayout = measure ( leftWrapperLayoutRef ) ;
445
+ const rightLayout = measure ( rightLayoutRef ) ;
446
+ leftWidth . value =
447
+ ( leftLayout ?. pageX ?? 0 ) - ( leftWrapperLayout ?. pageX ?? 0 ) ;
448
+
449
+ rightWidth . value =
450
+ rowWidth . value -
451
+ ( rightLayout ?. pageX ?? rowWidth . value ) +
452
+ ( leftWrapperLayout ?. pageX ?? 0 ) ;
453
+ } , [
454
+ leftLayoutRef ,
455
+ leftWrapperLayoutRef ,
456
+ rightLayoutRef ,
457
+ leftWidth ,
458
+ rightWidth ,
459
+ rowWidth . value ,
460
+ ] ) ;
461
+
443
462
const swipeableMethods = useMemo < SwipeableMethods > (
444
463
( ) => ( {
445
464
close ( ) {
446
465
'worklet' ;
447
- animateRow ( 0 ) ;
466
+ if ( _WORKLET ) {
467
+ animateRow ( 0 ) ;
468
+ return ;
469
+ }
470
+ runOnUI ( ( ) => {
471
+ animateRow ( 0 ) ;
472
+ } ) ( ) ;
448
473
} ,
449
474
openLeft ( ) {
450
475
'worklet' ;
451
- animateRow ( leftWidth . value ) ;
476
+ if ( _WORKLET ) {
477
+ updateElementWidths ( ) ;
478
+ animateRow ( leftWidth . value ) ;
479
+ return ;
480
+ }
481
+ runOnUI ( ( ) => {
482
+ updateElementWidths ( ) ;
483
+ animateRow ( leftWidth . value ) ;
484
+ } ) ( ) ;
452
485
} ,
453
486
openRight ( ) {
454
487
'worklet' ;
455
- // rightOffset and rowWidth are already much sooner than rightWidth
456
- animateRow ( ( rightOffset . value ?? 0 ) - rowWidth . value ) ;
488
+ if ( _WORKLET ) {
489
+ updateElementWidths ( ) ;
490
+ animateRow ( - rightWidth . value ) ;
491
+ return ;
492
+ }
493
+ runOnUI ( ( ) => {
494
+ updateElementWidths ( ) ;
495
+ animateRow ( - rightWidth . value ) ;
496
+ } ) ( ) ;
457
497
} ,
458
498
reset ( ) {
459
499
'worklet' ;
@@ -464,14 +504,14 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
464
504
} ,
465
505
} ) ,
466
506
[
507
+ animateRow ,
508
+ updateElementWidths ,
467
509
leftWidth ,
468
- rightOffset ,
469
- rowWidth ,
510
+ rightWidth ,
470
511
userDrag ,
471
512
showLeftProgress ,
472
513
appliedTranslation ,
473
514
rowState ,
474
- animateRow ,
475
515
]
476
516
) ;
477
517
@@ -484,38 +524,31 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
484
524
485
525
// As stated in `Dimensions.get` docstring, this function should be called on every render
486
526
// since dimensions may change (e.g. orientation change)
487
- const hiddenSwipeableOffset = Dimensions . get ( 'window' ) . width + 1 ;
488
527
489
528
const leftActionAnimation = useAnimatedStyle ( ( ) => {
490
529
return {
491
- transform : [
492
- {
493
- translateX :
494
- showLeftProgress . value === 0 ? - hiddenSwipeableOffset : 0 ,
495
- } ,
496
- ] ,
530
+ opacity : showLeftProgress . value === 0 ? 0 : 1 ,
497
531
} ;
498
532
} ) ;
499
533
500
534
const leftElement = useCallback (
501
535
( ) => (
502
- < Animated . View style = { [ styles . leftActions , leftActionAnimation ] } >
536
+ < Animated . View
537
+ ref = { leftWrapperLayoutRef }
538
+ style = { [ styles . leftActions , leftActionAnimation ] } >
503
539
{ renderLeftActions ?.(
504
540
showLeftProgress ,
505
541
appliedTranslation ,
506
542
swipeableMethods
507
543
) }
508
- < View
509
- onLayout = { ( { nativeEvent } ) =>
510
- ( leftWidth . value = nativeEvent . layout . x )
511
- }
512
- />
544
+ < Animated . View ref = { leftLayoutRef } />
513
545
</ Animated . View >
514
546
) ,
515
547
[
516
548
appliedTranslation ,
517
549
leftActionAnimation ,
518
- leftWidth ,
550
+ leftLayoutRef ,
551
+ leftWrapperLayoutRef ,
519
552
renderLeftActions ,
520
553
showLeftProgress ,
521
554
swipeableMethods ,
@@ -524,12 +557,7 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
524
557
525
558
const rightActionAnimation = useAnimatedStyle ( ( ) => {
526
559
return {
527
- transform : [
528
- {
529
- translateX :
530
- showRightProgress . value === 0 ? hiddenSwipeableOffset : 0 ,
531
- } ,
532
- ] ,
560
+ opacity : showRightProgress . value === 0 ? 0 : 1 ,
533
561
} ;
534
562
} ) ;
535
563
@@ -541,18 +569,14 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
541
569
appliedTranslation ,
542
570
swipeableMethods
543
571
) }
544
- < View
545
- onLayout = { ( { nativeEvent } ) => {
546
- rightOffset . value = nativeEvent . layout . x ;
547
- } }
548
- />
572
+ < Animated . View ref = { rightLayoutRef } />
549
573
</ Animated . View >
550
574
) ,
551
575
[
552
576
appliedTranslation ,
553
577
renderRightActions ,
554
578
rightActionAnimation ,
555
- rightOffset ,
579
+ rightLayoutRef ,
556
580
showRightProgress ,
557
581
swipeableMethods ,
558
582
]
@@ -564,8 +588,6 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
564
588
const { velocityX } = event ;
565
589
userDrag . value = event . translationX ;
566
590
567
- updateRightElementWidth ( ) ;
568
-
569
591
const leftThresholdProp = leftThreshold ?? leftWidth . value / 2 ;
570
592
const rightThresholdProp = rightThreshold ?? rightWidth . value / 2 ;
571
593
@@ -603,7 +625,6 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
603
625
rightWidth ,
604
626
rowState ,
605
627
userDrag ,
606
- updateRightElementWidth ,
607
628
]
608
629
) ;
609
630
@@ -632,9 +653,7 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
632
653
. enabled ( enabled !== false )
633
654
. enableTrackpadTwoFingerGesture ( enableTrackpadTwoFingerGesture )
634
655
. activeOffsetX ( [ - dragOffsetFromRightEdge , dragOffsetFromLeftEdge ] )
635
- . onStart ( ( ) => {
636
- updateRightElementWidth ( ) ;
637
- } )
656
+ . onStart ( updateElementWidths )
638
657
. onUpdate (
639
658
( event : GestureUpdateEvent < PanGestureHandlerEventPayload > ) => {
640
659
userDrag . value = event . translationX ;
@@ -679,7 +698,7 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
679
698
onSwipeableOpenStartDrag ,
680
699
rowState ,
681
700
updateAnimatedEvent ,
682
- updateRightElementWidth ,
701
+ updateElementWidths ,
683
702
userDrag ,
684
703
]
685
704
) ;
0 commit comments