react-native-reanimated-carousel 2.3.9 → 2.3.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.
- package/lib/commonjs/Carousel.js +1 -1
- package/lib/commonjs/Carousel.js.map +1 -1
- package/lib/commonjs/ScrollViewGesture.js +1 -1
- package/lib/commonjs/ScrollViewGesture.js.map +1 -1
- package/lib/commonjs/hooks/useAutoPlay.js +1 -1
- package/lib/commonjs/hooks/useAutoPlay.js.map +1 -1
- package/lib/commonjs/hooks/useCarouselController.js +1 -1
- package/lib/commonjs/hooks/useCarouselController.js.map +1 -1
- package/lib/commonjs/utils/computedWithAutoFillData.js +1 -1
- package/lib/commonjs/utils/computedWithAutoFillData.js.map +1 -1
- package/lib/module/Carousel.js +40 -25
- package/lib/module/Carousel.js.map +1 -1
- package/lib/module/ScrollViewGesture.js +8 -10
- package/lib/module/ScrollViewGesture.js.map +1 -1
- package/lib/module/hooks/useAutoPlay.js +7 -3
- package/lib/module/hooks/useAutoPlay.js.map +1 -1
- package/lib/module/hooks/useCarouselController.js +36 -43
- package/lib/module/hooks/useCarouselController.js.map +1 -1
- package/lib/module/utils/computedWithAutoFillData.js +25 -0
- package/lib/module/utils/computedWithAutoFillData.js.map +1 -1
- package/lib/typescript/hooks/useCarouselController.d.ts +4 -10
- package/lib/typescript/types.d.ts +4 -0
- package/lib/typescript/utils/computedWithAutoFillData.d.ts +4 -0
- package/package.json +3 -3
- package/src/Carousel.tsx +43 -29
- package/src/ScrollViewGesture.tsx +7 -9
- package/src/hooks/useAutoPlay.ts +4 -3
- package/src/hooks/useCarouselController.tsx +53 -62
- package/src/types.ts +4 -0
- package/src/utils/computedWithAutoFillData.ts +18 -0
|
@@ -1,28 +1,22 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import type Animated from 'react-native-reanimated';
|
|
3
2
|
import type { TCarouselActionOptions, TCarouselProps } from '../types';
|
|
4
3
|
interface IOpts {
|
|
5
4
|
loop: boolean;
|
|
6
5
|
size: number;
|
|
6
|
+
data: TCarouselProps['data'];
|
|
7
|
+
autoFillData: TCarouselProps['autoFillData'];
|
|
7
8
|
handlerOffsetX: Animated.SharedValue<number>;
|
|
8
9
|
withAnimation?: TCarouselProps['withAnimation'];
|
|
9
|
-
disable?: boolean;
|
|
10
10
|
duration?: number;
|
|
11
|
-
originalLength: number;
|
|
12
|
-
length: number;
|
|
13
11
|
defaultIndex?: number;
|
|
14
12
|
onScrollBegin?: () => void;
|
|
15
13
|
onScrollEnd?: () => void;
|
|
16
|
-
onChange: (index: number) => void;
|
|
17
14
|
}
|
|
18
15
|
export interface ICarouselController {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
sharedIndex: React.MutableRefObject<number>;
|
|
22
|
-
sharedPreIndex: React.MutableRefObject<number>;
|
|
16
|
+
sharedIndex: Animated.SharedValue<number>;
|
|
17
|
+
sharedPreIndex: Animated.SharedValue<number>;
|
|
23
18
|
prev: (opts?: TCarouselActionOptions) => void;
|
|
24
19
|
next: (opts?: TCarouselActionOptions) => void;
|
|
25
|
-
computedIndex: () => void;
|
|
26
20
|
getCurrentIndex: () => number;
|
|
27
21
|
to: (index: number, animated?: boolean) => void;
|
|
28
22
|
scrollTo: (opts?: TCarouselActionOptions) => void;
|
|
@@ -129,6 +129,10 @@ export declare type TCarouselProps<T = any> = {
|
|
|
129
129
|
* Specifies the scrolling animation effect.
|
|
130
130
|
*/
|
|
131
131
|
withAnimation?: WithAnimation;
|
|
132
|
+
/**
|
|
133
|
+
* Used to locate this view in end-to-end tests.
|
|
134
|
+
*/
|
|
135
|
+
testID?: string;
|
|
132
136
|
/**
|
|
133
137
|
* Custom carousel config.
|
|
134
138
|
*/
|
|
@@ -2,6 +2,10 @@ declare type BaseParams<T extends object = {}> = {
|
|
|
2
2
|
autoFillData: boolean;
|
|
3
3
|
loop: boolean;
|
|
4
4
|
} & T;
|
|
5
|
+
export declare function convertToSharedIndex(params: BaseParams<{
|
|
6
|
+
index: number;
|
|
7
|
+
rawDataLength: number;
|
|
8
|
+
}>): number;
|
|
5
9
|
export declare function computedOffsetXValueWithAutoFillData(params: BaseParams<{
|
|
6
10
|
rawDataLength: number;
|
|
7
11
|
value: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-reanimated-carousel",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.10",
|
|
4
4
|
"description": "Simple carousel component.fully implemented using Reanimated 2.Infinitely scrolling, very smooth.",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"types": "lib/typescript/index.d.ts",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"lint": "eslint \"src/**/*.{js,ts,tsx}\"",
|
|
27
27
|
"dev": "yarn watch 'yarn prepare' ./src",
|
|
28
28
|
"prepare": "bob build",
|
|
29
|
-
"release": "release-it --no-git.requireUpstream",
|
|
30
|
-
"preRelease": "release-it --no-git.requireUpstream --preRelease=beta",
|
|
29
|
+
"release": "yarn prepare && release-it --no-git.requireUpstream",
|
|
30
|
+
"preRelease": "yarn prepare && release-it --no-git.requireUpstream --preRelease=beta",
|
|
31
31
|
"ios": "yarn --cwd example ios",
|
|
32
32
|
"ios:pretty": "yarn --cwd example ios:pretty",
|
|
33
33
|
"web": "yarn --cwd example web",
|
package/src/Carousel.tsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import Animated, {
|
|
2
|
+
import Animated, {
|
|
3
|
+
runOnJS,
|
|
4
|
+
runOnUI,
|
|
5
|
+
useDerivedValue,
|
|
6
|
+
} from 'react-native-reanimated';
|
|
3
7
|
|
|
4
8
|
import { useCarouselController } from './hooks/useCarouselController';
|
|
5
9
|
import { useAutoPlay } from './hooks/useAutoPlay';
|
|
@@ -22,6 +26,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
|
|
|
22
26
|
const props = useInitProps(_props);
|
|
23
27
|
|
|
24
28
|
const {
|
|
29
|
+
testID,
|
|
25
30
|
data,
|
|
26
31
|
rawData,
|
|
27
32
|
loop,
|
|
@@ -73,28 +78,27 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
|
|
|
73
78
|
const carouselController = useCarouselController({
|
|
74
79
|
loop,
|
|
75
80
|
size,
|
|
81
|
+
data,
|
|
82
|
+
autoFillData,
|
|
76
83
|
handlerOffsetX,
|
|
77
|
-
length: data.length,
|
|
78
|
-
disable: !data.length,
|
|
79
84
|
withAnimation,
|
|
80
|
-
originalLength: data.length,
|
|
81
85
|
defaultIndex,
|
|
82
86
|
onScrollEnd: () => runOnJS(_onScrollEnd)(),
|
|
83
87
|
onScrollBegin: () => !!onScrollBegin && runOnJS(onScrollBegin)(),
|
|
84
|
-
onChange: (i) => !!onSnapToItem && runOnJS(onSnapToItem)(i),
|
|
85
88
|
duration: scrollAnimationDuration,
|
|
86
89
|
});
|
|
87
90
|
|
|
88
91
|
const {
|
|
92
|
+
sharedIndex,
|
|
93
|
+
sharedPreIndex,
|
|
94
|
+
to,
|
|
89
95
|
next,
|
|
90
96
|
prev,
|
|
91
|
-
|
|
92
|
-
sharedIndex,
|
|
93
|
-
computedIndex,
|
|
97
|
+
scrollTo,
|
|
94
98
|
getCurrentIndex,
|
|
95
99
|
} = carouselController;
|
|
96
100
|
|
|
97
|
-
const { start, pause } = useAutoPlay({
|
|
101
|
+
const { start: startAutoPlay, pause: pauseAutoPlay } = useAutoPlay({
|
|
98
102
|
autoPlay,
|
|
99
103
|
autoPlayInterval,
|
|
100
104
|
autoPlayReverse,
|
|
@@ -102,29 +106,44 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
|
|
|
102
106
|
});
|
|
103
107
|
|
|
104
108
|
const _onScrollEnd = React.useCallback(() => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
'worklet';
|
|
110
|
+
const _sharedIndex = Math.round(sharedIndex.value);
|
|
111
|
+
const _sharedPreIndex = Math.round(sharedPreIndex.value);
|
|
112
|
+
|
|
113
|
+
if (onSnapToItem) {
|
|
114
|
+
runOnJS(onSnapToItem)(_sharedIndex);
|
|
115
|
+
}
|
|
116
|
+
if (onScrollEnd) {
|
|
117
|
+
runOnJS(onScrollEnd)(_sharedPreIndex, _sharedIndex);
|
|
118
|
+
}
|
|
119
|
+
}, [onSnapToItem, onScrollEnd, sharedIndex, sharedPreIndex]);
|
|
108
120
|
|
|
109
121
|
const scrollViewGestureOnScrollBegin = React.useCallback(() => {
|
|
110
|
-
|
|
122
|
+
pauseAutoPlay();
|
|
111
123
|
onScrollBegin?.();
|
|
112
|
-
}, [onScrollBegin,
|
|
124
|
+
}, [onScrollBegin, pauseAutoPlay]);
|
|
113
125
|
|
|
114
126
|
const scrollViewGestureOnScrollEnd = React.useCallback(() => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
startAutoPlay();
|
|
128
|
+
/**
|
|
129
|
+
* TODO magic
|
|
130
|
+
*/
|
|
131
|
+
runOnUI(_onScrollEnd)();
|
|
132
|
+
}, [_onScrollEnd, startAutoPlay]);
|
|
118
133
|
|
|
119
|
-
const scrollViewGestureOnTouchBegin = React.useCallback(
|
|
134
|
+
const scrollViewGestureOnTouchBegin = React.useCallback(pauseAutoPlay, [
|
|
135
|
+
pauseAutoPlay,
|
|
136
|
+
]);
|
|
120
137
|
|
|
121
|
-
const scrollViewGestureOnTouchEnd = React.useCallback(
|
|
138
|
+
const scrollViewGestureOnTouchEnd = React.useCallback(startAutoPlay, [
|
|
139
|
+
startAutoPlay,
|
|
140
|
+
]);
|
|
122
141
|
|
|
123
142
|
const goToIndex = React.useCallback(
|
|
124
143
|
(i: number, animated?: boolean) => {
|
|
125
|
-
|
|
144
|
+
to(i, animated);
|
|
126
145
|
},
|
|
127
|
-
[
|
|
146
|
+
[to]
|
|
128
147
|
);
|
|
129
148
|
|
|
130
149
|
React.useImperativeHandle(
|
|
@@ -134,15 +153,9 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
|
|
|
134
153
|
prev,
|
|
135
154
|
getCurrentIndex,
|
|
136
155
|
goToIndex,
|
|
137
|
-
scrollTo
|
|
156
|
+
scrollTo,
|
|
138
157
|
}),
|
|
139
|
-
[
|
|
140
|
-
getCurrentIndex,
|
|
141
|
-
goToIndex,
|
|
142
|
-
next,
|
|
143
|
-
prev,
|
|
144
|
-
carouselController.scrollTo,
|
|
145
|
-
]
|
|
158
|
+
[getCurrentIndex, goToIndex, next, prev, scrollTo]
|
|
146
159
|
);
|
|
147
160
|
|
|
148
161
|
const visibleRanges = useVisibleRanges({
|
|
@@ -201,6 +214,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
|
|
|
201
214
|
{ width: width || '100%', height: height || '100%' },
|
|
202
215
|
style,
|
|
203
216
|
]}
|
|
217
|
+
testID={testID}
|
|
204
218
|
>
|
|
205
219
|
<ScrollViewGesture
|
|
206
220
|
size={size}
|
|
@@ -68,24 +68,22 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
68
68
|
const _withSpring = React.useCallback(
|
|
69
69
|
(toValue: number, onFinished?: () => void) => {
|
|
70
70
|
'worklet';
|
|
71
|
-
const callback = (isFinished: boolean) => {
|
|
72
|
-
'worklet';
|
|
73
|
-
if (isFinished) {
|
|
74
|
-
onFinished && runOnJS(onFinished)();
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
71
|
const defaultWithAnimation: WithTimingAnimation = {
|
|
79
72
|
type: 'timing',
|
|
80
73
|
config: {
|
|
81
|
-
duration: scrollAnimationDuration,
|
|
74
|
+
duration: scrollAnimationDuration + 100,
|
|
82
75
|
easing: Easing.easeOutQuart,
|
|
83
76
|
},
|
|
84
77
|
};
|
|
85
78
|
|
|
86
79
|
return dealWithAnimation(withAnimation ?? defaultWithAnimation)(
|
|
87
80
|
toValue,
|
|
88
|
-
|
|
81
|
+
(isFinished: boolean) => {
|
|
82
|
+
'worklet';
|
|
83
|
+
if (isFinished) {
|
|
84
|
+
onFinished && runOnJS(onFinished)();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
89
87
|
);
|
|
90
88
|
},
|
|
91
89
|
[scrollAnimationDuration, withAnimation]
|
package/src/hooks/useAutoPlay.ts
CHANGED
|
@@ -14,6 +14,7 @@ export function useAutoPlay(opts: {
|
|
|
14
14
|
carouselController,
|
|
15
15
|
} = opts;
|
|
16
16
|
|
|
17
|
+
const { prev, next } = carouselController;
|
|
17
18
|
const timer = React.useRef<NodeJS.Timer>();
|
|
18
19
|
const stopped = React.useRef<boolean>(!autoPlay);
|
|
19
20
|
|
|
@@ -25,10 +26,10 @@ export function useAutoPlay(opts: {
|
|
|
25
26
|
timer.current && clearTimeout(timer.current);
|
|
26
27
|
timer.current = setTimeout(() => {
|
|
27
28
|
autoPlayReverse
|
|
28
|
-
?
|
|
29
|
-
:
|
|
29
|
+
? prev({ onFinished: play })
|
|
30
|
+
: next({ onFinished: play });
|
|
30
31
|
}, autoPlayInterval);
|
|
31
|
-
}, [autoPlayReverse, autoPlayInterval,
|
|
32
|
+
}, [autoPlayReverse, autoPlayInterval, prev, next]);
|
|
32
33
|
|
|
33
34
|
const pause = React.useCallback(() => {
|
|
34
35
|
if (!autoPlay) {
|
|
@@ -1,38 +1,37 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type Animated from 'react-native-reanimated';
|
|
3
3
|
import { Easing } from '../constants';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
runOnJS,
|
|
6
|
+
useAnimatedReaction,
|
|
7
|
+
useSharedValue,
|
|
8
|
+
} from 'react-native-reanimated';
|
|
5
9
|
import type {
|
|
6
10
|
TCarouselActionOptions,
|
|
7
11
|
TCarouselProps,
|
|
8
12
|
WithTimingAnimation,
|
|
9
13
|
} from '../types';
|
|
10
14
|
import { dealWithAnimation } from '@/utils/dealWithAnimation';
|
|
15
|
+
import { convertToSharedIndex } from '@/utils/computedWithAutoFillData';
|
|
11
16
|
|
|
12
17
|
interface IOpts {
|
|
13
18
|
loop: boolean;
|
|
14
19
|
size: number;
|
|
20
|
+
data: TCarouselProps['data'];
|
|
21
|
+
autoFillData: TCarouselProps['autoFillData'];
|
|
15
22
|
handlerOffsetX: Animated.SharedValue<number>;
|
|
16
23
|
withAnimation?: TCarouselProps['withAnimation'];
|
|
17
|
-
disable?: boolean;
|
|
18
24
|
duration?: number;
|
|
19
|
-
originalLength: number;
|
|
20
|
-
length: number;
|
|
21
25
|
defaultIndex?: number;
|
|
22
26
|
onScrollBegin?: () => void;
|
|
23
27
|
onScrollEnd?: () => void;
|
|
24
|
-
// the length before fill data
|
|
25
|
-
onChange: (index: number) => void;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
export interface ICarouselController {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
sharedIndex: React.MutableRefObject<number>;
|
|
32
|
-
sharedPreIndex: React.MutableRefObject<number>;
|
|
31
|
+
sharedIndex: Animated.SharedValue<number>;
|
|
32
|
+
sharedPreIndex: Animated.SharedValue<number>;
|
|
33
33
|
prev: (opts?: TCarouselActionOptions) => void;
|
|
34
34
|
next: (opts?: TCarouselActionOptions) => void;
|
|
35
|
-
computedIndex: () => void;
|
|
36
35
|
getCurrentIndex: () => number;
|
|
37
36
|
to: (index: number, animated?: boolean) => void;
|
|
38
37
|
scrollTo: (opts?: TCarouselActionOptions) => void;
|
|
@@ -41,70 +40,64 @@ export interface ICarouselController {
|
|
|
41
40
|
export function useCarouselController(options: IOpts): ICarouselController {
|
|
42
41
|
const {
|
|
43
42
|
size,
|
|
43
|
+
data,
|
|
44
44
|
loop,
|
|
45
45
|
handlerOffsetX,
|
|
46
46
|
withAnimation,
|
|
47
|
-
disable = false,
|
|
48
|
-
originalLength,
|
|
49
|
-
length,
|
|
50
|
-
onChange,
|
|
51
|
-
duration,
|
|
52
47
|
defaultIndex = 0,
|
|
48
|
+
duration,
|
|
49
|
+
autoFillData,
|
|
53
50
|
} = options;
|
|
54
51
|
|
|
52
|
+
const dataInfo = React.useMemo(
|
|
53
|
+
() => ({
|
|
54
|
+
length: data.length,
|
|
55
|
+
disable: !data.length,
|
|
56
|
+
originalLength: data.length,
|
|
57
|
+
}),
|
|
58
|
+
[data]
|
|
59
|
+
);
|
|
60
|
+
|
|
55
61
|
const index = useSharedValue<number>(defaultIndex);
|
|
56
62
|
// The Index displayed to the user
|
|
57
|
-
const sharedIndex =
|
|
58
|
-
const sharedPreIndex =
|
|
63
|
+
const sharedIndex = useSharedValue<number>(defaultIndex);
|
|
64
|
+
const sharedPreIndex = useSharedValue<number>(defaultIndex);
|
|
59
65
|
|
|
60
66
|
const currentFixedPage = React.useCallback(() => {
|
|
61
67
|
if (loop) {
|
|
62
68
|
return -Math.round(handlerOffsetX.value / size);
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
const fixed = (handlerOffsetX.value / size) % length;
|
|
71
|
+
const fixed = (handlerOffsetX.value / size) % dataInfo.length;
|
|
66
72
|
return Math.round(
|
|
67
73
|
handlerOffsetX.value <= 0
|
|
68
74
|
? Math.abs(fixed)
|
|
69
|
-
: Math.abs(fixed > 0 ? length - fixed : 0)
|
|
75
|
+
: Math.abs(fixed > 0 ? dataInfo.length - fixed : 0)
|
|
70
76
|
);
|
|
71
|
-
}, [handlerOffsetX,
|
|
77
|
+
}, [handlerOffsetX, dataInfo, size, loop]);
|
|
72
78
|
|
|
73
|
-
const
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
const computedIndex = React.useCallback(
|
|
80
|
+
(handlerOffsetXValue: number) => {
|
|
81
|
+
'worklet';
|
|
82
|
+
sharedPreIndex.value = sharedIndex.value;
|
|
83
|
+
const toInt = (handlerOffsetXValue / size) % dataInfo.length;
|
|
84
|
+
const isPositive = handlerOffsetXValue <= 0;
|
|
85
|
+
const i = isPositive
|
|
86
|
+
? Math.abs(toInt)
|
|
87
|
+
: Math.abs(toInt > 0 ? dataInfo.length - toInt : 0);
|
|
88
|
+
index.value = i;
|
|
89
|
+
sharedIndex.value = convertToSharedIndex({
|
|
90
|
+
loop,
|
|
91
|
+
rawDataLength: dataInfo.originalLength,
|
|
92
|
+
autoFillData: autoFillData!,
|
|
93
|
+
index: i,
|
|
94
|
+
});
|
|
84
95
|
},
|
|
85
|
-
[
|
|
96
|
+
[sharedPreIndex, sharedIndex, size, dataInfo, index, loop, autoFillData]
|
|
86
97
|
);
|
|
87
98
|
|
|
88
|
-
|
|
89
|
-
sharedPreIndex.current = sharedIndex.current;
|
|
90
|
-
const toInt = (handlerOffsetX.value / size) % length;
|
|
91
|
-
const i =
|
|
92
|
-
handlerOffsetX.value <= 0
|
|
93
|
-
? Math.abs(toInt)
|
|
94
|
-
: Math.abs(toInt > 0 ? length - toInt : 0);
|
|
95
|
-
index.value = i;
|
|
96
|
-
const _sharedIndex = convertToSharedIndex(i);
|
|
97
|
-
sharedIndex.current = _sharedIndex;
|
|
98
|
-
onChange(_sharedIndex);
|
|
99
|
-
}, [
|
|
100
|
-
length,
|
|
99
|
+
useAnimatedReaction(() => handlerOffsetX.value, computedIndex, [
|
|
101
100
|
handlerOffsetX,
|
|
102
|
-
sharedPreIndex,
|
|
103
|
-
index,
|
|
104
|
-
size,
|
|
105
|
-
sharedIndex,
|
|
106
|
-
convertToSharedIndex,
|
|
107
|
-
onChange,
|
|
108
101
|
]);
|
|
109
102
|
|
|
110
103
|
const getCurrentIndex = React.useCallback(() => {
|
|
@@ -112,8 +105,8 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
112
105
|
}, [index]);
|
|
113
106
|
|
|
114
107
|
const canSliding = React.useCallback(() => {
|
|
115
|
-
return !disable;
|
|
116
|
-
}, [
|
|
108
|
+
return !dataInfo.disable;
|
|
109
|
+
}, [dataInfo]);
|
|
117
110
|
|
|
118
111
|
const onScrollEnd = React.useCallback(() => {
|
|
119
112
|
options.onScrollEnd?.();
|
|
@@ -151,7 +144,8 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
151
144
|
(opts: TCarouselActionOptions = {}) => {
|
|
152
145
|
'worklet';
|
|
153
146
|
const { count = 1, animated = true, onFinished } = opts;
|
|
154
|
-
if (!canSliding() || (!loop && index.value >= length - 1))
|
|
147
|
+
if (!canSliding() || (!loop && index.value >= dataInfo.length - 1))
|
|
148
|
+
return;
|
|
155
149
|
|
|
156
150
|
onScrollBegin?.();
|
|
157
151
|
|
|
@@ -172,7 +166,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
172
166
|
canSliding,
|
|
173
167
|
loop,
|
|
174
168
|
index,
|
|
175
|
-
|
|
169
|
+
dataInfo,
|
|
176
170
|
onScrollBegin,
|
|
177
171
|
handlerOffsetX,
|
|
178
172
|
size,
|
|
@@ -259,15 +253,12 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
259
253
|
);
|
|
260
254
|
|
|
261
255
|
return {
|
|
256
|
+
sharedIndex,
|
|
257
|
+
sharedPreIndex,
|
|
258
|
+
to,
|
|
262
259
|
next,
|
|
263
260
|
prev,
|
|
264
|
-
to,
|
|
265
261
|
scrollTo,
|
|
266
|
-
index,
|
|
267
|
-
length,
|
|
268
|
-
sharedIndex,
|
|
269
|
-
sharedPreIndex,
|
|
270
|
-
computedIndex,
|
|
271
262
|
getCurrentIndex,
|
|
272
263
|
};
|
|
273
264
|
}
|
package/src/types.ts
CHANGED
|
@@ -144,6 +144,10 @@ export type TCarouselProps<T = any> = {
|
|
|
144
144
|
* Specifies the scrolling animation effect.
|
|
145
145
|
*/
|
|
146
146
|
withAnimation?: WithAnimation;
|
|
147
|
+
/**
|
|
148
|
+
* Used to locate this view in end-to-end tests.
|
|
149
|
+
*/
|
|
150
|
+
testID?: string;
|
|
147
151
|
/**
|
|
148
152
|
* Custom carousel config.
|
|
149
153
|
*/
|
|
@@ -12,6 +12,24 @@ type BaseParams<T extends object = {}> = {
|
|
|
12
12
|
loop: boolean;
|
|
13
13
|
} & T;
|
|
14
14
|
|
|
15
|
+
export function convertToSharedIndex(
|
|
16
|
+
params: BaseParams<{ index: number; rawDataLength: number }>
|
|
17
|
+
) {
|
|
18
|
+
'worklet';
|
|
19
|
+
const { loop, rawDataLength, index, autoFillData } = params;
|
|
20
|
+
|
|
21
|
+
if (isAutoFillData({ loop, autoFillData })) {
|
|
22
|
+
switch (rawDataLength) {
|
|
23
|
+
case SINGLE_ITEM:
|
|
24
|
+
return 0;
|
|
25
|
+
case DOUBLE_ITEM:
|
|
26
|
+
return index % 2;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return index;
|
|
31
|
+
}
|
|
32
|
+
|
|
15
33
|
export function computedOffsetXValueWithAutoFillData(
|
|
16
34
|
params: BaseParams<{
|
|
17
35
|
rawDataLength: number;
|