react-native-reanimated-carousel 2.2.2 → 2.2.5-beta.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.
Files changed (78) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/lib/commonjs/Carousel.js +1 -221
  4. package/lib/commonjs/Carousel.js.map +1 -1
  5. package/lib/commonjs/LazyView.js +1 -25
  6. package/lib/commonjs/LazyView.js.map +1 -1
  7. package/lib/commonjs/ScrollViewGesture.js +1 -217
  8. package/lib/commonjs/ScrollViewGesture.js.map +1 -1
  9. package/lib/commonjs/constants/index.js +1 -21
  10. package/lib/commonjs/constants/index.js.map +1 -1
  11. package/lib/commonjs/hooks/useAutoPlay.js +1 -61
  12. package/lib/commonjs/hooks/useAutoPlay.js.map +1 -1
  13. package/lib/commonjs/hooks/useCarouselController.js +1 -194
  14. package/lib/commonjs/hooks/useCarouselController.js.map +1 -1
  15. package/lib/commonjs/hooks/useCommonVariables.js +1 -36
  16. package/lib/commonjs/hooks/useCommonVariables.js.map +1 -1
  17. package/lib/commonjs/hooks/useInitProps.js +1 -70
  18. package/lib/commonjs/hooks/useInitProps.js.map +1 -1
  19. package/lib/commonjs/hooks/useLayoutConfig.js +1 -39
  20. package/lib/commonjs/hooks/useLayoutConfig.js.map +1 -1
  21. package/lib/commonjs/hooks/useOffsetX.js +1 -54
  22. package/lib/commonjs/hooks/useOffsetX.js.map +1 -1
  23. package/lib/commonjs/hooks/useOnProgressChange.js +1 -38
  24. package/lib/commonjs/hooks/useOnProgressChange.js.map +1 -1
  25. package/lib/commonjs/hooks/usePropsErrorBoundary.js +1 -37
  26. package/lib/commonjs/hooks/usePropsErrorBoundary.js.map +1 -1
  27. package/lib/commonjs/hooks/useVisibleRanges.js +1 -42
  28. package/lib/commonjs/hooks/useVisibleRanges.js.map +1 -1
  29. package/lib/commonjs/index.js +1 -13
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/layouts/BaseLayout.js +1 -100
  32. package/lib/commonjs/layouts/BaseLayout.js.map +1 -1
  33. package/lib/commonjs/layouts/ParallaxLayout.js +1 -82
  34. package/lib/commonjs/layouts/ParallaxLayout.js.map +1 -1
  35. package/lib/commonjs/layouts/index.js +1 -20
  36. package/lib/commonjs/layouts/index.js.map +1 -1
  37. package/lib/commonjs/layouts/normal.js +1 -27
  38. package/lib/commonjs/layouts/normal.js.map +1 -1
  39. package/lib/commonjs/layouts/parallax.js +1 -36
  40. package/lib/commonjs/layouts/parallax.js.map +1 -1
  41. package/lib/commonjs/layouts/stack.js +1 -219
  42. package/lib/commonjs/layouts/stack.js.map +1 -1
  43. package/lib/commonjs/store/index.js +1 -14
  44. package/lib/commonjs/store/index.js.map +1 -1
  45. package/lib/commonjs/types.js +1 -5
  46. package/lib/commonjs/utils/dealWithAnimation.js +2 -0
  47. package/lib/commonjs/utils/dealWithAnimation.js.map +1 -0
  48. package/lib/commonjs/utils/log.js +1 -14
  49. package/lib/commonjs/utils/log.js.map +1 -1
  50. package/lib/module/Carousel.js +14 -10
  51. package/lib/module/Carousel.js.map +1 -1
  52. package/lib/module/ScrollViewGesture.js +46 -29
  53. package/lib/module/ScrollViewGesture.js.map +1 -1
  54. package/lib/module/hooks/useAutoPlay.js +5 -1
  55. package/lib/module/hooks/useAutoPlay.js.map +1 -1
  56. package/lib/module/hooks/useCarouselController.js +21 -7
  57. package/lib/module/hooks/useCarouselController.js.map +1 -1
  58. package/lib/module/layouts/BaseLayout.js +2 -1
  59. package/lib/module/layouts/BaseLayout.js.map +1 -1
  60. package/lib/module/layouts/stack.js.map +1 -1
  61. package/lib/module/utils/dealWithAnimation.js +17 -0
  62. package/lib/module/utils/dealWithAnimation.js.map +1 -0
  63. package/lib/typescript/Carousel.d.ts +3 -4
  64. package/lib/typescript/ScrollViewGesture.d.ts +3 -1
  65. package/lib/typescript/hooks/useCarouselController.d.ts +2 -1
  66. package/lib/typescript/layouts/BaseLayout.d.ts +2 -2
  67. package/lib/typescript/layouts/stack.d.ts +1 -1
  68. package/lib/typescript/types.d.ts +14 -2
  69. package/lib/typescript/utils/dealWithAnimation.d.ts +2 -0
  70. package/package.json +12 -2
  71. package/src/Carousel.tsx +203 -188
  72. package/src/ScrollViewGesture.tsx +70 -33
  73. package/src/hooks/useAutoPlay.ts +4 -1
  74. package/src/hooks/useCarouselController.tsx +28 -12
  75. package/src/layouts/BaseLayout.tsx +3 -3
  76. package/src/layouts/stack.ts +1 -1
  77. package/src/types.ts +22 -4
  78. package/src/utils/dealWithAnimation.ts +22 -0
