react-native-navigation-mode 1.1.0 → 1.1.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 (2) hide show
  1. package/README.md +210 -128
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -32,58 +32,12 @@
32
32
  </table>
33
33
  </div>
34
34
 
35
- ---
36
-
37
- ## 🤔 Why This Library?
38
-
39
- Android devices can use different navigation modes, but detecting which one is active has been a major pain point for React Native developers. Most existing solutions rely on unreliable workarounds:
40
-
41
- ### ❌ Common Bad Approaches
42
-
43
- - **Screen dimension calculations** - Breaks on different screen sizes and orientations
44
- - **Safe area inset guessing** - Inconsistent across devices and Android versions
45
- - **Margin-based detection** - Fragile and depends on UI layout changes
46
- - **Manual device databases** - Impossible to maintain for all Android devices
47
-
48
- ### ✅ This Library's Solution
49
-
50
- This library uses **official Android APIs** to directly query the system's navigation configuration:
51
-
52
- - **`config_navBarInteractionMode`** - The actual system resource Android uses internally
53
- - **Settings.Secure provider** - Fallback method for reliable detection
54
- - **Zero guesswork** - No calculations, no assumptions, just direct system queries
55
-
56
- ### 🚀 Critical for Edge-to-Edge Mode
57
-
58
- With Android 15 enforcing edge-to-edge display for apps targeting API 35 and Google mandating this for Play Store updates starting August 31, 2025, proper navigation detection is now **essential**:
35
+ ------
59
36
 
60
- - **Edge-to-edge enforcement** - Android 16 will remove the opt-out entirely
61
- - **Expo SDK 53+** - New projects use edge-to-edge by default
62
- - **React Native 0.79+** - Built-in support for 16KB page size and edge-to-edge
63
- - **Safe area management** - Critical for preventing content overlap with system bars (especially noticeable in 3-button navigation mode).
64
-
65
- ### Real-World Impact
66
-
67
- ```typescript
68
- // Before: Unreliable dimension-based guessing
69
- const isGesture = screenHeight === windowHeight; // 😢 Breaks easily
70
-
71
- // After: Direct system detection
72
- const isGesture = await isGestureNavigation(); // 🎯 Always accurate
73
- ```
74
-
75
- **Perfect for:**
76
-
77
- - 🎨 Adaptive UI layouts based on navigation type
78
- - 📱 Bottom sheet positioning and safe areas
79
- - 🧭 Navigation-aware component design
80
- - 🔄 Edge-to-edge layout compatibility
81
- - 📊 Analytics and user experience tracking
82
-
83
- ## ✨ Features
37
+ ## Key Features
84
38
 
85
39
  - 🎯 **Direct Native Detection** - No hacky workarounds or dimension-based guessing
86
- - ⚡ **Turbo Module** - Built with the latest React Native architecture
40
+ - ⚡ **Turbo Module** - Built for React Native New Architecture
87
41
  - 🔄 **Real-time Detection** - Accurate navigation mode identification
88
42
  - 📏 **Navigation Bar Height** - Get exact navigation bar height in dp for precise UI calculations
89
43
  - 📱 **Cross Platform** - Android detection + iOS compatibility
@@ -92,7 +46,9 @@ const isGesture = await isGestureNavigation(); // 🎯 Always accurate
92
46
  - 🛡️ **TypeScript** - Full type safety out of the box
93
47
  - ↕️ **Edge To Edge Support** - Full support for `react-native-edge-to-edge`
94
48
 
95
- ## Installation
49
+ ## 🚀 Quick Start
50
+
51
+ ### Installation
96
52
 
97
53
  Using yarn:
98
54
 
@@ -106,124 +62,250 @@ Using npm:
106
62
  npm install react-native-navigation-mode
107
63
  ```
108
64
 
109
- ### For React Native CLI
65
+ > **Note:** Auto-linking should handle setup automatically for all newer RN versions.
110
66
 
111
- Auto-linking handles setup automatically for React Native 0.60+.
67
+ ---
112
68
 
113
- ## Usage
69
+ ### Basic Usage
114
70
 
115
- ### Quick Check
71
+ ```tsx
72
+ import { useNavigationMode } from 'react-native-navigation-mode';
116
73
 
