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.
Files changed (60) hide show
  1. package/lib/commonjs/components/ReanimatedTopTab/ReanimatedTabView.js +4 -5
  2. package/lib/commonjs/components/ReanimatedTopTab/ReanimatedTabView.js.map +1 -1
  3. package/lib/commonjs/components/elements/TabBarBaseComponent.js +4 -4
  4. package/lib/commonjs/components/elements/TabBarBaseComponent.js.map +1 -1
  5. package/lib/commonjs/components/wrappers/GestureWrapper.js +5 -6
  6. package/lib/commonjs/components/wrappers/GestureWrapper.js.map +1 -1
  7. package/lib/commonjs/components/wrappers/ScrollView.js +3 -1
  8. package/lib/commonjs/components/wrappers/ScrollView.js.map +1 -1
  9. package/lib/commonjs/context/Context.hooks.js +19 -1
  10. package/lib/commonjs/context/Context.hooks.js.map +1 -1
  11. package/lib/commonjs/context/Context.js +6 -3
  12. package/lib/commonjs/context/Context.js.map +1 -1
  13. package/lib/commonjs/hooks/useScreenScrollable.js +4 -2
  14. package/lib/commonjs/hooks/useScreenScrollable.js.map +1 -1
  15. package/lib/commonjs/navigator/createReanimatedTopTabNavigator.js +2 -12
  16. package/lib/commonjs/navigator/createReanimatedTopTabNavigator.js.map +1 -1
  17. package/lib/module/components/ReanimatedTopTab/ReanimatedTabView.js +4 -5
  18. package/lib/module/components/ReanimatedTopTab/ReanimatedTabView.js.map +1 -1
  19. package/lib/module/components/elements/TabBarBaseComponent.js +4 -4
  20. package/lib/module/components/elements/TabBarBaseComponent.js.map +1 -1
  21. package/lib/module/components/wrappers/GestureWrapper.js +5 -6
  22. package/lib/module/components/wrappers/GestureWrapper.js.map +1 -1
  23. package/lib/module/components/wrappers/ScrollView.js +3 -1
  24. package/lib/module/components/wrappers/ScrollView.js.map +1 -1
  25. package/lib/module/context/Context.hooks.js +20 -2
  26. package/lib/module/context/Context.hooks.js.map +1 -1
  27. package/lib/module/context/Context.js +6 -3
  28. package/lib/module/context/Context.js.map +1 -1
  29. package/lib/module/hooks/useScreenScrollable.js +4 -2
  30. package/lib/module/hooks/useScreenScrollable.js.map +1 -1
  31. package/lib/module/navigator/createReanimatedTopTabNavigator.js +4 -14
  32. package/lib/module/navigator/createReanimatedTopTabNavigator.js.map +1 -1
  33. package/lib/typescript/src/components/ReanimatedTopTab/ReanimatedTabView.d.ts.map +1 -1
  34. package/lib/typescript/src/components/ReanimatedTopTab/types.d.ts +1 -3
  35. package/lib/typescript/src/components/ReanimatedTopTab/types.d.ts.map +1 -1
  36. package/lib/typescript/src/components/elements/TabBarBaseComponent.d.ts +4 -18
  37. package/lib/typescript/src/components/elements/TabBarBaseComponent.d.ts.map +1 -1
  38. package/lib/typescript/src/components/wrappers/GestureWrapper.d.ts.map +1 -1
  39. package/lib/typescript/src/components/wrappers/ScrollView.d.ts.map +1 -1
  40. package/lib/typescript/src/context/Context.d.ts.map +1 -1
  41. package/lib/typescript/src/context/Context.hooks.d.ts +1 -0
  42. package/lib/typescript/src/context/Context.hooks.d.ts.map +1 -1
  43. package/lib/typescript/src/hooks/useScreenScrollable.d.ts +1 -0
  44. package/lib/typescript/src/hooks/useScreenScrollable.d.ts.map +1 -1
  45. package/lib/typescript/src/index.d.ts +2 -1
  46. package/lib/typescript/src/index.d.ts.map +1 -1
  47. package/lib/typescript/src/navigator/createReanimatedTopTabNavigator.d.ts.map +1 -1
  48. package/lib/typescript/src/types.d.ts +1 -0
  49. package/lib/typescript/src/types.d.ts.map +1 -1
  50. package/package.json +1 -1
  51. package/src/components/ReanimatedTopTab/ReanimatedTabView.tsx +7 -11
  52. package/src/components/ReanimatedTopTab/types.ts +1 -4
  53. package/src/components/elements/TabBarBaseComponent.tsx +5 -20
  54. package/src/components/wrappers/GestureWrapper.tsx +5 -8
  55. package/src/components/wrappers/ScrollView.tsx +2 -0
  56. package/src/context/Context.hooks.ts +32 -2
  57. package/src/context/Context.tsx +9 -2
  58. package/src/hooks/useScreenScrollable.ts +4 -1
  59. package/src/navigator/createReanimatedTopTabNavigator.tsx +4 -22
  60. 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
- (nextValue) => {
51
- runOnJS(setGestureEnabled)(nextValue);
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(({ state }, stateManager) => {
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 { transformationY, transformationX, currentYPosition, headerHeight };
270
+ return {
271
+ transformationY,
272
+ transformationX,
273
+ currentYPosition,
274
+ headerHeight,
275
+ isHeaderHeightSet,
276
+ };
247
277
  };
248
278
 
249
279
  export const ContextHooks = {
@@ -23,8 +23,13 @@ export const Provider = memo(
23
23
 
24
24
  const topTabNativeGesture = useRef(Gesture.Native()).current;
25
25
 
26
- const { transformationX, transformationY, currentYPosition, headerHeight } =
27
- ContextHooks.useTransformHeaderOnTabChange({ config });
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
- !gestureEnabled.value || currentYPosition.value === -headerHeight.value,
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 { useCallback, useMemo } from 'react';
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={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;