react-navigation-reanimated-top-tabs 0.8.0 → 0.9.0
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/lib/commonjs/components/ReanimatedTopTab/AnimationHelper.js +20 -25
- package/lib/commonjs/components/ReanimatedTopTab/AnimationHelper.js.map +1 -1
- package/lib/commonjs/components/ReanimatedTopTab/ReanimatedTabView.js +9 -10
- package/lib/commonjs/components/ReanimatedTopTab/ReanimatedTabView.js.map +1 -1
- package/lib/commonjs/components/ReanimatedTopTab/types.js.map +1 -1
- package/lib/commonjs/components/elements/TabBarBaseComponent.js +2 -10
- package/lib/commonjs/components/elements/TabBarBaseComponent.js.map +1 -1
- package/lib/commonjs/components/elements/TabBarBaseItem.js +6 -3
- package/lib/commonjs/components/elements/TabBarBaseItem.js.map +1 -1
- package/lib/commonjs/components/elements/TabBarLabelBaseComponent.js +3 -3
- package/lib/commonjs/components/elements/TabBarLabelBaseComponent.js.map +1 -1
- package/lib/commonjs/components/wrappers/GestureWrapper.js +27 -8
- package/lib/commonjs/components/wrappers/GestureWrapper.js.map +1 -1
- package/lib/commonjs/context/Context.hooks.js +12 -10
- package/lib/commonjs/context/Context.hooks.js.map +1 -1
- package/lib/commonjs/context/Context.js +11 -8
- package/lib/commonjs/context/Context.js.map +1 -1
- package/lib/commonjs/hooks/useHeader.js +2 -2
- package/lib/commonjs/hooks/useHeader.js.map +1 -1
- package/lib/commonjs/hooks/useTabOffset.js +2 -2
- package/lib/commonjs/hooks/useTabOffset.js.map +1 -1
- package/lib/commonjs/navigator/createReanimatedTopTabNavigator.js +3 -1
- package/lib/commonjs/navigator/createReanimatedTopTabNavigator.js.map +1 -1
- package/lib/module/components/ReanimatedTopTab/AnimationHelper.js +20 -25
- package/lib/module/components/ReanimatedTopTab/AnimationHelper.js.map +1 -1
- package/lib/module/components/ReanimatedTopTab/ReanimatedTabView.js +10 -11
- package/lib/module/components/ReanimatedTopTab/ReanimatedTabView.js.map +1 -1
- package/lib/module/components/ReanimatedTopTab/types.js.map +1 -1
- package/lib/module/components/elements/TabBarBaseComponent.js +4 -12
- package/lib/module/components/elements/TabBarBaseComponent.js.map +1 -1
- package/lib/module/components/elements/TabBarBaseItem.js +7 -4
- package/lib/module/components/elements/TabBarBaseItem.js.map +1 -1
- package/lib/module/components/elements/TabBarLabelBaseComponent.js +3 -3
- package/lib/module/components/elements/TabBarLabelBaseComponent.js.map +1 -1
- package/lib/module/components/wrappers/GestureWrapper.js +29 -10
- package/lib/module/components/wrappers/GestureWrapper.js.map +1 -1
- package/lib/module/context/Context.hooks.js +12 -10
- package/lib/module/context/Context.hooks.js.map +1 -1
- package/lib/module/context/Context.js +11 -8
- package/lib/module/context/Context.js.map +1 -1
- package/lib/module/hooks/useHeader.js +2 -2
- package/lib/module/hooks/useHeader.js.map +1 -1
- package/lib/module/hooks/useTabOffset.js +2 -2
- package/lib/module/hooks/useTabOffset.js.map +1 -1
- package/lib/module/navigator/createReanimatedTopTabNavigator.js +3 -1
- package/lib/module/navigator/createReanimatedTopTabNavigator.js.map +1 -1
- package/lib/typescript/src/components/ReanimatedTopTab/AnimationHelper.d.ts.map +1 -1
- package/lib/typescript/src/components/ReanimatedTopTab/ReanimatedTabView.d.ts +0 -1
- package/lib/typescript/src/components/ReanimatedTopTab/ReanimatedTabView.d.ts.map +1 -1
- package/lib/typescript/src/components/ReanimatedTopTab/types.d.ts +0 -6
- package/lib/typescript/src/components/ReanimatedTopTab/types.d.ts.map +1 -1
- package/lib/typescript/src/components/elements/TabBarBaseComponent.d.ts +1 -1
- package/lib/typescript/src/components/elements/TabBarBaseComponent.d.ts.map +1 -1
- package/lib/typescript/src/components/elements/TabBarBaseItem.d.ts +1 -3
- package/lib/typescript/src/components/elements/TabBarBaseItem.d.ts.map +1 -1
- package/lib/typescript/src/components/wrappers/GestureWrapper.d.ts +2 -1
- package/lib/typescript/src/components/wrappers/GestureWrapper.d.ts.map +1 -1
- package/lib/typescript/src/context/Context.d.ts.map +1 -1
- package/lib/typescript/src/context/Context.hooks.d.ts +4 -3
- package/lib/typescript/src/context/Context.hooks.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/navigator/createReanimatedTopTabNavigator.d.ts +1 -1
- package/lib/typescript/src/navigator/createReanimatedTopTabNavigator.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +3 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ReanimatedTopTab/AnimationHelper.ts +21 -29
- package/src/components/ReanimatedTopTab/ReanimatedTabView.tsx +15 -17
- package/src/components/ReanimatedTopTab/types.ts +0 -4
- package/src/components/elements/TabBarBaseComponent.tsx +3 -26
- package/src/components/elements/TabBarBaseItem.tsx +6 -6
- package/src/components/elements/TabBarLabelBaseComponent.tsx +3 -3
- package/src/components/wrappers/GestureWrapper.tsx +31 -14
- package/src/context/Context.hooks.ts +13 -11
- package/src/context/Context.tsx +8 -5
- package/src/hooks/useHeader.ts +2 -2
- package/src/hooks/useTabOffset.ts +2 -2
- package/src/navigator/createReanimatedTopTabNavigator.tsx +2 -1
- package/src/types.ts +3 -1
|
@@ -6,16 +6,16 @@ import {
|
|
|
6
6
|
GestureHandlerRootView,
|
|
7
7
|
} from 'react-native-gesture-handler';
|
|
8
8
|
import Reanimated, {
|
|
9
|
-
Extrapolation,
|
|
10
9
|
interpolate,
|
|
11
10
|
LinearTransition,
|
|
12
11
|
runOnJS,
|
|
13
12
|
runOnUI,
|
|
13
|
+
useAnimatedReaction,
|
|
14
14
|
useAnimatedStyle,
|
|
15
|
-
useDerivedValue,
|
|
16
15
|
useSharedValue,
|
|
17
16
|
} from 'react-native-reanimated';
|
|
18
17
|
import type { ReanimatedTopTabNavigation } from 'react-navigation-reanimated-top-tabs';
|
|
18
|
+
import { useTabContext } from '../../hooks/useTabContext';
|
|
19
19
|
import { AnimationHelper } from './AnimationHelper';
|
|
20
20
|
import type { ReanimatedTabViewTypes } from './types';
|
|
21
21
|
|
|
@@ -24,7 +24,6 @@ export interface ReanimatedTabViewProps {
|
|
|
24
24
|
lazy?: boolean;
|
|
25
25
|
navigationState: ReanimatedTabViewTypes.NavigationState;
|
|
26
26
|
percentageTrigger?: number;
|
|
27
|
-
positionInterpolation?: ReanimatedTabViewTypes.PositionInterpolation;
|
|
28
27
|
renderScene: (params: ReanimatedTabViewTypes.SceneProps) => React.ReactNode;
|
|
29
28
|
renderTabBar?: (
|
|
30
29
|
params: ReanimatedTabViewTypes.RenderTabsParams
|
|
@@ -39,7 +38,6 @@ export const ReanimatedTabView = React.memo<ReanimatedTabViewProps>(
|
|
|
39
38
|
lazy = false,
|
|
40
39
|
navigationState,
|
|
41
40
|
percentageTrigger = 0.4,
|
|
42
|
-
positionInterpolation,
|
|
43
41
|
renderScene,
|
|
44
42
|
renderTabBar,
|
|
45
43
|
navigate,
|
|
@@ -50,18 +48,19 @@ export const ReanimatedTabView = React.memo<ReanimatedTabViewProps>(
|
|
|
50
48
|
navigationState.routes[navigationState.index],
|
|
51
49
|
]);
|
|
52
50
|
const scrollPosition = useSharedValue(navigationState.index);
|
|
51
|
+
const { positionX } = useTabContext();
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
useAnimatedReaction(
|
|
54
|
+
() => scrollPosition.value,
|
|
55
|
+
(value) => {
|
|
56
|
+
positionX.value = interpolate(
|
|
57
|
+
value,
|
|
58
|
+
navigationState.routes.map((_, i) => i * -width),
|
|
59
|
+
navigationState.routes.map((_, i) => i),
|
|
60
|
+
'clamp'
|
|
61
|
+
);
|
|
57
62
|
}
|
|
58
|
-
|
|
59
|
-
-scrollPosition.value,
|
|
60
|
-
positionInterpolation.input,
|
|
61
|
-
positionInterpolation.output,
|
|
62
|
-
Extrapolation.CLAMP
|
|
63
|
-
);
|
|
64
|
-
}, [positionInterpolation]);
|
|
63
|
+
);
|
|
65
64
|
|
|
66
65
|
const _navigate = (index: number) => {
|
|
67
66
|
scrollPosition.value = AnimationHelper.animation(-index * width);
|
|
@@ -108,7 +107,7 @@ export const ReanimatedTabView = React.memo<ReanimatedTabViewProps>(
|
|
|
108
107
|
_navigationState.value.index = state.index;
|
|
109
108
|
runOnJS(navigate)(state.index);
|
|
110
109
|
}),
|
|
111
|
-
[minimumValueToChangeView, width
|
|
110
|
+
[minimumValueToChangeView, width]
|
|
112
111
|
);
|
|
113
112
|
|
|
114
113
|
const scrollPositionStyle = useAnimatedStyle(() => ({
|
|
@@ -118,7 +117,7 @@ export const ReanimatedTabView = React.memo<ReanimatedTabViewProps>(
|
|
|
118
117
|
scrollPosition.value,
|
|
119
118
|
[-width * (navigationState.routes.length - 1), 0],
|
|
120
119
|
[-width * (navigationState.routes.length - 1), 0],
|
|
121
|
-
|
|
120
|
+
'clamp'
|
|
122
121
|
),
|
|
123
122
|
},
|
|
124
123
|
],
|
|
@@ -179,7 +178,6 @@ export const ReanimatedTabView = React.memo<ReanimatedTabViewProps>(
|
|
|
179
178
|
{renderTabBar
|
|
180
179
|
? renderTabBar({
|
|
181
180
|
navigationState,
|
|
182
|
-
position,
|
|
183
181
|
navigate: _navigate,
|
|
184
182
|
screenOptions,
|
|
185
183
|
})
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { SharedValue } from 'react-native-reanimated';
|
|
3
2
|
import type { ReanimatedTopTabNavigation } from 'react-navigation-reanimated-top-tabs';
|
|
4
3
|
|
|
5
4
|
export namespace ReanimatedTabViewTypes {
|
|
@@ -14,7 +13,6 @@ export namespace ReanimatedTabViewTypes {
|
|
|
14
13
|
|
|
15
14
|
export interface RenderTabsParams {
|
|
16
15
|
navigationState: NavigationState;
|
|
17
|
-
position: SharedValue<number>;
|
|
18
16
|
navigate(index: number): void;
|
|
19
17
|
screenOptions?: ReanimatedTopTabNavigation.NavigationOptions;
|
|
20
18
|
}
|
|
@@ -23,6 +21,4 @@ export namespace ReanimatedTabViewTypes {
|
|
|
23
21
|
jumpTo?: (key: string) => void;
|
|
24
22
|
route: Route;
|
|
25
23
|
}
|
|
26
|
-
|
|
27
|
-
export type PositionInterpolation = { input: number[]; output: number[] };
|
|
28
24
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { StyleSheet
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
3
|
import Reanimated, {
|
|
4
4
|
interpolate,
|
|
5
|
-
useAnimatedReaction,
|
|
6
5
|
useAnimatedStyle,
|
|
7
6
|
useSharedValue,
|
|
8
7
|
type AnimatedStyle,
|
|
@@ -20,13 +19,11 @@ export interface TabBarProps extends ReanimatedTabViewTypes.RenderTabsParams {
|
|
|
20
19
|
export const TabBarBaseComponent = ({
|
|
21
20
|
children,
|
|
22
21
|
navigationState,
|
|
23
|
-
position,
|
|
24
22
|
style,
|
|
25
23
|
navigate,
|
|
26
24
|
screenOptions,
|
|
27
25
|
}: TabBarProps) => {
|
|
28
|
-
const
|
|
29
|
-
const { topTabHeight, transformationX } = useTabContext();
|
|
26
|
+
const { topTabHeight, positionX } = useTabContext();
|
|
30
27
|
const width = useSharedValue(0);
|
|
31
28
|
|
|
32
29
|
const { tabBarIndicatorStyle, tabBarItemStyle, tabBarStyle } =
|
|
@@ -42,32 +39,13 @@ export const TabBarBaseComponent = ({
|
|
|
42
39
|
return {
|
|
43
40
|
transform: [
|
|
44
41
|
{
|
|
45
|
-
translateX: interpolate(
|
|
46
|
-
transformationX.value,
|
|
47
|
-
inputRange,
|
|
48
|
-
outputRange
|
|
49
|
-
),
|
|
42
|
+
translateX: interpolate(positionX.value, inputRange, outputRange),
|
|
50
43
|
},
|
|
51
44
|
],
|
|
52
45
|
width: width.value / navigationState.routes.length,
|
|
53
46
|
};
|
|
54
47
|
});
|
|
55
48
|
|
|
56
|
-
//Assign interpolated offsetX to transformationX
|
|
57
|
-
useAnimatedReaction(
|
|
58
|
-
() =>
|
|
59
|
-
interpolate(
|
|
60
|
-
position.value,
|
|
61
|
-
navigationState.routes.map((_, i) => i * layout.width),
|
|
62
|
-
navigationState.routes.map((_, i) => i),
|
|
63
|
-
'clamp'
|
|
64
|
-
),
|
|
65
|
-
(value) => {
|
|
66
|
-
transformationX.value = value;
|
|
67
|
-
},
|
|
68
|
-
[navigationState.routes]
|
|
69
|
-
);
|
|
70
|
-
|
|
71
49
|
return (
|
|
72
50
|
<Reanimated.View
|
|
73
51
|
onLayout={({ nativeEvent }) => {
|
|
@@ -87,7 +65,6 @@ export const TabBarBaseComponent = ({
|
|
|
87
65
|
<TabBarBaseItem
|
|
88
66
|
index={index}
|
|
89
67
|
inputRange={inputRange}
|
|
90
|
-
position={transformationX}
|
|
91
68
|
key={route.key}
|
|
92
69
|
onPress={() => {
|
|
93
70
|
navigate(index);
|
|
@@ -6,14 +6,13 @@ import {
|
|
|
6
6
|
type ViewStyle,
|
|
7
7
|
} from 'react-native';
|
|
8
8
|
import Animated, {
|
|
9
|
-
type SharedValue,
|
|
10
|
-
useAnimatedStyle,
|
|
11
9
|
interpolate,
|
|
10
|
+
useAnimatedStyle,
|
|
12
11
|
} from 'react-native-reanimated';
|
|
12
|
+
import { useTabContext } from '../../hooks/useTabContext';
|
|
13
13
|
import { type ReanimatedTabViewTypes } from '../ReanimatedTopTab/types';
|
|
14
14
|
|
|
15
15
|
interface TabBarBaseItemProps {
|
|
16
|
-
position: SharedValue<number>;
|
|
17
16
|
index: number;
|
|
18
17
|
inputRange: Array<number>;
|
|
19
18
|
onPress: (index: number) => void;
|
|
@@ -22,16 +21,17 @@ interface TabBarBaseItemProps {
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
export const TabBarBaseItem = ({
|
|
25
|
-
position,
|
|
26
24
|
index,
|
|
27
25
|
inputRange,
|
|
28
26
|
onPress,
|
|
29
27
|
route,
|
|
30
28
|
style,
|
|
31
29
|
}: TabBarBaseItemProps) => {
|
|
30
|
+
const { positionX } = useTabContext();
|
|
31
|
+
|
|
32
32
|
const activeStyle = useAnimatedStyle(() => ({
|
|
33
33
|
opacity: interpolate(
|
|
34
|
-
|
|
34
|
+
positionX.value,
|
|
35
35
|
inputRange,
|
|
36
36
|
inputRange.map((i) => (i === index ? 1 : 0))
|
|
37
37
|
),
|
|
@@ -40,7 +40,7 @@ export const TabBarBaseItem = ({
|
|
|
40
40
|
|
|
41
41
|
const inactiveStyle = useAnimatedStyle(() => ({
|
|
42
42
|
opacity: interpolate(
|
|
43
|
-
|
|
43
|
+
positionX.value,
|
|
44
44
|
inputRange,
|
|
45
45
|
inputRange.map((i) => (i === index ? 0 : 1))
|
|
46
46
|
),
|
|
@@ -16,12 +16,12 @@ export const TabBarLabelBaseComponent = ({
|
|
|
16
16
|
index,
|
|
17
17
|
...props
|
|
18
18
|
}: TabBarLabelTypes) => {
|
|
19
|
-
const
|
|
19
|
+
const positionX = useTabOffset();
|
|
20
20
|
|
|
21
21
|
const style = useAnimatedStyle(
|
|
22
22
|
() => ({
|
|
23
23
|
backgroundColor: interpolateColor(
|
|
24
|
-
|
|
24
|
+
positionX.value,
|
|
25
25
|
[index - 1, index, index + 1],
|
|
26
26
|
['transparent', 'blue', 'transparent']
|
|
27
27
|
),
|
|
@@ -32,7 +32,7 @@ export const TabBarLabelBaseComponent = ({
|
|
|
32
32
|
const textStyle = useAnimatedStyle(
|
|
33
33
|
() => ({
|
|
34
34
|
color: interpolateColor(
|
|
35
|
-
|
|
35
|
+
positionX.value,
|
|
36
36
|
[index - 1, index, index + 1],
|
|
37
37
|
['black', 'white', 'black']
|
|
38
38
|
),
|
|
@@ -2,7 +2,6 @@ import React, { useMemo, useRef, useState } from 'react';
|
|
|
2
2
|
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
3
3
|
import Reanimated, {
|
|
4
4
|
Easing,
|
|
5
|
-
interpolate,
|
|
6
5
|
runOnJS,
|
|
7
6
|
useAnimatedReaction,
|
|
8
7
|
useAnimatedStyle,
|
|
@@ -12,13 +11,19 @@ import Reanimated, {
|
|
|
12
11
|
} from 'react-native-reanimated';
|
|
13
12
|
|
|
14
13
|
import { useTabContext } from '../../hooks/useTabContext';
|
|
15
|
-
import { StyleSheet, View } from 'react-native';
|
|
14
|
+
import { Platform, StyleSheet, View } from 'react-native';
|
|
16
15
|
|
|
17
16
|
interface GestureWrapperProps {
|
|
18
17
|
children: React.ReactNode;
|
|
18
|
+
bounces?: boolean;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const GestureWrapper = ({ children }: GestureWrapperProps) => {
|
|
21
|
+
export const GestureWrapper = ({ children, bounces }: GestureWrapperProps) => {
|
|
22
|
+
const _bounces = Platform.select({
|
|
23
|
+
ios: bounces,
|
|
24
|
+
default: false,
|
|
25
|
+
});
|
|
26
|
+
|
|
22
27
|
const {
|
|
23
28
|
context,
|
|
24
29
|
currentScreenIndex,
|
|
@@ -26,6 +31,7 @@ export const GestureWrapper = ({ children }: GestureWrapperProps) => {
|
|
|
26
31
|
gestureEnabled,
|
|
27
32
|
headerHeight,
|
|
28
33
|
transformationY,
|
|
34
|
+
scrollY,
|
|
29
35
|
} = useTabContext();
|
|
30
36
|
|
|
31
37
|
const movedY = useSharedValue(0);
|
|
@@ -106,22 +112,33 @@ export const GestureWrapper = ({ children }: GestureWrapperProps) => {
|
|
|
106
112
|
[_gestureEnabled]
|
|
107
113
|
);
|
|
108
114
|
|
|
109
|
-
|
|
110
|
-
() =>
|
|
115
|
+
useAnimatedReaction(
|
|
116
|
+
() => {
|
|
117
|
+
if (transformationY.value > 0) {
|
|
118
|
+
if (_bounces) return transformationY.value * -0.3;
|
|
119
|
+
else return 0;
|
|
120
|
+
}
|
|
121
|
+
if (transformationY.value < -headerHeight.value) {
|
|
122
|
+
return headerHeight.value;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return -transformationY.value;
|
|
126
|
+
},
|
|
127
|
+
(value) => {
|
|
128
|
+
scrollY.value = value;
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const style = useAnimatedStyle(() => {
|
|
133
|
+
return {
|
|
111
134
|
flex: 1,
|
|
112
135
|
transform: [
|
|
113
136
|
{
|
|
114
|
-
translateY:
|
|
115
|
-
transformationY.value,
|
|
116
|
-
[0, -headerHeight.value],
|
|
117
|
-
[0, -headerHeight.value],
|
|
118
|
-
'clamp'
|
|
119
|
-
),
|
|
137
|
+
translateY: scrollY.value * -1,
|
|
120
138
|
},
|
|
121
139
|
],
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
);
|
|
140
|
+
};
|
|
141
|
+
}, []);
|
|
125
142
|
|
|
126
143
|
return (
|
|
127
144
|
<GestureDetector gesture={gesture}>
|
|
@@ -22,7 +22,7 @@ import { SectionList } from 'react-native';
|
|
|
22
22
|
*
|
|
23
23
|
* @param {Object} params - The parameters for configuring the scroll offset reset.
|
|
24
24
|
* @param {ReanimatedTopTabNavigation.ContextType["context"]} params.context - The context containing navigation and screen information.
|
|
25
|
-
* @param {ReanimatedTopTabNavigation.ContextType["
|
|
25
|
+
* @param {ReanimatedTopTabNavigation.ContextType["positionX"]} params.positionX - The horizontal transformation value used in animations.
|
|
26
26
|
* @param {ReanimatedTopTabNavigation.ContextType["currentYPosition"]} params.currentYPosition - The current vertical scroll position.
|
|
27
27
|
*
|
|
28
28
|
* The hook is responsible for resetting the vertical scroll offset of the "approaching" screen within a tabbed navigation interface,
|
|
@@ -32,11 +32,11 @@ import { SectionList } from 'react-native';
|
|
|
32
32
|
*/
|
|
33
33
|
const useResetApproachingScreenScrollOffset = ({
|
|
34
34
|
context,
|
|
35
|
-
|
|
35
|
+
positionX,
|
|
36
36
|
currentYPosition,
|
|
37
37
|
}: Pick<
|
|
38
38
|
ReanimatedTopTabNavigation.ContextType,
|
|
39
|
-
'context' | 'currentYPosition' | '
|
|
39
|
+
'context' | 'currentYPosition' | 'positionX'
|
|
40
40
|
>) => {
|
|
41
41
|
const screenOffsets = useDerivedValue(() =>
|
|
42
42
|
Object.values(context.screen.properties).map(({ scrollY }) => scrollY.value)
|
|
@@ -63,7 +63,7 @@ const useResetApproachingScreenScrollOffset = ({
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
useAnimatedReaction(
|
|
66
|
-
() =>
|
|
66
|
+
() => positionX.value,
|
|
67
67
|
(current, previous) => {
|
|
68
68
|
const approachingIndex = ContextHelpers.getTargetIndex(current, previous);
|
|
69
69
|
|
|
@@ -205,7 +205,7 @@ const usePrepareContext = ({
|
|
|
205
205
|
* @param {Array} params.config - An array of configuration settings to determine the header's transformation.
|
|
206
206
|
* @returns {Object} An object containing shared values for header transformations and positioning:
|
|
207
207
|
* - transformationY: The derived Y-axis transformation value for the header.
|
|
208
|
-
* -
|
|
208
|
+
* - positionX: The shared X-axis transformation value to be observed.
|
|
209
209
|
* - currentYPosition: The shared Y-axis position of the header.
|
|
210
210
|
* - headerHeight: The shared height value of the header.
|
|
211
211
|
*/
|
|
@@ -215,7 +215,8 @@ const useTransformHeaderOnTabChange = ({
|
|
|
215
215
|
const headerHeight = useSharedValue(0);
|
|
216
216
|
const isHeaderHeightSet = useSharedValue(false);
|
|
217
217
|
const transformationY = useSharedValue(0);
|
|
218
|
-
const
|
|
218
|
+
const scrollY = useSharedValue(0);
|
|
219
|
+
const positionX = useSharedValue(0);
|
|
219
220
|
const currentYPosition = useSharedValue(0);
|
|
220
221
|
|
|
221
222
|
//Hide header base on config
|
|
@@ -263,7 +264,7 @@ const useTransformHeaderOnTabChange = ({
|
|
|
263
264
|
);
|
|
264
265
|
|
|
265
266
|
useAnimatedReaction(
|
|
266
|
-
() =>
|
|
267
|
+
() => positionX.value,
|
|
267
268
|
(value) => {
|
|
268
269
|
if (currentYPosition.value === -headerHeight.value) return;
|
|
269
270
|
transformationY.value = interpolate(
|
|
@@ -277,21 +278,22 @@ const useTransformHeaderOnTabChange = ({
|
|
|
277
278
|
|
|
278
279
|
return {
|
|
279
280
|
transformationY,
|
|
280
|
-
|
|
281
|
+
positionX,
|
|
281
282
|
currentYPosition,
|
|
282
283
|
headerHeight,
|
|
283
284
|
isHeaderHeightSet,
|
|
285
|
+
scrollY,
|
|
284
286
|
};
|
|
285
287
|
};
|
|
286
288
|
|
|
287
289
|
const useApproachingTabChange = ({
|
|
288
290
|
config,
|
|
289
|
-
|
|
291
|
+
positionX,
|
|
290
292
|
gestureEnabled,
|
|
291
293
|
currentScreenIndex,
|
|
292
294
|
}: Pick<
|
|
293
295
|
ReanimatedTopTabNavigation.ContextType,
|
|
294
|
-
'config' | '
|
|
296
|
+
'config' | 'positionX' | 'currentScreenIndex' | 'gestureEnabled'
|
|
295
297
|
>) => {
|
|
296
298
|
const onIndexApproach = (index: number) => {
|
|
297
299
|
'worklet';
|
|
@@ -309,7 +311,7 @@ const useApproachingTabChange = ({
|
|
|
309
311
|
};
|
|
310
312
|
|
|
311
313
|
useAnimatedReaction(
|
|
312
|
-
() =>
|
|
314
|
+
() => positionX.value,
|
|
313
315
|
(current, previous) => {
|
|
314
316
|
const approachingIndex = ContextHelpers.getTargetIndex(current, previous);
|
|
315
317
|
onIndexApproach(approachingIndex);
|
package/src/context/Context.tsx
CHANGED
|
@@ -24,23 +24,24 @@ export const Provider = memo(
|
|
|
24
24
|
const topTabNativeGesture = useRef(Gesture.Native()).current;
|
|
25
25
|
|
|
26
26
|
const {
|
|
27
|
-
|
|
27
|
+
positionX,
|
|
28
28
|
transformationY,
|
|
29
29
|
currentYPosition,
|
|
30
30
|
headerHeight,
|
|
31
31
|
isHeaderHeightSet,
|
|
32
|
+
scrollY,
|
|
32
33
|
} = ContextHooks.useTransformHeaderOnTabChange({ config });
|
|
33
34
|
|
|
34
35
|
ContextHooks.useResetApproachingScreenScrollOffset({
|
|
35
36
|
currentYPosition,
|
|
36
|
-
|
|
37
|
+
positionX,
|
|
37
38
|
context,
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
ContextHooks.useApproachingTabChange({
|
|
41
42
|
config,
|
|
42
43
|
gestureEnabled,
|
|
43
|
-
|
|
44
|
+
positionX,
|
|
44
45
|
currentScreenIndex,
|
|
45
46
|
});
|
|
46
47
|
|
|
@@ -56,10 +57,11 @@ export const Provider = memo(
|
|
|
56
57
|
navHeight,
|
|
57
58
|
topTabHeight,
|
|
58
59
|
topTabNativeGesture,
|
|
59
|
-
|
|
60
|
+
positionX,
|
|
60
61
|
transformationY,
|
|
61
62
|
context,
|
|
62
63
|
isHeaderHeightSet,
|
|
64
|
+
scrollY,
|
|
63
65
|
}}
|
|
64
66
|
>
|
|
65
67
|
{children({
|
|
@@ -72,10 +74,11 @@ export const Provider = memo(
|
|
|
72
74
|
navHeight,
|
|
73
75
|
topTabHeight,
|
|
74
76
|
topTabNativeGesture,
|
|
75
|
-
|
|
77
|
+
positionX,
|
|
76
78
|
transformationY,
|
|
77
79
|
context,
|
|
78
80
|
isHeaderHeightSet,
|
|
81
|
+
scrollY,
|
|
79
82
|
})}
|
|
80
83
|
</Context.Provider>
|
|
81
84
|
);
|
package/src/hooks/useHeader.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { useTabContext } from './useTabContext';
|
|
|
2
2
|
import { withTiming } from 'react-native-reanimated';
|
|
3
3
|
|
|
4
4
|
export const useHeader = () => {
|
|
5
|
-
const { headerHeight,
|
|
5
|
+
const { headerHeight, transformationY } = useTabContext();
|
|
6
6
|
|
|
7
7
|
const hideHeader = () => {
|
|
8
|
-
|
|
8
|
+
transformationY.value = withTiming(-headerHeight.value);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
return { hideHeader };
|
|
@@ -3,6 +3,6 @@ import { useTabContext } from './useTabContext';
|
|
|
3
3
|
import { useDerivedValue } from 'react-native-reanimated';
|
|
4
4
|
|
|
5
5
|
export const useTabOffset = () => {
|
|
6
|
-
const {
|
|
7
|
-
return useDerivedValue(() =>
|
|
6
|
+
const { positionX } = useTabContext();
|
|
7
|
+
return useDerivedValue(() => positionX.value);
|
|
8
8
|
};
|
|
@@ -26,6 +26,7 @@ const TabViewNavigator = ({
|
|
|
26
26
|
config,
|
|
27
27
|
initialRouteName,
|
|
28
28
|
screenOptions = {},
|
|
29
|
+
bounces,
|
|
29
30
|
}: ReanimatedTopTabNavigation.TabViewNavigatorProps) => {
|
|
30
31
|
const { NavigationContent, descriptors, navigation, state } =
|
|
31
32
|
useNavigationBuilder<
|
|
@@ -94,7 +95,7 @@ const TabViewNavigator = ({
|
|
|
94
95
|
{TopComponent ? (
|
|
95
96
|
<TopComponent transformationY={transformationY} />
|
|
96
97
|
) : null}
|
|
97
|
-
<GestureWrapper>
|
|
98
|
+
<GestureWrapper bounces={bounces}>
|
|
98
99
|
<Reanimated.View
|
|
99
100
|
onLayout={({ nativeEvent }) => {
|
|
100
101
|
headerHeight.value = nativeEvent.layout.height;
|
package/src/types.ts
CHANGED
|
@@ -23,8 +23,9 @@ export namespace ReanimatedTopTabNavigation {
|
|
|
23
23
|
navHeight: SharedValue<number>;
|
|
24
24
|
topTabHeight: SharedValue<number>;
|
|
25
25
|
topTabNativeGesture: NativeGesture;
|
|
26
|
-
|
|
26
|
+
positionX: SharedValue<number>;
|
|
27
27
|
transformationY: SharedValue<number>;
|
|
28
|
+
scrollY: SharedValue<number>;
|
|
28
29
|
context: {
|
|
29
30
|
screen: {
|
|
30
31
|
properties: Record<
|
|
@@ -62,6 +63,7 @@ export namespace ReanimatedTopTabNavigation {
|
|
|
62
63
|
config?: string[];
|
|
63
64
|
initialRouteName?: string;
|
|
64
65
|
screenOptions?: StackNavigationOptions;
|
|
66
|
+
bounces?: boolean;
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
export type TopTabContextProps = Pick<ContextType, 'config' | 'context'> & {
|