117
- ```typescript
118
- import { isGestureNavigation } from 'react-native-navigation-mode';
74
+ export default function App() {
75
+ const { navigationMode, loading, error } = useNavigationMode();
119
76
 
120
- // Simple boolean check
121
- const isGesture = await isGestureNavigation();
122
- console.log('Gesture navigation:', isGesture); // true/false
77
+ if (loading) return (<Text>Detecting navigation mode...</Text>);
78
+ if (error) return (<Text>Error: {error.message}</Text>);
79
+
80
+ return (
81
+ <View>
82
+ <Text>Navigation Type: {navigationMode?.type}</Text>
83
+ <Text>Gesture Navigation: {navigationMode?.isGestureNavigation ? 'Yes' : 'No'}</Text>
84
+ <Text>Navigation Bar Height: {navigationMode?.navigationBarHeight}dp</Text>
85
+ </View>
86
+ );
87
+ }
123
88
  ```
124
89
 
125
- ### Detailed Information
90
+ ---
91
+
92
+ ## 🔧 API Reference
93
+
94
+ ### React Hook (Recommended)
95
+
96
+ #### `useNavigationMode(): { navigationMode, loading, error }`
97
+
98
+ - Returned property types:
99
+
100
+ | Property | Type | Description |
101
+ | ------------- | ------------------------------ | ------------------------------------------------------------ |
102
+ | navigatioMode | `NavigationModeInfo` or `null` | All properties mentioned in [NavigationModeInfo](#navigationmodeinfo). |
103
+ | loading | `boolean` | Indicates if navigation mode info is being fetched. |
104
+ | error | `Error` | Typescript error object containing the cause of the error. |
105
+
106
+ The easiest way to detect navigation mode with loading and error states.
107
+
108
+ ```tsx
109
+ import { useNavigationMode } from 'react-native-navigation-mode';
110
+
111
+ function MyComponent() {
112
+ const { navigationMode, loading, error } = useNavigationMode();
113
+
114
+ if (loading) return <Text>Loading...</Text>;
115
+ if (error) return <Text>Error: {error.message}</Text>;
116
+
117
+ return (
118
+ <View>
119
+ <Text>Navigation Type: {navigationMode?.type}</Text>
120
+ <Text>Is Gesture: {navigationMode?.isGestureNavigation ? 'Yes' : 'No'}</Text>
121
+ <Text>Bar Height: {navigationMode?.navigationBarHeight}dp</Text>
122
+ </View>
123
+ );
124
+ }
125
+ ```
126
+
127
+ ### Functions
128
+
129
+ #### `getNavigationMode(): Promise<`[NavigationModeInfo](#navigationmodeinfo)`>`
130
+
131
+ Returns comprehensive navigation mode information.
126
132
 
127
133
  ```typescript
128
134
  import { getNavigationMode } from 'react-native-navigation-mode';
129
135
 
130
- // Get comprehensive navigation info
131
136
  const navInfo = await getNavigationMode();
132
137
  console.log('Navigation type:', navInfo.type); // '3_button', '2_button', 'gesture', or 'unknown'
133
138
  ```
134
139
 
135
- ### Navigation Bar Height
140
+ #### `isGestureNavigation(): Promise<boolean>`
141
+
142
+ Quick check if device is using gesture navigation.
143
+
144
+ ```typescript
145
+ import { isGestureNavigation } from 'react-native-navigation-mode';
146
+
147
+ const isGesture = await isGestureNavigation();
148
+ console.log('Gesture navigation:', isGesture); // true/false
149
+ ```
150
+
151
+ #### `getNavigationBarHeight(): Promise<number>`
152
+
153
+ Returns the navigation bar height in density-independent pixels (dp).
136
154
 
137
155
  ```typescript
138
156
  import { getNavigationBarHeight } from 'react-native-navigation-mode';
139
157
 
140
- // Get navigation bar height in dp
141
158
  const height = await getNavigationBarHeight();
142
159
  console.log('Navigation bar height:', height); // number (dp)
143
160
  ```
144
161
 
145
- ### React Hook (Recommended)
162
+ ### Types
146
163
 
147
- ```typescript
148
- import React from 'react';
149
- import { View, Text } from 'react-native';
150
- import { useNavigationMode } from 'react-native-navigation-mode';
164
+ #### `NavigationModeInfo`
151
165
 
152
- export default function NavigationInfo() {
153
- const { navigationMode, loading, error } = useNavigationMode();
166
+ | Property | Type | Description |
167
+ | ------------------- | ----------------------------------------------------------- | --------------------------------------------------------- |
168
+ | type | `'3_button'` or `'2_button'` or `'gesture'` or `'unknown'` | 4 possible Android navigation modes that can be detected. |
169
+ | isGestureNavigation | `boolean` | Whether gesture navigation is active. |
170
+ | interactionMode | `number` or `undefined` | See [Navigation Mode Values](#navigation-mode-values) |
171
+ | navigationBarHeight | `number` or `undefined` | Navigation bar height in density-independent pixels (dp). |
154
172
 
155
- if (loading) return <Text>Detecting navigation mode...</Text>;
156
- if (error) return <Text>Error: {error.message}</Text>;
173
+ ### Navigation Mode Values
174
+
175
+ | Android Mode | Type | Description |
176
+ | ------------ | ---------- | --------------------------------------------------- |
177
+ | 0 | `3_button` | Traditional Android navigation (Back, Home, Recent) |
178
+ | 1 | `2_button` | Two-button navigation (Back, Home) |
179
+ | 2 | `gesture` | Full gesture navigation |
180
+ | -1 | `unknown` | Could not determine navigation mode |
181
+
182
+ ---
183
+
184
+ ## 💡 Usage Examples
185
+
186
+ ### Adaptive UI Layout
187
+
188
+ ```tsx
189
+ import { useNavigationMode } from 'react-native-navigation-mode';
190
+
191
+ export default function AdaptiveUI() {
192
+ const { navigationMode } = useNavigationMode();
157
193
 
158
194
  return (
159
- <View>
160
- <Text>Navigation Type: {navigationMode?.type}</Text>
161
- <Text>Gesture Navigation: {navigationMode?.isGestureNavigation ? 'Yes' : 'No'}</Text>
195
+ <View
196
+ style={{
197
+ // paddingBottom using real navigation bar height
198
+ paddingBottom: navigationMode?.navigationBarHeight || 0,
199
+ }}>
200
+ {/* Your content */}
162
201
  </View>
163
202
  );
164
203
  }
165
204
  ```
166
205
 
167
- ### Conditional UI Rendering
206
+ ### Conditional Rendering
168
207
 
169
- ```typescript
170
- import React from 'react';
171
- import { View } from 'react-native';
208
+ ```tsx
172
209
  import { useNavigationMode } from 'react-native-navigation-mode';
173
210
 
174
- export default function AdaptiveUI() {
211
+ export default function ConditionalUI() {
175
212
  const { navigationMode } = useNavigationMode();
176
213
 
177
214
  return (
178
- <View
179
- style={{
180
- paddingBottom: navigationMode?.navigationBarHeight
181
- }}
182
- >
183
- {/* Your content */}
215
+ <View>
216
+ {navigationMode?.isGestureNavigation && (
217
+ <Text>Swipe gestures are available!</Text>
218
+ )}
219
+
220
+ {navigationMode?.type === '3_button' && (
221
+ <Text>Traditional navigation buttons detected</Text>
222
+ )}
184
223
  </View>
185
224
  );
186
225
  }
187
226
  ```
188
227
 
189
- ## API Reference
228
+ ### Manual Detection
190
229
 
191
- ### Functions
230
+ ```typescript
231
+ import {
232
+ getNavigationMode,
233
+ isGestureNavigation,
234
+ getNavigationBarHeight
235
+ } from 'react-native-navigation-mode';
236
+
237
+ const checkNavigation = async () => {
238
+ // Get all info at once
239
+ const navInfo = await getNavigationMode();
240
+
241
+ // Or get specific info
242
+ const isGesture = await isGestureNavigation();
243
+ const barHeight = await getNavigationBarHeight();
244
+
245
+ console.log('Navigation info:', navInfo);
246
+ console.log('Is gesture:', isGesture);
247
+ console.log('Bar height:', barHeight);
248
+ };
249
+ ```
192
250
 
193
- #### `getNavigationMode(): Promise<NavigationModeInfo>`
251
+ ---
194
252
 
195
- Returns comprehensive navigation mode information.
253
+ ## 🤔 Why This Library?
196
254
 
197
- #### `isGestureNavigation(): Promise<boolean>`
255
+ Android devices can use different navigation modes, but detecting which one is active has been a major pain point for React Native developers. Most existing solutions rely on unreliable workarounds:
198
256
 
199
- Quick check if device is using gesture navigation.
257
+ ### Common Bad Approaches
200
258
 
201
- #### `getNavigationBarHeight(): Promise<number>`
259
+ - **Screen dimension calculations** - Breaks on different screen sizes and orientations
260
+ - **Safe area inset guessing** - Inconsistent across devices and Android versions
261
+ - **Margin-based detection** - Fragile and depends on UI layout changes
262
+ - **Manual device databases** - Impossible to maintain for all Android devices
202
263
 
203
- Returns the navigation bar height in density-independent pixels (dp).
264
+ ### This Library's Solution
204
265
 
205
- ### Hooks
266
+ This library uses **official Android APIs** to directly query the system's navigation configuration:
206
267
 
207
- #### `useNavigationMode(): { navigationMode, loading, error }`
268
+ - **`config_navBarInteractionMode`** - The actual system resource Android uses internally
269
+ - **Settings.Secure provider** - Fallback method for reliable detection
270
+ - **WindowInsets API** - Accurate navigation bar height detection
271
+ - **Zero guesswork** - No calculations, no assumptions, just direct system queries
208
272
 
209
- React hook for navigation mode detection with loading and error states.
273
+ ### 🚀 Critical for Edge-to-Edge Mode
210
274
 
211
- ### Types
275
+ With Android 15 enforcing edge-to-edge display for apps targeting API 35 and Google mandating this for Play Store updates starting August 31, 2025, proper navigation detection is now **essential**:
212
276
 
213
- #### `NavigationModeInfo`
277
+ - **Edge-to-edge enforcement** - Android 16 will remove the opt-out entirely
278
+ - **Expo SDK 53+** - New projects use edge-to-edge by default
279
+ - **React Native 0.79+** - Built-in support for 16KB page size and edge-to-edge
280
+ - **Safe area management** - Critical for preventing content overlap with system bars
214
281
 
215
- | Property | Type | Description |
216
- | ------------------- | ------------------------------------------------- | --------------------------------------------- |
217
- | type | `'3_button' | '2_button' | 'gesture' | 'unknown'` | Navigation mode type |
218
- | isGestureNavigation | `boolean` | Whether gesture navigation is active |
219
- | interactionMode | `number | undefined` | Raw Android interaction mode (0, 1, 2, or -1) |
220
- | navigationBarHeight | `number | undefined` | Navigation bar height in dp |
282
+ ### Real-World Impact
221
283
 
222
- ## Platform Support
284
+ ```typescript
285
+ // Before: Unreliable dimension-based guessing
286
+ const isGesture = screenHeight === windowHeight; // 😢 Breaks easily
223
287
 
224
- | Platform | Support | Notes |
225
- |----------|---------|-------|
226
- | Android | ✅ Full | Detects all navigation modes and navigation bar height via native Android APIs |
288
+ // After: Direct system detection
289
+ const isGesture = await isGestureNavigation(); // 🎯 Always accurate
290
+ ```
291
+
292
+ **Perfect for:**
293
+
294
+ - 🎨 Adaptive UI layouts based on navigation type
295
+ - 📱 Bottom sheet positioning and safe areas
296
+ - 🧭 Navigation-aware component design
297
+ - 🔄 Edge-to-edge layout compatibility
298
+ - 📊 Analytics and user experience tracking
299
+
300
+ ---
301
+
302
+ ## 🛠️ Technical Details
303
+
304
+ ### Platform Support
305
+
306
+ | Platform | Support | Notes |
307
+ | -------- | ------------ | ------------------------------------------------------------ |
308
+ | Android | ✅ Full | Detects all navigation modes and navigation bar height via native Android APIs |
227
309
  | iOS | ✅ Compatible | Always returns `gesture` and `navigationBarHeight: 0` (iOS uses gesture navigation) |
228
310
 
229
311
  ### Android Compatibility
@@ -234,51 +316,51 @@ React hook for navigation mode detection with loading and error states.
234
316
  - **API 30+** - WindowInsets-based navigation bar height detection
235
317
  - **API 24-29** - Resource-based navigation bar height fallback
236
318
 
237
- ## How It Works
319
+ ### How It Works
238
320
 
239
321
  The library uses multiple detection methods for maximum accuracy:
240
322
 
241
323
  1. **`config_navBarInteractionMode`** - Official Android configuration (API 29+)
242
324
  2. **Settings Provider** - Checks `navigation_mode` system setting
243
- 3. **Navigation Bar Detection** - Validates navigation bar presence
244
- 4. **Hardware Key Detection** - Fallback for older devices
245
-
246
- ### Navigation Mode Values
247
-
248
- | Android Mode | Type | Description |
249
- |--------------|------|-------------|
250
- | 0 | `3_button` | Traditional Android navigation (Back, Home, Recent) |
251
- | 1 | `2_button` | Two-button navigation (Back, Home) |
252
- | 2 | `gesture` | Full gesture navigation |
253
- | -1 | `unknown` | Could not determine navigation mode |
325
+ 3. **WindowInsets API** - Accurate navigation bar height detection (API 30+)
326
+ 4. **Resource-based fallback** - Navigation bar height for older devices
254
327
 
255
- ## Notes
328
+ ### Performance Notes
256
329
 
257
- 1. 1. 🍎 **iOS Behavior** - iOS always returns `isGestureNavigation: true` and `navigationBarHeight: 0` since iOS doesn't have Android-style navigation bars
330
+ 1. 🍎 **iOS Behavior** - iOS always returns `isGestureNavigation: true` and `navigationBarHeight: 0` since iOS doesn't have Android-style navigation bars
258
331
  2. ⚡ **Performance** - Turbo module ensures minimal performance impact
259
332
  3. 🔄 **Real-time** - Navigation mode is detected at call time, reflecting current device settings
260
333
 
261
- ## Troubleshooting
334
+ ---
335
+
336
+ ## 🐛 Troubleshooting
262
337
 
263
338
  ### Common Issues
264
339
 
265
340
  **"TurboModuleRegistry.getEnforcing(...) is not a function"**
341
+
266
342
  - Ensure you're using React Native 0.68+ with new architecture enabled
267
343
  - For older RN versions, the module will fallback gracefully
268
344
 
269
- **Always returns 'unknown' on Android**
345
+ **Always returns `'unknown'` on Android**
346
+
270
347
  - Check if your device/emulator supports the navigation mode APIs
271
348
  - Some custom ROMs may not expose standard Android navigation settings
272
349
 
273
- ## Contributing
350
+ **Navigation bar height returns `0`**
351
+
352
+ - This is normal on devices without navigation bars (some tablets)
353
+ - On older Android versions, fallback detection may not work on all devices
354
+
355
+ ## 🤝 Contributing
274
356
 
275
357
  See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
276
358
 
277
- ## License
359
+ ## 📄 License
278
360
 
279
361
  MIT
280
362
 
281
- ## Support the project
363
+ ## 💖 Support the Project
282
364
 
283
365
  <p align="center" valign="center">
284
366
  <a href="https://liberapay.com/FutureJJ/donate">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-navigation-mode",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Detect Android navigation mode (3-button, 2-button, or gesture)",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",