package/src/Carousel.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, { PropsWithChildren } from 'react';
1
+ import React from 'react';
2
2
  import Animated, { runOnJS, useDerivedValue } from 'react-native-reanimated';
3
3
 
4
4
  import { useCarouselController } from './hooks/useCarouselController';
@@ -17,199 +17,214 @@ import { CTX } from './store';
17
17
  import { useCommonVariables } from './hooks/useCommonVariables';
18
18
  import { useOnProgressChange } from './hooks/useOnProgressChange';
19
19
 
20
- function Carousel<T>(
21
- _props: PropsWithChildren<TCarouselProps<T>>,
22
- ref: React.Ref<ICarouselInstance>
23
- ) {
24
- const props = useInitProps(_props);
25
-
26
- const {
27
- data,
28
- rawData,
29
- loop,
30
- mode,
31
- style,
32
- width,
33
- height,
34
- vertical,
35
- autoPlay,
36
- windowSize,
37
- autoPlayReverse,
38
- autoPlayInterval,
39
- scrollAnimationDuration,
40
- renderItem,
41
- onScrollEnd,
42
- onSnapToItem,
43
- onScrollBegin,
44
- onProgressChange,
45
- customAnimation,
46
- } = props;
47
-
48
- const commonVariables = useCommonVariables(props);
49
- const { size, handlerOffsetX } = commonVariables;
50
-
51
- const offsetX = useDerivedValue(() => {
52
- const totalSize = size * data.length;
53
- const x = handlerOffsetX.value % totalSize;
54
-
55
- if (!loop) {
56
- return handlerOffsetX.value;
57
- }
58
- return isNaN(x) ? 0 : x;
59
- }, [loop, size, data]);
60
-
61
- usePropsErrorBoundary(props);
62
- useOnProgressChange({ size, offsetX, rawData, onProgressChange });
63
-
64
- const carouselController = useCarouselController({
65
- loop,
66
- size,
67
- handlerOffsetX,
68
- length: data.length,
69
- disable: !data.length,
70
- originalLength: data.length,
71
- onScrollEnd: () => runOnJS(_onScrollEnd)(),
72
- onScrollBegin: () => !!onScrollBegin && runOnJS(onScrollBegin)(),
73
- onChange: (i) => !!onSnapToItem && runOnJS(onSnapToItem)(i),
74
- duration: scrollAnimationDuration,
75
- });
76
-
77
- const {
78
- next,
79
- prev,
80
- sharedPreIndex,
81
- sharedIndex,
82
- computedIndex,
83
- getCurrentIndex,
84
- } = carouselController;
85
-
86
- const { start, pause } = useAutoPlay({
87
- autoPlay,
88
- autoPlayInterval,
89
- autoPlayReverse,
90
- carouselController,
91
- });
92
-
93
- const scrollViewGestureOnScrollBegin = React.useCallback(() => {
94
- pause();
95
- onScrollBegin?.();
96
- }, [onScrollBegin, pause]);
97
-
98
- const _onScrollEnd = React.useCallback(() => {
99
- computedIndex();
100
- onScrollEnd?.(sharedPreIndex.current, sharedIndex.current);
101
- }, [sharedPreIndex, sharedIndex, computedIndex, onScrollEnd]);
102
-
103
- const scrollViewGestureOnScrollEnd = React.useCallback(() => {
104
- start();
105
- _onScrollEnd();
106
- }, [_onScrollEnd, start]);
107
-
108
- const goToIndex = React.useCallback(
109
- (i: number, animated?: boolean) => {
110
- carouselController.to(i, animated);
111
- },
112
- [carouselController]
113
- );
114
-
115
- React.useImperativeHandle(
116
- ref,
117
- () => ({
118
- next,
119
- prev,
120
- getCurrentIndex,
121
- goToIndex,
122
- scrollTo: carouselController.scrollTo,
123
- }),
124
- [getCurrentIndex, goToIndex, next, prev, carouselController.scrollTo]
125
- );
126
-
127
- const visibleRanges = useVisibleRanges({
128
- total: data.length,
129
- viewSize: size,
130
- translation: handlerOffsetX,
131
- windowSize,
132
- });
133
-
134
- const layoutConfig = useLayoutConfig<T>({ ...props, size });
135
-
136
- const renderLayout = React.useCallback(
137
- (item: T, i: number) => {
138
- let realIndex = i;
139
- if (rawData.length === DATA_LENGTH.SINGLE_ITEM) {
140
- realIndex = i % 1;
141
- }
20
+ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
21
+ (_props, ref) => {
22
+ const props = useInitProps(_props);
142
23
 
143
- if (rawData.length === DATA_LENGTH.DOUBLE_ITEM) {
144
- realIndex = i % 2;
145
- }
146
-
147
- return (
148
- <BaseLayout
149
- key={i}
150
- index={i}
151
- handlerOffsetX={offsetX}
152
- visibleRanges={visibleRanges}
153
- animationStyle={customAnimation || layoutConfig}
154
- >
155
- {({ animationValue }) =>
156
- renderItem({
157
- item,
158
- index: realIndex,
159
- animationValue,
160
- })
161
- }
162
- </BaseLayout>
163
- );
164
- },
165
- [
24
+ const {
25
+ data,
166
26
  rawData,
167
- offsetX,
168
- visibleRanges,
27
+ loop,
28
+ mode,
29
+ style,
30
+ width,
31
+ height,
32
+ vertical,
33
+ autoPlay,
34
+ windowSize,
35
+ autoPlayReverse,
36
+ autoPlayInterval,
37
+ scrollAnimationDuration,
38
+ withAnimation,
169
39
  renderItem,
170
- layoutConfig,
40
+ onScrollEnd,
41
+ onSnapToItem,
42
+ onScrollBegin,
43
+ onProgressChange,
171
44
  customAnimation,
172
- ]
173
- );
174
-
175
- return (
176
- <CTX.Provider value={{ props, common: commonVariables }}>
177
- <View
178
- style={[
179
- styles.container,
180
- { width: width || '100%', height: height || '100%' },
181
- style,
182
- ]}
183
- >
184
- <ScrollViewGesture
185
- size={size}
186
- translation={handlerOffsetX}
187
- onScrollBegin={scrollViewGestureOnScrollBegin}
188
- onScrollEnd={scrollViewGestureOnScrollEnd}
45
+ } = props;
46
+
47
+ const commonVariables = useCommonVariables(props);
48
+ const { size, handlerOffsetX } = commonVariables;
49
+
50
+ const offsetX = useDerivedValue(() => {
51
+ const totalSize = size * data.length;
52
+ const x = handlerOffsetX.value % totalSize;
53
+
54
+ if (!loop) {
55
+ return handlerOffsetX.value;
56
+ }
57
+ return isNaN(x) ? 0 : x;
58
+ }, [loop, size, data]);
59
+
60
+ usePropsErrorBoundary(props);
61
+ useOnProgressChange({ size, offsetX, rawData, onProgressChange });
62
+
63
+ const carouselController = useCarouselController({
64
+ loop,
65
+ size,
66
+ handlerOffsetX,
67
+ length: data.length,
68
+ disable: !data.length,
69
+ withAnimation,
70
+ originalLength: data.length,
71
+ onScrollEnd: () => runOnJS(_onScrollEnd)(),
72
+ onScrollBegin: () => !!onScrollBegin && runOnJS(onScrollBegin)(),
73
+ onChange: (i) => !!onSnapToItem && runOnJS(onSnapToItem)(i),
74
+ duration: scrollAnimationDuration,
75
+ });
76
+
77
+ const {
78
+ next,
79
+ prev,
80
+ sharedPreIndex,
81
+ sharedIndex,
82
+ computedIndex,
83
+ getCurrentIndex,
84
+ } = carouselController;
85
+
86
+ const { start, pause } = useAutoPlay({
87
+ autoPlay,
88
+ autoPlayInterval,
89
+ autoPlayReverse,
90
+ carouselController,
91
+ });
92
+
93
+ const _onScrollEnd = React.useCallback(() => {
94
+ computedIndex();
95
+ onScrollEnd?.(sharedPreIndex.current, sharedIndex.current);
96
+ }, [sharedPreIndex, sharedIndex, computedIndex, onScrollEnd]);
97
+
98
+ const scrollViewGestureOnScrollBegin = React.useCallback(() => {
99
+ pause();
100
+ onScrollBegin?.();
101
+ }, [onScrollBegin, pause]);
102
+
103
+ const scrollViewGestureOnScrollEnd = React.useCallback(() => {
104
+ start();
105
+ _onScrollEnd();
106
+ }, [_onScrollEnd, start]);
107
+
108
+ const scrollViewGestureOnTouchBegin = React.useCallback(pause, [pause]);
109
+
110
+ const scrollViewGestureOnTouchEnd = React.useCallback(start, [start]);
111
+
112
+ const goToIndex = React.useCallback(
113
+ (i: number, animated?: boolean) => {
114
+ carouselController.to(i, animated);
115
+ },
116
+ [carouselController]
117
+ );
118
+
119
+ React.useImperativeHandle(
120
+ ref,
121
+ () => ({
122
+ next,
123
+ prev,
124
+ getCurrentIndex,
125
+ goToIndex,
126
+ scrollTo: carouselController.scrollTo,
127
+ }),
128
+ [
129
+ getCurrentIndex,
130
+ goToIndex,
131
+ next,
132
+ prev,
133
+ carouselController.scrollTo,
134
+ ]
135
+ );
136
+
137
+ const visibleRanges = useVisibleRanges({
138
+ total: data.length,
139
+ viewSize: size,
140
+ translation: handlerOffsetX,
141
+ windowSize,
142
+ });
143
+
144
+ const layoutConfig = useLayoutConfig({ ...props, size });
145
+
146
+ const renderLayout = React.useCallback(
147
+ (item: any, i: number) => {
148
+ let realIndex = i;
149
+ if (rawData.length === DATA_LENGTH.SINGLE_ITEM) {
150
+ realIndex = i % 1;
151
+ }
152
+
153
+ if (rawData.length === DATA_LENGTH.DOUBLE_ITEM) {
154
+ realIndex = i % 2;
155
+ }
156
+
157
+ return (
158
+ <BaseLayout
159
+ key={i}
160
+ index={i}
161
+ handlerOffsetX={offsetX}
162
+ visibleRanges={visibleRanges}
163
+ animationStyle={customAnimation || layoutConfig}
164
+ >
165
+ {({ animationValue }) =>
166
+ renderItem({
167
+ item,
168
+ index: realIndex,
169
+ animationValue,
170
+ })
171
+ }
172
+ </BaseLayout>
173
+ );
174
+ },
175
+ [
176
+ rawData,
177
+ offsetX,
178
+ visibleRanges,
179
+ renderItem,
180
+ layoutConfig,
181
+ customAnimation,
182
+ ]
183
+ );
184
+
185
+ return (
186
+ <CTX.Provider value={{ props, common: commonVariables }}>
187
+ <View
188
+ style={[
189
+ styles.container,
190
+ { width: width || '100%', height: height || '100%' },
191
+ style,
192
+ ]}
189
193
  >
190
- <Animated.View
191
- key={mode}
192
- style={[
193
- styles.container,
194
- {
195
- width: width || '100%',
196
- height: height || '100%',
197
- },
198
- style,
199
- vertical
200
- ? styles.itemsVertical
201
- : styles.itemsHorizontal,
202
- ]}
194
+ <ScrollViewGesture
195
+ size={size}
196
+ translation={handlerOffsetX}
197
+ onScrollBegin={scrollViewGestureOnScrollBegin}
198
+ onScrollEnd={scrollViewGestureOnScrollEnd}
199
+ onTouchBegin={scrollViewGestureOnTouchBegin}
200
+ onTouchEnd={scrollViewGestureOnTouchEnd}
203
201
  >
204
- {data.map(renderLayout)}
205
- </Animated.View>
206
- </ScrollViewGesture>
207
- </View>
208
- </CTX.Provider>
209
- );
210
- }
211
-
212
- export default React.forwardRef(Carousel) as typeof Carousel;
202
+ <Animated.View
203
+ key={mode}
204
+ style={[
205
+ styles.container,
206
+ {
207
+ width: width || '100%',
208
+ height: height || '100%',
209
+ },
210
+ style,
211
+ vertical
212
+ ? styles.itemsVertical
213
+ : styles.itemsHorizontal,
214
+ ]}
215
+ >
216
+ {data.map(renderLayout)}
217
+ </Animated.View>
218
+ </ScrollViewGesture>
219
+ </View>
220
+ </CTX.Provider>
221
+ );
222
+ }
223
+ );
224
+
225
+ export default Carousel as <T extends any>(
226
+ props: React.PropsWithChildren<TCarouselProps<T>>
227
+ ) => React.ReactElement;
213
228
 
