@react-navigation/lynx 0.3.0-canary-20260907-96fbfef4 → 0.3.0

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 +187 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,187 @@
1
+ # `@react-navigation/lynx`
2
+
3
+ [React Navigation](https://reactnavigation.org) for [Lynx](https://lynxjs.org).
4
+
5
+ This is the platform layer, the same role `@react-navigation/native` plays for
6
+ React Native: it owns what is Lynx-specific, re-exports
7
+ `@react-navigation/core` so an app has one import surface, and navigators sit
8
+ on top of it.
9
+
10
+ ## Installation
11
+
12
+ ```sh
13
+ npm install @react-navigation/lynx lynx-screens
14
+ ```
15
+
16
+ `@lynx-js/react` and `lynx-screens` are peer dependencies. The stack navigator
17
+ renders through `lynx-screens`, so its native side has to be linked into the
18
+ host app as well.
19
+
20
+ `react` has to resolve to a ReactLynx-compatible runtime, since
21
+ `@react-navigation/core` imports hooks React Native provides:
22
+
23
+ ```js
24
+ // lynx.config.js
25
+ resolve: {
26
+ alias: {
27
+ react$: require.resolve('@react-navigation/lynx/react-compat'),
28
+ },
29
+ },
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```tsx
35
+ import { createStaticNavigation } from '@react-navigation/lynx';
36
+ import { createLynxStackNavigator } from '@react-navigation/lynx/stack';
37
+
38
+ const Stack = createLynxStackNavigator({
39
+ initialRouteName: 'Home',
40
+ screens: {
41
+ Home: HomeScreen,
42
+ Detail: DetailScreen,
43
+ },
44
+ });
45
+
46
+ const Navigation = createStaticNavigation(Stack);
47
+
48
+ export function App() {
49
+ return (
50
+ <page>
51
+ <Navigation />
52
+ </page>
53
+ );
54
+ }
55
+ ```
56
+
57
+ `NavigationContainer` is exported too, for the dynamic API.
58
+
59
+ ### Screen options
60
+
61
+ ```tsx
62
+ const Stack = createLynxStackNavigator({
63
+ screens: {
64
+ Sheet: {
65
+ screen: SheetScreen,
66
+ options: {
67
+ presentation: 'formSheet',
68
+ contentStyle: { backgroundColor: '#fff' },
69
+ },
70
+ },
71
+ },
72
+ });
73
+ ```
74
+
75
+ `presentation` is `'card'` or `'formSheet'`. The navigator also emits
76
+ `transitionStart` and `transitionEnd`, each carrying `{ closing }`.
77
+
78
+ To stop a screen from being dismissed, use core's `usePreventRemove`:
79
+
80
+ ```tsx
81
+ usePreventRemove(hasUnsavedChanges, ({ data }) => {
82
+ confirm(() => navigation.dispatch(data.action));
83
+ });
84
+ ```
85
+
86
+ ## Deep linking
87
+
88
+ Path handling is `@react-navigation/core` unchanged: `config.screens` maps
89
+ paths onto route names and params, exactly as on React Native.
90
+
91
+ ```tsx
92
+ import type { LinkingOptions } from '@react-navigation/lynx';
93
+
94
+ const linking: LinkingOptions<ParamList> = {
95
+ config: {
96
+ screens: {
97
+ Home: '',
98
+ Detail: 'detail/:id',
99
+ },
100
+ },
101
+ };
102
+
103
+ <Navigation linking={linking} />;
104
+ ```
105
+
106
+ What is Lynx-specific is where the URL comes from. A card is not the process
107
+ that receives a link — the host app is — so the host has to hand it over.
108
+
109
+ **On a cold start**, the route rides in on `initData`, which the card can read
110
+ before any listener exists:
111
+
112
+ ```kotlin
113
+ // Android
114
+ TemplateData.fromMap(mapOf(
115
+ "__navigation" to mapOf(
116
+ "route" to "/detail/42",
117
+ "nonce" to System.currentTimeMillis(),
118
+ ),
119
+ ))
120
+ ```
121
+
122
+ ```swift
123
+ // iOS
124
+ LynxTemplateData(dictionary: [
125
+ "__navigation": ["route": "/detail/42", "nonce": Date().timeIntervalSince1970],
126
+ ])
127
+ ```
128
+
129
+ `nonce` is required. `initData` is state, not an event: navigating to the same
130
+ route twice would leave the value untouched and the second one would be
131
+ dropped. Anything that changes per navigation works.
132
+
133
+ **Later routes** arrive as a global event carrying `{ url }`:
134
+
135
+ ```kotlin
136
+ lynxView.sendGlobalEvent(
137
+ "reactnavigation.url",
138
+ JavaOnlyArray.of(JavaOnlyMap.from(mapOf("url" to "/detail/42"))),
139
+ )
140
+ ```
141
+
142
+ ```swift
143
+ lynxView.sendGlobalEvent("reactnavigation.url", withParams: [["url": "/detail/42"]])
144
+ ```
145
+
146
+ The name is namespaced on purpose. React Native can afford the bare `url`
147
+ because `RCTLinkingManager` is its own emitter; Lynx's `GlobalEventEmitter` is
148
+ one namespace shared by the whole card and its host. A bare `url` event is
149
+ still accepted, so a host already emitting React Native's works unchanged.
150
+
151
+ The two channels are not interchangeable. A cold start cannot use the event —
152
+ no listener exists yet — and a warm one should not use `initData`, because
153
+ without a changing nonce a repeat route is invisible. A host that does both
154
+ will navigate twice.
155
+
156
+ The route may be a bare path (`/detail/42`), or a full URL if the app sets
157
+ `prefixes`. Prefix stripping matches React Native, wildcards included:
158
+
159
+ ```tsx
160
+ const linking: LinkingOptions<ParamList> = {
161
+ prefixes: ['myapp://', 'https://*.example.com'],
162
+ config: { screens: { Detail: 'detail/:id' } },
163
+ };
164
+ ```
165
+
166
+ `getInitialURL`, `subscribe`, `getStateFromPath`, `getActionFromState` and
167
+ `filter` are all replaceable, the same as on React Native.
168
+
169
+ ### Reading it directly
170
+
171
+ `getInitialURL()` returns the launch route and is **synchronous** — React
172
+ Native has to await `Linking.getInitialURL()`, but on Lynx `initData` is
173
+ already in hand when the card starts, so the first render lands on the right
174
+ route instead of on the fallback.
175
+
176
+ ```tsx
177
+ import { getInitialURL, subscribe } from '@react-navigation/lynx';
178
+ ```
179
+
180
+ ## Differences from `@react-navigation/native`
181
+
182
+ - No `Link`, `useLinkTo`, `useLinkBuilder` or `useRoutePath` yet: only the
183
+ URL-to-navigation direction is implemented.
184
+ - No state persistence, and no container-level back-button handling — the
185
+ native stack owns dismissal per screen, so a container handler would fight
186
+ with it.
187
+ - `getInitialURL` is synchronous, as above.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-navigation/lynx",
3
- "version": "0.3.0-canary-20260907-96fbfef4",
3
+ "version": "0.3.0",
4
4
  "description": "Lynx integration for React Navigation",
5
5
  "keywords": [
6
6
  "react",