@momo-kits/foundation 0.161.2-test.1 → 0.162.2-test.1

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,20 +195,16 @@ 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
- // AI-GENERATED START
213
- // On iOS the home indicator is ~34pt but visual safe area needs only ~21pt cap.
214
- // On Android 15+ edge-to-edge the nav bar can be 48dp — no cap needed.
215
207
  const bottomInset = Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
216
- // AI-GENERATED END
217
-
218
208
  let keyboardOffset = heightHeader - bottomInset;
219
209
  if (headerType === 'extended' || animatedHeader || inputSearchProps) {
220
210
  keyboardOffset = -bottomInset;
@@ -259,8 +249,9 @@ const Screen = forwardRef(
259
249
  interpolate={{
260
250
  inputRange: [0, 50],
261
251
  outputRange: [1, 0],
252
+ extrapolate: 'clamp',
262
253
  }}
263
- animatedValue={animatedValue}
254
+ animatedValue={animatedValue.current}
264
255
  />
265
256
  ),
266
257
  };
@@ -275,7 +266,7 @@ const Screen = forwardRef(
275
266
  headerBackground: (props: any) => (
276
267
  <HeaderBackground
277
268
  {...props}
278
- animatedValue={animatedValue}
269
+ animatedValue={animatedValue.current}
279
270
  useShadowHeader={useShadowHeader}
280
271
  headerBackground={headerBackground}
281
272
  gradientColor={gradientColor}
@@ -294,8 +285,9 @@ const Screen = forwardRef(
294
285
  interpolate={{
295
286
  inputRange: [0, 50],
296
287
  outputRange: [1, 0],
288
+ extrapolate: 'clamp',
297
289
  }}
298
- animatedValue={animatedValue}
290
+ animatedValue={animatedValue.current}
299
291
  />
300
292
  ),
301
293
  };
@@ -330,7 +322,7 @@ const Screen = forwardRef(
330
322
  headerBackground: (props: any) => (
331
323
  <HeaderBackground
332
324
  {...props}
333
- animatedValue={animatedValue}
325
+ animatedValue={animatedValue.current}
334
326
  useGradient={false}
335
327
  useShadowHeader={useShadowHeader}
336
328
  headerBackground={headerBackground}
@@ -368,8 +360,9 @@ const Screen = forwardRef(
368
360
  interpolate={{
369
361
  inputRange: [0, 50],
370
362
  outputRange: [1, 0],
363
+ extrapolate: 'clamp',
371
364
  }}
372
- animatedValue={animatedValue}
365
+ animatedValue={animatedValue.current}
373
366
  />
374
367
  ),
375
368
  };
@@ -398,7 +391,7 @@ const Screen = forwardRef(
398
391
  headerLeft: (props: any) =>
399
392
  params?.hiddenBack ? null : <HeaderLeft {...props} />,
400
393
  headerTitle: () => (
401
- <SearchHeader {...params} animatedValue={animatedValue} />
394
+ <SearchHeader {...params} animatedValue={animatedValue.current} />
402
395
  ),
403
396
  };
404
397
 
@@ -449,51 +442,45 @@ const Screen = forwardRef(
449
442
  });
450
443
  });
451
444
 
452
- const onTintColorChange = useCallback(
453
- (offsetY: number) => {
454
- if (!animatedHeader) return;
455
- let color = animatedHeader?.headerTintColor ?? Colors.black_17;
456
- if (offsetY > 50) {
457
- color = Colors.black_17;
458
- }
459
- if (color !== currentTint.current) {
460
- currentTint.current = color;
461
- navigation?.setOptions({
462
- headerTintColor: color,
463
- });
464
- let barStyle: StatusBarStyle = 'dark-content';
465
- if (currentTint.current === Colors.black_01) {
466
- barStyle = 'light-content';
467
- }
468
- StatusBar.setBarStyle(barStyle, true);
469
- }
470
- },
471
- [animatedHeader, navigation],
472
- );
473
-
474
- const emitOnScroll = useCallback(
475
- (offsetY: number) => {
476
- scrollViewProps?.onScroll?.({
477
- nativeEvent: { contentOffset: { x: 0, y: offsetY } },
478
- } as NativeSyntheticEvent<NativeScrollEvent>);
479
- },
480
- [scrollViewProps],
481
- );
482
-
483
- const scrollHandler = useAnimatedScrollHandler({
484
- onScroll: (event) => {
485
- animatedValue.value = event.contentOffset.y;
486
- runOnJS(emitOnScroll)(event.contentOffset.y);
487
- runOnJS(onTintColorChange)(event.contentOffset.y);
488
- },
489
- });
490
-
491
445
  /**
492
446
  * animated when use scroll && animated value
493
447
  */
494
448
  if (scrollable) {
495
449
  Component = Animated.ScrollView;
496
- 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
+ );
497
484
  }
498
485
 
499
486
  /**
@@ -503,7 +490,11 @@ const Screen = forwardRef(
503
490
  const handleScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
504
491
  const offsetY = e.nativeEvent.contentOffset.y;
505
492
  if (inputSearchProps && offsetY < 100 && offsetY > 0) {
506
- animatedValue.value = withTiming(0, { duration: 300 });
493
+ Animated.timing(animatedValue.current, {
494
+ toValue: 0,
495
+ useNativeDriver: true,
496
+ duration: 300,
497
+ }).start();
507
498
  ref?.scrollTo?.({ y: 0, animated: true });
508
499
  }
509
500
  scrollViewProps?.onScrollEndDrag?.(e);
@@ -519,7 +510,7 @@ const Screen = forwardRef(
519
510
  style={[styles.screenBanner, { maxHeight: 210 + layoutOffset }]}
520
511
  >
521
512
  {animatedHeader?.component({
522
- animatedValue: animatedValue,
513
+ animatedValue: animatedValue.current,
523
514
  })}
524
515
  </View>
525
516
  );
@@ -586,7 +577,7 @@ const Screen = forwardRef(
586
577
  headerType={headerType}
587
578
  heightHeader={heightHeader}
588
579
  headerRightWidth={headerRightWidth}
589
- animatedValue={animatedValue}
580
+ animatedValue={animatedValue.current}
590
581
  inputSearchProps={inputSearchProps}
591
582
  navigation={navigation}
592
583
  inputSearchRef={inputSearchRef}
@@ -624,7 +615,7 @@ const Screen = forwardRef(
624
615
  <View>
625
616
  <FloatingButton
626
617
  {...floatingButtonProps}
627
- animatedValue={animatedValue}
618
+ animatedValue={animatedValue.current}
628
619
  bottom={
629
620
  Footer || isTab ? 12 : bottomInset + Spacing.S
630
621
  }
@@ -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>