react-native-reanimated-carousel 3.2.0 → 3.3.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 (40) hide show
  1. package/README.md +21 -12
  2. package/README.zh-CN.md +20 -12
  3. package/lib/commonjs/hooks/index.test.js +1 -1
  4. package/lib/commonjs/hooks/index.test.js.map +1 -1
  5. package/lib/commonjs/layouts/BaseLayout.js +1 -1
  6. package/lib/commonjs/layouts/BaseLayout.js.map +1 -1
  7. package/lib/module/hooks/index.test.js +0 -1
  8. package/lib/module/hooks/index.test.js.map +1 -1
  9. package/lib/module/layouts/BaseLayout.js +7 -0
  10. package/lib/module/layouts/BaseLayout.js.map +1 -1
  11. package/package.json +7 -19
  12. package/src/Carousel.tsx +0 -247
  13. package/src/LazyView.tsx +0 -14
  14. package/src/ScrollViewGesture.tsx +0 -328
  15. package/src/constants/index.ts +0 -16
  16. package/src/hooks/computeNewIndexWhenDataChanges.ts +0 -51
  17. package/src/hooks/index.test.ts +0 -82
  18. package/src/hooks/useAutoPlay.ts +0 -63
  19. package/src/hooks/useCarouselController.tsx +0 -317
  20. package/src/hooks/useCheckMounted.ts +0 -14
  21. package/src/hooks/useCommonVariables.ts +0 -73
  22. package/src/hooks/useInitProps.ts +0 -98
  23. package/src/hooks/useLayoutConfig.ts +0 -28
  24. package/src/hooks/useOffsetX.ts +0 -88
  25. package/src/hooks/useOnProgressChange.ts +0 -50
  26. package/src/hooks/usePropsErrorBoundary.ts +0 -31
  27. package/src/hooks/useVisibleRanges.tsx +0 -49
  28. package/src/index.tsx +0 -8
  29. package/src/layouts/BaseLayout.tsx +0 -118
  30. package/src/layouts/ParallaxLayout.tsx +0 -142
  31. package/src/layouts/index.tsx +0 -12
  32. package/src/layouts/normal.ts +0 -22
  33. package/src/layouts/parallax.ts +0 -89
  34. package/src/layouts/stack.ts +0 -362
  35. package/src/store/index.ts +0 -13
  36. package/src/types.ts +0 -237
  37. package/src/utils/computedWithAutoFillData.ts +0 -94
  38. package/src/utils/dealWithAnimation.ts +0 -19
  39. package/src/utils/handlerOffsetDirection.ts +0 -15
  40. package/src/utils/log.ts +0 -13
