react-native-navigation 8.7.5 → 8.7.6
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/android/ARCHITECTURE.md +458 -0
- package/android/src/main/java/com/reactnativenavigation/react/NavigationModule.java +2 -2
- package/android/src/main/java/com/reactnativenavigation/views/stack/topbar/titlebar/ButtonBar.kt +2 -0
- package/android/src/main/java/com/reactnativenavigation/views/stack/topbar/titlebar/IconBackgroundDrawable.kt +20 -17
- package/android/src/main/java/com/reactnativenavigation/views/stack/topbar/titlebar/TitleAndButtonsMeasurer.kt +2 -1
- package/android/src/main/java/com/reactnativenavigation/views/stack/topbar/titlebar/TitleBarReactView.kt +7 -10
- package/android/src/main/res/values/styles.xml +2 -0
- package/ios/ARCHITECTURE.md +416 -0
- package/ios/BottomTabsAfterInitialTabAttacher.mm +31 -0
- package/ios/BottomTabsAppearancePresenter.mm +69 -32
- package/ios/BottomTabsBasePresenter.mm +5 -4
- package/ios/RCTHelpers.mm +3 -1
- package/ios/RNNAppDelegate.mm +10 -0
- package/ios/RNNBottomTabsController.mm +19 -6
- package/ios/RNNBottomTabsOptions.mm +5 -1
- package/ios/RNNBridgeManager.mm +2 -0
- package/ios/RNNComponentViewController.mm +4 -2
- package/ios/RNNModalHostViewManagerHandler.h +5 -0
- package/ios/RNNModalHostViewManagerHandler.mm +2 -0
- package/ios/RNNOverlayWindow.mm +1 -2
- package/ios/RNNScrollEdgeAppearanceOptions.h +2 -0
- package/ios/RNNScrollEdgeAppearanceOptions.mm +2 -0
- package/ios/TopBarAppearancePresenter.mm +35 -0
- package/lib/module/ARCHITECTURE.md +301 -0
- package/lib/module/interfaces/Options.js.map +1 -1
- package/lib/typescript/interfaces/Options.d.ts +29 -0
- package/lib/typescript/interfaces/Options.d.ts.map +1 -1
- package/package.json +11 -11
- package/src/ARCHITECTURE.md +301 -0
- package/src/interfaces/Options.ts +30 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-navigation",
|
|
3
|
-
"version": "8.7.
|
|
3
|
+
"version": "8.7.6",
|
|
4
4
|
"description": "React Native Navigation - truly native navigation for iOS and Android",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"nativePackage": true,
|
|
@@ -94,15 +94,16 @@
|
|
|
94
94
|
"@babel/preset-env": "^7.25.3",
|
|
95
95
|
"@babel/runtime": "^7.25.0",
|
|
96
96
|
"@babel/types": "7.25.0",
|
|
97
|
+
"@d11/react-native-fast-image": "^8.13.0",
|
|
97
98
|
"@react-native-community/cli": "20.0.0",
|
|
98
99
|
"@react-native-community/cli-platform-android": "20.0.0",
|
|
99
100
|
"@react-native-community/cli-platform-ios": "20.0.0",
|
|
100
101
|
"@react-native-community/datetimepicker": "^8.2.0",
|
|
101
102
|
"@react-native-community/netinfo": "^11.4.1",
|
|
102
|
-
"@react-native/babel-preset": "0.
|
|
103
|
-
"@react-native/eslint-config": "0.
|
|
104
|
-
"@react-native/metro-config": "0.
|
|
105
|
-
"@react-native/typescript-config": "0.
|
|
103
|
+
"@react-native/babel-preset": "0.84.0",
|
|
104
|
+
"@react-native/eslint-config": "0.84.0",
|
|
105
|
+
"@react-native/metro-config": "0.84.0",
|
|
106
|
+
"@react-native/typescript-config": "0.84.0",
|
|
106
107
|
"@testing-library/jest-native": "^5.4.2",
|
|
107
108
|
"@testing-library/react-native": "^13.0.1",
|
|
108
109
|
"@types/hoist-non-react-statics": "^3.3.6",
|
|
@@ -130,15 +131,14 @@
|
|
|
130
131
|
"pixelmatch": "^5.2.1",
|
|
131
132
|
"pngjs": "^6.0.0",
|
|
132
133
|
"prettier": "2.8.8",
|
|
133
|
-
"react": "19.2.
|
|
134
|
-
"react-native": "0.
|
|
134
|
+
"react": "19.2.3",
|
|
135
|
+
"react-native": "0.84.0",
|
|
135
136
|
"react-native-builder-bob": "^0.40.13",
|
|
136
|
-
"react-native-fast-image": "^8.6.3",
|
|
137
137
|
"react-native-gesture-handler": "^2.29.1",
|
|
138
|
-
"react-native-reanimated": "4.
|
|
139
|
-
"react-native-worklets": "0.
|
|
138
|
+
"react-native-reanimated": "4.2.2",
|
|
139
|
+
"react-native-worklets": "0.7.4",
|
|
140
140
|
"react-redux": "9.1.2",
|
|
141
|
-
"react-test-renderer": "19.2.
|
|
141
|
+
"react-test-renderer": "19.2.3",
|
|
142
142
|
"redux": "^5.0.1",
|
|
143
143
|
"remx": "3.x.x",
|
|
144
144
|
"semver": "5.x.x",
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# JavaScript/TypeScript Architecture
|
|
2
|
+
|
|
3
|
+
The JavaScript layer provides the public API and orchestrates communication between React components and native navigation implementations.
|
|
4
|
+
|
|
5
|
+
## Entry Point
|
|
6
|
+
|
|
7
|
+
`index.ts` exports the `Navigation` singleton (a `NavigationDelegate` instance) along with re-exports from `Modal`, `EventsRegistry`, `Constants`, and all interfaces. Applications use `Navigation.*` for commands and `Navigation.events().*` for event subscriptions.
|
|
8
|
+
|
|
9
|
+
## Module Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
src/
|
|
13
|
+
├── index.ts # Main entry point, exports Navigation singleton
|
|
14
|
+
├── Navigation.ts # NavigationRoot - core orchestrator
|
|
15
|
+
├── NavigationDelegate.ts # Public API facade
|
|
16
|
+
├── adapters/ # Native bridge layer
|
|
17
|
+
├── commands/ # Command processing
|
|
18
|
+
├── components/ # React component management
|
|
19
|
+
├── events/ # Event system
|
|
20
|
+
├── interfaces/ # TypeScript type definitions
|
|
21
|
+
└── processors/ # Extensibility hooks
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Core Classes
|
|
25
|
+
|
|
26
|
+
### NavigationDelegate (Public API)
|
|
27
|
+
**File**: `NavigationDelegate.ts`
|
|
28
|
+
|
|
29
|
+
Facade providing the public `Navigation` API. All methods proxy to `NavigationRoot`.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
// Usage
|
|
33
|
+
import { Navigation } from 'react-native-navigation';
|
|
34
|
+
Navigation.setRoot({ root: { stack: { children: [...] } } });
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### NavigationRoot (Core Orchestrator)
|
|
38
|
+
**File**: `Navigation.ts`
|
|
39
|
+
|
|
40
|
+
Coordinates all subsystems. Constructed with dependencies:
|
|
41
|
+
- `NativeCommandsSender` - sends commands to native
|
|
42
|
+
- `NativeEventsReceiver` - receives events from native
|
|
43
|
+
- `AppRegistryService` - manages React Native component registry
|
|
44
|
+
|
|
45
|
+
Initializes and coordinates:
|
|
46
|
+
- `Store` - component instance & props storage
|
|
47
|
+
- `ComponentRegistry` - component registration
|
|
48
|
+
- `LayoutTreeParser` - converts layouts to internal nodes
|
|
49
|
+
- `LayoutTreeCrawler` - processes layout trees
|
|
50
|
+
- `Commands` - command execution
|
|
51
|
+
- `EventsRegistry` - event subscriptions
|
|
52
|
+
- `OptionsProcessor` - option processing
|
|
53
|
+
- `LayoutProcessor` - layout transformations
|
|
54
|
+
|
|
55
|
+
## Adapters Layer
|
|
56
|
+
|
|
57
|
+
Bridge between JavaScript and native/React Native APIs.
|
|
58
|
+
|
|
59
|
+
| Adapter | Purpose |
|
|
60
|
+
|---------|---------|
|
|
61
|
+
| `NativeCommandsSender` | Wraps TurboModule for command dispatch |
|
|
62
|
+
| `NativeEventsReceiver` | Wraps NativeEventEmitter for events |
|
|
63
|
+
| `NativeRNNTurboModule` | TurboModule spec interface |
|
|
64
|
+
| `NativeRNNTurboEventEmitter` | TurboModule event emitter spec |
|
|
65
|
+
| `UniqueIdProvider` | Generates unique component/command IDs |
|
|
66
|
+
| `ColorService` | Converts colors to native format |
|
|
67
|
+
| `AssetResolver` | Resolves require() image assets (class: AssetService) |
|
|
68
|
+
| `AppRegistryService` | Registers components with React Native |
|
|
69
|
+
| `Constants` | Platform dimension constants |
|
|
70
|
+
| `TouchablePreview` | 3D Touch / Haptic preview handling |
|
|
71
|
+
|
|
72
|
+
## Commands Layer
|
|
73
|
+
|
|
74
|
+
### Commands Class
|
|
75
|
+
**File**: `commands/Commands.ts`
|
|
76
|
+
|
|
77
|
+
Central command dispatcher. Each navigation command:
|
|
78
|
+
1. Validates input
|
|
79
|
+
2. Processes layout through pipeline
|
|
80
|
+
3. Sends to native via adapter
|
|
81
|
+
4. Returns promise with result
|
|
82
|
+
|
|
83
|
+
### Processing Pipeline
|
|
84
|
+
|
|
85
|
+
The pipeline executes in this exact order:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Input Layout (from API)
|
|
89
|
+
↓
|
|
90
|
+
1. OptionsCrawler.crawl() # Extract static options from component classes
|
|
91
|
+
↓
|
|
92
|
+
2. LayoutProcessor.process() # Apply registered layout processors
|
|
93
|
+
↓
|
|
94
|
+
3. LayoutTreeParser.parse() # Convert to internal LayoutNode tree
|
|
95
|
+
↓
|
|
96
|
+
4. LayoutTreeCrawler.crawl() # Process options, save props to Store
|
|
97
|
+
↓
|
|
98
|
+
5. OptionsProcessor (during crawl) # Resolve colors, assets, custom processors
|
|
99
|
+
↓
|
|
100
|
+
6. NativeCommandsSender # Send to native module
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### LayoutNode (Internal Tree)
|
|
104
|
+
```typescript
|
|
105
|
+
interface LayoutNode {
|
|
106
|
+
id: string; // Unique identifier
|
|
107
|
+
type: LayoutType; // Component|Stack|BottomTabs|etc
|
|
108
|
+
data: {
|
|
109
|
+
name?: string; // Component name
|
|
110
|
+
options?: any; // Processed options
|
|
111
|
+
passProps?: any; // Component props (cleared before native)
|
|
112
|
+
};
|
|
113
|
+
children: LayoutNode[];
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### LayoutType Enum
|
|
118
|
+
```typescript
|
|
119
|
+
enum LayoutType {
|
|
120
|
+
Component = 'Component',
|
|
121
|
+
Stack = 'Stack',
|
|
122
|
+
BottomTabs = 'BottomTabs',
|
|
123
|
+
SideMenuRoot = 'SideMenuRoot',
|
|
124
|
+
SideMenuCenter = 'SideMenuCenter',
|
|
125
|
+
SideMenuLeft = 'SideMenuLeft',
|
|
126
|
+
SideMenuRight = 'SideMenuRight',
|
|
127
|
+
TopTabs = 'TopTabs',
|
|
128
|
+
ExternalComponent = 'ExternalComponent',
|
|
129
|
+
SplitView = 'SplitView',
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Components Layer
|
|
134
|
+
|
|
135
|
+
### ComponentRegistry
|
|
136
|
+
**File**: `components/ComponentRegistry.ts`
|
|
137
|
+
|
|
138
|
+
Manages React component registration and wrapping.
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
Navigation.registerComponent('ScreenName', () => MyComponent);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### ComponentWrapper
|
|
145
|
+
**File**: `components/ComponentWrapper.tsx`
|
|
146
|
+
|
|
147
|
+
Higher-order component that:
|
|
148
|
+
- Wraps original component with lifecycle management
|
|
149
|
+
- Stores instance in `Store` for event dispatch
|
|
150
|
+
- Injects `componentId` and `componentName` props
|
|
151
|
+
|
|
152
|
+
### Store
|
|
153
|
+
**File**: `components/Store.ts`
|
|
154
|
+
|
|
155
|
+
Centralized storage for:
|
|
156
|
+
- `componentsByName` - registered component providers
|
|
157
|
+
- `componentsInstancesById` - mounted component instances
|
|
158
|
+
- `propsById` - static props by component ID
|
|
159
|
+
- `pendingPropsById` - props awaiting component mount
|
|
160
|
+
- `wrappedComponents` - cached wrapped components
|
|
161
|
+
- `lazyRegistratorFn` - function for lazy component registration
|
|
162
|
+
|
|
163
|
+
## Events Layer
|
|
164
|
+
|
|
165
|
+
### EventsRegistry
|
|
166
|
+
**File**: `events/EventsRegistry.ts`
|
|
167
|
+
|
|
168
|
+
Public API for event subscriptions:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
Navigation.events().registerComponentDidAppearListener(({ componentId }) => {});
|
|
172
|
+
Navigation.events().registerCommandCompletedListener(({ commandId }) => {});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### ComponentEventsObserver
|
|
176
|
+
**File**: `events/ComponentEventsObserver.ts`
|
|
177
|
+
|
|
178
|
+
Dispatches events to component instance methods:
|
|
179
|
+
- `componentWillAppear()`
|
|
180
|
+
- `componentDidAppear()`
|
|
181
|
+
- `componentDidDisappear()`
|
|
182
|
+
- `navigationButtonPressed()`
|
|
183
|
+
- `screenPopped()`
|
|
184
|
+
|
|
185
|
+
### CommandsObserver
|
|
186
|
+
**File**: `events/CommandsObserver.ts`
|
|
187
|
+
|
|
188
|
+
Notifies listeners of command lifecycle (start, complete).
|
|
189
|
+
|
|
190
|
+
## Events (Native → JS)
|
|
191
|
+
|
|
192
|
+
| Event | Description |
|
|
193
|
+
|-------|-------------|
|
|
194
|
+
| `RNN.AppLaunched` | App initialization complete |
|
|
195
|
+
| `RNN.ComponentWillAppear` | Component about to appear |
|
|
196
|
+
| `RNN.ComponentDidAppear` | Component now visible |
|
|
197
|
+
| `RNN.ComponentDidDisappear` | Component hidden |
|
|
198
|
+
| `RNN.NavigationButtonPressed` | TopBar button tapped |
|
|
199
|
+
| `RNN.BottomTabPressed` | Tab pressed (even if selected) |
|
|
200
|
+
| `RNN.BottomTabSelected` | Tab selection changed |
|
|
201
|
+
| `RNN.BottomTabLongPressed` | Tab long-pressed |
|
|
202
|
+
| `RNN.ModalDismissed` | Modal was dismissed |
|
|
203
|
+
| `RNN.ModalAttemptedToDismiss` | Swipe-to-dismiss attempted |
|
|
204
|
+
| `RNN.ScreenPopped` | Screen removed from stack |
|
|
205
|
+
| `RNN.SearchBarUpdated` | Search text changed |
|
|
206
|
+
| `RNN.SearchBarCancelPressed` | Search cancelled |
|
|
207
|
+
| `RNN.PreviewCompleted` | 3D Touch preview completed |
|
|
208
|
+
| `RNN.CommandCompleted` | Navigation command finished |
|
|
209
|
+
|
|
210
|
+
## Processors Layer
|
|
211
|
+
|
|
212
|
+
### OptionProcessorsStore
|
|
213
|
+
**File**: `processors/OptionProcessorsStore.ts`
|
|
214
|
+
|
|
215
|
+
Registers custom option processors:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
Navigation.addOptionProcessor('topBar.title.text', (value, commandName) => {
|
|
219
|
+
return value.toUpperCase(); // Transform all titles
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### LayoutProcessorsStore
|
|
224
|
+
**File**: `processors/LayoutProcessorsStore.ts`
|
|
225
|
+
|
|
226
|
+
Registers layout transformers:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
Navigation.addLayoutProcessor((layout, commandName) => {
|
|
230
|
+
// Add default options to all components
|
|
231
|
+
return layout;
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Interfaces
|
|
236
|
+
|
|
237
|
+
### Layout Types
|
|
238
|
+
**File**: `interfaces/Layout.ts`
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
interface LayoutRoot {
|
|
242
|
+
root: Layout;
|
|
243
|
+
modals?: any[];
|
|
244
|
+
overlays?: any[];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
type Layout = {
|
|
248
|
+
component?: LayoutComponent;
|
|
249
|
+
stack?: LayoutStack;
|
|
250
|
+
bottomTabs?: LayoutBottomTabs;
|
|
251
|
+
sideMenu?: LayoutSideMenu;
|
|
252
|
+
splitView?: LayoutSplitView;
|
|
253
|
+
topTabs?: LayoutTopTabs;
|
|
254
|
+
externalComponent?: ExternalComponent;
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Options Interface
|
|
259
|
+
**File**: `interfaces/Options.ts` (comprehensive)
|
|
260
|
+
|
|
261
|
+
Contains all configuration options for:
|
|
262
|
+
- Status bar, navigation bars
|
|
263
|
+
- Top bar (buttons, title, search)
|
|
264
|
+
- Bottom tabs
|
|
265
|
+
- Side menus
|
|
266
|
+
- Modals, overlays
|
|
267
|
+
- Animations
|
|
268
|
+
- Layout parameters
|
|
269
|
+
|
|
270
|
+
### NavigationComponent
|
|
271
|
+
**File**: `interfaces/NavigationComponent.ts`
|
|
272
|
+
|
|
273
|
+
Base class for navigation-aware components:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
class MyScreen extends NavigationComponent<Props> {
|
|
277
|
+
static options: Options = { ... };
|
|
278
|
+
|
|
279
|
+
componentDidAppear(event) { }
|
|
280
|
+
navigationButtonPressed(event) { }
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Dependencies
|
|
285
|
+
|
|
286
|
+
**Production**:
|
|
287
|
+
- `lodash` - utility functions
|
|
288
|
+
- `hoist-non-react-statics` - HOC support
|
|
289
|
+
- `react-lifecycles-compat` - lifecycle polyfill
|
|
290
|
+
- `tslib` - TypeScript helpers
|
|
291
|
+
|
|
292
|
+
**Peer**:
|
|
293
|
+
- `react`, `react-native` (required)
|
|
294
|
+
- `remx` (optional state management)
|
|
295
|
+
|
|
296
|
+
## Build Output
|
|
297
|
+
|
|
298
|
+
Uses `react-native-builder-bob`:
|
|
299
|
+
- **Source**: `src/`
|
|
300
|
+
- **Output**: `lib/`
|
|
301
|
+
- **Targets**: ESM modules + TypeScript declarations
|
|
@@ -457,7 +457,37 @@ export interface OptionsTopBarScrollEdgeAppearanceBackground {
|
|
|
457
457
|
translucent?: boolean;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
+
export interface OptionsTopBarScrollEdgeAppearanceTitle {
|
|
461
|
+
/**
|
|
462
|
+
* Font size
|
|
463
|
+
*/
|
|
464
|
+
fontSize?: number;
|
|
465
|
+
/**
|
|
466
|
+
* Text color
|
|
467
|
+
*/
|
|
468
|
+
color?: Color;
|
|
469
|
+
/**
|
|
470
|
+
* Set the font family for the title
|
|
471
|
+
*/
|
|
472
|
+
fontFamily?: FontFamily;
|
|
473
|
+
/**
|
|
474
|
+
* Set the font style for the title
|
|
475
|
+
*/
|
|
476
|
+
fontStyle?: FontStyle;
|
|
477
|
+
/**
|
|
478
|
+
* Specifies font weight. The values 'normal' and 'bold' are supported
|
|
479
|
+
* for most fonts. Not all fonts have a variant for each of the numeric
|
|
480
|
+
* values, in that case the closest one is chosen.
|
|
481
|
+
*/
|
|
482
|
+
fontWeight?: FontWeight;
|
|
483
|
+
}
|
|
484
|
+
|
|
460
485
|
export interface OptionsTopBarScrollEdgeAppearance {
|
|
486
|
+
/**
|
|
487
|
+
* Title configuration applied when the scroll view reaches the edge
|
|
488
|
+
* ### (iOS specific)
|
|
489
|
+
*/
|
|
490
|
+
title?: OptionsTopBarScrollEdgeAppearanceTitle;
|
|
461
491
|
background?: OptionsTopBarScrollEdgeAppearanceBackground;
|
|
462
492
|
active: boolean;
|
|
463
493
|
/**
|