@momo-kits/foundation 0.163.1-beta.15 → 0.163.1-beta.16

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.
@@ -38,10 +38,7 @@ const getStackOptions = (): StackNavigationOptions => {
38
38
  headerLeft: (props: any) => <HeaderLeft {...props} />,
39
39
  headerRight: (props: any) => <HeaderRight {...props} />,
40
40
  headerTintColor: Colors.black_17,
41
- /**
42
- * swipe back for iOS only, Android keeps the hardware back button
43
- */
44
- gestureEnabled: Platform.OS === 'ios',
41
+ gestureEnabled: false,
45
42
  ...TransitionPresets.SlideFromRightIOS,
46
43
  };
47
44
  };
@@ -57,23 +54,9 @@ const getModalOptions = (): StackNavigationOptions => {
57
54
  cardOverlayEnabled: true,
58
55
  animation: 'none',
59
56
  presentation: 'transparentModal',
60
- /**
61
- * modal & bottom sheet dismiss through their own overlay/pan gesture
62
- */
63
- gestureEnabled: false,
64
57
  };
65
58
  };
66
59
 
67
- /**
68
- * screen owns its back flow (guard popup, custom handler or no back button),
69
- * so swipe back must not bypass it
70
- */
71
- const hasCustomBackHandling = (params: NavigationOptions) =>
72
- params.preventBack !== undefined ||
73
- params.hiddenBack === true ||
74
- typeof params.onBackHandler === 'function' ||
75
- typeof params.onPressLeftHeader === 'function';
76
-
77
60
  /**
78
61
  * build react-navigation options
79
62
  */
@@ -142,13 +125,6 @@ const getOptions = (
142
125
  };
143
126
  }
144
127
 
