@fountain-ui/lab 2.0.0-beta.17 → 2.0.0-beta.20
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 +6 -13
- package/build/commonjs/Carousel/Carousel.js.map +1 -1
- package/build/commonjs/Carousel/components/ScrollViewGesture.js +4 -3
- package/build/commonjs/Carousel/components/ScrollViewGesture.js.map +1 -1
- package/build/commonjs/Carousel/hooks/index.js +3 -3
- package/build/commonjs/Carousel/hooks/index.js.map +1 -1
- package/build/commonjs/Carousel/hooks/useIndexController.js +14 -13
- package/build/commonjs/Carousel/hooks/useIndexController.js.map +1 -1
- package/build/commonjs/Carousel/hooks/{usePagingAnimation.js → usePagingAnimator.js} +44 -22
- package/build/commonjs/Carousel/hooks/usePagingAnimator.js.map +1 -0
- package/build/commonjs/Carousel/types.js +1 -1
- package/build/commonjs/Carousel/types.js.map +1 -1
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js +1 -1
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerNative.js +4 -3
- package/build/commonjs/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerWeb.js +4 -3
- package/build/commonjs/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/module/Carousel/Carousel.js +8 -12
- package/build/module/Carousel/Carousel.js.map +1 -1
- package/build/module/Carousel/components/ScrollViewGesture.js +4 -3
- package/build/module/Carousel/components/ScrollViewGesture.js.map +1 -1
- package/build/module/Carousel/hooks/index.js +1 -1
- package/build/module/Carousel/hooks/index.js.map +1 -1
- package/build/module/Carousel/hooks/useIndexController.js +14 -13
- package/build/module/Carousel/hooks/useIndexController.js.map +1 -1
- package/build/module/Carousel/hooks/{usePagingAnimation.js → usePagingAnimator.js} +43 -22
- package/build/module/Carousel/hooks/usePagingAnimator.js.map +1 -0
- package/build/module/Carousel/types.js +1 -1
- package/build/module/Carousel/types.js.map +1 -1
- package/build/module/ViewPager/ChildrenMemoizedPage.js +1 -1
- package/build/module/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/module/ViewPager/ViewPagerNative.js +5 -4
- package/build/module/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/module/ViewPager/ViewPagerWeb.js +5 -4
- package/build/module/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/typescript/Carousel/components/ScrollViewGesture.d.ts +1 -1
- package/build/typescript/Carousel/hooks/index.d.ts +1 -1
- package/build/typescript/Carousel/hooks/{usePagingAnimation.d.ts → usePagingAnimator.d.ts} +6 -5
- package/build/typescript/Carousel/types.d.ts +8 -4
- package/package.json +2 -2
- package/src/Carousel/Carousel.tsx +7 -12
- package/src/Carousel/components/ScrollViewGesture.tsx +8 -4
- package/src/Carousel/hooks/index.ts +1 -1
- package/src/Carousel/hooks/useIndexController.tsx +12 -20
- package/src/Carousel/hooks/{usePagingAnimation.ts → usePagingAnimator.ts} +48 -29
- package/src/Carousel/types.ts +9 -4
- package/src/ViewPager/ChildrenMemoizedPage.tsx +1 -1
- package/src/ViewPager/ViewPagerNative.tsx +4 -2
- package/src/ViewPager/ViewPagerWeb.tsx +4 -2
- package/build/commonjs/Carousel/hooks/usePagingAnimation.js.map +0 -1
- package/build/module/Carousel/hooks/usePagingAnimation.js.map +0 -1
|
@@ -4,8 +4,8 @@ import type { AutoplayController, StartPagingAnimation } from '../types';
|
|
|
4
4
|
export interface ScrollViewGestureProps {
|
|
5
5
|
autoplayController: AutoplayController;
|
|
6
6
|
children: ReactNode;
|
|
7
|
+
gestureTranslationX: Animated.Value;
|
|
7
8
|
interruptAnimation: () => void;
|
|
8
|
-
translateX: Animated.Value;
|
|
9
9
|
scrollEnabled: boolean;
|
|
10
10
|
startPagingAnimation: StartPagingAnimation;
|
|
11
11
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as useAutoplayController } from './useAutoplayController';
|
|
2
2
|
export { default as useIndexController } from './useIndexController';
|
|
3
3
|
export { default as useLoopedData } from './useLoopedData';
|
|
4
|
-
export { default as
|
|
4
|
+
export { default as usePagingAnimator } from './usePagingAnimator';
|
|
5
5
|
export { default as useItemVisibilityStore } from './useItemVisibilityStore';
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { Animated } from 'react-native';
|
|
2
2
|
import type { CreateScrollAnimation, IndexController, StartPagingAnimation } from '../types';
|
|
3
|
-
export interface
|
|
3
|
+
export interface PagingAnimatorConfig {
|
|
4
4
|
createScrollAnimation: CreateScrollAnimation;
|
|
5
5
|
itemWidth: number;
|
|
6
6
|
indexController: IndexController;
|
|
7
|
+
initialIndex: number;
|
|
7
8
|
loop: boolean;
|
|
8
9
|
numberOfData: number;
|
|
9
|
-
offsetX: Animated.Value;
|
|
10
|
-
translateX: Animated.Value;
|
|
11
10
|
}
|
|
12
|
-
export interface
|
|
11
|
+
export interface PagingAnimator {
|
|
12
|
+
gestureTranslationX: Animated.Value;
|
|
13
|
+
globalInterpolation: Animated.AnimatedInterpolation;
|
|
13
14
|
interruptAnimation: () => void;
|
|
14
15
|
startPagingAnimation: StartPagingAnimation;
|
|
15
16
|
}
|
|
16
|
-
export default function
|
|
17
|
+
export default function usePagingAnimator(config: PagingAnimatorConfig): PagingAnimator;
|
|
@@ -2,8 +2,8 @@ import type { ReactElement } from 'react';
|
|
|
2
2
|
import type { Animated, ViewProps } from 'react-native';
|
|
3
3
|
declare const directions: readonly ["next", "prev", "stay"];
|
|
4
4
|
export declare type PagingDirection = (typeof directions)[number];
|
|
5
|
-
declare const
|
|
6
|
-
export declare type
|
|
5
|
+
declare const scrollStates: readonly ["idle", "dragging", "interrupted"];
|
|
6
|
+
export declare type ScrollState = (typeof scrollStates)[number];
|
|
7
7
|
export declare type ItemHeight = number | 'auto';
|
|
8
8
|
export interface RenderItem<T> {
|
|
9
9
|
(info: {
|
|
@@ -27,15 +27,19 @@ export interface OnIndexChange {
|
|
|
27
27
|
export interface OnPositionChange {
|
|
28
28
|
(position: number): void;
|
|
29
29
|
}
|
|
30
|
+
export interface ScrollStateChangeEvent {
|
|
31
|
+
offset: number;
|
|
32
|
+
state: ScrollState;
|
|
33
|
+
}
|
|
30
34
|
export interface IndexController {
|
|
31
35
|
getCurrentIndex: GetCurrentIndex;
|
|
32
36
|
lastIndex: number;
|
|
33
|
-
|
|
34
|
-
notifyOffsetHasChanged: (offset: number) => void;
|
|
37
|
+
notifyScrollStateHasChanged: (event: ScrollStateChangeEvent) => void;
|
|
35
38
|
}
|
|
36
39
|
export declare type PagingAnimationType = 'directional' | 'index';
|
|
37
40
|
export interface BasePagingAnimationConfig {
|
|
38
41
|
animated?: boolean;
|
|
42
|
+
lastGestureTranslationX?: number;
|
|
39
43
|
}
|
|
40
44
|
export interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {
|
|
41
45
|
direction: PagingDirection;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fountain-ui/lab",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.20",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Fountain-UI Team",
|
|
6
6
|
"description": "Incubator for Fountain-UI React components.",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "e97185cf56e1f51817e29a7d1b7e43bcf8ef0342"
|
|
74
74
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import React, { forwardRef, memo, useImperativeHandle, useMemo
|
|
2
|
-
import { Animated } from 'react-native';
|
|
1
|
+
import React, { forwardRef, memo, useImperativeHandle, useMemo } from 'react';
|
|
3
2
|
import ViewabilityTrackerView from '../ViewabilityTrackerView';
|
|
4
3
|
import type CarouselProps from './CarouselProps';
|
|
5
4
|
import type { CarouselInstance } from './types';
|
|
@@ -8,7 +7,7 @@ import {
|
|
|
8
7
|
useIndexController,
|
|
9
8
|
useItemVisibilityStore,
|
|
10
9
|
useLoopedData,
|
|
11
|
-
|
|
10
|
+
usePagingAnimator,
|
|
12
11
|
} from './hooks';
|
|
13
12
|
import { createDefaultItemStyle, createDefaultScrollAnimation } from './animation';
|
|
14
13
|
import { InternalContext, RootView, ScrollViewGesture } from './components';
|
|
@@ -34,11 +33,6 @@ const Carousel = forwardRef<CarouselInstance, CarouselProps>(function Carousel(p
|
|
|
34
33
|
|
|
35
34
|
const data = useLoopedData(originalData, loop);
|
|
36
35
|
|
|
37
|
-
const initialTx = itemWidth * initialIndex;
|
|
38
|
-
const offsetX = useRef(new Animated.Value(initialTx)).current;
|
|
39
|
-
const translateX = useRef(new Animated.Value(0)).current;
|
|
40
|
-
const globalInterpolation = Animated.add(offsetX, translateX);
|
|
41
|
-
|
|
42
36
|
const [itemVisibilityStore, onPositionChange] = useItemVisibilityStore({
|
|
43
37
|
initialIndex,
|
|
44
38
|
numberOfData: data.length,
|
|
@@ -57,16 +51,17 @@ const Carousel = forwardRef<CarouselInstance, CarouselProps>(function Carousel(p
|
|
|
57
51
|
const { getCurrentIndex } = indexController;
|
|
58
52
|
|
|
59
53
|
const {
|
|
54
|
+
gestureTranslationX,
|
|
55
|
+
globalInterpolation,
|
|
60
56
|
interruptAnimation,
|
|
61
57
|
startPagingAnimation,
|
|
62
|
-
} =
|
|
58
|
+
} = usePagingAnimator({
|
|
63
59
|
createScrollAnimation,
|
|
64
60
|
itemWidth,
|
|
65
61
|
indexController,
|
|
62
|
+
initialIndex,
|
|
66
63
|
loop,
|
|
67
64
|
numberOfData: data.length,
|
|
68
|
-
offsetX,
|
|
69
|
-
translateX,
|
|
70
65
|
});
|
|
71
66
|
|
|
72
67
|
const autoplayController = useAutoplayController({
|
|
@@ -119,8 +114,8 @@ const Carousel = forwardRef<CarouselInstance, CarouselProps>(function Carousel(p
|
|
|
119
114
|
>
|
|
120
115
|
<ScrollViewGesture
|
|
121
116
|
autoplayController={autoplayController}
|
|
117
|
+
gestureTranslationX={gestureTranslationX}
|
|
122
118
|
interruptAnimation={interruptAnimation}
|
|
123
|
-
translateX={translateX}
|
|
124
119
|
scrollEnabled={scrollEnabled}
|
|
125
120
|
startPagingAnimation={startPagingAnimation}
|
|
126
121
|
>
|
|
@@ -8,8 +8,8 @@ import type { AutoplayController, PagingDirection, StartPagingAnimation } from '
|
|
|
8
8
|
export interface ScrollViewGestureProps {
|
|
9
9
|
autoplayController: AutoplayController;
|
|
10
10
|
children: ReactNode;
|
|
11
|
+
gestureTranslationX: Animated.Value,
|
|
11
12
|
interruptAnimation: () => void;
|
|
12
|
-
translateX: Animated.Value,
|
|
13
13
|
scrollEnabled: boolean;
|
|
14
14
|
startPagingAnimation: StartPagingAnimation;
|
|
15
15
|
}
|
|
@@ -40,7 +40,7 @@ export default function ScrollViewGesture(props: ScrollViewGestureProps) {
|
|
|
40
40
|
autoplayController,
|
|
41
41
|
children,
|
|
42
42
|
interruptAnimation,
|
|
43
|
-
|
|
43
|
+
gestureTranslationX,
|
|
44
44
|
scrollEnabled,
|
|
45
45
|
startPagingAnimation,
|
|
46
46
|
} = props;
|
|
@@ -54,7 +54,7 @@ export default function ScrollViewGesture(props: ScrollViewGestureProps) {
|
|
|
54
54
|
}, [interruptAnimation, pauseAutoplay]);
|
|
55
55
|
|
|
56
56
|
const handleGestureEvent = useCallback(Animated.event(
|
|
57
|
-
[{ nativeEvent: { translationX:
|
|
57
|
+
[{ nativeEvent: { translationX: gestureTranslationX } }],
|
|
58
58
|
{ useNativeDriver: true },
|
|
59
59
|
), []);
|
|
60
60
|
|
|
@@ -68,7 +68,11 @@ export default function ScrollViewGesture(props: ScrollViewGestureProps) {
|
|
|
68
68
|
|
|
69
69
|
startPagingAnimation(
|
|
70
70
|
'directional',
|
|
71
|
-
{
|
|
71
|
+
{
|
|
72
|
+
direction: direction,
|
|
73
|
+
isOriginatedFromGesture: true,
|
|
74
|
+
lastGestureTranslationX: translationX,
|
|
75
|
+
},
|
|
72
76
|
);
|
|
73
77
|
|
|
74
78
|
resumeAutoplay();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as useAutoplayController } from './useAutoplayController';
|
|
2
2
|
export { default as useIndexController } from './useIndexController';
|
|
3
3
|
export { default as useLoopedData } from './useLoopedData';
|
|
4
|
-
export { default as
|
|
4
|
+
export { default as usePagingAnimator } from './usePagingAnimator';
|
|
5
5
|
export { default as useItemVisibilityStore } from './useItemVisibilityStore';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import { useImperativeState } from '@fountain-ui/core';
|
|
3
3
|
import { mod } from '@fountain-ui/utils';
|
|
4
|
-
import type {
|
|
4
|
+
import type { IndexController, ScrollStateChangeEvent } from '../types';
|
|
5
5
|
|
|
6
6
|
export interface UseIndexControllerParameters {
|
|
7
7
|
initialIndex: number;
|
|
@@ -25,41 +25,33 @@ export default function useIndexController(params: UseIndexControllerParameters)
|
|
|
25
25
|
const currentIndex = useImperativeState(initialIndex);
|
|
26
26
|
const currentPosition = useImperativeState(initialIndex);
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
|
|
28
|
+
const notifyScrollStateHasChanged = useCallback(({ offset, state }: ScrollStateChangeEvent) => {
|
|
29
|
+
const normalized = -Math.round(offset / itemWidth);
|
|
30
|
+
const index = Math.floor(mod(normalized, numberOfOriginalData));
|
|
31
|
+
const position = Math.floor(mod(normalized, numberOfData));
|
|
32
|
+
|
|
33
|
+
if (state === 'idle' || state === 'interrupted') {
|
|
30
34
|
if (currentIndex.hasChanged()) {
|
|
31
35
|
onIndexChange?.(currentIndex.get());
|
|
32
36
|
}
|
|
33
|
-
|
|
34
37
|
if (currentPosition.hasChanged()) {
|
|
35
38
|
onPositionChange?.(currentPosition.get());
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
|
-
}, [
|
|
39
|
-
onIndexChange,
|
|
40
|
-
onPositionChange,
|
|
41
|
-
]);
|
|
42
|
-
|
|
43
|
-
const notifyOffsetHasChanged = useCallback((offset: number) => {
|
|
44
|
-
const roundedOffset = Math.round(offset / itemWidth) * itemWidth;
|
|
45
|
-
|
|
46
|
-
// To prevent floating point problem, make sure index is integer type.
|
|
47
|
-
const nextIndex = Math.floor(mod((-roundedOffset / itemWidth), numberOfOriginalData));
|
|
48
|
-
currentIndex.set(nextIndex);
|
|
49
41
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
currentPosition.set(nextPosition);
|
|
42
|
+
currentIndex.set(index);
|
|
43
|
+
currentPosition.set(position);
|
|
53
44
|
}, [
|
|
54
45
|
itemWidth,
|
|
55
46
|
numberOfData,
|
|
56
47
|
numberOfOriginalData,
|
|
48
|
+
onIndexChange,
|
|
49
|
+
onPositionChange,
|
|
57
50
|
]);
|
|
58
51
|
|
|
59
52
|
return {
|
|
60
53
|
getCurrentIndex: currentIndex.get,
|
|
61
54
|
lastIndex: numberOfOriginalData - 1,
|
|
62
|
-
|
|
63
|
-
notifyOffsetHasChanged,
|
|
55
|
+
notifyScrollStateHasChanged,
|
|
64
56
|
};
|
|
65
57
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useRef } from 'react';
|
|
1
|
+
import { useCallback, useMemo, useRef } from 'react';
|
|
2
2
|
import { Animated } from 'react-native';
|
|
3
3
|
import type {
|
|
4
4
|
CreateScrollAnimation,
|
|
@@ -11,17 +11,18 @@ import type {
|
|
|
11
11
|
StartPagingAnimation,
|
|
12
12
|
} from '../types';
|
|
13
13
|
|
|
14
|
-
export interface
|
|
14
|
+
export interface PagingAnimatorConfig {
|
|
15
15
|
createScrollAnimation: CreateScrollAnimation;
|
|
16
16
|
itemWidth: number;
|
|
17
17
|
indexController: IndexController;
|
|
18
|
+
initialIndex: number;
|
|
18
19
|
loop: boolean;
|
|
19
20
|
numberOfData: number;
|
|
20
|
-
offsetX: Animated.Value;
|
|
21
|
-
translateX: Animated.Value;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
export interface
|
|
23
|
+
export interface PagingAnimator {
|
|
24
|
+
gestureTranslationX: Animated.Value;
|
|
25
|
+
globalInterpolation: Animated.AnimatedInterpolation;
|
|
25
26
|
interruptAnimation: () => void;
|
|
26
27
|
startPagingAnimation: StartPagingAnimation;
|
|
27
28
|
}
|
|
@@ -54,24 +55,34 @@ function toValueCompensator(itemWidth: number) {
|
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
export default function
|
|
58
|
+
export default function usePagingAnimator(config: PagingAnimatorConfig): PagingAnimator {
|
|
58
59
|
const {
|
|
59
60
|
createScrollAnimation,
|
|
60
61
|
itemWidth,
|
|
61
62
|
indexController,
|
|
63
|
+
initialIndex,
|
|
62
64
|
loop,
|
|
63
65
|
numberOfData,
|
|
64
|
-
|
|
65
|
-
translateX,
|
|
66
|
-
} = params;
|
|
66
|
+
} = config;
|
|
67
67
|
|
|
68
68
|
const {
|
|
69
69
|
getCurrentIndex,
|
|
70
70
|
lastIndex,
|
|
71
|
-
|
|
72
|
-
notifyOffsetHasChanged,
|
|
71
|
+
notifyScrollStateHasChanged,
|
|
73
72
|
} = indexController;
|
|
74
73
|
|
|
74
|
+
const initialOffsetX = itemWidth * initialIndex;
|
|
75
|
+
const accumulativeOffsetX = useRef(new Animated.Value(initialOffsetX)).current;
|
|
76
|
+
const animationOffsetX = useRef(new Animated.Value(0)).current;
|
|
77
|
+
const gestureTranslationX = useRef(new Animated.Value(0)).current;
|
|
78
|
+
|
|
79
|
+
const globalInterpolation = useMemo(() => {
|
|
80
|
+
return Animated.add(
|
|
81
|
+
Animated.add(accumulativeOffsetX, animationOffsetX),
|
|
82
|
+
gestureTranslationX,
|
|
83
|
+
);
|
|
84
|
+
}, []);
|
|
85
|
+
|
|
75
86
|
const toValueRef = useRef<number>(0);
|
|
76
87
|
const currentOffsetRef = useRef<number>(0);
|
|
77
88
|
|
|
@@ -95,14 +106,12 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
|
|
|
95
106
|
const nextOffset = ensureOffsetBoundary(newOffset);
|
|
96
107
|
|
|
97
108
|
currentOffsetRef.current = nextOffset;
|
|
98
|
-
|
|
109
|
+
accumulativeOffsetX.setValue(nextOffset);
|
|
99
110
|
|
|
100
111
|
toValueRef.current = 0;
|
|
101
|
-
|
|
112
|
+
animationOffsetX.setValue(0);
|
|
102
113
|
}, [
|
|
103
114
|
ensureOffsetBoundary,
|
|
104
|
-
offsetX,
|
|
105
|
-
translateX,
|
|
106
115
|
]);
|
|
107
116
|
|
|
108
117
|
const interruptAnimation = useCallback(() => {
|
|
@@ -110,22 +119,22 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
|
|
|
110
119
|
return;
|
|
111
120
|
}
|
|
112
121
|
|
|
113
|
-
|
|
122
|
+
animationOffsetX.stopAnimation(lastValue => {
|
|
114
123
|
isAnimatingRef.current = false;
|
|
115
124
|
|
|
116
125
|
const prevOffset = currentOffsetRef.current;
|
|
117
126
|
const totalOffset = prevOffset + lastValue;
|
|
118
127
|
|
|
119
|
-
notifyOffsetHasChanged(totalOffset);
|
|
120
|
-
notifyAnimationState('interrupted');
|
|
121
|
-
|
|
122
128
|
requireNewOffset(totalOffset);
|
|
129
|
+
|
|
130
|
+
notifyScrollStateHasChanged({ offset: totalOffset, state: 'interrupted' });
|
|
123
131
|
});
|
|
124
|
-
}, [
|
|
132
|
+
}, [
|
|
133
|
+
notifyScrollStateHasChanged,
|
|
134
|
+
requireNewOffset,
|
|
135
|
+
]);
|
|
125
136
|
|
|
126
137
|
const finalizeAnimation = useCallback(() => {
|
|
127
|
-
notifyAnimationState('finished');
|
|
128
|
-
|
|
129
138
|
isAnimatingRef.current = false;
|
|
130
139
|
|
|
131
140
|
const prevOffset = currentOffsetRef.current;
|
|
@@ -133,8 +142,10 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
|
|
|
133
142
|
const totalOffset = prevOffset + toValue;
|
|
134
143
|
|
|
135
144
|
requireNewOffset(totalOffset);
|
|
145
|
+
|
|
146
|
+
notifyScrollStateHasChanged({ offset: totalOffset, state: 'idle' });
|
|
136
147
|
}, [
|
|
137
|
-
|
|
148
|
+
notifyScrollStateHasChanged,
|
|
138
149
|
requireNewOffset,
|
|
139
150
|
]);
|
|
140
151
|
|
|
@@ -202,18 +213,25 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
|
|
|
202
213
|
toValueRef.current = toValue;
|
|
203
214
|
isAnimatingRef.current = true;
|
|
204
215
|
|
|
205
|
-
|
|
216
|
+
notifyScrollStateHasChanged({
|
|
217
|
+
offset: currentOffsetRef.current + toValue,
|
|
218
|
+
state: 'dragging',
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const lastGestureTranslationX: number = configWithDefaults.lastGestureTranslationX ?? 0;
|
|
222
|
+
if (Number.isFinite(lastGestureTranslationX)) {
|
|
223
|
+
animationOffsetX.setValue(lastGestureTranslationX);
|
|
224
|
+
gestureTranslationX.setValue(0);
|
|
225
|
+
}
|
|
206
226
|
|
|
207
227
|
if (configWithDefaults.animated) {
|
|
208
|
-
const animation = createScrollAnimation(
|
|
228
|
+
const animation = createScrollAnimation(animationOffsetX, toValue);
|
|
209
229
|
|
|
210
230
|
animation.start(({ finished }) => {
|
|
211
231
|
if (finished) {
|
|
212
232
|
finalizeAnimation();
|
|
213
233
|
}
|
|
214
234
|
});
|
|
215
|
-
|
|
216
|
-
notifyAnimationState('started');
|
|
217
235
|
} else {
|
|
218
236
|
finalizeAnimation();
|
|
219
237
|
}
|
|
@@ -224,11 +242,12 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
|
|
|
224
242
|
itemWidth,
|
|
225
243
|
lastIndex,
|
|
226
244
|
loop,
|
|
227
|
-
|
|
228
|
-
notifyOffsetHasChanged,
|
|
245
|
+
notifyScrollStateHasChanged,
|
|
229
246
|
]);
|
|
230
247
|
|
|
231
248
|
return {
|
|
249
|
+
gestureTranslationX,
|
|
250
|
+
globalInterpolation,
|
|
232
251
|
interruptAnimation,
|
|
233
252
|
startPagingAnimation,
|
|
234
253
|
};
|
package/src/Carousel/types.ts
CHANGED
|
@@ -5,9 +5,9 @@ const directions = ['next', 'prev', 'stay'] as const;
|
|
|
5
5
|
|
|
6
6
|
export type PagingDirection = (typeof directions)[number];
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const scrollStates = ['idle', 'dragging', 'interrupted'] as const;
|
|
9
9
|
|
|
10
|
-
export type
|
|
10
|
+
export type ScrollState = (typeof scrollStates)[number];
|
|
11
11
|
|
|
12
12
|
export type ItemHeight = number | 'auto';
|
|
13
13
|
|
|
@@ -35,17 +35,22 @@ export interface OnPositionChange {
|
|
|
35
35
|
(position: number): void;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export interface ScrollStateChangeEvent {
|
|
39
|
+
offset: number;
|
|
40
|
+
state: ScrollState;
|
|
41
|
+
}
|
|
42
|
+
|
|
38
43
|
export interface IndexController {
|
|
39
44
|
getCurrentIndex: GetCurrentIndex;
|
|
40
45
|
lastIndex: number;
|
|
41
|
-
|
|
42
|
-
notifyOffsetHasChanged: (offset: number) => void;
|
|
46
|
+
notifyScrollStateHasChanged: (event: ScrollStateChangeEvent) => void;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
export type PagingAnimationType = 'directional' | 'index';
|
|
46
50
|
|
|
47
51
|
export interface BasePagingAnimationConfig {
|
|
48
52
|
animated?: boolean;
|
|
53
|
+
lastGestureTranslationX?: number;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
export interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Children, forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
|
|
1
|
+
import React, { Children, forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
|
2
2
|
import type { ViewPagerOnPageSelectedEvent } from 'react-native-pager-view';
|
|
3
3
|
import RNViewPager from 'react-native-pager-view';
|
|
4
4
|
import { useSyncAnimatedValue } from '@fountain-ui/core';
|
|
@@ -117,10 +117,12 @@ const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPag
|
|
|
117
117
|
|
|
118
118
|
const pageStore = usePageStore(sharedPage);
|
|
119
119
|
|
|
120
|
+
const contextValue = useMemo(() => ({ pageStore }), [pageStore]);
|
|
121
|
+
|
|
120
122
|
const PageComponent = pageComponent;
|
|
121
123
|
|
|
122
124
|
return (
|
|
123
|
-
<InternalContext.Provider value={
|
|
125
|
+
<InternalContext.Provider value={contextValue}>
|
|
124
126
|
<RNViewPager
|
|
125
127
|
ref={pagerRef}
|
|
126
128
|
initialPage={sharedPage.initialValue}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Children, forwardRef, useCallback, useImperativeHandle } from 'react';
|
|
1
|
+
import React, { Children, forwardRef, useCallback, useImperativeHandle, useMemo } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { StyleSheet, useSyncAnimatedValue } from '@fountain-ui/core';
|
|
4
4
|
import type ViewPagerProps from './ViewPagerProps';
|
|
@@ -42,10 +42,12 @@ const ViewPager = forwardRef<ViewPagerInstance, ViewPagerProps>(function ViewPag
|
|
|
42
42
|
|
|
43
43
|
const pageStore = usePageStore(sharedPage);
|
|
44
44
|
|
|
45
|
+
const contextValue = useMemo(() => ({ pageStore }), [pageStore]);
|
|
46
|
+
|
|
45
47
|
const PageComponent = pageComponent;
|
|
46
48
|
|
|
47
49
|
return (
|
|
48
|
-
<InternalContext.Provider value={
|
|
50
|
+
<InternalContext.Provider value={contextValue}>
|
|
49
51
|
<View style={[styles.root, style]}>
|
|
50
52
|
{Children.map(children, (child, index) => (
|
|
51
53
|
<PageComponent
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["directionToValue","itemWidth","direction","toValueCompensator","toValue","currentOffset","remainder","Math","abs","halfOfItemWidth","compensateVector","usePagingAnimation","params","createScrollAnimation","indexController","loop","numberOfData","offsetX","translateX","getCurrentIndex","lastIndex","notifyAnimationState","notifyOffsetHasChanged","toValueRef","useRef","currentOffsetRef","isAnimatingRef","maxWidth","ensureOffsetBoundary","useCallback","offset","isCloseToEnd","signOfOffset","requireNewOffset","newOffset","nextOffset","current","setValue","interruptAnimation","stopAnimation","lastValue","prevOffset","totalOffset","finalizeAnimation","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","compensateToValue","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","wantedToValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { Animated } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n IndexController,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n createScrollAnimation: CreateScrollAnimation;\n itemWidth: number;\n indexController: IndexController;\n loop: boolean;\n numberOfData: number;\n offsetX: Animated.Value;\n translateX: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n interruptAnimation: () => void;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nfunction toValueCompensator(itemWidth: number) {\n return function (toValue: number, currentOffset: number): number {\n const remainder = Math.abs(currentOffset % itemWidth);\n\n const halfOfItemWidth = Math.abs(itemWidth / 2);\n const compensateVector = remainder > halfOfItemWidth\n ? remainder - itemWidth\n : remainder;\n\n const direction = currentOffset > 0 ? -1 : 1;\n\n return toValue + (direction * compensateVector);\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n createScrollAnimation,\n itemWidth,\n indexController,\n loop,\n numberOfData,\n offsetX,\n translateX,\n } = params;\n\n const {\n getCurrentIndex,\n lastIndex,\n notifyAnimationState,\n notifyOffsetHasChanged,\n } = indexController;\n\n const toValueRef = useRef<number>(0);\n const currentOffsetRef = useRef<number>(0);\n\n const isAnimatingRef = useRef<boolean>(false);\n\n const maxWidth = Math.abs(numberOfData * itemWidth);\n\n const ensureOffsetBoundary: (offset: number) => number = useCallback((offset: number) => {\n if (loop) {\n const isCloseToEnd = Math.abs(offset) >= (maxWidth - itemWidth);\n if (isCloseToEnd) {\n const signOfOffset = offset > 0 ? 1 : -1;\n return offset + (-signOfOffset * maxWidth);\n }\n }\n\n return offset % maxWidth;\n }, [itemWidth, loop, maxWidth]);\n\n const requireNewOffset = useCallback((newOffset: number) => {\n const nextOffset = ensureOffsetBoundary(newOffset);\n\n currentOffsetRef.current = nextOffset;\n offsetX.setValue(nextOffset);\n\n toValueRef.current = 0;\n translateX.setValue(0);\n }, [\n ensureOffsetBoundary,\n offsetX,\n translateX,\n ]);\n\n const interruptAnimation = useCallback(() => {\n if (!isAnimatingRef.current) {\n return;\n }\n\n translateX.stopAnimation(lastValue => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const totalOffset = prevOffset + lastValue;\n\n notifyOffsetHasChanged(totalOffset);\n notifyAnimationState('interrupted');\n\n requireNewOffset(totalOffset);\n });\n }, [requireNewOffset, translateX]);\n\n const finalizeAnimation = useCallback(() => {\n notifyAnimationState('finished');\n\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const toValue = toValueRef.current;\n const totalOffset = prevOffset + toValue;\n\n requireNewOffset(totalOffset);\n }, [\n notifyAnimationState,\n requireNewOffset,\n ]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n if (isAnimatingRef.current) {\n return;\n }\n\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n const compensateToValue = toValueCompensator(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const wantedToValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);\n\n toValueRef.current = toValue;\n isAnimatingRef.current = true;\n\n notifyOffsetHasChanged(currentOffsetRef.current + toValue);\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(translateX, toValue);\n\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n\n notifyAnimationState('started');\n } else {\n finalizeAnimation();\n }\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n notifyAnimationState,\n notifyOffsetHasChanged,\n ]);\n\n return {\n interruptAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useRef","directionToValue","itemWidth","direction","toValueCompensator","toValue","currentOffset","remainder","Math","abs","halfOfItemWidth","compensateVector","usePagingAnimation","params","createScrollAnimation","indexController","loop","numberOfData","offsetX","translateX","getCurrentIndex","lastIndex","notifyAnimationState","notifyOffsetHasChanged","toValueRef","currentOffsetRef","isAnimatingRef","maxWidth","ensureOffsetBoundary","offset","isCloseToEnd","signOfOffset","requireNewOffset","newOffset","nextOffset","current","setValue","interruptAnimation","stopAnimation","lastValue","prevOffset","totalOffset","finalizeAnimation","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","compensateToValue","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","wantedToValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { Animated } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n IndexController,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n createScrollAnimation: CreateScrollAnimation;\n itemWidth: number;\n indexController: IndexController;\n loop: boolean;\n numberOfData: number;\n offsetX: Animated.Value;\n translateX: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n interruptAnimation: () => void;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nfunction toValueCompensator(itemWidth: number) {\n return function (toValue: number, currentOffset: number): number {\n const remainder = Math.abs(currentOffset % itemWidth);\n\n const halfOfItemWidth = Math.abs(itemWidth / 2);\n const compensateVector = remainder > halfOfItemWidth\n ? remainder - itemWidth\n : remainder;\n\n const direction = currentOffset > 0 ? -1 : 1;\n\n return toValue + (direction * compensateVector);\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n createScrollAnimation,\n itemWidth,\n indexController,\n loop,\n numberOfData,\n offsetX,\n translateX,\n } = params;\n\n const {\n getCurrentIndex,\n lastIndex,\n notifyAnimationState,\n notifyOffsetHasChanged,\n } = indexController;\n\n const toValueRef = useRef<number>(0);\n const currentOffsetRef = useRef<number>(0);\n\n const isAnimatingRef = useRef<boolean>(false);\n\n const maxWidth = Math.abs(numberOfData * itemWidth);\n\n const ensureOffsetBoundary: (offset: number) => number = useCallback((offset: number) => {\n if (loop) {\n const isCloseToEnd = Math.abs(offset) >= (maxWidth - itemWidth);\n if (isCloseToEnd) {\n const signOfOffset = offset > 0 ? 1 : -1;\n return offset + (-signOfOffset * maxWidth);\n }\n }\n\n return offset % maxWidth;\n }, [itemWidth, loop, maxWidth]);\n\n const requireNewOffset = useCallback((newOffset: number) => {\n const nextOffset = ensureOffsetBoundary(newOffset);\n\n currentOffsetRef.current = nextOffset;\n offsetX.setValue(nextOffset);\n\n toValueRef.current = 0;\n translateX.setValue(0);\n }, [\n ensureOffsetBoundary,\n offsetX,\n translateX,\n ]);\n\n const interruptAnimation = useCallback(() => {\n if (!isAnimatingRef.current) {\n return;\n }\n\n translateX.stopAnimation(lastValue => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const totalOffset = prevOffset + lastValue;\n\n notifyOffsetHasChanged(totalOffset);\n notifyAnimationState('interrupted');\n\n requireNewOffset(totalOffset);\n });\n }, [requireNewOffset, translateX]);\n\n const finalizeAnimation = useCallback(() => {\n notifyAnimationState('finished');\n\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const toValue = toValueRef.current;\n const totalOffset = prevOffset + toValue;\n\n requireNewOffset(totalOffset);\n }, [\n notifyAnimationState,\n requireNewOffset,\n ]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n if (isAnimatingRef.current) {\n return;\n }\n\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n const compensateToValue = toValueCompensator(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const wantedToValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);\n\n toValueRef.current = toValue;\n isAnimatingRef.current = true;\n\n notifyOffsetHasChanged(currentOffsetRef.current + toValue);\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(translateX, toValue);\n\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n\n notifyAnimationState('started');\n } else {\n finalizeAnimation();\n }\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n notifyAnimationState,\n notifyOffsetHasChanged,\n ]);\n\n return {\n interruptAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
|