214
229
  const styles = StyleSheet.create({
215
230
  container: {
@@ -12,10 +12,11 @@ import Animated, {
12
12
  useDerivedValue,
13
13
  useSharedValue,
14
14
  withDecay,
15
- withTiming,
16
15
  } from 'react-native-reanimated';
17
16
  import { Easing } from './constants';
18
17
  import { CTX } from './store';
18
+ import type { WithAnimation } from './types';
19
+ import { dealWithAnimation } from './utils/dealWithAnimation';
19
20
 
20
21
  type GestureContext = {
21
22
  panOffset: number;
@@ -25,8 +26,10 @@ type GestureContext = {
25
26
  interface Props {
26
27
  size: number;
27
28
  infinite?: boolean;
28
- onScrollEnd?: () => void;
29
29
  onScrollBegin?: () => void;
30
+ onScrollEnd?: () => void;
31
+ onTouchBegin?: () => void;
32
+ onTouchEnd?: () => void;
30
33
  style?: StyleProp<ViewStyle>;
31
34
  translation: Animated.SharedValue<number>;
32
35
  }
@@ -42,10 +45,18 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
42
45
  panGestureHandlerProps,
43
46
  loop: infinite,
44
47
  scrollAnimationDuration,
48
+ withAnimation,
45
49
  },
46
50
  } = React.useContext(CTX);
47
51
 
48
- const { translation, onScrollBegin, onScrollEnd, size } = props;
52
+ const {
53
+ translation,
54
+ size,
55
+ onScrollBegin,
56
+ onScrollEnd,
57
+ onTouchBegin,
58
+ onTouchEnd,
59
+ } = props;
49
60
 
50
61
  const maxPage = data.length;
51
62
  const isHorizontal = useDerivedValue(() => !vertical, [vertical]);
@@ -56,20 +67,27 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
56
67
  const _withSpring = React.useCallback(
57
68
  (toValue: number, onFinished?: () => void) => {
58
69
  'worklet';
59
- return withTiming(
60
- toValue,
61
- {
70
+ const callback = (isFinished: boolean) => {
71
+ 'worklet';
72
+ if (isFinished) {
73
+ onFinished && runOnJS(onFinished)();
74
+ }
75
+ };
76
+
77
+ const defaultWithAnimation: WithAnimation = {
78
+ type: 'timing',
79
+ config: {
62
80
  duration: scrollAnimationDuration,
63
81
  easing: Easing.easeOutQuart,
64
82
  },
65
- (isFinished) => {
66
- if (isFinished) {
67
- onFinished?.();
68
- }
69
- }
83
+ };
84
+
85
+ return dealWithAnimation(withAnimation ?? defaultWithAnimation)(
86
+ toValue,
87
+ callback
70
88
  );
71
89
  },
72
- [scrollAnimationDuration]
90
+ [scrollAnimationDuration, withAnimation]
73
91
  );
74
92
 
75
93
  const endWithSpring = React.useCallback(
@@ -116,22 +134,28 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
116
134
  ]
117
135
  );
118
136
 
119
- const resetBoundary = React.useCallback(() => {
120
- 'worklet';
121
- const onFinish = (isFinished: boolean) => {
137
+ const onFinish = React.useCallback(
138
+ (isFinished: boolean) => {
139
+ 'worklet';
122
140
  if (isFinished) {
123
141
  touching.value = false;
124
142
  onScrollEnd && runOnJS(onScrollEnd)();
125
143
  }
126
- };
127
- const activeDecay = () => {
128
- touching.value = true;
129
- translation.value = withDecay(
130
- { velocity: scrollEndVelocity.value },
131
- onFinish
132
- );
133
- };
144
+ },
145
+ [onScrollEnd, touching]
146
+ );
147
+
148
+ const activeDecay = React.useCallback(() => {
149
+ 'worklet';
150
+ touching.value = true;
151
+ translation.value = withDecay(
152
+ { velocity: scrollEndVelocity.value },
153
+ (isFinished) => onFinish(isFinished as boolean)
154
+ );
155
+ }, [onFinish, scrollEndVelocity.value, touching, translation]);
134
156
 
157
+ const resetBoundary = React.useCallback(() => {
158
+ 'worklet';
135
159
  if (touching.value) {
136
160
  return;
137
161
  }
@@ -158,15 +182,14 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
158
182
  }
159
183
  }
160
184
  }, [
161
- infinite,
162
- touching,
163
- _withSpring,
185
+ touching.value,
164
186
  translation,
165
- scrollEndTranslation,
166
- scrollEndVelocity,
167
- onScrollEnd,
168
187
  maxPage,
169
188
  size,
189
+ scrollEndTranslation.value,
190
+ infinite,
191
+ activeDecay,
192
+ _withSpring,
170
193
  ]);
171
194
 
172
195
  useAnimatedReaction(
@@ -176,7 +199,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
176
199
  resetBoundary();
177
200
  }
178
201
  },
179
- [pagingEnabled]
202
+ [pagingEnabled, resetBoundary]
180
203
  );
181
204
 
182
205
  const panGestureEventHandler = useAnimatedGestureHandler<
@@ -220,14 +243,24 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
220
243
  ? translationX
221
244
  : translationY;
222
245
 
223
- endWithSpring(() => onScrollEnd && runOnJS(onScrollEnd)());
246
+ // endWithSpring(() => onScrollEnd && runOnJS(onScrollEnd)());
247
+ endWithSpring(onScrollEnd);
224
248
 
225
249
  if (!infinite) {
226
250
  touching.value = false;
227
251
  }
228
252
  },
229
253
  },
