react-native-reanimated-carousel 2.3.8 → 2.3.11
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/hooks/useCommonVariables.js +1 -1
- package/lib/commonjs/hooks/useCommonVariables.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 +35 -44
- package/lib/module/hooks/useCarouselController.js.map +1 -1
- package/lib/module/hooks/useCommonVariables.js +2 -3
- package/lib/module/hooks/useCommonVariables.js.map +1 -1
- package/lib/module/utils/computedWithAutoFillData.js +25 -0
- package/lib/module/utils/computedWithAutoFillData.js.map +1 -1
- package/lib/typescript/{src/Carousel.d.ts → Carousel.d.ts} +0 -0
- package/lib/typescript/{src/LazyView.d.ts → LazyView.d.ts} +0 -0
- package/lib/typescript/{src/ScrollViewGesture.d.ts → ScrollViewGesture.d.ts} +0 -0
- package/lib/typescript/{src/constants → constants}/index.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useAutoPlay.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useCarouselController.d.ts +4 -10
- package/lib/typescript/{src/hooks → hooks}/useCheckMounted.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useCommonVariables.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useInitProps.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useLayoutConfig.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useOffsetX.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useOnProgressChange.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/usePropsErrorBoundary.d.ts +0 -0
- package/lib/typescript/{src/hooks → hooks}/useVisibleRanges.d.ts +0 -0
- package/lib/typescript/{src/index.d.ts → index.d.ts} +0 -0
- package/lib/typescript/{src/layouts → layouts}/BaseLayout.d.ts +0 -0
- package/lib/typescript/{src/layouts → layouts}/ParallaxLayout.d.ts +0 -0
- package/lib/typescript/{src/layouts → layouts}/index.d.ts +0 -0
- package/lib/typescript/{src/layouts → layouts}/normal.d.ts +0 -0
- package/lib/typescript/{src/layouts → layouts}/parallax.d.ts +0 -0
- package/lib/typescript/{src/layouts → layouts}/stack.d.ts +0 -0
- package/lib/typescript/{src/store → store}/index.d.ts +0 -0
- package/lib/typescript/{src/types.d.ts → types.d.ts} +5 -0
- package/lib/typescript/{src/utils → utils}/computedWithAutoFillData.d.ts +4 -0
- package/lib/typescript/{src/utils → utils}/dealWithAnimation.d.ts +0 -0
- package/lib/typescript/{src/utils → utils}/log.d.ts +0 -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 +55 -62
- package/src/hooks/useCommonVariables.ts +2 -2
- package/src/types.ts +4 -0
- package/src/utils/computedWithAutoFillData.ts +18 -0
- package/lib/typescript/exampleBare/App.d.ts +0 -2
|
@@ -10,6 +10,31 @@ function isAutoFillData(params) {
|
|
|
10
10
|
return !!params.loop && !!params.autoFillData;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export function convertToSharedIndex(params) {
|
|
14
|
+
'worklet';
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
loop,
|
|
18
|
+
rawDataLength,
|
|
19
|
+
index,
|
|
20
|
+
autoFillData
|
|
21
|
+
} = params;
|
|
22
|
+
|
|
23
|
+
if (isAutoFillData({
|
|
24
|
+
loop,
|
|
25
|
+
autoFillData
|
|
26
|
+
})) {
|
|
27
|
+
switch (rawDataLength) {
|
|
28
|
+
case SINGLE_ITEM:
|
|
29
|
+
return 0;
|
|
30
|
+
|
|
31
|
+
case DOUBLE_ITEM:
|
|
32
|
+
return index % 2;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return index;
|
|
37
|
+
}
|
|
13
38
|
export function computedOffsetXValueWithAutoFillData(params) {
|
|
14
39
|
'worklet';
|
|
15
40
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["computedWithAutoFillData.ts"],"names":["DATA_LENGTH","SINGLE_ITEM","DOUBLE_ITEM","isAutoFillData","params","loop","autoFillData","
|
|
1
|
+
{"version":3,"sources":["computedWithAutoFillData.ts"],"names":["DATA_LENGTH","SINGLE_ITEM","DOUBLE_ITEM","isAutoFillData","params","loop","autoFillData","convertToSharedIndex","rawDataLength","index","computedOffsetXValueWithAutoFillData","value","size","computedRealIndexWithAutoFillData","dataLength","computedFillDataWithAutoFillData","data"],"mappings":"AAAA,SAASA,WAAT,QAA4B,eAA5B;AAEA,MAAM;AAAEC,EAAAA,WAAF;AAAeC,EAAAA;AAAf,IAA+BF,WAArC;;AAEA,SAASG,cAAT,CAAwBC,MAAxB,EAA0E;AACtE;;AACA,SAAO,CAAC,CAACA,MAAM,CAACC,IAAT,IAAiB,CAAC,CAACD,MAAM,CAACE,YAAjC;AACH;;AAOD,OAAO,SAASC,oBAAT,CACHH,MADG,EAEL;AACE;;AACA,QAAM;AAAEC,IAAAA,IAAF;AAAQG,IAAAA,aAAR;AAAuBC,IAAAA,KAAvB;AAA8BH,IAAAA;AAA9B,MAA+CF,MAArD;;AAEA,MAAID,cAAc,CAAC;AAAEE,IAAAA,IAAF;AAAQC,IAAAA;AAAR,GAAD,CAAlB,EAA4C;AACxC,YAAQE,aAAR;AACI,WAAKP,WAAL;AACI,eAAO,CAAP;;AACJ,WAAKC,WAAL;AACI,eAAOO,KAAK,GAAG,CAAf;AAJR;AAMH;;AAED,SAAOA,KAAP;AACH;AAED,OAAO,SAASC,oCAAT,CACHN,MADG,EAML;AACE;;AAEA,QAAM;AAAEI,IAAAA,aAAF;AAAiBG,IAAAA,KAAjB;AAAwBC,IAAAA,IAAxB;AAA8BP,IAAAA,IAA9B;AAAoCC,IAAAA;AAApC,MAAqDF,MAA3D;;AAEA,MAAID,cAAc,CAAC;AAAEE,IAAAA,IAAF;AAAQC,IAAAA;AAAR,GAAD,CAAlB,EAA4C;AACxC,YAAQE,aAAR;AACI,WAAKP,WAAL;AACI,eAAOU,KAAK,GAAGC,IAAf;;AACJ,WAAKV,WAAL;AACI,eAAOS,KAAK,IAAIC,IAAI,GAAG,CAAX,CAAZ;AAJR;AAMH;;AAED,SAAOD,KAAP;AACH;AAED,OAAO,SAASE,iCAAT,CACHT,MADG,EAKL;AACE,QAAM;AAAEK,IAAAA,KAAF;AAASK,IAAAA,UAAT;AAAqBT,IAAAA,IAArB;AAA2BC,IAAAA;AAA3B,MAA4CF,MAAlD;;AAEA,MAAID,cAAc,CAAC;AAAEE,IAAAA,IAAF;AAAQC,IAAAA;AAAR,GAAD,CAAlB,EAA4C;AACxC,YAAQQ,UAAR;AACI,WAAKb,WAAL;AACI,eAAOQ,KAAK,GAAG,CAAf;;AACJ,WAAKP,WAAL;AACI,eAAOO,KAAK,GAAG,CAAf;AAJR;AAMH;;AAED,SAAOA,KAAP;AACH;AAED,OAAO,SAASM,gCAAT,CACHX,MADG,EAKA;AACH,QAAM;AAAEY,IAAAA,IAAF;AAAQX,IAAAA,IAAR;AAAcC,IAAAA,YAAd;AAA4BQ,IAAAA;AAA5B,MAA2CV,MAAjD;;AAEA,MAAID,cAAc,CAAC;AAAEE,IAAAA,IAAF;AAAQC,IAAAA;AAAR,GAAD,CAAlB,EAA4C;AACxC,YAAQQ,UAAR;AACI,WAAKb,WAAL;AACI,eAAO,CAACe,IAAI,CAAC,CAAD,CAAL,EAAUA,IAAI,CAAC,CAAD,CAAd,EAAmBA,IAAI,CAAC,CAAD,CAAvB,CAAP;;AACJ,WAAKd,WAAL;AACI,eAAO,CAACc,IAAI,CAAC,CAAD,CAAL,EAAUA,IAAI,CAAC,CAAD,CAAd,EAAmBA,IAAI,CAAC,CAAD,CAAvB,EAA4BA,IAAI,CAAC,CAAD,CAAhC,CAAP;AAJR;AAMH;;AAED,SAAOA,IAAP;AACH","sourcesContent":["import { DATA_LENGTH } from 'src/constants';\n\nconst { SINGLE_ITEM, DOUBLE_ITEM } = DATA_LENGTH;\n\nfunction isAutoFillData(params: { autoFillData: boolean; loop: boolean }) {\n 'worklet';\n return !!params.loop && !!params.autoFillData;\n}\n\ntype BaseParams<T extends object = {}> = {\n autoFillData: boolean;\n loop: boolean;\n} & T;\n\nexport function convertToSharedIndex(\n params: BaseParams<{ index: number; rawDataLength: number }>\n) {\n 'worklet';\n const { loop, rawDataLength, index, autoFillData } = params;\n\n if (isAutoFillData({ loop, autoFillData })) {\n switch (rawDataLength) {\n case SINGLE_ITEM:\n return 0;\n case DOUBLE_ITEM:\n return index % 2;\n }\n }\n\n return index;\n}\n\nexport function computedOffsetXValueWithAutoFillData(\n params: BaseParams<{\n rawDataLength: number;\n value: number;\n size: number;\n }>\n) {\n 'worklet';\n\n const { rawDataLength, value, size, loop, autoFillData } = params;\n\n if (isAutoFillData({ loop, autoFillData })) {\n switch (rawDataLength) {\n case SINGLE_ITEM:\n return value % size;\n case DOUBLE_ITEM:\n return value % (size * 2);\n }\n }\n\n return value;\n}\n\nexport function computedRealIndexWithAutoFillData(\n params: BaseParams<{\n index: number;\n dataLength: number;\n }>\n) {\n const { index, dataLength, loop, autoFillData } = params;\n\n if (isAutoFillData({ loop, autoFillData })) {\n switch (dataLength) {\n case SINGLE_ITEM:\n return index % 1;\n case DOUBLE_ITEM:\n return index % 2;\n }\n }\n\n return index;\n}\n\nexport function computedFillDataWithAutoFillData<T>(\n params: BaseParams<{\n data: T[];\n dataLength: number;\n }>\n): T[] {\n const { data, loop, autoFillData, dataLength } = params;\n\n if (isAutoFillData({ loop, autoFillData })) {\n switch (dataLength) {\n case SINGLE_ITEM:\n return [data[0], data[0], data[0]];\n case DOUBLE_ITEM:\n return [data[0], data[1], data[0], data[1]];\n }\n }\n\n return data;\n}\n"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -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;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import type { ViewStyle } from 'react-native';
|
|
2
3
|
import type { PanGestureHandlerProps } from 'react-native-gesture-handler';
|
|
3
4
|
import type { AnimatedStyleProp, WithSpringConfig, WithTimingConfig } from 'react-native-reanimated';
|
|
@@ -128,6 +129,10 @@ export declare type TCarouselProps<T = any> = {
|
|
|
128
129
|
* Specifies the scrolling animation effect.
|
|
129
130
|
*/
|
|
130
131
|
withAnimation?: WithAnimation;
|
|
132
|
+
/**
|
|
133
|
+
* Used to locate this view in end-to-end tests.
|
|
134
|
+
*/
|
|
135
|
+
testID?: string;
|
|
131
136
|
/**
|
|
132
137
|
* Custom carousel config.
|
|
133
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;
|
|
File without changes
|
|
File without changes
|
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.11",
|
|
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
|
+
useDerivedValue,
|
|
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,66 @@ 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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return i;
|
|
84
|
-
},
|
|
85
|
-
[originalLength, loop]
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const computedIndex = React.useCallback(() => {
|
|
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);
|
|
79
|
+
useDerivedValue(() => {
|
|
80
|
+
const handlerOffsetXValue = handlerOffsetX.value;
|
|
81
|
+
sharedPreIndex.value = sharedIndex.value;
|
|
82
|
+
const toInt = (handlerOffsetXValue / size) % dataInfo.length;
|
|
83
|
+
const isPositive = handlerOffsetXValue <= 0;
|
|
84
|
+
const i = isPositive
|
|
85
|
+
? Math.abs(toInt)
|
|
86
|
+
: Math.abs(toInt > 0 ? dataInfo.length - toInt : 0);
|
|
95
87
|
index.value = i;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
sharedIndex.value = convertToSharedIndex({
|
|
89
|
+
loop,
|
|
90
|
+
rawDataLength: dataInfo.originalLength,
|
|
91
|
+
autoFillData: autoFillData!,
|
|
92
|
+
index: i,
|
|
93
|
+
});
|
|
99
94
|
}, [
|
|
100
|
-
length,
|
|
101
|
-
handlerOffsetX,
|
|
102
95
|
sharedPreIndex,
|
|
103
|
-
index,
|
|
104
|
-
size,
|
|
105
96
|
sharedIndex,
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
size,
|
|
98
|
+
dataInfo,
|
|
99
|
+
index,
|
|
100
|
+
loop,
|
|
101
|
+
autoFillData,
|
|
102
|
+
handlerOffsetX,
|
|
108
103
|
]);
|
|
109
104
|
|
|
110
105
|
const getCurrentIndex = React.useCallback(() => {
|
|
@@ -112,8 +107,8 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
112
107
|
}, [index]);
|
|
113
108
|
|
|
114
109
|
const canSliding = React.useCallback(() => {
|
|
115
|
-
return !disable;
|
|
116
|
-
}, [
|
|
110
|
+
return !dataInfo.disable;
|
|
111
|
+
}, [dataInfo]);
|
|
117
112
|
|
|
118
113
|
const onScrollEnd = React.useCallback(() => {
|
|
119
114
|
options.onScrollEnd?.();
|
|
@@ -151,7 +146,8 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
151
146
|
(opts: TCarouselActionOptions = {}) => {
|
|
152
147
|
'worklet';
|
|
153
148
|
const { count = 1, animated = true, onFinished } = opts;
|
|
154
|
-
if (!canSliding() || (!loop && index.value >= length - 1))
|
|
149
|
+
if (!canSliding() || (!loop && index.value >= dataInfo.length - 1))
|
|
150
|
+
return;
|
|
155
151
|
|
|
156
152
|
onScrollBegin?.();
|
|
157
153
|
|
|
@@ -172,7 +168,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
172
168
|
canSliding,
|
|
173
169
|
loop,
|
|
174
170
|
index,
|
|
175
|
-
|
|
171
|
+
dataInfo,
|
|
176
172
|
onScrollBegin,
|
|
177
173
|
handlerOffsetX,
|
|
178
174
|
size,
|
|
@@ -259,15 +255,12 @@ export function useCarouselController(options: IOpts): ICarouselController {
|
|
|
259
255
|
);
|
|
260
256
|
|
|
261
257
|
return {
|
|
258
|
+
sharedIndex,
|
|
259
|
+
sharedPreIndex,
|
|
260
|
+
to,
|
|
262
261
|
next,
|
|
263
262
|
prev,
|
|
264
|
-
to,
|
|
265
263
|
scrollTo,
|
|
266
|
-
index,
|
|
267
|
-
length,
|
|
268
|
-
sharedIndex,
|
|
269
|
-
sharedPreIndex,
|
|
270
|
-
computedIndex,
|
|
271
264
|
getCurrentIndex,
|
|
272
265
|
};
|
|
273
266
|
}
|
|
@@ -11,7 +11,7 @@ interface ICommonVariables {
|
|
|
11
11
|
export function useCommonVariables(
|
|
12
12
|
props: TInitializeCarouselProps<any>
|
|
13
13
|
): ICommonVariables {
|
|
14
|
-
const { vertical, height, width, data, defaultIndex
|
|
14
|
+
const { vertical, height, width, data, defaultIndex } = props;
|
|
15
15
|
const size = vertical ? height : width;
|
|
16
16
|
const validLength = data.length - 1;
|
|
17
17
|
const defaultHandlerOffsetX = -Math.abs(defaultIndex * size);
|
|
@@ -19,7 +19,7 @@ export function useCommonVariables(
|
|
|
19
19
|
|
|
20
20
|
React.useEffect(() => {
|
|
21
21
|
handlerOffsetX.value = defaultHandlerOffsetX;
|
|
22
|
-
}, [vertical, handlerOffsetX, defaultHandlerOffsetX
|
|
22
|
+
}, [vertical, handlerOffsetX, defaultHandlerOffsetX]);
|
|
23
23
|
|
|
24
24
|
return {
|
|
25
25
|
size,
|
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;
|