react-navigation-reanimated-top-tabs 0.5.0 → 0.6.1
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/ReanimatedTabView.js +4 -5
- package/lib/commonjs/components/ReanimatedTopTab/ReanimatedTabView.js.map +1 -1
- package/lib/commonjs/components/elements/TabBarBaseComponent.js +4 -4
- package/lib/commonjs/components/elements/TabBarBaseComponent.js.map +1 -1
- package/lib/commonjs/components/wrappers/GestureWrapper.js +5 -6
- package/lib/commonjs/components/wrappers/GestureWrapper.js.map +1 -1
- package/lib/commonjs/components/wrappers/ScrollView.js +3 -1
- package/lib/commonjs/components/wrappers/ScrollView.js.map +1 -1
- package/lib/commonjs/context/Context.hooks.js +19 -1
- package/lib/commonjs/context/Context.hooks.js.map +1 -1
- package/lib/commonjs/context/Context.js +6 -3
- package/lib/commonjs/context/Context.js.map +1 -1
- package/lib/commonjs/hooks/useScreenScrollable.js +4 -2
- package/lib/commonjs/hooks/useScreenScrollable.js.map +1 -1
- package/lib/commonjs/navigator/createReanimatedTopTabNavigator.js +2 -12
- package/lib/commonjs/navigator/createReanimatedTopTabNavigator.js.map +1 -1
- package/lib/module/components/ReanimatedTopTab/ReanimatedTabView.js +4 -5
- package/lib/module/components/ReanimatedTopTab/ReanimatedTabView.js.map +1 -1
- package/lib/module/components/elements/TabBarBaseComponent.js +4 -4
- package/lib/module/components/elements/TabBarBaseComponent.js.map +1 -1
- package/lib/module/components/wrappers/GestureWrapper.js +5 -6
- package/lib/module/components/wrappers/GestureWrapper.js.map +1 -1
- package/lib/module/components/wrappers/ScrollView.js +3 -1
- package/lib/module/components/wrappers/ScrollView.js.map +1 -1
- package/lib/module/context/Context.hooks.js +20 -2
- package/lib/module/context/Context.hooks.js.map +1 -1
- package/lib/module/context/Context.js +6 -3
- package/lib/module/context/Context.js.map +1 -1
- package/lib/module/hooks/useScreenScrollable.js +4 -2
- package/lib/module/hooks/useScreenScrollable.js.map +1 -1
- package/lib/module/navigator/createReanimatedTopTabNavigator.js +4 -14
- package/lib/module/navigator/createReanimatedTopTabNavigator.js.map +1 -1
- package/lib/typescript/src/components/ReanimatedTopTab/ReanimatedTabView.d.ts.map +1 -1
- package/lib/typescript/src/components/ReanimatedTopTab/types.d.ts +1 -3
- package/lib/typescript/src/components/ReanimatedTopTab/types.d.ts.map +1 -1
- package/lib/typescript/src/components/elements/TabBarBaseComponent.d.ts +4 -18
- package/lib/typescript/src/components/elements/TabBarBaseComponent.d.ts.map +1 -1
- package/lib/typescript/src/components/wrappers/GestureWrapper.d.ts.map +1 -1
- package/lib/typescript/src/components/wrappers/ScrollView.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 +1 -0
- package/lib/typescript/src/context/Context.hooks.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useScreenScrollable.d.ts +1 -0
- package/lib/typescript/src/hooks/useScreenScrollable.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/navigator/createReanimatedTopTabNavigator.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +1 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ReanimatedTopTab/ReanimatedTabView.tsx +7 -11
- package/src/components/ReanimatedTopTab/types.ts +1 -4
- package/src/components/elements/TabBarBaseComponent.tsx +5 -20
- package/src/components/wrappers/GestureWrapper.tsx +5 -8
- package/src/components/wrappers/ScrollView.tsx +2 -0
- package/src/context/Context.hooks.ts +32 -2
- package/src/context/Context.tsx +9 -2
- package/src/hooks/useScreenScrollable.ts +4 -1
- package/src/navigator/createReanimatedTopTabNavigator.tsx +4 -22
- package/src/types.ts +1 -0
|
@@ -47,8 +47,9 @@ export const GestureWrapper = ({ children }: GestureWrapperProps) => {
|
|
|
47
47
|
|
|
48
48
|
useAnimatedReaction(
|
|
49
49
|
() => gestureEnabled.value,
|
|
50
|
-
(
|
|
51
|
-
|
|
50
|
+
(next, prev) => {
|
|
51
|
+
if (next === prev) return;
|
|
52
|
+
runOnJS(setGestureEnabled)(next);
|
|
52
53
|
},
|
|
53
54
|
[]
|
|
54
55
|
);
|
|
@@ -57,13 +58,9 @@ export const GestureWrapper = ({ children }: GestureWrapperProps) => {
|
|
|
57
58
|
() =>
|
|
58
59
|
Gesture.Pan()
|
|
59
60
|
.activeOffsetY([-10, 10])
|
|
60
|
-
.onTouchesMove((
|
|
61
|
+
.onTouchesMove((_, stateManager) => {
|
|
61
62
|
'worklet';
|
|
62
|
-
if (
|
|
63
|
-
currentScreenScrollOffset.value > 0 &&
|
|
64
|
-
state !== 4 &&
|
|
65
|
-
state !== 3
|
|
66
|
-
) {
|
|
63
|
+
if (currentScreenScrollOffset.value > 0 || !gestureEnabled.value) {
|
|
67
64
|
stateManager.fail();
|
|
68
65
|
}
|
|
69
66
|
})
|
|
@@ -31,6 +31,7 @@ export const ScrollView = ({
|
|
|
31
31
|
onScroll,
|
|
32
32
|
bounces,
|
|
33
33
|
animatedProps,
|
|
34
|
+
overScrollMode,
|
|
34
35
|
} = useScreenScrollable();
|
|
35
36
|
const { innerLayout } = useScreenProperties();
|
|
36
37
|
const { context } = useTabContext();
|
|
@@ -58,6 +59,7 @@ export const ScrollView = ({
|
|
|
58
59
|
onScroll={onScroll}
|
|
59
60
|
bounces={bounces}
|
|
60
61
|
animatedProps={animatedProps}
|
|
62
|
+
overScrollMode={overScrollMode}
|
|
61
63
|
{...props}
|
|
62
64
|
>
|
|
63
65
|
{children}
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
TabNavigationState,
|
|
14
14
|
} from '@react-navigation/native';
|
|
15
15
|
import { Gesture } from 'react-native-gesture-handler';
|
|
16
|
-
import { assign } from 'lodash';
|
|
16
|
+
import { assign, throttle } from 'lodash';
|
|
17
17
|
import { ContextHelpers } from './Context.helpers';
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -205,6 +205,7 @@ const useTransformHeaderOnTabChange = ({
|
|
|
205
205
|
config,
|
|
206
206
|
}: Pick<ReanimatedTopTabNavigation.ContextType, 'config'>) => {
|
|
207
207
|
const headerHeight = useSharedValue(0);
|
|
208
|
+
const isHeaderHeightSet = useSharedValue(false);
|
|
208
209
|
const transformationY = useSharedValue(0);
|
|
209
210
|
const transformationX = useSharedValue(0);
|
|
210
211
|
const currentYPosition = useSharedValue(0);
|
|
@@ -230,6 +231,29 @@ const useTransformHeaderOnTabChange = ({
|
|
|
230
231
|
[config]
|
|
231
232
|
);
|
|
232
233
|
|
|
234
|
+
// NOTE: headerHeight is setting onLayout, so at very first render it has value equal 0,
|
|
235
|
+
// but right after the header content renders onLayout calls once again.
|
|
236
|
+
// That's why we use debounce
|
|
237
|
+
const debouncedSetIsHeaderSet = throttle(() => {
|
|
238
|
+
isHeaderHeightSet.value = true;
|
|
239
|
+
}, 10);
|
|
240
|
+
|
|
241
|
+
const cancel = () => {
|
|
242
|
+
debouncedSetIsHeaderSet.cancel();
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
useAnimatedReaction(
|
|
246
|
+
() => headerHeight.value,
|
|
247
|
+
(prepared, previous) => {
|
|
248
|
+
runOnJS(cancel)();
|
|
249
|
+
|
|
250
|
+
if (previous !== prepared) {
|
|
251
|
+
runOnJS(debouncedSetIsHeaderSet)();
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
[]
|
|
255
|
+
);
|
|
256
|
+
|
|
233
257
|
useAnimatedReaction(
|
|
234
258
|
() => transformationX.value,
|
|
235
259
|
(value) => {
|
|
@@ -243,7 +267,13 @@ const useTransformHeaderOnTabChange = ({
|
|
|
243
267
|
}
|
|
244
268
|
);
|
|
245
269
|
|
|
246
|
-
return {
|
|
270
|
+
return {
|
|
271
|
+
transformationY,
|
|
272
|
+
transformationX,
|
|
273
|
+
currentYPosition,
|
|
274
|
+
headerHeight,
|
|
275
|
+
isHeaderHeightSet,
|
|
276
|
+
};
|
|
247
277
|
};
|
|
248
278
|
|
|
249
279
|
export const ContextHooks = {
|
package/src/context/Context.tsx
CHANGED
|
@@ -23,8 +23,13 @@ export const Provider = memo(
|
|
|
23
23
|
|
|
24
24
|
const topTabNativeGesture = useRef(Gesture.Native()).current;
|
|
25
25
|
|
|
26
|
-
const {
|
|
27
|
-
|
|
26
|
+
const {
|
|
27
|
+
transformationX,
|
|
28
|
+
transformationY,
|
|
29
|
+
currentYPosition,
|
|
30
|
+
headerHeight,
|
|
31
|
+
isHeaderHeightSet,
|
|
32
|
+
} = ContextHooks.useTransformHeaderOnTabChange({ config });
|
|
28
33
|
|
|
29
34
|
ContextHooks.useResetApproachingScreenScrollOffset({
|
|
30
35
|
currentYPosition,
|
|
@@ -47,6 +52,7 @@ export const Provider = memo(
|
|
|
47
52
|
transformationX,
|
|
48
53
|
transformationY,
|
|
49
54
|
context,
|
|
55
|
+
isHeaderHeightSet,
|
|
50
56
|
}}
|
|
51
57
|
>
|
|
52
58
|
{children({
|
|
@@ -62,6 +68,7 @@ export const Provider = memo(
|
|
|
62
68
|
transformationX,
|
|
63
69
|
transformationY,
|
|
64
70
|
context,
|
|
71
|
+
isHeaderHeightSet,
|
|
65
72
|
})}
|
|
66
73
|
</Context.Provider>
|
|
67
74
|
);
|
|
@@ -25,6 +25,7 @@ export const useScreenScrollable = () => {
|
|
|
25
25
|
context,
|
|
26
26
|
topTabHeight,
|
|
27
27
|
transformationY,
|
|
28
|
+
isHeaderHeightSet,
|
|
28
29
|
} = useTabContext();
|
|
29
30
|
|
|
30
31
|
const screen = useScreenProperties();
|
|
@@ -33,7 +34,8 @@ export const useScreenScrollable = () => {
|
|
|
33
34
|
|
|
34
35
|
const animatedProps = useAnimatedProps(() => ({
|
|
35
36
|
scrollEnabled:
|
|
36
|
-
|
|
37
|
+
isHeaderHeightSet.value &&
|
|
38
|
+
(!gestureEnabled.value || currentYPosition.value === -headerHeight.value),
|
|
37
39
|
}));
|
|
38
40
|
|
|
39
41
|
const onScroll = useAnimatedScrollHandler(({ contentOffset }) => {
|
|
@@ -69,6 +71,7 @@ export const useScreenScrollable = () => {
|
|
|
69
71
|
bounces: false,
|
|
70
72
|
contentContainerStyle: { paddingBottom: bottom },
|
|
71
73
|
onScroll,
|
|
74
|
+
overScrollMode: 'never' as const,
|
|
72
75
|
style,
|
|
73
76
|
};
|
|
74
77
|
};
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createNavigatorFactory,
|
|
3
3
|
type ParamListBase,
|
|
4
|
-
TabActions,
|
|
5
4
|
type TabNavigationState,
|
|
6
5
|
TabRouter,
|
|
7
6
|
useNavigationBuilder,
|
|
8
7
|
} from '@react-navigation/native';
|
|
9
8
|
import type { DefaultRouterOptions } from '@react-navigation/routers';
|
|
10
9
|
import { GestureWrapper } from '../components/wrappers/GestureWrapper';
|
|
11
|
-
import {
|
|
12
|
-
type RenderTabsParams,
|
|
13
|
-
TabBarBaseComponent,
|
|
14
|
-
} from '../components/elements/TabBarBaseComponent';
|
|
10
|
+
import { TabBarBaseComponent } from '../components/elements/TabBarBaseComponent';
|
|
15
11
|
import { Provider } from '../context/Context';
|
|
16
12
|
import { type ReanimatedTopTabNavigation } from '../types';
|
|
17
13
|
import { omit } from 'lodash';
|
|
18
|
-
import {
|
|
14
|
+
import { useMemo } from 'react';
|
|
19
15
|
import Reanimated, { type SharedValue } from 'react-native-reanimated';
|
|
20
16
|
import type { ReanimatedTabViewTypes } from '../components/ReanimatedTopTab/types';
|
|
21
17
|
import { ReanimatedTabView } from '../components/ReanimatedTopTab/ReanimatedTabView';
|
|
@@ -58,7 +54,6 @@ const TabViewNavigator = ({
|
|
|
58
54
|
gestureEnabled: SharedValue<boolean>
|
|
59
55
|
) =>
|
|
60
56
|
(index: number) => {
|
|
61
|
-
navigation.navigate(state.routes[index]?.name ?? '');
|
|
62
57
|
currentScreenIndex.value = index;
|
|
63
58
|
switch (_config[index]) {
|
|
64
59
|
case 'normal': {
|
|
@@ -70,6 +65,7 @@ const TabViewNavigator = ({
|
|
|
70
65
|
break;
|
|
71
66
|
}
|
|
72
67
|
}
|
|
68
|
+
navigation.navigate(state.routes[index]?.name ?? '');
|
|
73
69
|
};
|
|
74
70
|
|
|
75
71
|
const navigationState = useMemo(
|
|
@@ -100,20 +96,6 @@ const TabViewNavigator = ({
|
|
|
100
96
|
[state]
|
|
101
97
|
);
|
|
102
98
|
|
|
103
|
-
const navigate = (route: any) => {
|
|
104
|
-
navigation.dispatch({
|
|
105
|
-
...TabActions.jumpTo(route.name, route.params),
|
|
106
|
-
target: state.key,
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const renderTabBar = useCallback(
|
|
111
|
-
(props: RenderTabsParams) => (
|
|
112
|
-
<TabBarComponent {...props} navigate={navigate} />
|
|
113
|
-
),
|
|
114
|
-
[]
|
|
115
|
-
);
|
|
116
|
-
|
|
117
99
|
const renderScene = ({ route }: ReanimatedTabViewTypes.SceneProps) =>
|
|
118
100
|
descriptors[route.key]?.render();
|
|
119
101
|
|
|
@@ -147,7 +129,7 @@ const TabViewNavigator = ({
|
|
|
147
129
|
gestureEnabled
|
|
148
130
|
)}
|
|
149
131
|
renderScene={renderScene}
|
|
150
|
-
renderTabBar={
|
|
132
|
+
renderTabBar={TabBarComponent}
|
|
151
133
|
/>
|
|
152
134
|
</GestureWrapper>
|
|
153
135
|
</NavigationContent>
|
package/src/types.ts
CHANGED
|
@@ -14,6 +14,7 @@ export namespace ReanimatedTopTabNavigation {
|
|
|
14
14
|
currentYPosition: SharedValue<number>;
|
|
15
15
|
gestureEnabled: SharedValue<boolean>;
|
|
16
16
|
headerHeight: SharedValue<number>;
|
|
17
|
+
isHeaderHeightSet: SharedValue<boolean>;
|
|
17
18
|
navHeight: SharedValue<number>;
|
|
18
19
|
topTabHeight: SharedValue<number>;
|
|
19
20
|
topTabNativeGesture: NativeGesture;
|