230
- [pagingEnabled, isHorizontal.value, infinite, maxPage, size, enableSnap]
254
+ [
255
+ pagingEnabled,
256
+ isHorizontal.value,
257
+ infinite,
258
+ maxPage,
259
+ size,
260
+ enableSnap,
261
+ onScrollBegin,
262
+ onScrollEnd,
263
+ ]
231
264
  );
232
265
 
233
266
  const directionStyle = React.useMemo(() => {
@@ -235,7 +268,11 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
235
268
  }, [vertical]);
236
269
 
237
270
  return (
238
- <Animated.View style={[styles.container, directionStyle, style]}>
271
+ <Animated.View
272
+ style={[styles.container, directionStyle, style]}
273
+ onTouchStart={onTouchBegin}
274
+ onTouchEnd={onTouchEnd}
275
+ >
239
276
  <PanGestureHandler
240
277
  {...panGestureHandlerProps}
241
278
  onGestureEvent={panGestureEventHandler}
@@ -30,9 +30,12 @@ export function useAutoPlay(opts: {
30
30
  }, [autoPlayReverse, autoPlayInterval, carouselController]);
31
31
 
32
32
  const pause = React.useCallback(() => {
33
+ if (!autoPlay) {
34
+ return;
35
+ }
33
36
  timer.current && clearInterval(timer.current);
34
37
  stopped.current = true;
35
- }, []);
38
+ }, [autoPlay]);
36
39
 
