@momo-kits/foundation 0.161.2-beta.1 → 0.161.2-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,22 +8,13 @@ import React, {
8
8
  useState,
9
9
  } from 'react';
10
10
  import {
11
+ Animated,
11
12
  PixelRatio,
12
13
  TextInput,
13
14
  TextInputFocusEvent,
14
15
  TouchableOpacity,
15
16
  View,
16
17
  } from 'react-native';
17
- import Animated, {
18
- cancelAnimation,
19
- Easing,
20
- useAnimatedStyle,
21
- useSharedValue,
22
- withDelay,
23
- withRepeat,
24
- withSequence,
25
- withTiming,
26
- } from 'react-native-reanimated';
27
18
  import { useComponentId } from '../Application';
28
19
  import { Spacing, Styles } from '../Consts';
29
20
  import { useScaleSize, Text } from '../Text';
@@ -41,43 +32,37 @@ import {
41
32
  const OTPCaret: FC<CaretProps> = ({ index, length }) => {
42
33
  const DURATION = 300;
43
34
  const { theme } = useContext(ApplicationContext);
44
- const opacity = useSharedValue(0);
35
+ const opacity = useRef(new Animated.Value(0)).current;
45
36
 
46
37
  useEffect(() => {
47
- opacity.value = withRepeat(
48
- withSequence(
49
- withTiming(1, { duration: DURATION, easing: Easing.linear }),
50
- withDelay(
51
- DURATION * 2,
52
- withTiming(0, { duration: DURATION, easing: Easing.linear }),
53
- ),
54
- ),
55
- -1,
56
- false,
57
- );
58
- return () => {
59
- cancelAnimation(opacity);
60
- };
38
+ Animated.loop(
39
+ Animated.sequence([
40
+ Animated.timing(opacity, {
41
+ toValue: 1,
42
+ duration: DURATION,
43
+ useNativeDriver: true,
44
+ }),
45
+ Animated.delay(DURATION * 2),
46
+ Animated.timing(opacity, {
47
+ toValue: 0,
48
+ duration: DURATION,
49
+ useNativeDriver: true,
50
+ }),
51
+ ]),
52
+ ).start();
61
53
  }, [opacity]);
62
-
63
- const animatedStyle = useAnimatedStyle(() => ({
64
- opacity: opacity.value,
65
- }));
66
-
67
54
  const spacingStyle = !isNaN(Number(length)) &&
68
55
  index !== Number(length) - 1 && { marginRight: Spacing.L };
69
56
 
70
57
  return (
71
58
  <View style={[Styles.rowCenter, spacingStyle]}>
72
59
  <Animated.View
73
- style={[
74
- {
75
- height: useScaleSize(12),
76
- width: 1,
77
- backgroundColor: theme.colors.primary,
78
- },
79
- animatedStyle,
80
- ]}
60
+ style={{
61
+ height: useScaleSize(12),
62
+ width: 1,
63
+ backgroundColor: theme.colors.primary,
64
+ opacity,
65
+ }}
81
66
  />
82
67
  <Text color={theme.colors.text.hint} typography={'body_default_regular'}>
83
68
  -
@@ -1,18 +1,17 @@
1
- import React, { useContext, useEffect, useState } from 'react';
2
1
  import {
2
+ default as React,
3
+ useContext,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
8
+ import {
9
+ Animated,
3
10
  LayoutChangeEvent,
4
11
  StyleSheet,
5
12
  TouchableOpacity,
6
13
  View,
7
14
  } from 'react-native';
8
- import Animated, {
9
- useAnimatedReaction,
10
- useAnimatedStyle,
11
- useSharedValue,
12
- withTiming,
13
- runOnJS,
14
- type SharedValue,
15
- } from 'react-native-reanimated';
16
15
  import { ApplicationContext } from '../Context';
17
16
  import { Icon } from '../Icon';
18
17
  import { useScaleSize } from '../Text';
@@ -24,7 +23,7 @@ export interface FloatingButtonProps {
24
23
  icon?: string;
25
24
  iconColor?: string;
26
25
  size?: 'small' | 'large';
27
- animatedValue?: SharedValue<number>;
26
+ animatedValue?: Animated.Value;
28
27
  bottom?: number;
29
28
  renderComponent?: () => React.ReactNode;
30
29
  }
@@ -43,67 +42,68 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
43
42
  const { theme } = useContext(ApplicationContext);
44
43
  const scaledFontSize = useScaleSize(16);
45
44
  const scaledLineHeight = useScaleSize(22);
46
- const maxWidth = useSharedValue(0);
45
+ const maxWidth = useRef(0);
47
46
  const minWidth = size === 'small' ? 36 : 48;
48
- const opacityAnimated = useSharedValue(0);
49
- const widthAnimated = useSharedValue<number | null>(null);
50
- const lastOffset = useSharedValue(0);
51
- const lastDirection = useSharedValue<string | null>(null);
52
- const [showText, setShowText] = useState(true);
47
+ const [opacityAnimated] = useState(new Animated.Value(0)); // Initial opacity set to 0
48
+ const [widthAnimated, setWidthAnimated] = useState<Animated.Value>();
49
+ const lastOffset = useRef(0);
50
+ const lastDirection = useRef<string>(null);
51
+ const [showText, setShowText] = React.useState(true);
53
52
 
54
53
  useEffect(() => {
55
54
  if (!label) return;
56
- opacityAnimated.value = withTiming(1, { duration: 100 });
57
- }, [label, opacityAnimated]);
58
55
 
59
- useAnimatedReaction(
60
- () => animatedValue?.value ?? 0,
61
- (value) => {
62
- 'worklet';
63
- if (!label || !animatedValue) return;
64
- if (value !== lastOffset.value && value > 0) {
65
- const direction = value > lastOffset.value ? 'down' : 'up';
66
- lastOffset.value = value;
67
- if (lastDirection.value !== direction) {
68
- lastDirection.value = direction;
56
+ Animated.timing(opacityAnimated, {
57
+ toValue: 1,
58
+ duration: 100,
59
+ useNativeDriver: true,
60
+ }).start();
61
+
62
+ const listener = animatedValue?.addListener(({ value }) => {
63
+ if (value !== lastOffset.current && value > 0) {
64
+ const direction = value > lastOffset.current ? 'down' : 'up';
65
+ lastOffset.current = value;
66
+ if (lastDirection.current !== direction) {
67
+ lastDirection.current = direction;
69
68
  if (direction === 'down') {
70
- opacityAnimated.value = withTiming(0, { duration: 100 });
71
- widthAnimated.value = withTiming(
72
- minWidth,
73
- { duration: 100 },
74
- (finished) => {
75
- if (finished) runOnJS(setShowText)(false);
76
- },
77
- );
69
+ Animated.timing(opacityAnimated, {
70
+ toValue: 0,
71
+ duration: 100,
72
+ useNativeDriver: true,
73
+ }).start();
74
+ Animated.timing(widthAnimated!, {
75
+ toValue: minWidth,
76
+ duration: 100,
77
+ useNativeDriver: false,
78
+ }).start(() => setShowText(false));
78
79
  } else {
79
- opacityAnimated.value = withTiming(1, { duration: 100 });
80
- widthAnimated.value = withTiming(
81
- maxWidth.value,
82
- { duration: 100 },
83
- (finished) => {
84
- if (finished) runOnJS(setShowText)(true);
85
- },
86
- );
80
+ Animated.timing(opacityAnimated, {
81
+ toValue: 1,
82
+ duration: 100,
83
+ useNativeDriver: true,
84
+ }).start();
85
+ Animated.timing(widthAnimated!, {
86
+ toValue: maxWidth.current,
87
+ duration: 100,
88
+ useNativeDriver: false,
89
+ }).start(() => setShowText(true));
87
90
  }
88
91
  }
89
92
  }
90
- },
91
- [label, animatedValue, minWidth],
92
- );
93
-
94
- const containerStyle = useAnimatedStyle(() => ({
95
- width: widthAnimated.value ?? undefined,
96
- }));
93
+ });
97
94
 
98
- const labelStyle = useAnimatedStyle(() => ({
99
- opacity: opacityAnimated.value,
100
- }));
95
+ return () => {
96
+ if (listener) {
97
+ animatedValue?.removeListener(listener);
98
+ }
99
+ };
100
+ }, [animatedValue, label, minWidth, opacityAnimated, widthAnimated]);
101
101
 
102
102
  const handleLayout = (event: LayoutChangeEvent) => {
103
103
  const layout = event.nativeEvent.layout;
104
- if (widthAnimated.value != null) return;
105
- maxWidth.value = layout.width;
106
- widthAnimated.value = layout.width;
104
+ if (widthAnimated) return;
105
+ maxWidth.current = layout.width;
106
+ setWidthAnimated(new Animated.Value(layout.width));
107
107
  };
108
108
 
109
109
  if (renderComponent) {
@@ -132,11 +132,11 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
132
132
  {
133
133
  right: position === 'right' ? 12 : undefined,
134
134
  alignSelf: position === 'center' ? 'center' : 'flex-end',
135
+ width: widthAnimated,
135
136
  height: size === 'small' ? 36 : 48,
136
137
  backgroundColor: theme.colors.primary,
137
138
  bottom,
138
139
  },
139
- containerStyle,
140
140
  ]}
141
141
  >
142
142
  <TouchableOpacity
@@ -156,9 +156,9 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
156
156
  {
157
157
  fontSize: scaledFontSize,
158
158
  lineHeight: scaledLineHeight,
159
+ opacity: opacityAnimated,
159
160
  color: 'white',
160
161
  },
161
- labelStyle,
162
162
  ]}
163
163
  numberOfLines={1}
164
164
  >
package/Layout/Screen.tsx CHANGED
@@ -12,6 +12,7 @@ import React, {
12
12
  useRef,
13
13
  } from 'react';
14
14
  import {
15
+ Animated,
15
16
  KeyboardAvoidingView,
16
17
  NativeScrollEvent,
17
18
  NativeSyntheticEvent,
@@ -24,13 +25,6 @@ import {
24
25
  View,
25
26
  ViewProps,
26
27
  } from 'react-native';
27
- import Animated, {
28
- runOnJS,
29
- useAnimatedScrollHandler,
30
- useSharedValue,
31
- withTiming,
32
- type SharedValue,
33
- } from 'react-native-reanimated';
34
28
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
35
29
  import { ApplicationContext, ScreenContext } from '../Context';
36
30
  import Navigation from '../Application/Navigation';
@@ -144,7 +138,7 @@ export interface ScreenProps extends ViewProps {
144
138
  /**
145
139
  * Optional. Animated value for header.
146
140
  */
147
- animatedValue?: SharedValue<number>;
141
+ animatedValue?: Animated.Value;
148
142
 
149
143
  /**
150
144
  * Optional. If `true`, use shadow header.
@@ -201,17 +195,19 @@ const Screen = forwardRef(
201
195
  const screen: any = useContext(ScreenContext);
202
196
  const insets = useSafeAreaInsets();
203
197
  const heightHeader = useHeaderHeight();
204
- const internalAnimatedValue = useSharedValue(0);
205
- const animatedValue = customAnimatedValue ?? internalAnimatedValue;
198
+ const animatedValue = useRef<Animated.Value>(
199
+ customAnimatedValue || new Animated.Value(0),
200
+ );
206
201
  const currentTint = useRef<string | undefined>(undefined);
207
202
  const isTab = navigation?.instance?.getState?.()?.type === 'tab';
208
203
 
209
- let handleScroll: any;
204
+ let handleScroll;
210
205
  let Component: any = View;
211
206
 
212
- let keyboardOffset = heightHeader - Math.min(insets.bottom, 21);
207
+ const bottomInset = Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
208
+ let keyboardOffset = heightHeader - bottomInset;
213
209
  if (headerType === 'extended' || animatedHeader || inputSearchProps) {
214
- keyboardOffset = -Math.min(insets.bottom, 21);
210
+ keyboardOffset = -bottomInset;
215
211
  }
216
212
 
217
213
  /**
@@ -253,8 +249,9 @@ const Screen = forwardRef(
253
249
  interpolate={{
254
250
  inputRange: [0, 50],
255
251
  outputRange: [1, 0],
252
+ extrapolate: 'clamp',
256
253
  }}
257
- animatedValue={animatedValue}
254
+ animatedValue={animatedValue.current}
258
255
  />
259
256
  ),
260
257
  };
@@ -269,7 +266,7 @@ const Screen = forwardRef(
269
266
  headerBackground: (props: any) => (
270
267
  <HeaderBackground
271
268
  {...props}
272
- animatedValue={animatedValue}
269
+ animatedValue={animatedValue.current}
273
270
  useShadowHeader={useShadowHeader}
274
271
  headerBackground={headerBackground}
275
272
  gradientColor={gradientColor}
@@ -288,8 +285,9 @@ const Screen = forwardRef(
288
285
  interpolate={{
289
286
  inputRange: [0, 50],
290
287
  outputRange: [1, 0],
288
+ extrapolate: 'clamp',
291
289
  }}
292
- animatedValue={animatedValue}
290
+ animatedValue={animatedValue.current}
293
291
  />
294
292
  ),
295
293
  };
@@ -324,7 +322,7 @@ const Screen = forwardRef(
324
322
  headerBackground: (props: any) => (
325
323
  <HeaderBackground
326
324
  {...props}
327
- animatedValue={animatedValue}
325
+ animatedValue={animatedValue.current}
328
326
  useGradient={false}
329
327
  useShadowHeader={useShadowHeader}
330
328
  headerBackground={headerBackground}
@@ -362,8 +360,9 @@ const Screen = forwardRef(
362
360
  interpolate={{
363
361
  inputRange: [0, 50],
364
362
  outputRange: [1, 0],
363
+ extrapolate: 'clamp',
365
364
  }}
366
- animatedValue={animatedValue}
365
+ animatedValue={animatedValue.current}
367
366
  />
368
367
  ),
369
368
  };
@@ -392,7 +391,7 @@ const Screen = forwardRef(
392
391
  headerLeft: (props: any) =>
393
392
  params?.hiddenBack ? null : <HeaderLeft {...props} />,
394
393
  headerTitle: () => (
395
- <SearchHeader {...params} animatedValue={animatedValue} />
394
+ <SearchHeader {...params} animatedValue={animatedValue.current} />
396
395
  ),
397
396
  };
398
397
 
@@ -443,51 +442,45 @@ const Screen = forwardRef(
443
442
  });
444
443
  });
445
444
 
446
- const onTintColorChange = useCallback(
447
- (offsetY: number) => {
448
- if (!animatedHeader) return;
449
- let color = animatedHeader?.headerTintColor ?? Colors.black_17;
450
- if (offsetY > 50) {
451
- color = Colors.black_17;
452
- }
453
- if (color !== currentTint.current) {
454
- currentTint.current = color;
455
- navigation?.setOptions({
456
- headerTintColor: color,
457
- });
458
- let barStyle: StatusBarStyle = 'dark-content';
459
- if (currentTint.current === Colors.black_01) {
460
- barStyle = 'light-content';
461
- }
462
- StatusBar.setBarStyle(barStyle, true);
463
- }
464
- },
465
- [animatedHeader, navigation],
466
- );
467
-
468
- const emitOnScroll = useCallback(
469
- (offsetY: number) => {
470
- scrollViewProps?.onScroll?.({
471
- nativeEvent: { contentOffset: { x: 0, y: offsetY } },
472
- } as NativeSyntheticEvent<NativeScrollEvent>);
473
- },
474
- [scrollViewProps],
475
- );
476
-
477
- const scrollHandler = useAnimatedScrollHandler({
478
- onScroll: (event) => {
479
- animatedValue.value = event.contentOffset.y;
480
- runOnJS(emitOnScroll)(event.contentOffset.y);
481
- runOnJS(onTintColorChange)(event.contentOffset.y);
482
- },
483
- });
484
-
485
445
  /**
486
446
  * animated when use scroll && animated value
487
447
  */
488
448
  if (scrollable) {
489
449
  Component = Animated.ScrollView;
490
- handleScroll = scrollHandler;
450
+ handleScroll = Animated.event(
451
+ [
452
+ {
453
+ nativeEvent: {
454
+ contentOffset: { y: animatedValue.current as Animated.Value },
455
+ },
456
+ },
457
+ ],
458
+ {
459
+ useNativeDriver: true,
460
+ listener: (e: NativeSyntheticEvent<NativeScrollEvent>) => {
461
+ scrollViewProps?.onScroll?.(e);
462
+ if (animatedHeader) {
463
+ const offsetY = e.nativeEvent.contentOffset.y;
464
+ let color = animatedHeader?.headerTintColor ?? Colors.black_17;
465
+ if (offsetY > 50) {
466
+ color = Colors.black_17;
467
+ }
468
+ if (color !== currentTint.current) {
469
+ currentTint.current = color;
470
+ navigation?.setOptions({
471
+ headerTintColor: color,
472
+ });
473
+
474
+ let barStyle: StatusBarStyle = 'dark-content';
475
+ if (currentTint.current === Colors.black_01) {
476
+ barStyle = 'light-content';
477
+ }
478
+ StatusBar.setBarStyle(barStyle, true);
479
+ }
480
+ }
481
+ },
482
+ },
483
+ );
491
484
  }
492
485
 
493
486
  /**
@@ -497,7 +490,11 @@ const Screen = forwardRef(
497
490
  const handleScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
498
491
  const offsetY = e.nativeEvent.contentOffset.y;
499
492
  if (inputSearchProps && offsetY < 100 && offsetY > 0) {
500
- animatedValue.value = withTiming(0, { duration: 300 });
493
+ Animated.timing(animatedValue.current, {
494
+ toValue: 0,
495
+ useNativeDriver: true,
496
+ duration: 300,
497
+ }).start();
501
498
  ref?.scrollTo?.({ y: 0, animated: true });
502
499
  }
503
500
  scrollViewProps?.onScrollEndDrag?.(e);
@@ -513,7 +510,7 @@ const Screen = forwardRef(
513
510
  style={[styles.screenBanner, { maxHeight: 210 + layoutOffset }]}
514
511
  >
515
512
  {animatedHeader?.component({
516
- animatedValue: animatedValue,
513
+ animatedValue: animatedValue.current,
517
514
  })}
518
515
  </View>
519
516
  );
@@ -580,7 +577,7 @@ const Screen = forwardRef(
580
577
  headerType={headerType}
581
578
  heightHeader={heightHeader}
582
579
  headerRightWidth={headerRightWidth}
583
- animatedValue={animatedValue}
580
+ animatedValue={animatedValue.current}
584
581
  inputSearchProps={inputSearchProps}
585
582
  navigation={navigation}
586
583
  inputSearchRef={inputSearchRef}
@@ -618,9 +615,9 @@ const Screen = forwardRef(
618
615
  <View>
619
616
  <FloatingButton
620
617
  {...floatingButtonProps}
621
- animatedValue={animatedValue}
618
+ animatedValue={animatedValue.current}
622
619
  bottom={
623
- Footer || isTab ? 12 : Math.min(insets.bottom, 21) + Spacing.S
620
+ Footer || isTab ? 12 : bottomInset + Spacing.S
624
621
  }
625
622
  />
626
623
  </View>
@@ -631,7 +628,7 @@ const Screen = forwardRef(
631
628
  style={[
632
629
  styles.shadow,
633
630
  {
634
- paddingBottom: Math.min(insets.bottom, 21) + Spacing.S,
631
+ paddingBottom: bottomInset + Spacing.S,
635
632
  backgroundColor: theme.colors.background.surface,
636
633
  },
637
634
  ]}
@@ -1,10 +1,5 @@
1
- import React, { FC, useContext, useEffect } from 'react';
2
- import { View } from 'react-native';
3
- import Animated, {
4
- useAnimatedStyle,
5
- useSharedValue,
6
- withTiming,
7
- } from 'react-native-reanimated';
1
+ import React, { FC, useContext, useEffect, useRef } from 'react';
2
+ import { Animated, View } from 'react-native';
8
3
  import styles from './styles';
9
4
  import { ProgressBarProps } from './types';
10
5
  import { ApplicationContext } from '../Context';
@@ -12,15 +7,20 @@ import { Radius } from '../Consts';
12
7
 
13
8
  const ProgressBar: FC<ProgressBarProps> = ({ percent = 0, style }) => {
14
9
  const { theme } = useContext(ApplicationContext);
15
- const animation = useSharedValue(0);
10
+ const animation = useRef(new Animated.Value(0)).current;
16
11
 
17
12
  useEffect(() => {
18
- animation.value = withTiming(percent, { duration: 200 });
13
+ Animated.timing(animation, {
14
+ toValue: percent,
15
+ duration: 200,
16
+ useNativeDriver: false,
17
+ }).start();
19
18
  }, [percent, animation]);
20
19
 
21
- const animatedStyle = useAnimatedStyle(() => ({
22
- width: `${Math.min(Math.max(animation.value, 0), 100)}%`,
23
- }));
20
+ const width = animation.interpolate({
21
+ inputRange: [0, 100],
22
+ outputRange: ['0%', '100%'],
23
+ });
24
24
 
25
25
  return (
26
26
  <View
@@ -31,14 +31,12 @@ const ProgressBar: FC<ProgressBarProps> = ({ percent = 0, style }) => {
31
31
  ]}
32
32
  >
33
33
  <Animated.View
34
- style={[
35
- {
36
- height: 4,
37
- borderRadius: Radius.XXS,
38
- backgroundColor: theme.colors.primary,
39
- },
40
- animatedStyle,
41
- ]}
34
+ style={{
35
+ height: 4,
36
+ borderRadius: Radius.XXS,
37
+ width,
38
+ backgroundColor: theme.colors.primary,
39
+ }}
42
40
  />
43
41
  </View>
44
42
  );
@@ -1,5 +1,5 @@
1
1
  import React, { FC, useContext } from 'react';
2
- import { View } from 'react-native';
2
+ import { Animated } from 'react-native';
3
3
  import styles from './styles';
4
4
  import { DotProps } from './types';
5
5
  import { ApplicationContext } from '../Context';
@@ -13,7 +13,7 @@ const Dot: FC<DotProps> = ({ active, style }) => {
13
13
  { backgroundColor: theme.colors.background.pressed },
14
14
  ];
15
15
 
16
- return <View style={[style, dotStyle]} />;
16
+ return <Animated.View style={[style, dotStyle]} />;
17
17
  };
18
18
 
19
19
  export default Dot;
@@ -1,12 +1,5 @@
1
- import React, { FC, useContext, useState } from 'react';
2
- import { View } from 'react-native';
3
- import Animated, {
4
- Extrapolation,
5
- interpolate,
6
- useAnimatedScrollHandler,
7
- useAnimatedStyle,
8
- useSharedValue,
9
- } from 'react-native-reanimated';
1
+ import React, { FC, useContext, useRef, useState } from 'react';
2
+ import { Animated, View } from 'react-native';
10
3
  import { ScrollIndicatorProps } from './types';
11
4
  import styles from './styles';
12
5
  import { ApplicationContext, MiniAppContext } from '../Context';
@@ -20,37 +13,40 @@ const PaginationScroll: FC<ScrollIndicatorProps> = ({
20
13
  }) => {
21
14
  const { theme } = useContext(ApplicationContext);
22
15
  const context = useContext<any>(MiniAppContext);
23
- const left = useSharedValue(0);
16
+ const left = useRef(new Animated.Value(0)).current;
24
17
  const [scrollViewWidth, setScrollViewWidth] = useState(0);
25
18
  const [scrollContentWidth, setScrollContentWidth] = useState(0);
26
19
 
27
20
  const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
28
21
 
29
- const onScroll = useAnimatedScrollHandler({
30
- onScroll: (event) => {
31
- left.value = event.contentOffset.x;
32
- },
33
- });
34
-
35
- const indicatorStyle = useAnimatedStyle(() => {
36
- if (!scrollViewWidth || !scrollContentWidth) {
37
- return {};
22
+ const translateX = () => {
23
+ if (scrollViewWidth && scrollContentWidth) {
24
+ const value = left.interpolate({
25
+ inputRange: [0, scrollContentWidth - scrollViewWidth],
26
+ outputRange: [0, INDICATOR_CONTAINER_WIDTH - INDICATOR_WIDTH],
27
+ extrapolate: 'clamp',
28
+ });
29
+ return { transform: [{ translateX: value }] };
38
30
  }
39
- const value = interpolate(
40
- left.value,
41
- [0, scrollContentWidth - scrollViewWidth],
42
- [0, INDICATOR_CONTAINER_WIDTH - INDICATOR_WIDTH],
43
- Extrapolation.CLAMP,
44
- );
45
- return { transform: [{ translateX: value }] };
46
- });
31
+ return {};
32
+ };
47
33
 
48
34
  const renderScrollView = () => {
49
35
  return (
50
36
  <Animated.ScrollView
51
- ref={scrollViewRef as any}
52
- onScroll={onScroll}
53
- scrollEventThrottle={16}
37
+ ref={scrollViewRef}
38
+ onScroll={Animated.event(
39
+ [
40
+ {
41
+ nativeEvent: {
42
+ contentOffset: {
43
+ x: left,
44
+ },
45
+ },
46
+ },
47
+ ],
48
+ { useNativeDriver: true },
49
+ )}
54
50
  alwaysBounceHorizontal={false}
55
51
  showsHorizontalScrollIndicator={false}
56
52
  horizontal
@@ -80,7 +76,7 @@ const PaginationScroll: FC<ScrollIndicatorProps> = ({
80
76
  {
81
77
  backgroundColor: theme.colors.primary,
82
78
  },
83
- indicatorStyle,
79
+ translateX(),
84
80
  ]}
85
81
  />
86
82
  </View>