145
- /**
146
- * only ever turns swipe back off, screens opt in via gestureEnabled
147
- */
148
- if (params.gestureEnabled === undefined && hasCustomBackHandling(params)) {
149
- options.gestureEnabled = false;
150
- }
151
-
152
128
  return {
153
129
  ...params,
154
130
  ...options,
package/Layout/Screen.tsx CHANGED
@@ -26,7 +26,6 @@ import {
26
26
  ViewProps,
27
27
  } from 'react-native';
28
28
  import { useSharedValue, withTiming } from 'react-native-reanimated';
29
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
30
29
  import { ApplicationContext, ScreenContext } from '../Context';
31
30
  import Navigation from '../Application/Navigation';
32
31
  import {
@@ -41,7 +40,7 @@ import styles from './styles';
41
40
  import { HeaderType } from './types';
42
41
  import { InputRef } from '../Input';
43
42
  import { exportHeaderTitle, getOptions } from '../Application/utils';
44
- import { validateChildren } from './utils';
43
+ import { useBottomSafeAreaInset, validateChildren } from './utils';
45
44
  import Section from './Section';
46
45
  import {
47
46
  HeaderBackground,
@@ -195,7 +194,9 @@ const Screen = forwardRef(
195
194
  const { width: widthDevice } = useWindowDimensions();
196
195
  const { theme, navigator } = useContext(ApplicationContext);
197
196
  const screen: any = useContext(ScreenContext);
198
- const insets = useSafeAreaInsets();
197
+ // AI-GENERATED START: keyboard-aware bottom inset (DS-747)
198
+ const bottomInset = useBottomSafeAreaInset();
199
+ // AI-GENERATED END: keyboard-aware bottom inset (DS-747)
199
200
  const heightHeader = useHeaderHeight();
200
201
 
201
202
  /**
@@ -238,7 +239,6 @@ const Screen = forwardRef(
238
239
  let handleScroll;
239
240
  let Component: any = View;
240
241
 
241
- const bottomInset = Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
242
242
  let keyboardOffset = heightHeader - bottomInset;
243
243
  if (headerType === 'extended' || animatedHeader || inputSearchProps) {
244
244
  keyboardOffset = -bottomInset;
package/Layout/utils.ts CHANGED
@@ -1,5 +1,6 @@
1
- import React, { Fragment, ReactElement } from 'react';
2
- import { useWindowDimensions } from 'react-native';
1
+ import React, { Fragment, ReactElement, useEffect, useState } from 'react';
2
+ import { Keyboard, Platform, useWindowDimensions } from 'react-native';
3
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
3
4
 
4
5
  /**
5
6
  * validate children type
@@ -44,4 +45,72 @@ const useGridSystem = () => {
44
45
  return { numberOfColumns };
45
46
  };
46
47
 
47
- export { useGridSystem, validateChildren };
48
+ // AI-GENERATED START: keyboard-aware bottom safe-area inset (DS-747)
49
+ /**
50
+ * Android 16 (API 36) ignores `android:windowOptOutEdgeToEdgeEnforcement`, so the host
51
+ * app is always edge-to-edge and `insets.bottom` reports the navigation bar height
52
+ * instead of 0. Android <= 15 still honours the opt-out, which is why the footer only
53
+ * jitters on Android 16.
54
+ */
55
+ const IS_EDGE_TO_EDGE_ENFORCED =
56
+ Platform.OS === 'android' && Number(Platform.Version) >= 36;
57
+
58
+ /**
59
+ * Tracks IME visibility. On Android `keyboardDidShow` is emitted as soon as the IME
60
+ * becomes visible, ahead of the root view being resized for it.
61
+ */
62
+ const useIsKeyboardVisible = () => {
63
+ const [isKeyboardVisible, setIsKeyboardVisible] = useState(
64
+ () => IS_EDGE_TO_EDGE_ENFORCED && Keyboard.isVisible(),
65
+ );
66
+
67
+ useEffect(() => {
68
+ if (!IS_EDGE_TO_EDGE_ENFORCED) {
69
+ return;
70
+ }
71
+
72
+ const showSubscription = Keyboard.addListener('keyboardDidShow', () =>
73
+ setIsKeyboardVisible(true),
74
+ );
75
+ const hideSubscription = Keyboard.addListener('keyboardDidHide', () =>
76
+ setIsKeyboardVisible(false),
77
+ );
78
+
79
+ return () => {
80
+ showSubscription.remove();
81
+ hideSubscription.remove();
82
+ };
83
+ }, []);
84
+
85
+ return isKeyboardVisible;
86
+ };
87
+
88
+ /**
89
+ * Bottom safe-area inset for chrome anchored to the bottom edge (footer, floating
90
+ * button, scroll padding).
91
+ *
92
+ * `react-native-safe-area-context` recomputes its insets from an `onPreDraw` pass, so
93
+ * the drop to 0 that happens once the IME covers the navigation bar only reaches JS
94
+ * *after* the root view has already shrunk, and then only as a state update. For those
95
+ * frames the footer keeps padding for a navigation bar the keyboard already covers, so
96
+ * it lifts off the keyboard and snaps back down when the new inset lands. Zeroing the
97
+ * inset on keyboard visibility removes that intermediate state.
98
+ *
99
+ * The keyboard flag is only allowed to *remove* inset, never to restore it: on hide it
100
+ * flips back before the root view grows again, and `insets.bottom` is still 0 at that
101
+ * point, so the restore stays driven by the inset itself and the footer does not jump
102
+ * the other way.
103
+ */
104
+ const useBottomSafeAreaInset = () => {
105
+ const insets = useSafeAreaInsets();
106
+ const isKeyboardVisible = useIsKeyboardVisible();
107
+
108
+ if (Platform.OS === 'ios') {
109
+ return Math.min(insets.bottom, 21);
110
+ }
111
+
112
+ return isKeyboardVisible ? 0 : insets.bottom;
113
+ };
114
+ // AI-GENERATED END: keyboard-aware bottom safe-area inset (DS-747)
115
+
116
+ export { useBottomSafeAreaInset, useGridSystem, validateChildren };
package/package.json CHANGED
@@ -1,35 +1,35 @@
1
1
  {
2
- "name": "@momo-kits/foundation",
3
- "version": "0.163.1-beta.15",
4
- "description": "React Native Component Kits",
5
- "main": "index.ts",
6
- "scripts": {},
7
- "keywords": [
8
- "@momo-kits/foundation"
9
- ],
10
- "dependencies": {
11
- "react-native-fast-image": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-fast-image.git#v8.11.0",
12
- "@react-navigation/bottom-tabs": "7.4.2",
13
- "@react-navigation/core": "7.12.1",
14
- "@react-navigation/elements": "2.5.2",
15
- "@react-navigation/native": "7.1.14",
16
- "@react-navigation/routers": "7.4.1",
17
- "@react-navigation/stack": "7.4.2",
18
- "react-native-gesture-handler": "2.27.1",
19
- "react-native-linear-gradient": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-linear-gradient#v3.0.0",
20
- "react-native-reanimated": "4.2.2",
21
- "react-native-safe-area-context": "5.5.2",
22
- "@shopify/flash-list": "2.1.0",
23
- "lottie-react-native": "7.2.4"
24
- },
25
- "peerDependencies": {
26
- "react-native": "*"
27
- },
28
- "devDependencies": {
29
- "@types/color": "3.0.6"
30
- },
31
- "publishConfig": {
32
- "registry": "https://registry.npmjs.org/"
33
- },
34
- "license": "MoMo"
35
- }
2
+ "name": "@momo-kits/foundation",
3
+ "version": "0.163.1-beta.16",
4
+ "description": "React Native Component Kits",
5
+ "main": "index.ts",
6
+ "scripts": {},
7
+ "keywords": [
8
+ "@momo-kits/foundation"
9
+ ],
10
+ "dependencies": {
11
+ "react-native-fast-image": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-fast-image.git#v8.11.0",
12
+ "@react-navigation/bottom-tabs": "7.4.2",
13
+ "@react-navigation/core": "7.12.1",
14
+ "@react-navigation/elements": "2.5.2",
15
+ "@react-navigation/native": "7.1.14",
16
+ "@react-navigation/routers": "7.4.1",
17
+ "@react-navigation/stack": "7.4.2",
18
+ "react-native-gesture-handler": "2.27.1",
19
+ "react-native-linear-gradient": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-linear-gradient#v3.0.0",
20
+ "react-native-reanimated": "4.2.2",
21
+ "react-native-safe-area-context": "5.5.2",
22
+ "@shopify/flash-list": "2.1.0",
23
+ "lottie-react-native": "7.2.4"
24
+ },
25
+ "peerDependencies": {
26
+ "react-native": "*"
27
+ },
28
+ "devDependencies": {
29
+ "@types/color": "3.0.6"
30
+ },
31
+ "publishConfig": {
32
+ "registry": "https://registry.npmjs.org/"
33
+ },
34
+ "license": "MoMo"
35
+ }