77 TextStyle ,
88 View ,
99 ViewStyle ,
10+ I18nManager ,
1011} from 'react-native' ;
1112import { Gesture , GestureDetector } from 'react-native-gesture-handler' ;
1213import type { WithTimingConfig } from 'react-native-reanimated' ;
@@ -42,6 +43,7 @@ export enum PanDirectionEnum {
4243 RIGHT = 2 ,
4344 END = 3 ,
4445}
46+
4547export type SliderThemeType =
4648 | {
4749 /**
@@ -301,6 +303,11 @@ export type AwesomeSliderProps = {
301303 * When 'heartbeat' is set to true, the progress bar color will animate back and forth between its current color and the color specified for the heartbeat.
302304 */
303305 heartbeat ?: boolean ;
306+ /**
307+ * Whether the slider is in RTL mode.
308+ * @default true
309+ */
310+ isRTL ?: boolean ;
304311} ;
305312const defaultTheme : SliderThemeType = {
306313 minimumTrackTintColor : palette . Main ,
@@ -362,6 +369,7 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
362369 heartbeat = false ,
363370 snapThreshold = 0 ,
364371 snapThresholdMode = 'absolute' ,
372+ isRTL = I18nManager . isRTL ,
365373} ) {
366374 const step = propsStep || steps ;
367375
@@ -408,7 +416,6 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
408416 } else {
409417 seekWidth = progressToValue ( progress . value ) + thumbWidth / 2 ;
410418 }
411- sliderTotalValue . value ; // hack: force recompute styles when 'sliderTotalValue' changes
412419
413420 return {
414421 width :
@@ -428,7 +435,7 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
428435 const animatedThumbStyle = useAnimatedStyle ( ( ) => {
429436 let translateX = 0 ;
430437 // when you set step
431-
438+ const subtractedWidth = width . value - thumbWidth ;
432439 if ( snappingEnabled && markLeftArr . value . length >= step ) {
433440 translateX = stepTimingOptions
434441 ? withTiming ( markLeftArr . value [ thumbIndex . value ] ! , stepTimingOptions )
@@ -437,21 +444,19 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
437444 translateX = clamp (
438445 thumbValue . value ,
439446 0 ,
440- width . value ? width . value - thumbWidth : 0
447+ width . value ? subtractedWidth : 0
441448 ) ;
442449 } else {
443450 translateX = clamp (
444451 progressToValue ( progress . value ) ,
445452 0 ,
446- width . value ? width . value - thumbWidth : 0
453+ width . value ? subtractedWidth : 0
447454 ) ;
448455 }
449-
450- sliderTotalValue . value ; // hack: force recompute styles when 'sliderTotalValue' change
451456 return {
452457 transform : [
453458 {
454- translateX,
459+ translateX : isRTL ? subtractedWidth - translateX : translateX ,
455460 } ,
456461 {
457462 scale : withTiming ( thumbScaleValue ? thumbScaleValue . value : 1 , {
@@ -460,7 +465,7 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
460465 } ,
461466 ] ,
462467 } ;
463- } , [ progress , minimumValue , maximumValue , width , snappingEnabled ] ) ;
468+ } , [ progress , minimumValue , maximumValue , width , snappingEnabled , isRTL ] ) ;
464469
465470 const animatedBubbleStyle = useAnimatedStyle ( ( ) => {
466471 let translateX = 0 ;
@@ -470,6 +475,11 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
470475 } else {
471476 translateX = thumbValue . value + thumbWidth / 2 ;
472477 }
478+ translateX = isRTL ? width . value - translateX : translateX ;
479+
480+ const minX = bubbleWidth / 2 - thumbWidth / 2 ;
481+ const maxX = width . value - bubbleWidth / 2 ;
482+
473483 return {
474484 opacity : bubbleOpacity . value ,
475485 transform : [
@@ -479,26 +489,15 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
479489 {
480490 translateX :
481491 snappingEnabled && stepTimingOptions
482- ? withTiming (
483- clamp (
484- translateX ,
485- bubbleWidth / 2 ,
486- width . value - bubbleWidth / 2
487- ) ,
488- stepTimingOptions
489- )
490- : clamp (
491- translateX ,
492- bubbleWidth / 2 ,
493- width . value - bubbleWidth / 2
494- ) ,
492+ ? withTiming ( clamp ( translateX , minX , maxX ) , stepTimingOptions )
493+ : clamp ( translateX , minX , maxX ) ,
495494 } ,
496495 {
497496 scale : bubbleOpacity . value ,
498497 } ,
499498 ] ,
500499 } ;
501- } , [ bubbleTranslateY , bubbleWidth , width , snappingEnabled ] ) ;
500+ } , [ bubbleTranslateY , bubbleWidth , width , snappingEnabled , isRTL ] ) ;
502501
503502 const animatedCacheXStyle = useAnimatedStyle ( ( ) => {
504503 const cacheX =
@@ -738,7 +737,8 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
738737 const onGestureEvent = useMemo ( ( ) => {
739738 const gesture = Gesture . Pan ( )
740739 . hitSlop ( panHitSlop )
741- . onBegin ( ( { x } ) => {
740+ . onBegin ( ( { x : xValue } ) => {
741+ const x = isRTL ? width . value - xValue : xValue ;
742742 if ( disableTrackPress ) {
743743 isTouchInThumbRange . value =
744744 Math . abs ( x - thumbPosition . value ) <= thumbTouchSize ;
@@ -762,7 +762,8 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
762762 runOnJS ( onSlidingStart ) ( ) ;
763763 }
764764 } )
765- . onUpdate ( ( { x } ) => {
765+ . onUpdate ( ( { x : xValue } ) => {
766+ const x = isRTL ? width . value - xValue : xValue ;
766767 if ( disable || ( ! isTouchInThumbRange . value && disableTrackPress ) ) {
767768 return ;
768769 }
@@ -777,7 +778,8 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
777778
778779 onActiveSlider ( x ) ;
779780 } )
780- . onEnd ( ( { x } ) => {
781+ . onEnd ( ( { x : xValue } ) => {
782+ const x = isRTL ? width . value - xValue : xValue ;
781783 isScrubbingInner . value = false ;
782784 if ( disable ) {
783785 return ;
@@ -850,12 +852,15 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
850852 xToProgress ,
851853 shareValueToSeconds ,
852854 disableTrackPress ,
855+ isRTL ,
856+ width ,
853857 ] ) ;
854858 const onSingleTapEvent = useMemo (
855859 ( ) =>
856860 Gesture . Tap ( )
857861 . hitSlop ( panHitSlop )
858- . onEnd ( ( { x } , isFinished ) => {
862+ . onEnd ( ( { x : xValue } , isFinished ) => {
863+ const x = isRTL ? width . value - xValue : xValue ;
859864 if ( onTap ) {
860865 runOnJS ( onTap ) ( ) ;
861866 }
@@ -890,6 +895,8 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
890895 onTap ,
891896 panHitSlop ,
892897 shareValueToSeconds ,
898+ isRTL ,
899+ width ,
893900 ]
894901 ) ;
895902
@@ -1095,7 +1102,13 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
10951102 ) ;
10961103 } )
10971104 : null }
1098- < Animated . View style = { [ styles . thumb , animatedThumbStyle ] } >
1105+ < Animated . View
1106+ style = { [
1107+ styles . thumb ,
1108+ animatedThumbStyle ,
1109+ isRTL ? { right : 0 } : { left : 0 } ,
1110+ ] }
1111+ >
10991112 { renderThumb ? (
11001113 renderThumb ( )
11011114 ) : (
@@ -1113,9 +1126,11 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
11131126 style = { [
11141127 styles . bubble ,
11151128 {
1116- left : - bubbleMaxWidth / 2 + bubbleOffsetX ,
11171129 width : bubbleMaxWidth ,
11181130 } ,
1131+ isRTL
1132+ ? { right : - bubbleMaxWidth / 2 + bubbleOffsetX }
1133+ : { left : - bubbleMaxWidth / 2 + bubbleOffsetX } ,
11191134 animatedBubbleStyle ,
11201135 ] }
11211136 >
@@ -1173,7 +1188,6 @@ const styles = StyleSheet.create({
11731188 } ,
11741189 thumb : {
11751190 position : 'absolute' ,
1176- left : 0 ,
11771191 } ,
11781192 bubble : {
11791193 position : 'absolute' ,
0 commit comments