-
-
Notifications
You must be signed in to change notification settings - Fork 301
/
ItemRenderer.tsx
105 lines (92 loc) · 2.67 KB
/
ItemRenderer.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import React from "react";
import type { FC } from "react";
import type { ViewStyle } from "react-native";
import type Animated from "react-native-reanimated";
import { useAnimatedReaction, type AnimatedStyleProp, runOnJS } from "react-native-reanimated";
import type { TAnimationStyle } from "./BaseLayout";
import { BaseLayout } from "./BaseLayout";
import type { VisibleRanges } from "../hooks/useVisibleRanges";
import { useVisibleRanges } from "../hooks/useVisibleRanges";
import type { CarouselRenderItem } from "../types";
import { computedRealIndexWithAutoFillData } from "../utils/computed-with-auto-fill-data";
interface Props {
data: any[]
dataLength: number
rawDataLength: number
loop: boolean
size: number
windowSize?: number
autoFillData: boolean
offsetX: Animated.SharedValue<number>
handlerOffset: Animated.SharedValue<number>
layoutConfig: TAnimationStyle
renderItem: CarouselRenderItem<any>
customAnimation?: ((value: number) => AnimatedStyleProp<ViewStyle>)
}
export const ItemRenderer: FC<Props> = (props) => {
const {
data,
size,
windowSize,
handlerOffset,
offsetX,
dataLength,
rawDataLength,
loop,
autoFillData,
layoutConfig,
renderItem,
customAnimation,
} = props;
const visibleRanges = useVisibleRanges({
total: dataLength,
viewSize: size,
translation: handlerOffset,
windowSize,
loop,
});
const [displayedItems, setDisplayedItems] = React.useState<VisibleRanges>(null!);
useAnimatedReaction(
() => visibleRanges.value,
ranges => runOnJS(setDisplayedItems)(ranges),
[visibleRanges],
);
if (!displayedItems)
return null;
return (
<>
{
data.map((item, index) => {
const realIndex = computedRealIndexWithAutoFillData({
index,
dataLength: rawDataLength,
loop,
autoFillData,
});
const { negativeRange, positiveRange } = displayedItems;
const shouldRender = (index >= negativeRange[0] && index <= negativeRange[1])
|| (index >= positiveRange[0] && index <= positiveRange[1]);
if (!shouldRender)
return null;
return (
<BaseLayout
key={index}
index={index}
handlerOffset={offsetX}
visibleRanges={visibleRanges}
animationStyle={customAnimation || layoutConfig}
>
{({ animationValue }) =>
renderItem({
item,
index: realIndex,
animationValue,
})
}
</BaseLayout>
);
})
}
</>
);
};