@react-navigation/native 8.0.0-alpha.27 → 8.0.0-alpha.29

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 (99) hide show
  1. package/ios/ReactNavigationSFSymbolView.mm +22 -9
  2. package/ios/ReactNavigationSFSymbolView.swift +351 -65
  3. package/lib/module/__stubs__/createStackNavigator.js +9 -1
  4. package/lib/module/__stubs__/createStackNavigator.js.map +1 -1
  5. package/lib/module/__stubs__/window.js +3 -0
  6. package/lib/module/__stubs__/window.js.map +1 -1
  7. package/lib/module/createMemoryHistory.js +7 -3
  8. package/lib/module/createMemoryHistory.js.map +1 -1
  9. package/lib/module/createStandardNavigationFactories.js +99 -0
  10. package/lib/module/createStandardNavigationFactories.js.map +1 -0
  11. package/lib/module/extractPathFromURL.js +1 -1
  12. package/lib/module/extractPathFromURL.js.map +1 -1
  13. package/lib/module/getStateFromHref.js +2 -2
  14. package/lib/module/getStateFromHref.js.map +1 -1
  15. package/lib/module/index.js +1 -0
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/module/native/SFSymbol.ios.js +35 -14
  18. package/lib/module/native/SFSymbol.ios.js.map +1 -1
  19. package/lib/module/native/SFSymbolViewNativeComponent.ts +22 -9
  20. package/lib/module/useLinkBuilder.js +4 -3
  21. package/lib/module/useLinkBuilder.js.map +1 -1
  22. package/lib/module/useLinking.js +11 -2
  23. package/lib/module/useLinking.js.map +1 -1
  24. package/lib/module/useLinking.native.js +5 -5
  25. package/lib/module/useLinking.native.js.map +1 -1
  26. package/lib/module/useMemoArray.js +25 -0
  27. package/lib/module/useMemoArray.js.map +1 -0
  28. package/lib/module/useScrollToTop.js +2 -1
  29. package/lib/module/useScrollToTop.js.map +1 -1
  30. package/lib/typescript/src/Link.d.ts +1 -1
  31. package/lib/typescript/src/Link.d.ts.map +1 -1
  32. package/lib/typescript/src/LinkingContext.d.ts +1 -1
  33. package/lib/typescript/src/LinkingContext.d.ts.map +1 -1
  34. package/lib/typescript/src/LocaleDirContext.d.ts +1 -1
  35. package/lib/typescript/src/LocaleDirContext.d.ts.map +1 -1
  36. package/lib/typescript/src/NavigationContainer.d.ts +2 -2
  37. package/lib/typescript/src/NavigationContainer.d.ts.map +1 -1
  38. package/lib/typescript/src/__stubs__/createStackNavigator.d.ts +1 -1
  39. package/lib/typescript/src/__stubs__/createStackNavigator.d.ts.map +1 -1
  40. package/lib/typescript/src/__stubs__/window.d.ts.map +1 -1
  41. package/lib/typescript/src/createMemoryHistory.d.ts +1 -1
  42. package/lib/typescript/src/createMemoryHistory.d.ts.map +1 -1
  43. package/lib/typescript/src/createStandardNavigationFactories.d.ts +31 -0
  44. package/lib/typescript/src/createStandardNavigationFactories.d.ts.map +1 -0
  45. package/lib/typescript/src/createStaticNavigation.d.ts +3 -3
  46. package/lib/typescript/src/createStaticNavigation.d.ts.map +1 -1
  47. package/lib/typescript/src/extractPathFromURL.d.ts +1 -1
  48. package/lib/typescript/src/extractPathFromURL.d.ts.map +1 -1
  49. package/lib/typescript/src/getStateFromHref.d.ts +3 -3
  50. package/lib/typescript/src/getStateFromHref.d.ts.map +1 -1
  51. package/lib/typescript/src/index.d.ts +15 -14
  52. package/lib/typescript/src/index.d.ts.map +1 -1
  53. package/lib/typescript/src/native/CornerInset.d.ts +1 -1
  54. package/lib/typescript/src/native/CornerInset.d.ts.map +1 -1
  55. package/lib/typescript/src/native/CornerInset.ios.d.ts +2 -2
  56. package/lib/typescript/src/native/CornerInset.ios.d.ts.map +1 -1
  57. package/lib/typescript/src/native/MaterialSymbol.android.d.ts +1 -1
  58. package/lib/typescript/src/native/MaterialSymbol.android.d.ts.map +1 -1
  59. package/lib/typescript/src/native/MaterialSymbol.d.ts +1 -1
  60. package/lib/typescript/src/native/MaterialSymbol.d.ts.map +1 -1
  61. package/lib/typescript/src/native/SFSymbol.d.ts +1 -1
  62. package/lib/typescript/src/native/SFSymbol.d.ts.map +1 -1
  63. package/lib/typescript/src/native/SFSymbol.ios.d.ts +2 -2
  64. package/lib/typescript/src/native/SFSymbol.ios.d.ts.map +1 -1
  65. package/lib/typescript/src/native/SFSymbolViewNativeComponent.d.ts +22 -9
  66. package/lib/typescript/src/native/SFSymbolViewNativeComponent.d.ts.map +1 -1
  67. package/lib/typescript/src/native/types.d.ts +227 -31
  68. package/lib/typescript/src/native/types.d.ts.map +1 -1
  69. package/lib/typescript/src/server/index.d.ts +1 -1
  70. package/lib/typescript/src/server/index.d.ts.map +1 -1
  71. package/lib/typescript/src/theming/MaterialTheme.d.ts +1 -1
  72. package/lib/typescript/src/theming/MaterialTheme.d.ts.map +1 -1
  73. package/lib/typescript/src/useDocumentTitle.d.ts +1 -1
  74. package/lib/typescript/src/useDocumentTitle.d.ts.map +1 -1
  75. package/lib/typescript/src/useLinkBuilder.d.ts.map +1 -1
  76. package/lib/typescript/src/useLinking.d.ts +6 -6
  77. package/lib/typescript/src/useLinking.d.ts.map +1 -1
  78. package/lib/typescript/src/useLinking.native.d.ts +10 -10
  79. package/lib/typescript/src/useLinking.native.d.ts.map +1 -1
  80. package/lib/typescript/src/useLocale.d.ts +1 -1
  81. package/lib/typescript/src/useMemoArray.d.ts +2 -0
  82. package/lib/typescript/src/useMemoArray.d.ts.map +1 -0
  83. package/lib/typescript/src/useScrollToTop.d.ts.map +1 -1
  84. package/package.json +13 -12
  85. package/src/__stubs__/createStackNavigator.tsx +13 -5
  86. package/src/__stubs__/window.tsx +5 -0
  87. package/src/createMemoryHistory.tsx +10 -3
  88. package/src/createStandardNavigationFactories.tsx +218 -0
  89. package/src/extractPathFromURL.tsx +1 -1
  90. package/src/getStateFromHref.tsx +8 -3
  91. package/src/index.tsx +4 -0
  92. package/src/native/SFSymbol.ios.tsx +73 -14
  93. package/src/native/SFSymbolViewNativeComponent.ts +22 -9
  94. package/src/native/types.tsx +278 -32
  95. package/src/useLinkBuilder.tsx +4 -2
  96. package/src/useLinking.native.tsx +17 -10
  97. package/src/useLinking.tsx +19 -2
  98. package/src/useMemoArray.tsx +41 -0
  99. package/src/useScrollToTop.tsx +2 -1