@@ -1,88 +0,0 @@
1
- import type Animated from "react-native-reanimated";
2
- import {
3
- Extrapolate,
4
- interpolate,
5
- useDerivedValue,
6
- } from "react-native-reanimated";
7
-
8
- import type { IVisibleRanges } from "./useVisibleRanges";
9
-
10
- export interface IOpts {
11
- index: number
12
- size: number
13
- handlerOffset: Animated.SharedValue<number>
14
- dataLength: number
15
- type?: "positive" | "negative"
16
- viewCount?: number
17
- loop?: boolean
18
- }
19
-
20
- export const useOffsetX = (opts: IOpts, visibleRanges: IVisibleRanges) => {
21
- const {
22
- handlerOffset,
23
- index,
24
- size,
25
- loop,
26
- dataLength,
27
- type = "positive",
28
- viewCount: _viewCount,
29
- } = opts;
30
-
31
- const ITEM_LENGTH = dataLength;
32
- const VALID_LENGTH = ITEM_LENGTH - 1;
33
- const TOTAL_WIDTH = size * ITEM_LENGTH;
34
- const HALF_WIDTH = 0.5 * size;
35
-
36
- const viewCount = _viewCount ?? Math.round((ITEM_LENGTH - 1) / 2);
37
- const positiveCount
38
- = type === "positive" ? viewCount : VALID_LENGTH - viewCount;
39
-
40
- let startPos = size * index;
41
- if (index > positiveCount)
42
- startPos = (index - ITEM_LENGTH) * size;
43
-
44
- const MAX = positiveCount * size;
45
- const MIN = -((VALID_LENGTH - positiveCount) * size);
46
-
47
- const x = useDerivedValue(() => {
48
- const { negativeRange, positiveRange } = visibleRanges.value;
49
- if (
50
- (index < negativeRange[0] || index > negativeRange[1])
51
- && (index < positiveRange[0] || index > positiveRange[1])
52
- )
53
- return Number.MAX_SAFE_INTEGER;
54
-
55
- if (loop) {
56
- const inputRange = [
57
- -TOTAL_WIDTH,
58
- MIN - HALF_WIDTH - startPos - Number.MIN_VALUE,
59
- MIN - HALF_WIDTH - startPos,
60
- 0,
61
- MAX + HALF_WIDTH - startPos,
62
- MAX + HALF_WIDTH - startPos + Number.MIN_VALUE,
63
- TOTAL_WIDTH,
64
- ];
65
-
66
- const outputRange = [
67
- startPos,
68
- MAX + HALF_WIDTH - Number.MIN_VALUE,
69
- MIN - HALF_WIDTH,
70
- startPos,
71
- MAX + HALF_WIDTH,
72
- MIN - HALF_WIDTH + Number.MIN_VALUE,
73
- startPos,
74
- ];
75
-
76
- return interpolate(
77
- handlerOffset.value,
78
- inputRange,
79
- outputRange,
80
- Extrapolate.CLAMP,
81
- );
82
- }
83
-
84
- return handlerOffset.value + size * index;
85
- }, [loop, dataLength, viewCount, type, size, visibleRanges]);
86
-
87
- return x;
88
- };
@@ -1,50 +0,0 @@
1
- import type Animated from "react-native-reanimated";
2
- import {
3
- runOnJS,
4
- useAnimatedReaction,
5
- } from "react-native-reanimated";
6
-
7
- import type { TCarouselProps } from "../types";
8
- import { computedOffsetXValueWithAutoFillData } from "../utils/computedWithAutoFillData";
9
-
10
- export function useOnProgressChange(
11
- opts: {
12
- size: number
13
- autoFillData: boolean
14
- loop: boolean
15
- offsetX: Animated.SharedValue<number>
16
- rawDataLength: number
17
- } & Pick<TCarouselProps, "onProgressChange">,
18
- ) {
19
- const { autoFillData, loop, offsetX, size, rawDataLength, onProgressChange }
20
- = opts;
21
-
22
- useAnimatedReaction(
23
- () => offsetX.value,
24
- (_value) => {
25
- let value = computedOffsetXValueWithAutoFillData({
26
- value: _value,
27
- rawDataLength,
28
- size,
29
- autoFillData,
30
- loop,
31
- });
32
-
33
- if (!loop) {
34
- value = Math.max(
35
- -((rawDataLength - 1) * size),
36
- Math.min(value, 0),
37
- );
38
- }
39
-
40
- let absoluteProgress = Math.abs(value / size);
41
-
42
- if (value > 0)
43
- absoluteProgress = rawDataLength - absoluteProgress;
44
-
45
- if (onProgressChange)
46
- runOnJS(onProgressChange)(value, absoluteProgress);
47
- },
48
- [loop, autoFillData, rawDataLength, onProgressChange],
49
- );
50
- }
@@ -1,31 +0,0 @@
1
- import React from "react";
2
-
3
- import type { TCarouselProps } from "../types";
4
-
5
- export function usePropsErrorBoundary(props: TCarouselProps & { dataLength: number }) {
6
- React.useEffect(() => {
7
- const { defaultIndex, dataLength: viewCount } = props;
8
-
9
- if (typeof defaultIndex === "number" && viewCount > 0) {
10
- if (defaultIndex < 0 || defaultIndex >= viewCount) {
11
- throw new Error(
12
- "DefaultIndex must be in the range of data length.",
13
- );
14
- }
15
- }
16
-
17
- // TODO
18
- if (!props.mode || props.mode === "parallax") {
19
- if (!props.vertical && !props.width) {
20
- throw new Error(
21
- "`width` must be specified for horizontal carousels.",
22
- );
23
- }
24
- if (props.vertical && !props.height) {
25
- throw new Error(
26
- "`height` must be specified for vertical carousels.",
27
- );
28
- }
29
- }
30
- }, [props]);
31
- }
@@ -1,49 +0,0 @@
1
- import type Animated from "react-native-reanimated";
2
- import { useDerivedValue } from "react-native-reanimated";
3
-
4
- export type IVisibleRanges = Animated.SharedValue<{
5
- negativeRange: number[]
6
- positiveRange: number[]
7
- }>;
8
-
9
- export function useVisibleRanges(options: {
10
- total: number
11
- viewSize: number
12
- windowSize?: number
13
- translation: Animated.SharedValue<number>
14
- }): IVisibleRanges {
15
- const {
16
- total = 0,
17
- viewSize,
18
- translation,
19
- windowSize: _windowSize = 0,
20
- } = options;
21
-
22
- const windowSize = total <= _windowSize ? total : _windowSize;
23
-
24
- const ranges = useDerivedValue(() => {
25
- const positiveCount = Math.round(windowSize / 2);
26
- const negativeCount = windowSize - positiveCount;
27
- let curIndex = Math.round(-translation.value / viewSize);
28
- curIndex = curIndex < 0 ? (curIndex % total) + total : curIndex;
29
- const negativeRange = [
30
- (curIndex - negativeCount + total) % total,
31
- (curIndex - 1 + total) % total,
32
- ];
33
- const positiveRange = [
34
- (curIndex + total) % total,
35
- (curIndex + positiveCount + total) % total,
36
- ];
37
- if (negativeRange[0] < total && negativeRange[0] > negativeRange[1]) {
38
- negativeRange[1] = total - 1;
39
- positiveRange[0] = 0;
40
- }
41
- if (positiveRange[0] > positiveRange[1]) {
42
- negativeRange[1] = total - 1;
43
- positiveRange[0] = 0;
44
- }
45
- return { negativeRange, positiveRange };
46
- }, [total, windowSize, translation]);
47
-
48
- return ranges;
49
- }
package/src/index.tsx DELETED
@@ -1,8 +0,0 @@
1
- import Carousel from "./Carousel";
2
- export type {
3
- TCarouselProps,
4
- ICarouselInstance,
5
- IComputedDirectionTypes,
6
- } from "./types";
7
-
8
- export default Carousel;
@@ -1,118 +0,0 @@
1
- import React from "react";
2
- import type { ViewStyle } from "react-native";
3
- import type { AnimatedStyleProp } from "react-native-reanimated";
4
- import Animated, {
5
- runOnJS,
6
- useAnimatedReaction,
7
- useAnimatedStyle,
8
- useDerivedValue,
9
- } from "react-native-reanimated";
10
-
11
- import type { ILayoutConfig } from "./stack";
12
-
13
- import { useCheckMounted } from "../hooks/useCheckMounted";
14
- import type { IOpts } from "../hooks/useOffsetX";
15
- import { useOffsetX } from "../hooks/useOffsetX";
16
- import type { IVisibleRanges } from "../hooks/useVisibleRanges";
17
- import { LazyView } from "../LazyView";
18
- import { CTX } from "../store";
19
-
20
- export type TAnimationStyle = (value: number) => AnimatedStyleProp<ViewStyle>;
21
-
22
- export const BaseLayout: React.FC<{
23
- index: number
24
- handlerOffset: Animated.SharedValue<number>
25
- visibleRanges: IVisibleRanges
26
- animationStyle: TAnimationStyle
27
- children: (ctx: {
28
- animationValue: Animated.SharedValue<number>
29
- }) => React.ReactElement
30
- }> = (props) => {
31
- const mounted = useCheckMounted();
32
- const { handlerOffset, index, children, visibleRanges, animationStyle }
33
- = props;
34
-
35
- const context = React.useContext(CTX);
36
- const {
37
- props: {
38
- loop,
39
- dataLength,
40
- width,
41
- height,
42
- vertical,
43
- customConfig,
44
- mode,
45
- modeConfig,
46
- },
47
- } = context;
48
- const size = vertical ? height : width;
49
- const [shouldUpdate, setShouldUpdate] = React.useState(false);
50
- let offsetXConfig: IOpts = {
51
- handlerOffset,
52
- index,
53
- size,
54
- dataLength,
55
- loop,
56
- ...(typeof customConfig === "function" ? customConfig() : {}),
57
- };
58
-
59
- if (mode === "horizontal-stack") {
60
- const { snapDirection, showLength } = modeConfig as ILayoutConfig;
61
-
62
- offsetXConfig = {
63
- handlerOffset,
64
- index,
65
- size,
66
- dataLength,
67
- loop,
68
- type: snapDirection === "right" ? "negative" : "positive",
69
- viewCount: showLength,
70
- };
71
- }
72
-
73
- const x = useOffsetX(offsetXConfig, visibleRanges);
74
- const animationValue = useDerivedValue(() => x.value / size, [x, size]);
75
- const animatedStyle = useAnimatedStyle(
76
- () => animationStyle(x.value / size),
77
- [animationStyle],
78
- );
79
-
80
- const updateView = React.useCallback(
81
- (negativeRange: number[], positiveRange: number[]) => {
82
- mounted.current
83
- && setShouldUpdate(
84
- (index >= negativeRange[0] && index <= negativeRange[1])
85
- || (index >= positiveRange[0] && index <= positiveRange[1]),
86
- );
87
- },
88
- [index, mounted],
89
- );
90
-
91
- useAnimatedReaction(
92
- () => visibleRanges.value,
93
- () => {
94
- runOnJS(updateView)(
95
- visibleRanges.value.negativeRange,
96
- visibleRanges.value.positiveRange,
97
- );
98
- },
99
- [visibleRanges.value],
100
- );
101
-
102
- return (
103
- <Animated.View
104
- style={[
105
- {
106
- width: width || "100%",
107
- height: height || "100%",
108
- position: "absolute",
109
- },
110
- animatedStyle,
111
- ]}
112
- >
113
- <LazyView shouldUpdate={shouldUpdate}>
114
- {children({ animationValue })}
115
- </LazyView>
116
- </Animated.View>
117
- );
118
- };
@@ -1,142 +0,0 @@
1
- import React from "react";
2
- import Animated, {
3
- Extrapolate,
4
- interpolate,
5
- runOnJS,
6
- useAnimatedReaction,
7
- useAnimatedStyle,
8
- } from "react-native-reanimated";
9
-
10
- import type { ILayoutConfig } from "./parallax";
11
-
12
- import { useOffsetX } from "../hooks/useOffsetX";
13
- import type { IVisibleRanges } from "../hooks/useVisibleRanges";
14
- import { LazyView } from "../LazyView";
15
- import type { IComputedDirectionTypes } from "../types";
16
-
17
- export const ParallaxLayout: React.FC<
18
- IComputedDirectionTypes<
19
- {
20
- loop?: boolean
21
- handlerOffset: Animated.SharedValue<number>
22
- index: number
23
- dataLength: number
24
- visibleRanges: IVisibleRanges
25
- } & ILayoutConfig
26
- >
27
- > = (props) => {
28
- const {
29
- handlerOffset,
30
- parallaxScrollingOffset = 100,
31
- parallaxScrollingScale = 0.8,
32
- parallaxAdjacentItemScale = parallaxScrollingScale ** 2,
33
- index,
34
- width,
35
- height,
36
- loop,
37
- dataLength,
38
- children,
39
- visibleRanges,
40
- vertical,
41
- } = props;
42
-
43
- const [shouldUpdate, setShouldUpdate] = React.useState(false);
44
-
45
- const size = props.vertical ? props.height : props.width;
46
-
47
- const x = useOffsetX(
48
- {
49
- handlerOffset,
50
- index,
51
- size,
52
- dataLength,
53
- loop,
54
- },
55
- visibleRanges,
56
- );
57
-
58
- const offsetXStyle = useAnimatedStyle(() => {
59
- const value = x.value / size;
60
-
61
- const translate = interpolate(
62
- value,
63
- [-1, 0, 1],
64
- [
65
- -size + parallaxScrollingOffset,
66
- 0,
67
- size - parallaxScrollingOffset,
68
- ],
69
- Extrapolate.EXTEND,
70
- );
71
-
72
- const zIndex = interpolate(
73
- value,
74
- [-1, 0, 1],
75
- [0, size, 0],
76
- Extrapolate.CLAMP,
77
- );
78
-
79
- const scale = interpolate(
80
- value,
81
- [-1, 0, 1],
82
- [
83
- parallaxAdjacentItemScale,
84
- parallaxScrollingScale,
85
- parallaxAdjacentItemScale,
86
- ],
87
- Extrapolate.CLAMP,
88
- );
89
-
90
- return {
91
- transform: [
92
- vertical
93
- ? {
94
- translateY: translate,
95
- }
96
- : {
97
- translateX: translate,
98
- },
99
- {
100
- scale,
101
- },
102
- ],
103
- zIndex,
104
- };
105
- }, [loop, vertical, parallaxScrollingOffset]);
106
-
107
- const updateView = React.useCallback(
108
- (negativeRange: number[], positiveRange: number[]) => {
109
- setShouldUpdate(
110
- (index >= negativeRange[0] && index <= negativeRange[1])
111
- || (index >= positiveRange[0] && index <= positiveRange[1]),
112
- );
113
- },
114
- [index],
115
- );
116
-
117
- useAnimatedReaction(
118
- () => visibleRanges.value,
119
- () => {
120
- runOnJS(updateView)(
121
- visibleRanges.value.negativeRange,
122
- visibleRanges.value.positiveRange,
123
- );
124
- },
125
- [visibleRanges.value],
126
- );
127
-
128
- return (
129
- <Animated.View
130
- style={[
131
- {
132
- width: width || "100%",
133
- height: height || "100%",
134
- position: "absolute",
135
- },
136
- offsetXStyle,
137
- ]}
138
- >
139
- <LazyView shouldUpdate={shouldUpdate}>{children}</LazyView>
140
- </Animated.View>
141
- );
142
- };
@@ -1,12 +0,0 @@
1
- import { normalLayout } from "./normal";
2
- import { parallaxLayout } from "./parallax";
3
- import { horizontalStackLayout, verticalStackLayout } from "./stack";
4
-
5
- export type TMode = "parallax" | "horizontal-stack" | "vertical-stack";
6
-
7
- export const Layouts = {
8
- normal: normalLayout,
9
- parallax: parallaxLayout,
10
- horizontalStack: horizontalStackLayout,
11
- verticalStack: verticalStackLayout,
12
- };
@@ -1,22 +0,0 @@
1
- import { interpolate } from "react-native-reanimated";
2
-
3
- export function normalLayout(opts: { size: number; vertical: boolean }) {
4
- const { size, vertical } = opts;
5
-
6
- return (value: number) => {
7
- "worklet";
8
- const translate = interpolate(value, [-1, 0, 1], [-size, 0, size]);
9
-
10
- return {
11
- transform: [
12
- vertical
13
- ? {
14
- translateY: translate,
15
- }
16
- : {
17
- translateX: translate,
18
- },
19
- ],
20
- };
21
- };
22
- }
@@ -1,89 +0,0 @@
1
- import { Extrapolate, interpolate } from "react-native-reanimated";
2
-
3
- import type { IComputedDirectionTypes } from "../types";
4
-
5
- interface TBaseConfig {
6
- size: number
7
- vertical: boolean
8
- }
9
-
10
- export interface ILayoutConfig {
11
- /**
12
- * control prev/next item offset.
13
- * @default 100
14
- */
15
- parallaxScrollingOffset?: number
16
- /**
17
- * control prev/current/next item offset.
18
- * @default 0.8
19
- */
20
- parallaxScrollingScale?: number
21
- /**
22
- * control prev/next item offset.
23
- * @default Math.pow(parallaxScrollingScale, 2)
24
- */
25
- parallaxAdjacentItemScale?: number
26
- }
27
-
28
- export type TParallaxModeProps = IComputedDirectionTypes<{
29
- /**
30
- * Carousel Animated transitions.
31
- */
32
- mode?: "parallax"
33
- modeConfig?: ILayoutConfig
34
- }>;
35
-
36
- export function parallaxLayout(
37
- baseConfig: TBaseConfig,
38
- modeConfig: ILayoutConfig = {},
39
- ) {
40
- const { size, vertical } = baseConfig;
41
- const {
42
- parallaxScrollingOffset = 100,
43
- parallaxScrollingScale = 0.8,
44
- parallaxAdjacentItemScale = parallaxScrollingScale ** 2,
45
- } = modeConfig;
46
-
47
- return (value: number) => {
48
- "worklet";
49
- const translate = interpolate(
50
- value,
51
- [-1, 0, 1],
52
- [-size + parallaxScrollingOffset, 0, size - parallaxScrollingOffset],
53
- );
54
-
55
- const zIndex = interpolate(
56
- value,
57
- [-1, 0, 1],
58
- [0, size, 0],
59
- Extrapolate.CLAMP,
60
- );
61
-
62
- const scale = interpolate(
63
- value,
64
- [-1, 0, 1],
65
- [
66
- parallaxAdjacentItemScale,
67
- parallaxScrollingScale,
68
- parallaxAdjacentItemScale,
69
- ],
70
- Extrapolate.CLAMP,
71
- );
72
-
73
- return {
74
- transform: [
75
- vertical
76
- ? {
77
- translateY: translate,
78
- }
79
- : {
80
- translateX: translate,
81
- },
82
- {
83
- scale,
84
- },
85
- ],
86
- zIndex,
87
- };
88
- };
89
- }