37
40
  const start = React.useCallback(() => {
38
41
  if (!autoPlay) {
@@ -1,13 +1,19 @@
1
1
  import React from 'react';
2
2
  import type Animated from 'react-native-reanimated';
3
3
  import { Easing } from '../constants';
4
- import { runOnJS, useSharedValue, withTiming } from 'react-native-reanimated';
5
- import type { TCarouselActionOptions } from '../types';
4
+ import { runOnJS, useSharedValue } from 'react-native-reanimated';
5
+ import type {
6
+ TCarouselActionOptions,
7
+ TCarouselProps,
8
+ WithAnimation,
9
+ } from '../types';
10
+ import { dealWithAnimation } from '@/utils/dealWithAnimation';
6
11
 
7
12
  interface IOpts {
8
13
  loop: boolean;
9
14
  size: number;
10
15
  handlerOffsetX: Animated.SharedValue<number>;
16
+ withAnimation?: TCarouselProps['withAnimation'];
11
17
  disable?: boolean;
12
18
  duration?: number;
13
19
  originalLength: number;
@@ -36,6 +42,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
36
42
  size,
37
43
  loop,
38
44
  handlerOffsetX,
45
+ withAnimation,
39
46
  disable = false,
40
47
  originalLength,
41
48
  length,
@@ -116,22 +123,31 @@ export function useCarouselController(options: IOpts): ICarouselController {
116
123
 
117
124
  const scrollWithTiming = React.useCallback(
118
125
  (toValue: number, onFinished?: () => void) => {
119
- return withTiming(
120
- toValue,
121
- { duration, easing: Easing.easeOutQuart },
122
- (isFinished: boolean) => {
123
- if (isFinished) {
124
- runOnJS(onScrollEnd)();
125
- onFinished && runOnJS(onFinished)();
126
- }
126
+ 'worklet';
127
+ const callback = (isFinished: boolean) => {
128
+ 'worklet';
129
+ if (isFinished) {
130
+ runOnJS(onScrollEnd)();
131
+ onFinished && runOnJS(onFinished)();
127
132
  }
133
+ };
134
+
135
+ const defaultWithAnimation: WithAnimation = {
136
+ type: 'timing',
137
+ config: { duration, easing: Easing.easeOutQuart },
138
+ };
139
+
140
+ return dealWithAnimation(withAnimation ?? defaultWithAnimation)(
141
+ toValue,
142
+ callback
128
143
  );
129
144
  },
130
- [onScrollEnd, duration]
145
+ [duration, withAnimation, onScrollEnd]
131
146
  );
132
147
 
133
148
  const next = React.useCallback(
134
149
  (opts: TCarouselActionOptions = {}) => {
150
+ 'worklet';
135
151
  const { count = 1, animated = true, onFinished } = opts;
136
152
  if (!canSliding() || (!loop && index.value >= length - 1)) return;
137
153
 
@@ -144,7 +160,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
144
160
  handlerOffsetX.value = scrollWithTiming(
145
161
  -nextPage * size,
146
162
  onFinished
147
- );
163
+ ) as any;
148
164
  } else {
149
165
  handlerOffsetX.value = -nextPage * size;
150
166
  onFinished?.();