@@ -85,76 +85,280 @@ export type MaterialSymbolOptions = {
85
85
  color?: ColorValue | undefined;
86
86
  };
87
87
 
88
- export type SFSymbolScale = 'small' | 'medium' | 'large';
88
+ type SFSymbolScale = 'small' | 'medium' | 'large';
89
89
 
90
- export type SFSymbolMode =
90
+ type SFSymbolRenderingMode =
91
91
  | 'monochrome'
92
92
  | 'hierarchical'
93
93
  | 'palette'
94
94
  | 'multicolor';
95
95
 
96
- export type SFSymbolAnimationEffect =
96
+ export type SFSymbolEffectName =
97
97
  | 'bounce'
98
98
  | 'pulse'
99
99
  | 'appear'
100
100
  | 'disappear'
101
101
  | 'variableColor'
102
+ | 'scale'
102
103
  | 'breathe'
103
104
  | 'wiggle'
104
- | 'rotate';
105
+ | 'rotate'
106
+ | 'drawOn'
107
+ | 'drawOff';
105
108
 
106
- export type SFSymbolAnimationConfig = {
109
+ export type SFSymbolContentTransitionEffect = 'automatic' | 'replace';
110
+
111
+ export type SFSymbolEffectRepeat =
112
+ | 'continuous'
113
+ | 'nonRepeating'
114
+ | {
115
+ /**
116
+ * Number of times to repeat the effect.
117
+ */
118
+ count?: number | undefined;
119
+ /**
120
+ * Delay in seconds between repeated effect cycles.
121
+ */
122
+ delay?: number | undefined;
123
+ };
124
+
125
+ export type SFSymbolEffectScope = 'byLayer' | 'wholeSymbol' | 'individually';
126
+
127
+ export type SFSymbolEffectDirection =
128
+ | 'up'
129
+ | 'down'
130
+ | 'left'
131
+ | 'right'
132
+ | 'forward'
133
+ | 'backward'
134
+ | 'clockwise'
135
+ | 'counterClockwise';
136
+
137
+ export type SFSymbolBreatheVariant = 'plain' | 'pulse';
138
+
139
+ export type SFSymbolDrawDirection = 'reversed' | 'nonReversed';
140
+
141
+ export type SFSymbolInactiveLayers = 'hide' | 'dim';
142
+
143
+ type SFSymbolEffectBaseConfig = {
107
144
  /**
108
- * The animation effect to apply.
145
+ * Speed multiplier for the effect.
146
+ *
147
+ * @default 1
148
+ */
149
+ speed?: number | undefined;
150
+ /**
151
+ * Repeat behavior for the effect. Use an object for periodic repeats.
109
152
  */
110
- effect: SFSymbolAnimationEffect;
153
+ repeat?: SFSymbolEffectRepeat | undefined;
154
+ };
155
+
156
+ type SFSymbolScopedEffectConfig = SFSymbolEffectBaseConfig & {
111
157
  /**
112
- * Whether the animation repeats continuously.
158
+ * Whether to animate the whole symbol at once or by layer.
113
159
  *
114
- * @default false
160
+ * @default 'byLayer'
161
+ */
162
+ scope?: Extract<SFSymbolEffectScope, 'byLayer' | 'wholeSymbol'> | undefined;
163
+ };
164
+
165
+ type SFSymbolDirectionalEffectName = 'bounce' | 'appear' | 'disappear';
166
+
167
+ type SFSymbolDirectionalEffectConfig = SFSymbolScopedEffectConfig & {
168
+ /**
169
+ * The symbol effect to apply.
170
+ */
171
+ type: SFSymbolDirectionalEffectName;
172
+ /**
173
+ * The direction the symbol moves during the effect.
174
+ */
175
+ direction?: 'up' | 'down' | undefined;
176
+ };
177
+
178
+ type SFSymbolScaleEffectConfig = SFSymbolScopedEffectConfig & {
179
+ /**
180
+ * The symbol effect to apply.
181
+ */
182
+ type: 'scale';
183
+ /**
184
+ * Whether the symbol scales up or down.
185
+ */
186
+ direction?: 'up' | 'down' | undefined;
187
+ };
188
+
189
+ type SFSymbolBasicScopedEffectConfig = SFSymbolScopedEffectConfig & {
190
+ /**
191
+ * The symbol effect to apply.
192
+ */
193
+ type: 'pulse';
194
+ };
195
+
196
+ type SFSymbolBreatheEffectConfig = SFSymbolScopedEffectConfig & {
197
+ /**
198
+ * The symbol effect to apply.
199
+ */
200
+ type: 'breathe';
201
+ /**
202
+ * The breathe effect variant.
203
+ */
204
+ variant?: SFSymbolBreatheVariant | undefined;
205
+ };
206
+
207
+ type SFSymbolWiggleEffectConfig = SFSymbolScopedEffectConfig & {
208
+ /**
209
+ * The symbol effect to apply.
210
+ */
211
+ type: 'wiggle';
212
+ /**
213
+ * The direction the symbol wiggles toward.
214
+ */
215
+ direction?: SFSymbolEffectDirection | undefined;
216
+ /**
217
+ * A custom wiggle angle in degrees. Overrides `direction` when set.
218
+ */
219
+ angle?: number | undefined;
220
+ };
221
+
222
+ type SFSymbolRotateEffectConfig = SFSymbolScopedEffectConfig & {
223
+ /**
224
+ * The symbol effect to apply.
115
225
  */
116
- repeating?: boolean | undefined;
226
+ type: 'rotate';
117
227
  /**
118
- * Number of times to repeat the animation.
119
- * Ignored if `repeating` is `true`.
228
+ * Which way the symbol rotates.
120
229
  */
121
- repeatCount?: number | undefined;
230
+ direction?: 'clockwise' | 'counterClockwise' | undefined;
231
+ };
232
+
233
+ type SFSymbolDrawEffectConfig = SFSymbolEffectBaseConfig & {
122
234
  /**
123
- * Speed multiplier for the animation.
235
+ * The symbol effect to apply.
236
+ */
237
+ type: 'drawOn';
238
+ /**
239
+ * Whether to animate the whole symbol at once, by layer, or individually.
124
240
  *
125
- * @default 1
241
+ * @default 'byLayer'
126
242
  */
127
- speed?: number | undefined;
243
+ scope?: SFSymbolEffectScope | undefined;
244
+ };
245
+
246
+ type SFSymbolDrawOffEffectConfig = SFSymbolEffectBaseConfig & {
247
+ /**
248
+ * The symbol effect to apply.
249
+ */
250
+ type: 'drawOff';
128
251
  /**
129
- * Whether to animate the whole symbol at once or layer by layer.
252
+ * Whether to animate the whole symbol at once, by layer, or individually.
130
253
  *
131
- * @default false
254
+ * @default 'byLayer'
132
255
  */
133
- wholeSymbol?: boolean | undefined;
256
+ scope?: SFSymbolEffectScope | undefined;
134
257
  /**
135
- * Direction of the animation.
136
- * Applicable to `bounce` and `wiggle`.
258
+ * Whether the draw-off animation follows the symbol's authored draw
259
+ * order or plays it in reverse.
260
+ * - `nonReversed`: follows the symbol's draw order.
261
+ * - `reversed`: plays it in reverse.
137
262
  */
138
- direction?: 'up' | 'down' | undefined;
263
+ drawDirection?: SFSymbolDrawDirection | undefined;
264
+ };
265
+
266
+ type SFSymbolVariableColorEffectConfig = SFSymbolEffectBaseConfig & {
267
+ /**
268
+ * The symbol effect to apply.
269
+ */
270
+ type: 'variableColor';
139
271
  /**
140
272
  * Whether the variable color effect reverses with each cycle.
141
- * Only applicable to `variableColor`.
142
273
  *
143
274
  * @default false
144
275
  */
145
276
  reversing?: boolean | undefined;
146
277
  /**
147
- * Whether each layer remains changed until the end of the cycle.
148
- * Only applicable to `variableColor`.
278
+ * Whether layers light up cumulatively and stay active through the
279
+ * cycle, rather than one at a time.
149
280
  *
150
281
  * @default false
151
282
  */
152
283
  cumulative?: boolean | undefined;
284
+ /**
285
+ * How layers that aren't currently active are displayed.
286
+ * - `hide`: inactive layers are invisible.
287
+ * - `dim`: inactive layers stay visible but faded.
288
+ *
289
+ * Defaults to the symbol's standard appearance when unset.
290
+ */
291
+ inactiveLayers?: SFSymbolInactiveLayers | undefined;
153
292
  };
154
293
 
155
- export type SFSymbolAnimation =
156
- | SFSymbolAnimationEffect
157
- | SFSymbolAnimationConfig;
294
+ type SFSymbolEffectConfig =
295
+ | SFSymbolDirectionalEffectConfig
296
+ | SFSymbolScaleEffectConfig
297
+ | SFSymbolBasicScopedEffectConfig
298
+ | SFSymbolBreatheEffectConfig
299
+ | SFSymbolWiggleEffectConfig
300
+ | SFSymbolRotateEffectConfig
301
+ | SFSymbolDrawEffectConfig
302
+ | SFSymbolDrawOffEffectConfig
303
+ | SFSymbolVariableColorEffectConfig;
304
+
305
+ export type SFSymbolContentTransitionScope = 'byLayer' | 'wholeSymbol';
306
+
307
+ export type SFSymbolReplaceTransitionVariant = 'downUp' | 'upUp' | 'offUp';
308
+
309
+ type SFSymbolContentTransitionBaseConfig = {
310
+ /**
311
+ * Speed multiplier for the transition.
312
+ *
313
+ * @default 1
314
+ */
315
+ speed?: number | undefined;
316
+ };
317
+
318
+ type SFSymbolContentTransitionConfig =
319
+ | (SFSymbolContentTransitionBaseConfig & {
320
+ /**
321
+ * The transition effect to apply when the symbol `name` or `variableValue` changes.
322
+ */
323
+ type: 'automatic';
324
+ })
325
+ | (SFSymbolContentTransitionBaseConfig & {
326
+ /**
327
+ * The transition effect to apply when the symbol `name` or `variableValue` changes.
328
+ */
329
+ type: 'replace';
330
+ /**
331
+ * The direction the outgoing and incoming symbols move.
332
+ * - `downUp`: the old symbol slides down, the new one comes up.
333
+ * - `upUp`: both the old and new symbols move up.
334
+ * - `offUp`: the old symbol fades in place, the new one comes up.
335
+ */
336
+ variant?: SFSymbolReplaceTransitionVariant | undefined;
337
+ /**
338
+ * Whether to transition the whole symbol at once or by layer.
339
+ *
340
+ * @default 'byLayer'
341
+ */
342
+ scope?: SFSymbolContentTransitionScope | undefined;
343
+ /**
344
+ * Whether to prefer Magic Replace when possible.
345
+ *
346
+ * Falls back to regular Replace on iOS 17.
347
+ *
348
+ * @default false
349
+ */
350
+ magic?: boolean | undefined;
351
+ });
352
+
353
+ type SFSymbolEffect = SFSymbolEffectName | SFSymbolEffectConfig;
354
+
355
+ type SFSymbolContentTransition =
356
+ | SFSymbolContentTransitionEffect
357
+ | SFSymbolContentTransitionConfig;
358
+
359
+ type SFSymbolVariableValueMode = 'automatic' | 'color' | 'draw';
360
+
361
+ type SFSymbolColorRenderingMode = 'automatic' | 'flat' | 'gradient';
158
362
 
159
363
  export type SFSymbolOptions = {
160
364
  /**
@@ -163,6 +367,7 @@ export type SFSymbolOptions = {
163
367
  name: import('sf-symbols-typescript').SFSymbol;
164
368
  /**
165
369
  * The size of the symbol.
370
+ *
166
371
  * @default 24
167
372
  */
168
373
  size?: number | undefined;
@@ -184,11 +389,33 @@ export type SFSymbolOptions = {
184
389
  | (typeof FONT_WEIGHTS)[keyof typeof FONT_WEIGHTS]
185
390
  | undefined;
186
391
  /**
187
- * The scale of the symbol relative to the font size.
392
+ * The symbol's scale variant (`small`, `medium`, or `large`).
188
393
  *
189
394
  * @default 'medium'
190
395
  */
191
396
  scale?: SFSymbolScale | undefined;
397
+ /**
398
+ * The value used to customize variable symbols.
399
+ * Must be between `0` and `1`.
400
+ *
401
+ * Variable symbols (e.g. `wifi`, `speaker.wave.3`) have layers that
402
+ * activate progressively to represent a magnitude. This controls how
403
+ * many are shown: `0` renders the fewest, `1` the full symbol.
404
+ *
405
+ * Has no effect on symbols that aren't variable.
406
+ */
407
+ variableValue?: number | undefined;
408
+ /**
409
+ * How the partial state from `variableValue` is rendered.
410
+ * - `automatic`: the system chooses based on the symbol.
411
+ * - `color`: fades inactive layers using opacity.
412
+ * - `draw`: partially draws layers instead of fading them.
413
+ *
414
+ * Requires iOS 26+. Ignored on earlier versions.
415
+ *
416
+ * @default 'automatic'
417
+ */
418
+ variableValueMode?: SFSymbolVariableValueMode | undefined;
192
419
  /**
193
420
  * The rendering mode of the symbol.
194
421
  * - `monochrome`: Single color tint (default).
@@ -198,7 +425,7 @@ export type SFSymbolOptions = {
198
425
  *
199
426
  * @default 'monochrome'
200
427
  */
201
- mode?: SFSymbolMode | undefined;
428
+ renderingMode?: SFSymbolRenderingMode | undefined;
202
429
  /**
203
430
  * The colors for non-monochrome rendering modes.
204
431
  * - `hierarchical`: uses `primary` as the base color.
@@ -215,8 +442,27 @@ export type SFSymbolOptions = {
215
442
  }
216
443
  | undefined;
217
444
  /**
218
- * The animation effect to apply to the symbol.
445
+ * How color is applied across the symbol's layers.
446
+ * - `automatic`: the system chooses based on the symbol.
447
+ * - `flat`: a solid color per layer.
448
+ * - `gradient`: a gradient derived from each layer's color.
449
+ *
450
+ * Requires iOS 26+. Ignored on earlier versions.
451
+ *
452
+ * @default 'automatic'
453
+ */
454
+ colorRenderingMode?: SFSymbolColorRenderingMode | undefined;
455
+ /**
456
+ * The effect to apply to the symbol.
457
+ *
458
+ * Requires iOS 17+. Effects introduced in later iOS versions are ignored
459
+ * on earlier versions.
460
+ */
461
+ effect?: SFSymbolEffect | undefined;
462
+ /**
463
+ * The content transition to apply when the symbol `name` or `variableValue` changes.
464
+ *
219
465
  * Requires iOS 17+. Ignored on earlier versions.
220
466
  */
221
- animation?: SFSymbolAnimation | undefined;
467
+ contentTransition?: SFSymbolContentTransition | undefined;
222
468
  };
@@ -3,6 +3,7 @@ import {
3
3
  findFocusedRoute,
4
4
  getActionFromState,
5
5
  getPathFromState,
6
+ NavigationContainerRefContext,
6
7
  NavigationHelpersContext,
7
8
  NavigationRouteContext,
8
9
  useStateForPath,
@@ -109,6 +110,7 @@ export function useBuildHref() {
109
110
  * Helper to build a navigation action from a href based on the linking options.
110
111
  */
111
112
  export function useBuildAction() {
113
+ const navigation = React.use(NavigationContainerRefContext);
112
114
  const { options } = React.use(LinkingContext);
113
115
 
114
116
  const getActionFromStateHelper =
@@ -116,7 +118,7 @@ export function useBuildAction() {
116
118
 
117
119
  const buildAction = React.useCallback(
118
120
  (href: string) => {
119
- const state = getStateFromHref(href, options);
121
+ const state = getStateFromHref(href, options, navigation?.getRootState());
120
122
 
121
123
  if (state) {
122
124
  const action = getActionFromStateHelper(state, options?.config);
@@ -128,7 +130,7 @@ export function useBuildAction() {
128
130
  );
129
131
  }
130
132
  },
131
- [options, getActionFromStateHelper]
133
+ [navigation, options, getActionFromStateHelper]
132
134
  );
133
135
 
134
136
  return buildAction;
@@ -2,6 +2,7 @@ import {
2
2
  getActionFromState as getActionFromStateDefault,
3
3
  getStateFromPath as getStateFromPathDefault,
4
4
  type NavigationContainerRef,
5
+ type NavigationState,
5
6
  type ParamListBase,
6
7
  useNavigationIndependentTree,
7
8
  } from '@react-navigation/core';
@@ -115,18 +116,22 @@ export function useLinking<ParamList extends ParamListBase>(
115
116
  });
116
117
 
117
118
  const getStateFromURL = React.useCallback(
118
- (url: string | null | undefined) => {
119
+ (url: string | null | undefined, previous: NavigationState | undefined) => {
119
120
  if (!url) {
120
121
  return undefined;
121
122
  }
122
123
 
123
124
  try {
124
- return getStateFromHref(url, {
125
- prefixes: prefixesRef.current,
126
- filter: filterRef.current,
127
- config: configRef.current,
128
- getStateFromPath: getStateFromPathRef.current,
129
- });
125
+ return getStateFromHref(
126
+ url,
127
+ {
128
+ prefixes: prefixesRef.current,
129
+ filter: filterRef.current,
130
+ config: configRef.current,
131
+ getStateFromPath: getStateFromPathRef.current,
132
+ },
133
+ previous
134
+ );
130
135
  } catch (e) {
131
136
  return undefined;
132
137
  }
@@ -143,14 +148,14 @@ export function useLinking<ParamList extends ParamListBase>(
143
148
  if (url != null) {
144
149
  if (typeof url !== 'string') {
145
150
  return url.then((url) => {
146
- const state = getStateFromURL(url);
151
+ const state = getStateFromURL(url, undefined);
147
152
 
148
153
  return state;
149
154
  });
150
155
  }
151
156
  }
152
157
 
153
- state = getStateFromURL(url);
158
+ state = getStateFromURL(url, undefined);
154
159
  }
155
160
 
156
161
  const thenable: Thenable<ResultState | undefined> = {
@@ -169,7 +174,9 @@ export function useLinking<ParamList extends ParamListBase>(
169
174
  }
170
175
 
171
176
  const navigation = ref.current;
172
- const state = navigation ? getStateFromURL(url) : undefined;
177
+ const state = navigation
178
+ ? getStateFromURL(url, navigation.getRootState())
179
+ : undefined;
173
180
 
174
181
  if (navigation) {
175
182
  REACT_NAVIGATION_DEVTOOLS.get(navigation)?.listeners.forEach(
@@ -56,6 +56,10 @@ const findMatchingState = <T extends NavigationState>(
56
56
  const aRoute = a.routes[a.index];
57
57
  const bRoute = b.routes[b.index];
58
58
 
59
+ if (aRoute == null || bRoute == null) {
60
+ return [a, b];
61
+ }
62
+
59
63
  const aChildState = aRoute.state as T | undefined;
60
64
  const bChildState = bRoute.state as T | undefined;
61
65
 
@@ -88,6 +92,11 @@ const isPoppingLastEntry = (
88
92
  ): boolean => {
89
93
  const currentRoute = current.routes[current.index];
90
94
  const recordRoute = record.routes[record.index];
95
+
96
+ if (currentRoute == null || recordRoute == null) {
97
+ return false;
98
+ }
99
+
91
100
  const currentRouteHistory = currentRoute.history;
92
101
  const recordRouteHistory = recordRoute.history ?? [];
93
102
 
@@ -106,7 +115,11 @@ const isPoppingLastEntry = (
106
115
  const recordRoutes = getRoutesUntilIndex(record);
107
116
 
108
117
  if (currentRoutes.length === recordRoutes.length + 1) {
109
- return recordRoutes.every((route, i) => route.key === currentRoutes[i].key);
118
+ return recordRoutes.every((route, i) => {
119
+ const currentRoute = currentRoutes[i];
120
+
121
+ return currentRoute != null && route.key === currentRoute.key;
122
+ });
110
123
  }
111
124
 
112
125
  return false;
@@ -302,7 +315,11 @@ export function useLinking<ParamList extends ParamListBase>(
302
315
  let state: ResultState | undefined;
303
316
 
304
317
  try {
305
- state = getStateFromPathRef.current(path, configRef.current);
318
+ state = getStateFromPathRef.current(
319
+ path,
320
+ configRef.current,
321
+ navigation.getRootState()
322
+ );
306
323
  } catch (e) {
307
324
  console.error(e);
308
325
 
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+
3
+ export function useMemoArray<T>(
4
+ entries: [item: T, deps: readonly unknown[]][]
5
+ ): T[] {
6
+ const previousRef = React.useRef<
7
+ | {
8
+ entries: { item: T; deps: readonly unknown[] }[];
9
+ items: T[];
10
+ }
11
+ | undefined
12
+ >(undefined);
13
+
14
+ const previous = previousRef.current;
15
+ const next = entries.map(([item, deps], index) => {
16
+ const previousEntry = previous?.entries[index];
17
+ const depsEqual =
18
+ previousEntry &&
19
+ previousEntry.deps.length === deps.length &&
20
+ previousEntry.deps.every((it, index) => Object.is(it, deps[index]));
21
+
22
+ return depsEqual ? previousEntry : { item, deps };
23
+ });
24
+
25
+ if (
26
+ previous &&
27
+ previous.entries.length === next.length &&
28
+ next.every((entry, index) => entry === previous.entries[index])
29
+ ) {
30
+ return previous.items;
31
+ }
32
+
33
+ const items = next.map((entry) => entry.item);
34
+
35
+ previousRef.current = {
36
+ entries: next,
37
+ items,
38
+ };
39
+
40
+ return items;
41
+ }
@@ -91,9 +91,10 @@ export function useScrollToTop(ref: React.RefObject<ScrollableWrapper>) {
91
91
 
92
92
  // In a nested stack navigator, tab press resets the stack to first screen
93
93
  // So we should scroll to top only when we are on first screen
94
+ const firstRoute = navigation.getState().routes[0];
94
95
  const isFirst =
95
96
  tabNavigations.includes(navigation) ||
96
- navigation.getState().routes[0].key === route.key;
97
+ firstRoute?.key === route.key;
97
98
 
98
99
  // Run the operation in the next frame so we're sure all listeners have been run
99
100
  // This is necessary to know if preventDefault() has been called