react-native-reanimated-carousel 4.0.0-alpha.6 → 4.0.0-alpha.8
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/components/BaseLayout.js +2 -20
- package/lib/commonjs/components/BaseLayout.js.map +1 -1
- package/lib/commonjs/components/Carousel.js +19 -41
- package/lib/commonjs/components/Carousel.js.map +1 -1
- package/lib/commonjs/components/ItemRenderer.js +80 -0
- package/lib/commonjs/components/ItemRenderer.js.map +1 -0
- package/lib/commonjs/hooks/useCarouselController.js +4 -3
- package/lib/commonjs/hooks/useCarouselController.js.map +1 -1
- package/lib/commonjs/hooks/useOffsetX.test.js.map +1 -1
- package/lib/commonjs/hooks/useVisibleRanges.js +36 -18
- package/lib/commonjs/hooks/useVisibleRanges.js.map +1 -1
- package/lib/commonjs/utils/handleroffset-direction.js +5 -5
- package/lib/commonjs/utils/handleroffset-direction.js.map +1 -1
- package/lib/commonjs/utils/handleroffset-direction.test.js +46 -0
- package/lib/commonjs/utils/handleroffset-direction.test.js.map +1 -0
- package/lib/module/components/BaseLayout.js +3 -15
- package/lib/module/components/BaseLayout.js.map +1 -1
- package/lib/module/components/Carousel.js +19 -38
- package/lib/module/components/Carousel.js.map +1 -1
- package/lib/module/components/ItemRenderer.js +62 -0
- package/lib/module/components/ItemRenderer.js.map +1 -0
- package/lib/module/hooks/useCarouselController.js +4 -3
- package/lib/module/hooks/useCarouselController.js.map +1 -1
- package/lib/module/hooks/useOffsetX.test.js.map +1 -1
- package/lib/module/hooks/useVisibleRanges.js +35 -18
- package/lib/module/hooks/useVisibleRanges.js.map +1 -1
- package/lib/module/utils/handleroffset-direction.js +5 -5
- package/lib/module/utils/handleroffset-direction.js.map +1 -1
- package/lib/module/utils/handleroffset-direction.test.js +41 -0
- package/lib/module/utils/handleroffset-direction.test.js.map +1 -0
- package/lib/typescript/components/ItemRenderer.d.ts +22 -0
- package/lib/typescript/hooks/useCarouselController.d.ts +2 -1
- package/lib/typescript/hooks/useVisibleRanges.d.ts +7 -4
- package/lib/typescript/utils/handleroffset-direction.d.ts +2 -1
- package/lib/typescript/utils/handleroffset-direction.test.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/BaseLayout.tsx +3 -33
- package/src/components/Carousel.tsx +18 -53
- package/src/components/ItemRenderer.tsx +105 -0
- package/src/hooks/useCarouselController.tsx +16 -13
- package/src/hooks/useOffsetX.test.ts +1 -1
- package/src/hooks/useVisibleRanges.tsx +56 -24
- package/src/utils/handleroffset-direction.test.ts +52 -0
- package/src/utils/handleroffset-direction.ts +12 -9
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { useRef } from "react";
|
|
1
2
|
import type Animated from "react-native-reanimated";
|
|
2
3
|
import { useDerivedValue } from "react-native-reanimated";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
type Range = [number, number];
|
|
6
|
+
|
|
7
|
+
export interface VisibleRanges {
|
|
8
|
+
negativeRange: Range
|
|
9
|
+
positiveRange: Range
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type IVisibleRanges = Animated.SharedValue<VisibleRanges>;
|
|
8
13
|
|
|
9
14
|
export function useVisibleRanges(options: {
|
|
10
15
|
total: number
|
|
@@ -17,11 +22,12 @@ export function useVisibleRanges(options: {
|
|
|
17
22
|
total = 0,
|
|
18
23
|
viewSize,
|
|
19
24
|
translation,
|
|
20
|
-
windowSize: _windowSize
|
|
25
|
+
windowSize: _windowSize,
|
|
21
26
|
loop,
|
|
22
27
|
} = options;
|
|
23
28
|
|
|
24
|
-
const windowSize =
|
|
29
|
+
const windowSize = _windowSize ?? total;
|
|
30
|
+
const cachedRanges = useRef<VisibleRanges>(null!);
|
|
25
31
|
|
|
26
32
|
const ranges = useDerivedValue(() => {
|
|
27
33
|
const positiveCount = Math.round(windowSize / 2);
|
|
@@ -30,36 +36,62 @@ export function useVisibleRanges(options: {
|
|
|
30
36
|
let currentIndex = Math.round(-translation.value / viewSize);
|
|
31
37
|
currentIndex = currentIndex < 0 ? (currentIndex % total) + total : currentIndex;
|
|
32
38
|
|
|
39
|
+
let newRanges: VisibleRanges;
|
|
40
|
+
|
|
33
41
|
if (!loop) {
|
|
34
42
|
// Adjusting negative range if the carousel is not loopable.
|
|
35
43
|
// So, It will be only displayed the positive items.
|
|
36
|
-
|
|
44
|
+
newRanges = {
|
|
37
45
|
negativeRange: [0 + currentIndex - (windowSize - 1), 0 + currentIndex],
|
|
38
|
-
positiveRange: [0 + currentIndex, windowSize - 1
|
|
46
|
+
positiveRange: [0 + currentIndex, currentIndex + (windowSize - 1)],
|
|
39
47
|
};
|
|
40
48
|
}
|
|
49
|
+
else {
|
|
50
|
+
const negativeRange: Range = [
|
|
51
|
+
(currentIndex - negativeCount + total) % total,
|
|
52
|
+
(currentIndex - 1 + total) % total,
|
|
53
|
+
];
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
const positiveRange: Range = [
|
|
56
|
+
(currentIndex + total) % total,
|
|
57
|
+
(currentIndex + positiveCount + total) % total,
|
|
58
|
+
];
|
|
46
59
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
if (negativeRange[0] < total && negativeRange[0] > negativeRange[1]) {
|
|
61
|
+
negativeRange[1] = total - 1;
|
|
62
|
+
positiveRange[0] = 0;
|
|
63
|
+
}
|
|
64
|
+
if (positiveRange[0] > positiveRange[1]) {
|
|
65
|
+
negativeRange[1] = total - 1;
|
|
66
|
+
positiveRange[0] = 0;
|
|
67
|
+
}
|
|
51
68
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
positiveRange[0] = 0;
|
|
55
|
-
}
|
|
56
|
-
if (positiveRange[0] > positiveRange[1]) {
|
|
57
|
-
negativeRange[1] = total - 1;
|
|
58
|
-
positiveRange[0] = 0;
|
|
69
|
+
// console.log({ negativeRange, positiveRange ,total,windowSize,a:total <= _windowSize})
|
|
70
|
+
newRanges = { negativeRange, positiveRange };
|
|
59
71
|
}
|
|
60
72
|
|
|
61
|
-
|
|
73
|
+
if (
|
|
74
|
+
isArraysEqual(
|
|
75
|
+
cachedRanges.current?.negativeRange ?? [],
|
|
76
|
+
newRanges.negativeRange,
|
|
77
|
+
)
|
|
78
|
+
&& isArraysEqual(
|
|
79
|
+
cachedRanges.current?.positiveRange ?? [],
|
|
80
|
+
newRanges.positiveRange,
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
return cachedRanges.current;
|
|
84
|
+
|
|
85
|
+
cachedRanges.current = newRanges;
|
|
86
|
+
return cachedRanges.current;
|
|
62
87
|
}, [loop, total, windowSize, translation]);
|
|
63
88
|
|
|
64
89
|
return ranges;
|
|
65
90
|
}
|
|
91
|
+
|
|
92
|
+
function isArraysEqual(a: number[], b: number[]): boolean {
|
|
93
|
+
"worklet";
|
|
94
|
+
if (a.length !== b.length) return false;
|
|
95
|
+
|
|
96
|
+
return a.every((value, index) => value === b[index]);
|
|
97
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useSharedValue } from "react-native-reanimated";
|
|
2
|
+
|
|
3
|
+
import { renderHook } from "@testing-library/react-hooks";
|
|
4
|
+
|
|
5
|
+
import { handlerOffsetDirection } from "./handleroffset-direction";
|
|
6
|
+
|
|
7
|
+
describe("handlerOffsetDirection", () => {
|
|
8
|
+
it("should return -1 when default value equals to zero", () => {
|
|
9
|
+
const result = renderHook(() => {
|
|
10
|
+
const handlerOffsetAnimVal = useSharedValue(0);
|
|
11
|
+
return handlerOffsetDirection(handlerOffsetAnimVal);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
expect(result.result.current).toBe(-1);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should return 1 when default value is greater than zero", () => {
|
|
18
|
+
const result = renderHook(() => {
|
|
19
|
+
const handlerOffsetAnimVal = useSharedValue(1);
|
|
20
|
+
return handlerOffsetDirection(handlerOffsetAnimVal);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
expect(result.result.current).toBe(1);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should return -1 when default value is less than zero", () => {
|
|
27
|
+
const result = renderHook(() => {
|
|
28
|
+
const handlerOffsetAnimVal = useSharedValue(-1);
|
|
29
|
+
return handlerOffsetDirection(handlerOffsetAnimVal);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
expect(result.result.current).toBe(-1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should return 1 when default value equals to zero and fixedDirection is negative", () => {
|
|
36
|
+
const result = renderHook(() => {
|
|
37
|
+
const handlerOffsetAnimVal = useSharedValue(-1);
|
|
38
|
+
return handlerOffsetDirection(handlerOffsetAnimVal, "positive");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(result.result.current).toBe(1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should return -1 when default value is greater than zero and fixedDirection is negative", () => {
|
|
45
|
+
const result = renderHook(() => {
|
|
46
|
+
const handlerOffsetAnimVal = useSharedValue(1);
|
|
47
|
+
return handlerOffsetDirection(handlerOffsetAnimVal, "negative");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(result.result.current).toBe(-1);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { SharedValue } from "react-native-reanimated";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import type { TCarouselProps } from "../types";
|
|
4
|
+
|
|
5
|
+
export function handlerOffsetDirection(handlerOffset: SharedValue<number>, fixedDirection?: TCarouselProps["fixedDirection"]): -1 | 1 {
|
|
4
6
|
"worklet";
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
if (fixedDirection === "negative")
|
|
9
|
+
return -1;
|
|
10
|
+
|
|
11
|
+
if (fixedDirection === "positive")
|
|
12
|
+
return 1;
|
|
13
|
+
|
|
14
|
+
if (handlerOffset.value === 0)
|
|
15
|
+
return -1;
|
|
13
16
|
|
|
14
|
-
return
|
|
17
|
+
return Math.sign(handlerOffset.value) as -1 | 1;
|
|
15
18
|
}
|