@fountain-ui/lab 2.0.0-beta.11 → 2.0.0-beta.12
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/build/commonjs/Carousel/Carousel.js +137 -0
- package/build/commonjs/Carousel/Carousel.js.map +1 -0
- package/build/commonjs/Carousel/CarouselProps.js.map +1 -1
- package/build/commonjs/Carousel/animation/animationUtils.js +9 -0
- package/build/commonjs/Carousel/animation/animationUtils.js.map +1 -0
- package/build/commonjs/Carousel/animation/createDefaultItemStyle.js +15 -0
- package/build/commonjs/Carousel/animation/createDefaultItemStyle.js.map +1 -0
- package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js +20 -0
- package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js.map +1 -0
- package/build/commonjs/Carousel/animation/index.js +40 -0
- package/build/commonjs/Carousel/animation/index.js.map +1 -0
- package/build/commonjs/Carousel/animation/normalItemStyleFactory.js +27 -0
- package/build/commonjs/Carousel/animation/normalItemStyleFactory.js.map +1 -0
- package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js +65 -0
- package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js.map +1 -0
- package/build/commonjs/Carousel/components/InternalContext.js +29 -0
- package/build/commonjs/Carousel/components/InternalContext.js.map +1 -0
- package/build/commonjs/Carousel/components/ItemView.js +64 -0
- package/build/commonjs/Carousel/components/ItemView.js.map +1 -0
- package/build/commonjs/Carousel/components/RootView.js +68 -0
- package/build/commonjs/Carousel/components/RootView.js.map +1 -0
- package/build/commonjs/Carousel/components/ScrollViewGesture.js +76 -0
- package/build/commonjs/Carousel/components/ScrollViewGesture.js.map +1 -0
- package/build/commonjs/Carousel/components/index.js +40 -0
- package/build/commonjs/Carousel/components/index.js.map +1 -0
- package/build/commonjs/Carousel/hooks/index.js +64 -0
- package/build/commonjs/Carousel/hooks/index.js.map +1 -0
- package/build/commonjs/Carousel/hooks/useAutoplayController.js +55 -0
- package/build/commonjs/Carousel/hooks/useAutoplayController.js.map +1 -0
- package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js +23 -0
- package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js.map +1 -0
- package/build/commonjs/Carousel/hooks/useIndexController.js +70 -0
- package/build/commonjs/Carousel/hooks/useIndexController.js.map +1 -0
- package/build/commonjs/Carousel/hooks/useItemInterpolation.js +63 -0
- package/build/commonjs/Carousel/hooks/useItemInterpolation.js.map +1 -0
- package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js +95 -0
- package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js.map +1 -0
- package/build/commonjs/Carousel/hooks/useLoopedData.js +33 -0
- package/build/commonjs/Carousel/hooks/useLoopedData.js.map +1 -0
- package/build/commonjs/Carousel/hooks/usePagingAnimation.js +124 -0
- package/build/commonjs/Carousel/hooks/usePagingAnimation.js.map +1 -0
- package/build/commonjs/Carousel/index.js +16 -2
- package/build/commonjs/Carousel/index.js.map +1 -1
- package/build/commonjs/Carousel/types.js +7 -0
- package/build/commonjs/Carousel/types.js.map +1 -0
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js +44 -47
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/commonjs/ViewPager/PageStateContext.js +22 -0
- package/build/commonjs/ViewPager/PageStateContext.js.map +1 -0
- package/build/commonjs/ViewPager/ViewPagerNative.js +23 -10
- package/build/commonjs/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerProps.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerWeb.js +9 -7
- package/build/commonjs/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/commonjs/ViewPager/index.js +8 -0
- package/build/commonjs/ViewPager/index.js.map +1 -1
- package/build/commonjs/ViewPager/index.native.js +8 -0
- package/build/commonjs/ViewPager/index.native.js.map +1 -1
- package/build/commonjs/ViewPager/utils.js +3 -1
- package/build/commonjs/ViewPager/utils.js.map +1 -1
- package/build/commonjs/ViewabilityTrackerView/Viewability.js +2 -0
- package/build/commonjs/ViewabilityTrackerView/Viewability.js.map +1 -0
- package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerView.js +45 -0
- package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerView.js.map +1 -0
- package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerViewProps.js +2 -0
- package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerViewProps.js.map +1 -0
- package/build/commonjs/{Carousel/index.native.js → ViewabilityTrackerView/index.js} +3 -3
- package/build/commonjs/ViewabilityTrackerView/index.js.map +1 -0
- package/build/commonjs/ViewabilityTrackerView/measureViewability.js +42 -0
- package/build/commonjs/ViewabilityTrackerView/measureViewability.js.map +1 -0
- package/build/commonjs/ViewabilityTrackerView/useViewabilityTracker.js +88 -0
- package/build/commonjs/ViewabilityTrackerView/useViewabilityTracker.js.map +1 -0
- package/build/commonjs/hooks/index.js +16 -0
- package/build/commonjs/hooks/index.js.map +1 -1
- package/build/commonjs/hooks/useDeferredExecutor.js +45 -0
- package/build/commonjs/hooks/useDeferredExecutor.js.map +1 -0
- package/build/commonjs/hooks/useIsMounted.js +22 -0
- package/build/commonjs/hooks/useIsMounted.js.map +1 -0
- package/build/commonjs/index.js +22 -1
- package/build/commonjs/index.js.map +1 -1
- package/build/module/Carousel/Carousel.js +115 -0
- package/build/module/Carousel/Carousel.js.map +1 -0
- package/build/module/Carousel/CarouselProps.js.map +1 -1
- package/build/module/Carousel/animation/animationUtils.js +2 -0
- package/build/module/Carousel/animation/animationUtils.js.map +1 -0
- package/build/module/Carousel/animation/createDefaultItemStyle.js +3 -0
- package/build/module/Carousel/animation/createDefaultItemStyle.js.map +1 -0
- package/build/module/Carousel/animation/createDefaultScrollAnimation.js +11 -0
- package/build/module/Carousel/animation/createDefaultScrollAnimation.js.map +1 -0
- package/build/module/Carousel/animation/index.js +5 -0
- package/build/module/Carousel/animation/index.js.map +1 -0
- package/build/module/Carousel/animation/normalItemStyleFactory.js +18 -0
- package/build/module/Carousel/animation/normalItemStyleFactory.js.map +1 -0
- package/build/module/Carousel/animation/parallaxItemStyleFactory.js +55 -0
- package/build/module/Carousel/animation/parallaxItemStyleFactory.js.map +1 -0
- package/build/module/Carousel/components/InternalContext.js +19 -0
- package/build/module/Carousel/components/InternalContext.js.map +1 -0
- package/build/module/Carousel/components/ItemView.js +44 -0
- package/build/module/Carousel/components/ItemView.js.map +1 -0
- package/build/module/Carousel/components/RootView.js +47 -0
- package/build/module/Carousel/components/RootView.js.map +1 -0
- package/build/module/Carousel/components/ScrollViewGesture.js +62 -0
- package/build/module/Carousel/components/ScrollViewGesture.js.map +1 -0
- package/build/module/Carousel/components/index.js +5 -0
- package/build/module/Carousel/components/index.js.map +1 -0
- package/build/module/Carousel/hooks/index.js +8 -0
- package/build/module/Carousel/hooks/index.js.map +1 -0
- package/build/module/Carousel/hooks/useAutoplayController.js +45 -0
- package/build/module/Carousel/hooks/useAutoplayController.js.map +1 -0
- package/build/module/Carousel/hooks/useDimensionChangeReaction.js +14 -0
- package/build/module/Carousel/hooks/useDimensionChangeReaction.js.map +1 -0
- package/build/module/Carousel/hooks/useIndexController.js +54 -0
- package/build/module/Carousel/hooks/useIndexController.js.map +1 -0
- package/build/module/Carousel/hooks/useItemInterpolation.js +51 -0
- package/build/module/Carousel/hooks/useItemInterpolation.js.map +1 -0
- package/build/module/Carousel/hooks/useItemVisibilityStore.js +87 -0
- package/build/module/Carousel/hooks/useItemVisibilityStore.js.map +1 -0
- package/build/module/Carousel/hooks/useLoopedData.js +24 -0
- package/build/module/Carousel/hooks/useLoopedData.js.map +1 -0
- package/build/module/Carousel/hooks/usePagingAnimation.js +115 -0
- package/build/module/Carousel/hooks/usePagingAnimation.js.map +1 -0
- package/build/module/Carousel/index.js +2 -1
- package/build/module/Carousel/index.js.map +1 -1
- package/build/module/Carousel/types.js +3 -0
- package/build/module/Carousel/types.js.map +1 -0
- package/build/module/ViewPager/ChildrenMemoizedPage.js +40 -45
- package/build/module/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/module/ViewPager/PageStateContext.js +10 -0
- package/build/module/ViewPager/PageStateContext.js.map +1 -0
- package/build/module/ViewPager/ViewPagerNative.js +26 -13
- package/build/module/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/module/ViewPager/ViewPagerProps.js.map +1 -1
- package/build/module/ViewPager/ViewPagerWeb.js +10 -8
- package/build/module/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/module/ViewPager/index.js +1 -0
- package/build/module/ViewPager/index.js.map +1 -1
- package/build/module/ViewPager/index.native.js +1 -0
- package/build/module/ViewPager/index.native.js.map +1 -1
- package/build/module/ViewPager/utils.js +1 -0
- package/build/module/ViewPager/utils.js.map +1 -1
- package/build/module/ViewabilityTrackerView/Viewability.js +2 -0
- package/build/module/ViewabilityTrackerView/Viewability.js.map +1 -0
- package/build/module/ViewabilityTrackerView/ViewabilityTrackerView.js +28 -0
- package/build/module/ViewabilityTrackerView/ViewabilityTrackerView.js.map +1 -0
- package/build/module/ViewabilityTrackerView/ViewabilityTrackerViewProps.js +2 -0
- package/build/module/ViewabilityTrackerView/ViewabilityTrackerViewProps.js.map +1 -0
- package/build/module/ViewabilityTrackerView/index.js +2 -0
- package/build/module/ViewabilityTrackerView/index.js.map +1 -0
- package/build/module/ViewabilityTrackerView/measureViewability.js +34 -0
- package/build/module/ViewabilityTrackerView/measureViewability.js.map +1 -0
- package/build/module/ViewabilityTrackerView/useViewabilityTracker.js +73 -0
- package/build/module/ViewabilityTrackerView/useViewabilityTracker.js.map +1 -0
- package/build/module/hooks/index.js +2 -0
- package/build/module/hooks/index.js.map +1 -1
- package/build/module/hooks/useDeferredExecutor.js +33 -0
- package/build/module/hooks/useDeferredExecutor.js.map +1 -0
- package/build/module/hooks/useIsMounted.js +13 -0
- package/build/module/hooks/useIsMounted.js.map +1 -0
- package/build/module/index.js +2 -0
- package/build/module/index.js.map +1 -1
- package/build/typescript/Carousel/Carousel.d.ts +5 -0
- package/build/typescript/Carousel/CarouselProps.d.ts +32 -48
- package/build/typescript/Carousel/animation/animationUtils.d.ts +1 -0
- package/build/typescript/Carousel/animation/createDefaultItemStyle.d.ts +2 -0
- package/build/typescript/Carousel/animation/createDefaultScrollAnimation.d.ts +2 -0
- package/build/typescript/Carousel/animation/index.d.ts +4 -0
- package/build/typescript/Carousel/animation/normalItemStyleFactory.d.ts +2 -0
- package/build/typescript/Carousel/animation/parallaxItemStyleFactory.d.ts +9 -0
- package/build/typescript/Carousel/components/InternalContext.d.ts +14 -0
- package/build/typescript/Carousel/components/ItemView.d.ts +7 -0
- package/build/typescript/Carousel/components/RootView.d.ts +16 -0
- package/build/typescript/Carousel/components/ScrollViewGesture.d.ts +12 -0
- package/build/typescript/Carousel/components/index.d.ts +4 -0
- package/build/typescript/Carousel/hooks/index.d.ts +7 -0
- package/build/typescript/Carousel/hooks/useAutoplayController.d.ts +7 -0
- package/build/typescript/Carousel/hooks/useDimensionChangeReaction.d.ts +7 -0
- package/build/typescript/Carousel/hooks/useIndexController.d.ts +10 -0
- package/build/typescript/Carousel/hooks/useItemInterpolation.d.ts +2 -0
- package/build/typescript/Carousel/hooks/useItemVisibilityStore.d.ts +7 -0
- package/build/typescript/Carousel/hooks/useLoopedData.d.ts +1 -0
- package/build/typescript/Carousel/hooks/usePagingAnimation.d.ts +18 -0
- package/build/typescript/Carousel/index.d.ts +3 -1
- package/build/typescript/Carousel/types.d.ts +57 -0
- package/build/typescript/ViewPager/PageStateContext.d.ts +7 -0
- package/build/typescript/ViewPager/ViewPagerNative.d.ts +1 -1
- package/build/typescript/ViewPager/ViewPagerProps.d.ts +11 -0
- package/build/typescript/ViewPager/ViewPagerWeb.d.ts +1 -1
- package/build/typescript/ViewPager/index.d.ts +1 -0
- package/build/typescript/ViewPager/index.native.d.ts +1 -0
- package/build/typescript/ViewPager/utils.d.ts +1 -0
- package/build/typescript/ViewabilityTrackerView/Viewability.d.ts +3 -0
- package/build/typescript/ViewabilityTrackerView/ViewabilityTrackerView.d.ts +2 -0
- package/build/typescript/ViewabilityTrackerView/ViewabilityTrackerViewProps.d.ts +22 -0
- package/build/typescript/ViewabilityTrackerView/index.d.ts +2 -0
- package/build/typescript/ViewabilityTrackerView/measureViewability.d.ts +11 -0
- package/build/typescript/ViewabilityTrackerView/useViewabilityTracker.d.ts +11 -0
- package/build/typescript/hooks/index.d.ts +2 -0
- package/build/typescript/hooks/useDeferredExecutor.d.ts +11 -0
- package/build/typescript/hooks/useIsMounted.d.ts +4 -0
- package/build/typescript/index.d.ts +2 -0
- package/package.json +4 -19
- package/src/Carousel/Carousel.tsx +151 -0
- package/src/Carousel/CarouselProps.ts +34 -53
- package/src/Carousel/animation/animationUtils.ts +1 -0
- package/src/Carousel/animation/createDefaultItemStyle.ts +3 -0
- package/src/Carousel/animation/createDefaultScrollAnimation.ts +13 -0
- package/src/Carousel/animation/index.ts +4 -0
- package/src/Carousel/animation/normalItemStyleFactory.ts +19 -0
- package/src/Carousel/animation/parallaxItemStyleFactory.ts +79 -0
- package/src/Carousel/components/InternalContext.ts +33 -0
- package/src/Carousel/components/ItemView.tsx +56 -0
- package/src/Carousel/components/RootView.tsx +66 -0
- package/src/Carousel/components/ScrollViewGesture.tsx +80 -0
- package/src/Carousel/components/index.ts +4 -0
- package/src/Carousel/hooks/index.ts +7 -0
- package/src/Carousel/hooks/useAutoplayController.ts +54 -0
- package/src/Carousel/hooks/useDimensionChangeReaction.ts +25 -0
- package/src/Carousel/hooks/useIndexController.tsx +76 -0
- package/src/Carousel/hooks/useItemInterpolation.ts +107 -0
- package/src/Carousel/hooks/useItemVisibilityStore.ts +107 -0
- package/src/Carousel/hooks/useLoopedData.ts +26 -0
- package/src/Carousel/hooks/usePagingAnimation.ts +148 -0
- package/src/Carousel/index.ts +4 -2
- package/src/Carousel/types.ts +67 -0
- package/src/ViewPager/ChildrenMemoizedPage.tsx +48 -43
- package/src/ViewPager/PageStateContext.ts +15 -0
- package/src/ViewPager/ViewPagerNative.tsx +35 -11
- package/src/ViewPager/ViewPagerProps.ts +13 -0
- package/src/ViewPager/ViewPagerWeb.tsx +9 -5
- package/src/ViewPager/index.native.ts +1 -0
- package/src/ViewPager/index.ts +1 -0
- package/src/ViewPager/utils.tsx +2 -1
- package/src/ViewabilityTrackerView/Viewability.ts +3 -0
- package/src/ViewabilityTrackerView/ViewabilityTrackerView.tsx +33 -0
- package/src/ViewabilityTrackerView/ViewabilityTrackerViewProps.ts +25 -0
- package/src/ViewabilityTrackerView/index.ts +2 -0
- package/src/ViewabilityTrackerView/measureViewability.ts +56 -0
- package/src/ViewabilityTrackerView/useViewabilityTracker.ts +85 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useDeferredExecutor.ts +46 -0
- package/src/hooks/useIsMounted.ts +19 -0
- package/src/index.ts +3 -0
- package/build/commonjs/Carousel/CarouselNative.js +0 -72
- package/build/commonjs/Carousel/CarouselNative.js.map +0 -1
- package/build/commonjs/Carousel/CarouselWeb.js +0 -237
- package/build/commonjs/Carousel/CarouselWeb.js.map +0 -1
- package/build/commonjs/Carousel/index.native.js.map +0 -1
- package/build/commonjs/Carousel/utils.js +0 -19
- package/build/commonjs/Carousel/utils.js.map +0 -1
- package/build/module/Carousel/CarouselNative.js +0 -54
- package/build/module/Carousel/CarouselNative.js.map +0 -1
- package/build/module/Carousel/CarouselWeb.js +0 -215
- package/build/module/Carousel/CarouselWeb.js.map +0 -1
- package/build/module/Carousel/index.native.js +0 -2
- package/build/module/Carousel/index.native.js.map +0 -1
- package/build/module/Carousel/utils.js +0 -7
- package/build/module/Carousel/utils.js.map +0 -1
- package/build/typescript/Carousel/CarouselNative.d.ts +0 -2
- package/build/typescript/Carousel/CarouselWeb.d.ts +0 -4
- package/build/typescript/Carousel/index.native.d.ts +0 -1
- package/build/typescript/Carousel/utils.d.ts +0 -6
- package/src/Carousel/CarouselNative.tsx +0 -67
- package/src/Carousel/CarouselWeb.tsx +0 -222
- package/src/Carousel/index.native.ts +0 -1
- package/src/Carousel/utils.ts +0 -11
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
export default function useLoopedData<ItemT>(
|
|
4
|
+
originalData: ReadonlyArray<ItemT>,
|
|
5
|
+
loop: boolean,
|
|
6
|
+
): ReadonlyArray<ItemT> {
|
|
7
|
+
return useMemo(() => {
|
|
8
|
+
if (!loop) {
|
|
9
|
+
return originalData;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const numberOfData = originalData.length;
|
|
13
|
+
|
|
14
|
+
if (numberOfData === 1) {
|
|
15
|
+
const [first] = originalData;
|
|
16
|
+
return [first, first, first];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (numberOfData === 2) {
|
|
20
|
+
const [first, second] = originalData;
|
|
21
|
+
return [first, second, first, second];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return originalData;
|
|
25
|
+
}, [originalData, loop]);
|
|
26
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { Animated, Platform } from 'react-native';
|
|
3
|
+
import type { CreateScrollAnimation, GetCurrentIndex, PagingDirection, StartPagingAnimation } from '../types';
|
|
4
|
+
|
|
5
|
+
export interface PagingAnimationConfig {
|
|
6
|
+
controlledTx: Animated.Value;
|
|
7
|
+
createScrollAnimation: CreateScrollAnimation;
|
|
8
|
+
getCurrentIndex: GetCurrentIndex;
|
|
9
|
+
itemWidth: number;
|
|
10
|
+
lastIndex: number;
|
|
11
|
+
loop: boolean;
|
|
12
|
+
numberOfData: number;
|
|
13
|
+
offsetTx: Animated.Value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface UsePagingAnimation {
|
|
17
|
+
finalizeAnimation: () => void;
|
|
18
|
+
globalInterpolation: Animated.AnimatedInterpolation;
|
|
19
|
+
startAnimation: StartPagingAnimation;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function directionToValue(itemWidth: number) {
|
|
23
|
+
return function (direction: PagingDirection): number {
|
|
24
|
+
switch (direction) {
|
|
25
|
+
case 'next':
|
|
26
|
+
return -itemWidth;
|
|
27
|
+
case 'prev':
|
|
28
|
+
return itemWidth;
|
|
29
|
+
case 'stay':
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default function usePagingAnimation(config: PagingAnimationConfig): UsePagingAnimation {
|
|
36
|
+
const {
|
|
37
|
+
controlledTx,
|
|
38
|
+
createScrollAnimation,
|
|
39
|
+
getCurrentIndex,
|
|
40
|
+
itemWidth,
|
|
41
|
+
lastIndex,
|
|
42
|
+
loop,
|
|
43
|
+
numberOfData,
|
|
44
|
+
offsetTx,
|
|
45
|
+
} = config;
|
|
46
|
+
|
|
47
|
+
const animationRef = useRef<Animated.CompositeAnimation | null>(null);
|
|
48
|
+
const toValueRef = useRef<number>(0);
|
|
49
|
+
|
|
50
|
+
const globalInterpolation = useMemo(
|
|
51
|
+
() => Animated.add(controlledTx, offsetTx),
|
|
52
|
+
[controlledTx, offsetTx],
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const subscriptionId = controlledTx.addListener((value) => {
|
|
57
|
+
const currentTx = value.value;
|
|
58
|
+
|
|
59
|
+
// Prevent infinite loop
|
|
60
|
+
if (currentTx !== 0) {
|
|
61
|
+
const maxWidth = numberOfData * itemWidth;
|
|
62
|
+
|
|
63
|
+
if (Math.abs(Math.round(currentTx)) === Math.round(maxWidth)) {
|
|
64
|
+
// reset position
|
|
65
|
+
controlledTx.setValue(0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return () => {
|
|
71
|
+
controlledTx.removeListener(subscriptionId);
|
|
72
|
+
};
|
|
73
|
+
}, [numberOfData, itemWidth]);
|
|
74
|
+
|
|
75
|
+
const finalizeAnimation = useCallback(() => {
|
|
76
|
+
const stopUnfinishedSnapAnimation = () => {
|
|
77
|
+
if (animationRef.current) {
|
|
78
|
+
animationRef.current?.stop();
|
|
79
|
+
animationRef.current = null;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const resetBoundary = () => {
|
|
84
|
+
controlledTx.setOffset(toValueRef.current);
|
|
85
|
+
controlledTx.flattenOffset();
|
|
86
|
+
|
|
87
|
+
// FIXME: react-native-web bug maybe?
|
|
88
|
+
// `AnimatedValue.flattenOffset()` does not trigger any event listener.
|
|
89
|
+
// Accessing value directly via `_value` is dangerous but working on web (`useNativeDriver` always false).
|
|
90
|
+
// So setting same value with `value.setValue(value._value)` will trigger event listener.
|
|
91
|
+
if (Platform.OS === 'web') {
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
controlledTx.setValue(controlledTx._value);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
offsetTx.setValue(0);
|
|
97
|
+
toValueRef.current = 0;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
stopUnfinishedSnapAnimation();
|
|
101
|
+
|
|
102
|
+
resetBoundary();
|
|
103
|
+
}, [controlledTx]);
|
|
104
|
+
|
|
105
|
+
const startAnimation = useCallback((direction: PagingDirection, isGesture: boolean = false) => {
|
|
106
|
+
const getToValueByDirection = directionToValue(itemWidth);
|
|
107
|
+
|
|
108
|
+
const currentIndex = getCurrentIndex();
|
|
109
|
+
|
|
110
|
+
const computeToValueOnNoLoop = (): number => {
|
|
111
|
+
if (currentIndex === 0 && direction === 'prev') {
|
|
112
|
+
return isGesture
|
|
113
|
+
? getToValueByDirection('stay')
|
|
114
|
+
: -lastIndex * itemWidth; // last position
|
|
115
|
+
} else if (currentIndex === lastIndex && direction === 'next') {
|
|
116
|
+
return isGesture
|
|
117
|
+
? getToValueByDirection('stay')
|
|
118
|
+
: lastIndex * itemWidth; // first position
|
|
119
|
+
}
|
|
120
|
+
return getToValueByDirection(direction);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const toValue = loop ? getToValueByDirection(direction) : computeToValueOnNoLoop();
|
|
124
|
+
const animation = createScrollAnimation(offsetTx, toValue);
|
|
125
|
+
|
|
126
|
+
animationRef.current = animation;
|
|
127
|
+
toValueRef.current = toValue;
|
|
128
|
+
|
|
129
|
+
animation.start(({ finished }) => {
|
|
130
|
+
if (finished) {
|
|
131
|
+
finalizeAnimation();
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}, [
|
|
135
|
+
createScrollAnimation,
|
|
136
|
+
getCurrentIndex,
|
|
137
|
+
finalizeAnimation,
|
|
138
|
+
itemWidth,
|
|
139
|
+
lastIndex,
|
|
140
|
+
loop,
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
globalInterpolation,
|
|
145
|
+
finalizeAnimation,
|
|
146
|
+
startAnimation,
|
|
147
|
+
};
|
|
148
|
+
};
|
package/src/Carousel/index.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export { default } from './
|
|
2
|
-
export type { default as CarouselProps } from './CarouselProps';
|
|
1
|
+
export { default } from './Carousel';
|
|
2
|
+
export type { default as CarouselProps } from './CarouselProps';
|
|
3
|
+
export type { CarouselInstance } from './types';
|
|
4
|
+
export { normalItemStyleFactory, parallaxItemStyleFactory } from './animation';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { Animated, ViewProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
const directions = ['next', 'prev', 'stay'] as const;
|
|
5
|
+
|
|
6
|
+
export type PagingDirection = (typeof directions)[number];
|
|
7
|
+
|
|
8
|
+
export interface RenderItem<T> {
|
|
9
|
+
(info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CreateScrollAnimation {
|
|
13
|
+
(aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CreateItemStyle {
|
|
17
|
+
(itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface GetCurrentIndex {
|
|
21
|
+
(): number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface IndexController {
|
|
25
|
+
currentIndex: number;
|
|
26
|
+
getCurrentIndex: GetCurrentIndex;
|
|
27
|
+
lastIndex: number;
|
|
28
|
+
monitorElement: ReactElement;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface StartPagingAnimation {
|
|
32
|
+
(direction: PagingDirection, isGesture?: boolean): void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type VisibleIndexRanges = Array<[number, number]>;
|
|
36
|
+
|
|
37
|
+
export interface StoreSubscription {
|
|
38
|
+
(): void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ItemVisibilityStore {
|
|
42
|
+
dispatch: (ranges: VisibleIndexRanges) => void;
|
|
43
|
+
subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;
|
|
44
|
+
removeAllListeners: () => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface AutoplayController {
|
|
48
|
+
pause: () => void;
|
|
49
|
+
resume: () => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface CarouselInstance {
|
|
53
|
+
/**
|
|
54
|
+
* Scroll to next visible item.
|
|
55
|
+
*/
|
|
56
|
+
next: () => void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Scroll to previous visible item.
|
|
60
|
+
*/
|
|
61
|
+
prev: () => void;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get current visible item index.
|
|
65
|
+
*/
|
|
66
|
+
getCurrentIndex: GetCurrentIndex;
|
|
67
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import React, { memo, useState } from 'react';
|
|
1
|
+
import React, { memo, useMemo, useState } from 'react';
|
|
2
2
|
import { Platform, View } from 'react-native';
|
|
3
3
|
import { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
|
|
4
4
|
import { StyleSheet } from '@fountain-ui/core';
|
|
5
5
|
import type { PageProps } from './ViewPagerProps';
|
|
6
|
-
|
|
7
|
-
const OFFSCREEN_RERENDER_LIMIT = 1;
|
|
6
|
+
import PageStateContext from './PageStateContext';
|
|
8
7
|
|
|
9
8
|
const styles = StyleSheet.create({
|
|
9
|
+
fill: { width: '100%', height: '100%' },
|
|
10
10
|
none: { display: 'none' },
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
interface
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
interface InternalPageState {
|
|
14
|
+
isActive: boolean;
|
|
15
|
+
isLoaded: boolean;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function Page(props: PageProps) {
|
|
@@ -20,79 +20,84 @@ function Page(props: PageProps) {
|
|
|
20
20
|
index,
|
|
21
21
|
children,
|
|
22
22
|
loading,
|
|
23
|
+
offscreenPageRerenderLimit,
|
|
23
24
|
sharedIndex,
|
|
24
25
|
} = props;
|
|
25
26
|
|
|
26
|
-
const assumeInitialPageState = ():
|
|
27
|
+
const assumeInitialPageState = (): InternalPageState => {
|
|
27
28
|
const activeIndex = sharedIndex.value;
|
|
28
29
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
if (Platform.OS === 'web') {
|
|
32
|
-
return { active, visited: active };
|
|
33
|
-
}
|
|
30
|
+
const isActive = index === activeIndex;
|
|
34
31
|
|
|
35
32
|
if (loading === 'eager') {
|
|
36
|
-
return {
|
|
33
|
+
return { isActive, isLoaded: true };
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
const
|
|
40
|
-
&& index <= activeIndex +
|
|
36
|
+
const isLoaded = index >= activeIndex - offscreenPageRerenderLimit
|
|
37
|
+
&& index <= activeIndex + offscreenPageRerenderLimit;
|
|
41
38
|
|
|
42
|
-
return {
|
|
39
|
+
return { isActive, isLoaded };
|
|
43
40
|
};
|
|
44
41
|
|
|
45
|
-
const [pageState, setPageState] = useState<
|
|
42
|
+
const [pageState, setPageState] = useState<InternalPageState>(assumeInitialPageState);
|
|
46
43
|
|
|
47
|
-
const content = pageState.
|
|
48
|
-
|
|
49
|
-
const updatePageState = (active: boolean, neighbor: boolean) => {
|
|
50
|
-
setPageState(prevState => {
|
|
51
|
-
if (prevState.active !== active) {
|
|
52
|
-
return { active, visited: active || prevState.visited };
|
|
53
|
-
}
|
|
44
|
+
const content = pageState.isLoaded ? children : null;
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
const onActiveStateChange = (isActive: boolean) => {
|
|
47
|
+
setPageState(prevState => ({
|
|
48
|
+
...prevState,
|
|
49
|
+
isActive,
|
|
50
|
+
isLoaded: isActive || prevState.isLoaded,
|
|
51
|
+
}));
|
|
52
|
+
};
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
const onBecomeNeighbor = () => {
|
|
55
|
+
setPageState(prevState => ({
|
|
56
|
+
...prevState,
|
|
57
|
+
isLoaded: true,
|
|
58
|
+
}));
|
|
61
59
|
};
|
|
62
60
|
|
|
63
61
|
useAnimatedReaction(
|
|
64
62
|
() => {
|
|
65
63
|
const activeIndex = sharedIndex.value;
|
|
66
64
|
|
|
67
|
-
const
|
|
68
|
-
|
|
65
|
+
const isActive = index === activeIndex;
|
|
66
|
+
|
|
67
|
+
const shouldRerender = index >= activeIndex - offscreenPageRerenderLimit
|
|
68
|
+
&& index <= activeIndex + offscreenPageRerenderLimit;
|
|
69
69
|
|
|
70
|
-
const
|
|
71
|
-
const willNeighbor = Platform.OS === 'web' ? false : (willVisible && !willActive);
|
|
70
|
+
const becomeNeighbor = shouldRerender && !isActive;
|
|
72
71
|
|
|
73
|
-
return {
|
|
72
|
+
return { isActive, becomeNeighbor };
|
|
74
73
|
},
|
|
75
74
|
(nextState, prevState) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
runOnJS(updatePageState)(nextState.willActive, nextState.willNeighbor);
|
|
75
|
+
if (nextState.isActive !== prevState?.isActive) {
|
|
76
|
+
runOnJS(onActiveStateChange)(nextState.isActive);
|
|
77
|
+
} else if (nextState.becomeNeighbor) {
|
|
78
|
+
runOnJS(onBecomeNeighbor)();
|
|
81
79
|
}
|
|
82
80
|
},
|
|
83
81
|
[index],
|
|
84
82
|
);
|
|
85
83
|
|
|
84
|
+
const contextValue = useMemo(() => ({
|
|
85
|
+
isActive: pageState.isActive,
|
|
86
|
+
}), [pageState.isActive]);
|
|
87
|
+
|
|
86
88
|
const style = Platform.OS === 'web'
|
|
87
|
-
? (pageState.
|
|
88
|
-
:
|
|
89
|
+
? (pageState.isActive ? StyleSheet.absoluteFill : styles.none)
|
|
90
|
+
: styles.fill;
|
|
89
91
|
|
|
90
92
|
return (
|
|
91
93
|
<View
|
|
92
|
-
children={content}
|
|
93
94
|
collapsable={false}
|
|
94
95
|
style={style}
|
|
95
|
-
|
|
96
|
+
>
|
|
97
|
+
<PageStateContext.Provider value={contextValue}>
|
|
98
|
+
{content}
|
|
99
|
+
</PageStateContext.Provider>
|
|
100
|
+
</View>
|
|
96
101
|
);
|
|
97
102
|
}
|
|
98
103
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
interface PageState {
|
|
4
|
+
isActive: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const initialPageState: Readonly<PageState> = { isActive: false };
|
|
8
|
+
|
|
9
|
+
const PageStateContext = createContext<PageState>(initialPageState);
|
|
10
|
+
|
|
11
|
+
export const useViewPagerPageState = () => {
|
|
12
|
+
return useContext(PageStateContext);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default PageStateContext;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, { Children, forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
|
|
1
|
+
import React, { Children, forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
|
|
2
2
|
import type { ViewPagerOnPageSelectedEvent } from 'react-native-pager-view';
|
|
3
3
|
import RNViewPager from 'react-native-pager-view';
|
|
4
|
-
import { useSharedValue } from 'react-native-reanimated';
|
|
4
|
+
import { runOnJS, useAnimatedReaction, useSharedValue } from 'react-native-reanimated';
|
|
5
5
|
import type ViewPagerProps from './ViewPagerProps';
|
|
6
6
|
import type { ViewPagerInstance } from './ViewPagerProps';
|
|
7
|
-
import { defaultInitialPage, defaultLoading, defaultPageComponent } from './utils';
|
|
7
|
+
import { defaultInitialPage, defaultLoading, defaultOffscreenPageRerenderLimit, defaultPageComponent } from './utils';
|
|
8
8
|
|
|
9
9
|
const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPager(props, ref) {
|
|
10
10
|
const {
|
|
@@ -12,26 +12,43 @@ const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPag
|
|
|
12
12
|
initialPage = defaultInitialPage,
|
|
13
13
|
keyboardDismissMode = 'on-drag',
|
|
14
14
|
loading = defaultLoading,
|
|
15
|
+
offscreenPageRerenderLimit = defaultOffscreenPageRerenderLimit,
|
|
15
16
|
onChange,
|
|
16
17
|
pageComponent = defaultPageComponent,
|
|
17
18
|
pageForceRerenderKey,
|
|
18
19
|
scrollEnabled = true,
|
|
19
20
|
style,
|
|
21
|
+
UNSTABLE_sharedIndex,
|
|
20
22
|
} = props;
|
|
21
23
|
|
|
22
|
-
const
|
|
24
|
+
const fallbackSharedIndex = useSharedValue<number>(initialPage);
|
|
25
|
+
|
|
26
|
+
const sharedIndex = UNSTABLE_sharedIndex ?? fallbackSharedIndex;
|
|
27
|
+
|
|
23
28
|
const pagerRef = useRef<RNViewPager | null>(null);
|
|
24
29
|
|
|
25
|
-
const
|
|
26
|
-
|
|
30
|
+
const animationFrameRef = useRef<number>(NaN);
|
|
31
|
+
|
|
32
|
+
const setPage = useCallback((newIndex: number) => {
|
|
33
|
+
animationFrameRef.current = requestAnimationFrame(() => {
|
|
27
34
|
pagerRef.current?.setPage(newIndex);
|
|
28
35
|
});
|
|
29
|
-
};
|
|
36
|
+
}, []);
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
return () => {
|
|
40
|
+
if (animationFrameRef.current) {
|
|
41
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
useAnimatedReaction(
|
|
47
|
+
() => sharedIndex.value,
|
|
48
|
+
(result) => {
|
|
49
|
+
runOnJS(setPage)(result);
|
|
50
|
+
},
|
|
51
|
+
[setPage],
|
|
35
52
|
);
|
|
36
53
|
|
|
37
54
|
const handlePageSelected = useCallback((e: ViewPagerOnPageSelectedEvent) => {
|
|
@@ -49,6 +66,12 @@ const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPag
|
|
|
49
66
|
}
|
|
50
67
|
}, [onChange]);
|
|
51
68
|
|
|
69
|
+
useImperativeHandle(
|
|
70
|
+
ref,
|
|
71
|
+
() => ({ setPage }),
|
|
72
|
+
[setPage],
|
|
73
|
+
);
|
|
74
|
+
|
|
52
75
|
const PageComponent = pageComponent;
|
|
53
76
|
|
|
54
77
|
return (
|
|
@@ -67,6 +90,7 @@ const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPag
|
|
|
67
90
|
children={child}
|
|
68
91
|
index={index}
|
|
69
92
|
loading={loading}
|
|
93
|
+
offscreenPageRerenderLimit={offscreenPageRerenderLimit}
|
|
70
94
|
rerenderKey={pageForceRerenderKey}
|
|
71
95
|
sharedIndex={sharedIndex}
|
|
72
96
|
/>
|
|
@@ -8,6 +8,7 @@ export type KeyboardDismissMode = 'none' | 'on-drag';
|
|
|
8
8
|
export type PageProps = PropsWithChildren<ViewProps> & {
|
|
9
9
|
index: number;
|
|
10
10
|
loading: ViewPagerProps['loading'];
|
|
11
|
+
offscreenPageRerenderLimit: number;
|
|
11
12
|
sharedIndex: SharedValue<number>;
|
|
12
13
|
rerenderKey?: ViewPagerProps['pageForceRerenderKey'];
|
|
13
14
|
};
|
|
@@ -44,6 +45,13 @@ export default interface ViewPagerProps extends ComponentProps<{
|
|
|
44
45
|
*/
|
|
45
46
|
loading?: Loading;
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Mobile only. The number of pages that should be re-rendered to either side of the current page.
|
|
50
|
+
* Changing this value after the component mount has no effect.
|
|
51
|
+
* @default 0
|
|
52
|
+
*/
|
|
53
|
+
offscreenPageRerenderLimit?: number;
|
|
54
|
+
|
|
47
55
|
/**
|
|
48
56
|
* Callback fired when an index is changed.
|
|
49
57
|
*/
|
|
@@ -71,4 +79,9 @@ export default interface ViewPagerProps extends ComponentProps<{
|
|
|
71
79
|
* @default 'on-drag'
|
|
72
80
|
*/
|
|
73
81
|
keyboardDismissMode?: KeyboardDismissMode;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Unstable API.
|
|
85
|
+
*/
|
|
86
|
+
UNSTABLE_sharedIndex?: SharedValue<number>;
|
|
74
87
|
}> {}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Children, forwardRef, useImperativeHandle } from 'react';
|
|
1
|
+
import React, { Children, forwardRef, useImperativeHandle, useCallback } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { useSharedValue } from 'react-native-reanimated';
|
|
4
4
|
import { StyleSheet } from '@fountain-ui/core';
|
|
@@ -22,18 +22,21 @@ const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPag
|
|
|
22
22
|
pageComponent = defaultPageComponent,
|
|
23
23
|
pageForceRerenderKey,
|
|
24
24
|
style,
|
|
25
|
+
UNSTABLE_sharedIndex,
|
|
25
26
|
} = props;
|
|
26
27
|
|
|
27
|
-
const
|
|
28
|
+
const fallbackSharedIndex = useSharedValue<number>(initialPage);
|
|
28
29
|
|
|
29
|
-
const
|
|
30
|
+
const sharedIndex = UNSTABLE_sharedIndex ?? fallbackSharedIndex;
|
|
31
|
+
|
|
32
|
+
const setPage = useCallback((newIndex: number) => {
|
|
30
33
|
sharedIndex.value = newIndex;
|
|
31
|
-
};
|
|
34
|
+
}, [sharedIndex]);
|
|
32
35
|
|
|
33
36
|
useImperativeHandle(
|
|
34
37
|
ref,
|
|
35
38
|
() => ({ setPage }),
|
|
36
|
-
[],
|
|
39
|
+
[setPage],
|
|
37
40
|
);
|
|
38
41
|
|
|
39
42
|
const PageComponent = pageComponent;
|
|
@@ -46,6 +49,7 @@ const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPag
|
|
|
46
49
|
children={child}
|
|
47
50
|
index={index}
|
|
48
51
|
loading={loading}
|
|
52
|
+
offscreenPageRerenderLimit={0} // All offscreen pages will not be re-rendered
|
|
49
53
|
rerenderKey={pageForceRerenderKey}
|
|
50
54
|
sharedIndex={sharedIndex}
|
|
51
55
|
/>
|
package/src/ViewPager/index.ts
CHANGED
package/src/ViewPager/utils.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { Loading, PageComponent } from './ViewPagerProps';
|
|
3
2
|
import ChildrenMemoizedPage from './ChildrenMemoizedPage';
|
|
4
3
|
|
|
@@ -6,4 +5,6 @@ export const defaultInitialPage: number = 0;
|
|
|
6
5
|
|
|
7
6
|
export const defaultLoading: Loading = 'lazy';
|
|
8
7
|
|
|
8
|
+
export const defaultOffscreenPageRerenderLimit: number = 0;
|
|
9
|
+
|
|
9
10
|
export const defaultPageComponent: PageComponent = ChildrenMemoizedPage;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import useViewabilityTracker from './useViewabilityTracker';
|
|
4
|
+
import type ViewabilityTrackerViewProps from './ViewabilityTrackerViewProps';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export default function ViewabilityTrackerView(props: ViewabilityTrackerViewProps) {
|
|
8
|
+
const {
|
|
9
|
+
enabled = true,
|
|
10
|
+
measurementIntervalMillis = 1000,
|
|
11
|
+
onViewabilityChange,
|
|
12
|
+
visiblePercentThreshold = 50,
|
|
13
|
+
...otherProps
|
|
14
|
+
} = props;
|
|
15
|
+
|
|
16
|
+
const viewRef = useRef<View>(null);
|
|
17
|
+
|
|
18
|
+
useViewabilityTracker({
|
|
19
|
+
enabled,
|
|
20
|
+
measurementIntervalMillis,
|
|
21
|
+
onViewabilityChange,
|
|
22
|
+
viewRef,
|
|
23
|
+
visiblePercentThreshold,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<View
|
|
28
|
+
{...otherProps}
|
|
29
|
+
ref={viewRef}
|
|
30
|
+
collapsable={false}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ViewProps } from 'react-native';
|
|
2
|
+
import type { OverridableComponentProps } from '@fountain-ui/core';
|
|
3
|
+
import type Viewability from './Viewability';
|
|
4
|
+
|
|
5
|
+
export default interface ViewabilityTrackerViewProps extends OverridableComponentProps<ViewProps, {
|
|
6
|
+
/**
|
|
7
|
+
* @default true
|
|
8
|
+
*/
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @default 1000
|
|
13
|
+
*/
|
|
14
|
+
measurementIntervalMillis?: number;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
onViewabilityChange?: (viewability: Viewability) => void;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @default 50
|
|
23
|
+
*/
|
|
24
|
+
visiblePercentThreshold?: number;
|
|
25
|
+
}> {}
|