@fountain-ui/lab 2.0.0-beta.12 → 2.0.0-beta.15
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 +39 -37
- package/build/commonjs/Carousel/Carousel.js.map +1 -1
- package/build/commonjs/Carousel/CarouselProps.js.map +1 -1
- package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js +2 -2
- package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js.map +1 -1
- package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js +15 -15
- package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js.map +1 -1
- package/build/commonjs/Carousel/components/InternalContext.js.map +1 -1
- package/build/commonjs/Carousel/components/ItemView.js +6 -4
- package/build/commonjs/Carousel/components/ItemView.js.map +1 -1
- package/build/commonjs/Carousel/components/RootView.js +21 -3
- package/build/commonjs/Carousel/components/RootView.js.map +1 -1
- package/build/commonjs/Carousel/components/ScrollViewGesture.js +18 -13
- package/build/commonjs/Carousel/components/ScrollViewGesture.js.map +1 -1
- package/build/commonjs/Carousel/{hooks → components}/useItemInterpolation.js +6 -4
- package/build/commonjs/Carousel/components/useItemInterpolation.js.map +1 -0
- package/build/commonjs/Carousel/hooks/index.js +0 -16
- package/build/commonjs/Carousel/hooks/index.js.map +1 -1
- package/build/commonjs/Carousel/hooks/useAutoplayController.js +4 -1
- package/build/commonjs/Carousel/hooks/useAutoplayController.js.map +1 -1
- package/build/commonjs/Carousel/hooks/useIndexController.js +15 -46
- package/build/commonjs/Carousel/hooks/useIndexController.js.map +1 -1
- package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js +12 -12
- package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js.map +1 -1
- package/build/commonjs/Carousel/hooks/usePagingAnimation.js +121 -69
- package/build/commonjs/Carousel/hooks/usePagingAnimation.js.map +1 -1
- package/build/commonjs/Carousel/tick.js +16 -0
- package/build/commonjs/Carousel/tick.js.map +1 -0
- package/build/commonjs/Carousel/types.js.map +1 -1
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js +53 -47
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/commonjs/ViewPager/InternalContext.js +17 -0
- package/build/commonjs/ViewPager/InternalContext.js.map +1 -0
- package/build/commonjs/ViewPager/ViewPagerNative.js +74 -23
- package/build/commonjs/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerProps.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerWeb.js +23 -12
- package/build/commonjs/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/commonjs/ViewPager/index.js.map +1 -1
- package/build/commonjs/ViewPager/types.js +6 -0
- package/build/commonjs/ViewPager/types.js.map +1 -0
- package/build/commonjs/ViewPager/usePageStore.js +35 -0
- package/build/commonjs/ViewPager/usePageStore.js.map +1 -0
- package/build/commonjs/ViewPager/utils.js.map +1 -1
- package/build/commonjs/ViewabilityTrackerView/measureViewability.js +6 -6
- package/build/commonjs/ViewabilityTrackerView/measureViewability.js.map +1 -1
- package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js +1 -1
- package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
- package/build/module/Carousel/Carousel.js +39 -39
- package/build/module/Carousel/Carousel.js.map +1 -1
- package/build/module/Carousel/CarouselProps.js.map +1 -1
- package/build/module/Carousel/animation/createDefaultScrollAnimation.js +2 -2
- package/build/module/Carousel/animation/createDefaultScrollAnimation.js.map +1 -1
- package/build/module/Carousel/animation/parallaxItemStyleFactory.js +15 -15
- package/build/module/Carousel/animation/parallaxItemStyleFactory.js.map +1 -1
- package/build/module/Carousel/components/InternalContext.js.map +1 -1
- package/build/module/Carousel/components/ItemView.js +5 -3
- package/build/module/Carousel/components/ItemView.js.map +1 -1
- package/build/module/Carousel/components/RootView.js +22 -4
- package/build/module/Carousel/components/RootView.js.map +1 -1
- package/build/module/Carousel/components/ScrollViewGesture.js +18 -13
- package/build/module/Carousel/components/ScrollViewGesture.js.map +1 -1
- package/build/module/Carousel/{hooks → components}/useItemInterpolation.js +3 -3
- package/build/module/Carousel/components/useItemInterpolation.js.map +1 -0
- package/build/module/Carousel/hooks/index.js +0 -2
- package/build/module/Carousel/hooks/index.js.map +1 -1
- package/build/module/Carousel/hooks/useAutoplayController.js +4 -1
- package/build/module/Carousel/hooks/useAutoplayController.js.map +1 -1
- package/build/module/Carousel/hooks/useIndexController.js +14 -39
- package/build/module/Carousel/hooks/useIndexController.js.map +1 -1
- package/build/module/Carousel/hooks/useItemVisibilityStore.js +10 -11
- package/build/module/Carousel/hooks/useItemVisibilityStore.js.map +1 -1
- package/build/module/Carousel/hooks/usePagingAnimation.js +122 -69
- package/build/module/Carousel/hooks/usePagingAnimation.js.map +1 -1
- package/build/module/Carousel/tick.js +6 -0
- package/build/module/Carousel/tick.js.map +1 -0
- package/build/module/Carousel/types.js.map +1 -1
- package/build/module/ViewPager/ChildrenMemoizedPage.js +53 -47
- package/build/module/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/module/ViewPager/InternalContext.js +7 -0
- package/build/module/ViewPager/InternalContext.js.map +1 -0
- package/build/module/ViewPager/ViewPagerNative.js +72 -23
- package/build/module/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/module/ViewPager/ViewPagerProps.js.map +1 -1
- package/build/module/ViewPager/ViewPagerWeb.js +21 -13
- package/build/module/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/module/ViewPager/index.js.map +1 -1
- package/build/module/ViewPager/types.js +2 -0
- package/build/module/ViewPager/types.js.map +1 -0
- package/build/module/ViewPager/usePageStore.js +25 -0
- package/build/module/ViewPager/usePageStore.js.map +1 -0
- package/build/module/ViewPager/utils.js.map +1 -1
- package/build/module/ViewabilityTrackerView/measureViewability.js +2 -2
- package/build/module/ViewabilityTrackerView/measureViewability.js.map +1 -1
- package/build/module/hooks/useUnstableCollapsibleAppBar.js +1 -1
- package/build/module/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
- package/build/typescript/Carousel/CarouselProps.d.ts +4 -3
- package/build/typescript/Carousel/animation/parallaxItemStyleFactory.d.ts +5 -5
- package/build/typescript/Carousel/components/InternalContext.d.ts +2 -2
- package/build/typescript/Carousel/components/ItemView.d.ts +2 -0
- package/build/typescript/Carousel/components/RootView.d.ts +4 -4
- package/build/typescript/Carousel/components/ScrollViewGesture.d.ts +3 -3
- package/build/typescript/Carousel/{hooks → components}/useItemInterpolation.d.ts +0 -0
- package/build/typescript/Carousel/hooks/index.d.ts +0 -2
- package/build/typescript/Carousel/hooks/useIndexController.d.ts +0 -2
- package/build/typescript/Carousel/hooks/useItemVisibilityStore.d.ts +5 -2
- package/build/typescript/Carousel/hooks/usePagingAnimation.d.ts +8 -10
- package/build/typescript/Carousel/tick.d.ts +2 -0
- package/build/typescript/Carousel/types.d.ts +26 -5
- package/build/typescript/ViewPager/ChildrenMemoizedPage.d.ts +1 -1
- package/build/typescript/ViewPager/InternalContext.d.ts +7 -0
- package/build/typescript/ViewPager/ViewPagerNative.d.ts +2 -2
- package/build/typescript/ViewPager/ViewPagerProps.d.ts +4 -22
- package/build/typescript/ViewPager/ViewPagerWeb.d.ts +2 -2
- package/build/typescript/ViewPager/index.d.ts +2 -1
- package/build/typescript/ViewPager/types.d.ts +19 -0
- package/build/typescript/ViewPager/usePageStore.d.ts +2 -0
- package/build/typescript/ViewPager/utils.d.ts +1 -1
- package/package.json +3 -3
- package/src/Carousel/Carousel.tsx +32 -40
- package/src/Carousel/CarouselProps.ts +4 -3
- package/src/Carousel/animation/createDefaultScrollAnimation.ts +2 -2
- package/src/Carousel/animation/parallaxItemStyleFactory.ts +24 -24
- package/src/Carousel/components/InternalContext.ts +2 -2
- package/src/Carousel/components/ItemView.tsx +13 -3
- package/src/Carousel/components/RootView.tsx +19 -6
- package/src/Carousel/components/ScrollViewGesture.tsx +23 -15
- package/src/Carousel/{hooks → components}/useItemInterpolation.ts +3 -3
- package/src/Carousel/hooks/index.ts +0 -2
- package/src/Carousel/hooks/useAutoplayController.ts +4 -1
- package/src/Carousel/hooks/useIndexController.tsx +14 -44
- package/src/Carousel/hooks/useItemVisibilityStore.ts +17 -13
- package/src/Carousel/hooks/usePagingAnimation.ts +161 -83
- package/src/Carousel/tick.ts +6 -0
- package/src/Carousel/types.ts +34 -5
- package/src/ViewPager/ChildrenMemoizedPage.tsx +53 -50
- package/src/ViewPager/InternalContext.ts +13 -0
- package/src/ViewPager/ViewPagerNative.tsx +91 -44
- package/src/ViewPager/ViewPagerProps.ts +4 -27
- package/src/ViewPager/ViewPagerWeb.tsx +28 -23
- package/src/ViewPager/index.ts +2 -1
- package/src/ViewPager/types.ts +24 -0
- package/src/ViewPager/usePageStore.ts +30 -0
- package/src/ViewPager/utils.tsx +1 -1
- package/src/ViewabilityTrackerView/measureViewability.ts +1 -3
- package/src/hooks/useUnstableCollapsibleAppBar.ts +1 -1
- package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js +0 -23
- package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js.map +0 -1
- package/build/commonjs/Carousel/hooks/useItemInterpolation.js.map +0 -1
- package/build/module/Carousel/hooks/useDimensionChangeReaction.js +0 -14
- package/build/module/Carousel/hooks/useDimensionChangeReaction.js.map +0 -1
- package/build/module/Carousel/hooks/useItemInterpolation.js.map +0 -1
- package/build/typescript/Carousel/hooks/useDimensionChangeReaction.d.ts +0 -7
- package/src/Carousel/hooks/useDimensionChangeReaction.ts +0 -25
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RefObject } from 'react';
|
|
2
2
|
import type { ComponentProps } from '@fountain-ui/core';
|
|
3
|
-
import type { CarouselInstance, CreateItemStyle, CreateScrollAnimation, RenderItem } from './types';
|
|
3
|
+
import type { CarouselInstance, CreateItemStyle, CreateScrollAnimation, ItemHeight, RenderItem } from './types';
|
|
4
4
|
|
|
5
5
|
export default interface CarouselProps<ItemT = any> extends ComponentProps<{
|
|
6
6
|
ref?: RefObject<CarouselInstance>;
|
|
@@ -47,9 +47,10 @@ export default interface CarouselProps<ItemT = any> extends ComponentProps<{
|
|
|
47
47
|
initialIndex?: number;
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* The item
|
|
50
|
+
* The item height.
|
|
51
|
+
* For a performance reason, always consider to provide a number value.
|
|
51
52
|
*/
|
|
52
|
-
itemHeight:
|
|
53
|
+
itemHeight: ItemHeight;
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
56
|
* The item width.
|
|
@@ -6,8 +6,8 @@ export default function createDefaultScrollAnimation(
|
|
|
6
6
|
): Animated.CompositeAnimation {
|
|
7
7
|
return Animated.timing(animatedValue, {
|
|
8
8
|
toValue: toValue,
|
|
9
|
-
duration:
|
|
10
|
-
easing: Easing.bezier(0.
|
|
9
|
+
duration: 220,
|
|
10
|
+
easing: Easing.bezier(0.35, 0.5, 0.5, 0.75),
|
|
11
11
|
useNativeDriver: true,
|
|
12
12
|
});
|
|
13
13
|
};
|
|
@@ -2,40 +2,40 @@ import type { CreateItemStyle } from '../types';
|
|
|
2
2
|
import { itemInterpolationInputRange } from './animationUtils';
|
|
3
3
|
|
|
4
4
|
export interface ParallaxAnimationConfig {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
activeItemScale?: number;
|
|
6
|
+
activeItemOpacity?: number;
|
|
7
|
+
adjacentItemScale?: number;
|
|
8
|
+
adjacentItemOpacity?: number;
|
|
9
|
+
scrollingOffset?: number;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const defaultParallaxAnimationConfig: Required<Readonly<ParallaxAnimationConfig>> = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
activeItemScale: 0.9,
|
|
14
|
+
activeItemOpacity: 1,
|
|
15
|
+
adjacentItemScale: Math.pow(0.9, 2),
|
|
16
|
+
adjacentItemOpacity: 0.5,
|
|
17
|
+
scrollingOffset: 50,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export default function parallaxItemStyleFactory(config: ParallaxAnimationConfig = defaultParallaxAnimationConfig) {
|
|
21
21
|
const {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
activeItemOpacity,
|
|
23
|
+
activeItemScale,
|
|
24
|
+
adjacentItemOpacity,
|
|
25
|
+
adjacentItemScale,
|
|
26
|
+
scrollingOffset,
|
|
27
27
|
}: Required<ParallaxAnimationConfig> = {
|
|
28
|
-
...config,
|
|
29
28
|
...defaultParallaxAnimationConfig,
|
|
29
|
+
...config,
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
const createItemStyle: CreateItemStyle = (itemInterpolation, itemWidth) => {
|
|
33
33
|
const translate = itemInterpolation.interpolate({
|
|
34
34
|
inputRange: itemInterpolationInputRange,
|
|
35
35
|
outputRange: [
|
|
36
|
-
-itemWidth +
|
|
36
|
+
-itemWidth + scrollingOffset,
|
|
37
37
|
0,
|
|
38
|
-
itemWidth -
|
|
38
|
+
itemWidth - scrollingOffset,
|
|
39
39
|
],
|
|
40
40
|
});
|
|
41
41
|
|
|
@@ -48,9 +48,9 @@ export default function parallaxItemStyleFactory(config: ParallaxAnimationConfig
|
|
|
48
48
|
const scale = itemInterpolation.interpolate({
|
|
49
49
|
inputRange: itemInterpolationInputRange,
|
|
50
50
|
outputRange: [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
adjacentItemScale,
|
|
52
|
+
activeItemScale,
|
|
53
|
+
adjacentItemScale,
|
|
54
54
|
],
|
|
55
55
|
extrapolate: 'clamp',
|
|
56
56
|
});
|
|
@@ -58,9 +58,9 @@ export default function parallaxItemStyleFactory(config: ParallaxAnimationConfig
|
|
|
58
58
|
const opacity = itemInterpolation.interpolate({
|
|
59
59
|
inputRange: itemInterpolationInputRange,
|
|
60
60
|
outputRange: [
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
adjacentItemOpacity,
|
|
62
|
+
activeItemOpacity,
|
|
63
|
+
adjacentItemOpacity,
|
|
64
64
|
],
|
|
65
65
|
extrapolate: 'clamp',
|
|
66
66
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createContext } from 'react';
|
|
2
2
|
import { Animated } from 'react-native';
|
|
3
|
-
import type { CreateItemStyle, ItemVisibilityStore } from '../types';
|
|
3
|
+
import type { CreateItemStyle, ItemHeight, ItemVisibilityStore } from '../types';
|
|
4
4
|
|
|
5
5
|
export interface InternalContextValue<ItemT> {
|
|
6
6
|
createItemStyle: CreateItemStyle;
|
|
7
7
|
data: ReadonlyArray<ItemT>;
|
|
8
8
|
globalInterpolation: Animated.AnimatedInterpolation;
|
|
9
|
-
itemHeight:
|
|
9
|
+
itemHeight: ItemHeight;
|
|
10
10
|
itemWidth: number;
|
|
11
11
|
itemVisibilityStore: ItemVisibilityStore;
|
|
12
12
|
loop: boolean;
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
2
|
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import type { ViewProps } from 'react-native';
|
|
3
4
|
import { Animated } from 'react-native';
|
|
4
5
|
import { StyleSheet } from '@fountain-ui/core';
|
|
5
|
-
import
|
|
6
|
+
import useItemInterpolation from './useItemInterpolation';
|
|
6
7
|
import InternalContext from './InternalContext';
|
|
7
8
|
|
|
8
9
|
export interface ItemViewProps {
|
|
9
10
|
children: (interpolation: Animated.AnimatedInterpolation) => ReactElement | null;
|
|
10
11
|
index: number;
|
|
12
|
+
onLayout?: ViewProps['onLayout'];
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export default function ItemView(props: ItemViewProps) {
|
|
14
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
children,
|
|
18
|
+
index,
|
|
19
|
+
onLayout,
|
|
20
|
+
} = props;
|
|
15
21
|
|
|
16
22
|
const {
|
|
17
23
|
createItemStyle,
|
|
@@ -39,8 +45,12 @@ export default function ItemView(props: ItemViewProps) {
|
|
|
39
45
|
return (
|
|
40
46
|
<Animated.View
|
|
41
47
|
children={visible ? children(interpolation) : null}
|
|
48
|
+
onLayout={onLayout}
|
|
42
49
|
style={[
|
|
43
|
-
{
|
|
50
|
+
{
|
|
51
|
+
width: itemWidth,
|
|
52
|
+
height: itemHeight !== 'auto' ? itemHeight : undefined,
|
|
53
|
+
},
|
|
44
54
|
styles.absolute,
|
|
45
55
|
// @ts-ignore
|
|
46
56
|
itemStyle,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React, { memo, ReactElement,
|
|
2
|
-
import type { ViewProps,
|
|
1
|
+
import React, { forwardRef, memo, ReactElement, useState } from 'react';
|
|
2
|
+
import type { View, ViewProps, LayoutChangeEvent } from 'react-native';
|
|
3
3
|
import { Animated } from 'react-native';
|
|
4
4
|
import { StyleSheet } from '@fountain-ui/core';
|
|
5
|
-
import type { RenderItem } from '../types';
|
|
5
|
+
import type { ItemHeight, RenderItem } from '../types';
|
|
6
6
|
import ItemView from './ItemView';
|
|
7
7
|
|
|
8
8
|
const styles = StyleSheet.create({
|
|
@@ -12,13 +12,14 @@ const styles = StyleSheet.create({
|
|
|
12
12
|
},
|
|
13
13
|
horizontal: {
|
|
14
14
|
flexDirection: 'row',
|
|
15
|
-
|
|
15
|
+
overflowX: 'hidden',
|
|
16
|
+
overflowY: 'visible',
|
|
16
17
|
},
|
|
17
18
|
});
|
|
18
19
|
|
|
19
20
|
export type RootViewProps<ItemT> = ViewProps & {
|
|
20
21
|
data: ReadonlyArray<ItemT>;
|
|
21
|
-
itemHeight:
|
|
22
|
+
itemHeight: ItemHeight;
|
|
22
23
|
originalData: ReadonlyArray<ItemT>;
|
|
23
24
|
renderItem: RenderItem<ItemT>;
|
|
24
25
|
};
|
|
@@ -33,10 +34,22 @@ const RootView = forwardRef<View, RootViewProps<any>>(function RootView(props, r
|
|
|
33
34
|
...otherProps
|
|
34
35
|
} = props;
|
|
35
36
|
|
|
37
|
+
const [maxHeightOfRenderedItems, setMaxHeightOfRenderedItems] = useState(0);
|
|
38
|
+
|
|
39
|
+
const handleItemLayout = (e: LayoutChangeEvent) => {
|
|
40
|
+
const { nativeEvent: { layout: { height } } } = e;
|
|
41
|
+
|
|
42
|
+
const heightInt = Math.round(height);
|
|
43
|
+
if (heightInt > maxHeightOfRenderedItems) {
|
|
44
|
+
setMaxHeightOfRenderedItems(heightInt);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
36
48
|
const renderItemView = (item: any, index: number): ReactElement => (
|
|
37
49
|
<ItemView
|
|
38
50
|
key={index}
|
|
39
51
|
index={index}
|
|
52
|
+
onLayout={itemHeight === 'auto' ? handleItemLayout : undefined}
|
|
40
53
|
>
|
|
41
54
|
{(interpolation) => renderItem({
|
|
42
55
|
item,
|
|
@@ -49,7 +62,7 @@ const RootView = forwardRef<View, RootViewProps<any>>(function RootView(props, r
|
|
|
49
62
|
const viewStyles = [
|
|
50
63
|
styles.root,
|
|
51
64
|
styles.horizontal,
|
|
52
|
-
{ height: itemHeight },
|
|
65
|
+
{ height: itemHeight === 'auto' ? maxHeightOfRenderedItems : itemHeight },
|
|
53
66
|
style,
|
|
54
67
|
];
|
|
55
68
|
|
|
@@ -8,14 +8,14 @@ import type { AutoplayController, PagingDirection, StartPagingAnimation } from '
|
|
|
8
8
|
export interface ScrollViewGestureProps {
|
|
9
9
|
autoplayController: AutoplayController;
|
|
10
10
|
children: ReactNode;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
interruptAnimation: () => void;
|
|
12
|
+
translateX: Animated.Value,
|
|
13
13
|
scrollEnabled: boolean;
|
|
14
|
-
|
|
14
|
+
startPagingAnimation: StartPagingAnimation;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const SCROLL_TO_ADJACENT_TX_THRESHOLD =
|
|
18
|
-
const SCROLL_TO_ADJACENT_VX_THRESHOLD =
|
|
17
|
+
const SCROLL_TO_ADJACENT_TX_THRESHOLD = 80;
|
|
18
|
+
const SCROLL_TO_ADJACENT_VX_THRESHOLD = 1000;
|
|
19
19
|
|
|
20
20
|
const ACTIVE_OFFSET_ABS_X = 5;
|
|
21
21
|
const activeOffsetX: number[] = [-ACTIVE_OFFSET_ABS_X, ACTIVE_OFFSET_ABS_X];
|
|
@@ -23,21 +23,26 @@ const activeOffsetX: number[] = [-ACTIVE_OFFSET_ABS_X, ACTIVE_OFFSET_ABS_X];
|
|
|
23
23
|
const endAnimationStates: Readonly<GestureHandlerState[]> = [
|
|
24
24
|
GestureHandlerState.CANCELLED,
|
|
25
25
|
GestureHandlerState.END,
|
|
26
|
+
GestureHandlerState.FAILED,
|
|
26
27
|
];
|
|
27
28
|
|
|
28
29
|
function shouldScrollToAdjacent(translationX: number, velocityX: number): boolean {
|
|
29
|
-
|
|
30
|
+
const isSameDirection = translationX * velocityX > 0;
|
|
31
|
+
const isEnoughMovement =
|
|
32
|
+
Math.abs(translationX) >= SCROLL_TO_ADJACENT_TX_THRESHOLD
|
|
30
33
|
|| Math.abs(velocityX) >= SCROLL_TO_ADJACENT_VX_THRESHOLD;
|
|
34
|
+
|
|
35
|
+
return isSameDirection && isEnoughMovement;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
export default function ScrollViewGesture(props: ScrollViewGestureProps) {
|
|
34
39
|
const {
|
|
35
40
|
autoplayController,
|
|
36
41
|
children,
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
interruptAnimation,
|
|
43
|
+
translateX,
|
|
39
44
|
scrollEnabled,
|
|
40
|
-
|
|
45
|
+
startPagingAnimation,
|
|
41
46
|
} = props;
|
|
42
47
|
|
|
43
48
|
const { pause: pauseAutoplay, resume: resumeAutoplay } = autoplayController;
|
|
@@ -45,11 +50,11 @@ export default function ScrollViewGesture(props: ScrollViewGestureProps) {
|
|
|
45
50
|
const handleGestureBegin = useCallback(() => {
|
|
46
51
|
pauseAutoplay();
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
}, [
|
|
53
|
+
interruptAnimation();
|
|
54
|
+
}, [interruptAnimation, pauseAutoplay]);
|
|
50
55
|
|
|
51
56
|
const handleGestureEvent = useCallback(Animated.event(
|
|
52
|
-
[{ nativeEvent: { translationX:
|
|
57
|
+
[{ nativeEvent: { translationX: translateX } }],
|
|
53
58
|
{ useNativeDriver: true },
|
|
54
59
|
), []);
|
|
55
60
|
|
|
@@ -57,15 +62,18 @@ export default function ScrollViewGesture(props: ScrollViewGestureProps) {
|
|
|
57
62
|
const { nativeEvent: { translationX, velocityX, state } } = event;
|
|
58
63
|
|
|
59
64
|
if (endAnimationStates.includes(state)) {
|
|
60
|
-
const
|
|
65
|
+
const direction: PagingDirection = shouldScrollToAdjacent(translationX, velocityX)
|
|
61
66
|
? (translationX < 0 ? 'next' : 'prev')
|
|
62
67
|
: 'stay';
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
startPagingAnimation(
|
|
70
|
+
'directional',
|
|
71
|
+
{ direction: direction, isOriginatedFromGesture: true },
|
|
72
|
+
);
|
|
65
73
|
|
|
66
74
|
resumeAutoplay();
|
|
67
75
|
}
|
|
68
|
-
}, [
|
|
76
|
+
}, [startPagingAnimation, resumeAutoplay]);
|
|
69
77
|
|
|
70
78
|
return (
|
|
71
79
|
<PanGestureHandler
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useContext, useMemo } from 'react';
|
|
2
2
|
import { Animated } from 'react-native';
|
|
3
|
-
import
|
|
3
|
+
import InternalContext from './InternalContext';
|
|
4
4
|
|
|
5
5
|
const OVERSCROLL_FRICTION_FACTOR = 4;
|
|
6
6
|
|
|
@@ -94,9 +94,9 @@ export default function useItemInterpolation(index: number): Animated.AnimatedIn
|
|
|
94
94
|
? interpolationConfigOnLoop
|
|
95
95
|
: interpolationConfigOnNoLoop;
|
|
96
96
|
|
|
97
|
-
const
|
|
97
|
+
const localOffsetX = globalInterpolation.interpolate(interpolationConfig);
|
|
98
98
|
|
|
99
|
-
return Animated.divide(
|
|
99
|
+
return Animated.divide(localOffsetX, itemWidth);
|
|
100
100
|
}, [
|
|
101
101
|
globalInterpolation,
|
|
102
102
|
interpolationConfigOnLoop,
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export { default as useAutoplayController } from './useAutoplayController';
|
|
2
|
-
export { default as useDimensionChangeReaction } from './useDimensionChangeReaction';
|
|
3
2
|
export { default as useIndexController } from './useIndexController';
|
|
4
|
-
export { default as useItemInterpolation } from './useItemInterpolation';
|
|
5
3
|
export { default as useLoopedData } from './useLoopedData';
|
|
6
4
|
export { default as usePagingAnimation } from './usePagingAnimation';
|
|
7
5
|
export { default as useItemVisibilityStore } from './useItemVisibilityStore';
|
|
@@ -25,7 +25,10 @@ export default function useAutoplayController(config: AutoplayConfig): AutoplayC
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
executor.execute(() => {
|
|
28
|
-
startPagingAnimation(
|
|
28
|
+
startPagingAnimation(
|
|
29
|
+
'directional',
|
|
30
|
+
{ direction: 'next', isOriginatedFromGesture: false },
|
|
31
|
+
);
|
|
29
32
|
play();
|
|
30
33
|
}, intervalMillis);
|
|
31
34
|
}, [intervalMillis, startPagingAnimation]);
|
|
@@ -1,76 +1,46 @@
|
|
|
1
|
-
import React, { useCallback,
|
|
2
|
-
import {
|
|
1
|
+
import React, { useCallback, useRef } from 'react';
|
|
2
|
+
import { mod } from '@fountain-ui/utils';
|
|
3
3
|
import type { IndexController } from '../types';
|
|
4
4
|
|
|
5
5
|
export interface UseIndexControllerParameters {
|
|
6
|
-
controlledTx: Animated.AnimatedValue;
|
|
7
6
|
initialIndex: number;
|
|
8
7
|
itemWidth: number;
|
|
9
8
|
numberOfOriginalData: number;
|
|
10
9
|
onIndexChange?: (newIndex: number) => void;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
const normalizeIndex = (maybeIndex: number, numberOfData: number): number =>
|
|
14
|
-
Math.abs(Math.floor(maybeIndex)) % numberOfData;
|
|
15
|
-
|
|
16
12
|
export default function useIndexController(params: UseIndexControllerParameters): IndexController {
|
|
17
13
|
const {
|
|
18
|
-
controlledTx,
|
|
19
14
|
initialIndex,
|
|
20
15
|
itemWidth,
|
|
21
16
|
numberOfOriginalData,
|
|
22
17
|
onIndexChange,
|
|
23
18
|
} = params;
|
|
24
19
|
|
|
25
|
-
const
|
|
26
|
-
const [index, setIndex] = useState<number>(indexRef.current);
|
|
20
|
+
const currentIndexRef = useRef<number>(initialIndex);
|
|
27
21
|
|
|
28
|
-
const
|
|
29
|
-
const negative = new Animated.Value(-1);
|
|
30
|
-
const reversedTx = Animated.multiply(controlledTx, negative);
|
|
31
|
-
const normalized = Animated.divide(reversedTx, itemWidth);
|
|
32
|
-
return Animated.modulo(normalized, numberOfOriginalData);
|
|
33
|
-
}, [
|
|
34
|
-
controlledTx,
|
|
35
|
-
itemWidth,
|
|
36
|
-
numberOfOriginalData,
|
|
37
|
-
]);
|
|
22
|
+
const getCurrentIndex = useCallback(() => currentIndexRef.current, []);
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
const newIndex = normalizeIndex(observedValue.value, numberOfOriginalData);
|
|
24
|
+
const notifyOffsetHasChanged = useCallback((offset: number) => {
|
|
25
|
+
const roundedOffset = Math.round(offset / itemWidth) * itemWidth;
|
|
42
26
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
setIndex(newIndex);
|
|
27
|
+
// To prevent floating point problem, make sure index is integer type.
|
|
28
|
+
const nextIndex = Math.floor(mod((-roundedOffset / itemWidth), numberOfOriginalData));
|
|
46
29
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
30
|
+
if (nextIndex !== currentIndexRef.current) {
|
|
31
|
+
currentIndexRef.current = nextIndex;
|
|
50
32
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
};
|
|
33
|
+
onIndexChange?.(nextIndex);
|
|
34
|
+
}
|
|
54
35
|
}, [
|
|
55
|
-
|
|
36
|
+
itemWidth,
|
|
56
37
|
numberOfOriginalData,
|
|
57
38
|
onIndexChange,
|
|
58
39
|
]);
|
|
59
40
|
|
|
60
|
-
const getCurrentIndex = useCallback(() => indexRef.current, []);
|
|
61
|
-
|
|
62
41
|
return {
|
|
63
|
-
currentIndex: index,
|
|
64
42
|
getCurrentIndex,
|
|
65
43
|
lastIndex: numberOfOriginalData - 1,
|
|
66
|
-
|
|
67
|
-
<Animated.View
|
|
68
|
-
collapsable={false}
|
|
69
|
-
style={[
|
|
70
|
-
{ zIndex: maybeIndex },
|
|
71
|
-
{ width: 1, height: 1, position: 'absolute' },
|
|
72
|
-
]}
|
|
73
|
-
/>
|
|
74
|
-
),
|
|
44
|
+
notifyOffsetHasChanged,
|
|
75
45
|
};
|
|
76
46
|
};
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { mod } from '@fountain-ui/utils';
|
|
2
3
|
import type { ItemVisibilityStore, VisibleIndexRanges } from '../types';
|
|
3
4
|
|
|
4
5
|
export interface Parameters {
|
|
5
|
-
|
|
6
|
+
initialIndex: number;
|
|
6
7
|
numberOfData: number;
|
|
7
8
|
windowSize: number;
|
|
8
9
|
}
|
|
9
10
|
|
|
11
|
+
export interface OnIndexChange {
|
|
12
|
+
(newIndex: number): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
class SimpleItemVisibilityStore implements ItemVisibilityStore {
|
|
11
16
|
|
|
12
17
|
private store: VisibleIndexRanges;
|
|
@@ -52,10 +57,6 @@ function normalize(windowSize: number, numberOfData: number): number {
|
|
|
52
57
|
return windowSize;
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
function mod(value: number, modulo: number): number {
|
|
56
|
-
return ((value % modulo) + modulo) % modulo;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
60
|
function makeVisibleIndexRanges(numberOfData: number, windowSize: number, index: number): VisibleIndexRanges {
|
|
60
61
|
const ws = normalize(windowSize, numberOfData);
|
|
61
62
|
|
|
@@ -81,21 +82,24 @@ function makeVisibleIndexRanges(numberOfData: number, windowSize: number, index:
|
|
|
81
82
|
];
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
export default function useItemVisibilityStore(params: Parameters): ItemVisibilityStore {
|
|
85
|
+
export default function useItemVisibilityStore(params: Parameters): [ItemVisibilityStore, OnIndexChange] {
|
|
85
86
|
const {
|
|
86
|
-
|
|
87
|
+
initialIndex,
|
|
87
88
|
numberOfData,
|
|
88
89
|
windowSize,
|
|
89
90
|
} = params;
|
|
90
91
|
|
|
91
|
-
const [initialRange] = useState(() =>
|
|
92
|
+
const [initialRange] = useState(() => {
|
|
93
|
+
return makeVisibleIndexRanges(numberOfData, windowSize, initialIndex);
|
|
94
|
+
});
|
|
95
|
+
|
|
92
96
|
const store = useRef(new SimpleItemVisibilityStore(initialRange)).current;
|
|
93
97
|
|
|
94
|
-
|
|
95
|
-
const newRanges = makeVisibleIndexRanges(numberOfData, windowSize,
|
|
98
|
+
const onIndexChange: OnIndexChange = useCallback((newIndex) => {
|
|
99
|
+
const newRanges = makeVisibleIndexRanges(numberOfData, windowSize, newIndex);
|
|
96
100
|
|
|
97
101
|
store.dispatch(newRanges);
|
|
98
|
-
}, [
|
|
102
|
+
}, [numberOfData, windowSize]);
|
|
99
103
|
|
|
100
104
|
useEffect(() => {
|
|
101
105
|
return () => {
|
|
@@ -103,5 +107,5 @@ export default function useItemVisibilityStore(params: Parameters): ItemVisibili
|
|
|
103
107
|
};
|
|
104
108
|
}, []);
|
|
105
109
|
|
|
106
|
-
return store;
|
|
110
|
+
return [store, onIndexChange];
|
|
107
111
|
};
|