@react-navigation/core 8.0.0-alpha.19 → 8.0.0-alpha.20

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 (144) hide show
  1. package/lib/module/BaseNavigationContainer.js +6 -2
  2. package/lib/module/BaseNavigationContainer.js.map +1 -1
  3. package/lib/module/StaticNavigation.js +72 -61
  4. package/lib/module/StaticNavigation.js.map +1 -1
  5. package/lib/module/findFocusedRoute.js +7 -4
  6. package/lib/module/findFocusedRoute.js.map +1 -1
  7. package/lib/module/getActionFromState.js +25 -12
  8. package/lib/module/getActionFromState.js.map +1 -1
  9. package/lib/module/getPathFromState.js +24 -9
  10. package/lib/module/getPathFromState.js.map +1 -1
  11. package/lib/module/getPatternParts.js +3 -0
  12. package/lib/module/getPatternParts.js.map +1 -1
  13. package/lib/module/getStateFromPath.js +164 -78
  14. package/lib/module/getStateFromPath.js.map +1 -1
  15. package/lib/module/index.js +1 -1
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/module/types.js +8 -0
  18. package/lib/module/types.js.map +1 -1
  19. package/lib/module/useDescriptors.js +13 -6
  20. package/lib/module/useDescriptors.js.map +1 -1
  21. package/lib/module/useFocusEvents.js +5 -1
  22. package/lib/module/useFocusEvents.js.map +1 -1
  23. package/lib/module/useNavigation.js.map +1 -1
  24. package/lib/module/useNavigationBuilder.js +18 -5
  25. package/lib/module/useNavigationBuilder.js.map +1 -1
  26. package/lib/module/useNavigationCache.js +1 -1
  27. package/lib/module/useNavigationCache.js.map +1 -1
  28. package/lib/module/useNavigationState.js.map +1 -1
  29. package/lib/module/useOnAction.js +1 -1
  30. package/lib/module/useOnAction.js.map +1 -1
  31. package/lib/module/useRoute.js.map +1 -1
  32. package/lib/module/validatePathConfig.js +2 -1
  33. package/lib/module/validatePathConfig.js.map +1 -1
  34. package/lib/typescript/src/BaseNavigationContainer.d.ts +2 -2
  35. package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
  36. package/lib/typescript/src/EnsureSingleNavigator.d.ts +1 -1
  37. package/lib/typescript/src/EnsureSingleNavigator.d.ts.map +1 -1
  38. package/lib/typescript/src/Group.d.ts +1 -1
  39. package/lib/typescript/src/Group.d.ts.map +1 -1
  40. package/lib/typescript/src/NavigationBuilderContext.d.ts +1 -1
  41. package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
  42. package/lib/typescript/src/NavigationContainerRefContext.d.ts +1 -1
  43. package/lib/typescript/src/NavigationContainerRefContext.d.ts.map +1 -1
  44. package/lib/typescript/src/NavigationHelpersContext.d.ts +1 -1
  45. package/lib/typescript/src/NavigationHelpersContext.d.ts.map +1 -1
  46. package/lib/typescript/src/NavigationIndependentTree.d.ts +1 -1
  47. package/lib/typescript/src/NavigationIndependentTree.d.ts.map +1 -1
  48. package/lib/typescript/src/NavigationProvider.d.ts +6 -6
  49. package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
  50. package/lib/typescript/src/PreventRemoveProvider.d.ts +1 -1
  51. package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
  52. package/lib/typescript/src/SceneView.d.ts +3 -2
  53. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  54. package/lib/typescript/src/Screen.d.ts +1 -1
  55. package/lib/typescript/src/Screen.d.ts.map +1 -1
  56. package/lib/typescript/src/StaticNavigation.d.ts +68 -73
  57. package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
  58. package/lib/typescript/src/createNavigationContainerRef.d.ts +1 -1
  59. package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
  60. package/lib/typescript/src/createNavigatorFactory.d.ts +3 -3
  61. package/lib/typescript/src/createNavigatorFactory.d.ts.map +1 -1
  62. package/lib/typescript/src/findFocusedRoute.d.ts.map +1 -1
  63. package/lib/typescript/src/getActionFromState.d.ts +1 -1
  64. package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
  65. package/lib/typescript/src/getPathFromState.d.ts +1 -1
  66. package/lib/typescript/src/getPathFromState.d.ts.map +1 -1
  67. package/lib/typescript/src/getPatternParts.d.ts +1 -0
  68. package/lib/typescript/src/getPatternParts.d.ts.map +1 -1
  69. package/lib/typescript/src/getStateFromPath.d.ts +2 -2
  70. package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
  71. package/lib/typescript/src/index.d.ts +34 -33
  72. package/lib/typescript/src/index.d.ts.map +1 -1
  73. package/lib/typescript/src/theming/ThemeContext.d.ts +1 -1
  74. package/lib/typescript/src/theming/ThemeContext.d.ts.map +1 -1
  75. package/lib/typescript/src/theming/ThemeProvider.d.ts +2 -2
  76. package/lib/typescript/src/theming/ThemeProvider.d.ts.map +1 -1
  77. package/lib/typescript/src/theming/useTheme.d.ts +1 -1
  78. package/lib/typescript/src/theming/useTheme.d.ts.map +1 -1
  79. package/lib/typescript/src/types.d.ts +72 -37
  80. package/lib/typescript/src/types.d.ts.map +1 -1
  81. package/lib/typescript/src/useChildListeners.d.ts +3 -3
  82. package/lib/typescript/src/useChildListeners.d.ts.map +1 -1
  83. package/lib/typescript/src/useComponent.d.ts +1 -1
  84. package/lib/typescript/src/useComponent.d.ts.map +1 -1
  85. package/lib/typescript/src/useDescriptors.d.ts +5 -5
  86. package/lib/typescript/src/useDescriptors.d.ts.map +1 -1
  87. package/lib/typescript/src/useEventEmitter.d.ts +1 -1
  88. package/lib/typescript/src/useEventEmitter.d.ts.map +1 -1
  89. package/lib/typescript/src/useFocusEvents.d.ts +2 -2
  90. package/lib/typescript/src/useFocusEvents.d.ts.map +1 -1
  91. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts +2 -2
  92. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts.map +1 -1
  93. package/lib/typescript/src/useKeyedChildListeners.d.ts +3 -3
  94. package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
  95. package/lib/typescript/src/useNavigation.d.ts +5 -3
  96. package/lib/typescript/src/useNavigation.d.ts.map +1 -1
  97. package/lib/typescript/src/useNavigationBuilder.d.ts +7 -7
  98. package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
  99. package/lib/typescript/src/useNavigationCache.d.ts +3 -3
  100. package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
  101. package/lib/typescript/src/useNavigationContainerRef.d.ts +1 -1
  102. package/lib/typescript/src/useNavigationContainerRef.d.ts.map +1 -1
  103. package/lib/typescript/src/useNavigationHelpers.d.ts +4 -4
  104. package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
  105. package/lib/typescript/src/useNavigationState.d.ts +2 -2
  106. package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
  107. package/lib/typescript/src/useOnAction.d.ts +3 -3
  108. package/lib/typescript/src/useOnAction.d.ts.map +1 -1
  109. package/lib/typescript/src/useOnGetState.d.ts +1 -1
  110. package/lib/typescript/src/useOnGetState.d.ts.map +1 -1
  111. package/lib/typescript/src/useOnPreventRemove.d.ts +3 -3
  112. package/lib/typescript/src/useOnPreventRemove.d.ts.map +1 -1
  113. package/lib/typescript/src/useOptionsGetters.d.ts +1 -1
  114. package/lib/typescript/src/useOptionsGetters.d.ts.map +1 -1
  115. package/lib/typescript/src/usePreventRemoveContext.d.ts +1 -1
  116. package/lib/typescript/src/useRoute.d.ts +2 -2
  117. package/lib/typescript/src/useRoute.d.ts.map +1 -1
  118. package/lib/typescript/src/useRouteCache.d.ts +2 -2
  119. package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
  120. package/lib/typescript/src/useStateForPath.d.ts +1 -1
  121. package/lib/typescript/src/useStateForPath.d.ts.map +1 -1
  122. package/lib/typescript/src/utilities.d.ts +4 -3
  123. package/lib/typescript/src/utilities.d.ts.map +1 -1
  124. package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
  125. package/package.json +18 -17
  126. package/src/BaseNavigationContainer.tsx +7 -2
  127. package/src/StaticNavigation.tsx +220 -248
  128. package/src/findFocusedRoute.tsx +10 -5
  129. package/src/getActionFromState.tsx +43 -30
  130. package/src/getPathFromState.tsx +40 -20
  131. package/src/getPatternParts.tsx +8 -0
  132. package/src/getStateFromPath.tsx +244 -67
  133. package/src/index.tsx +39 -1
  134. package/src/types.tsx +167 -122
  135. package/src/useDescriptors.tsx +22 -10
  136. package/src/useFocusEvents.tsx +7 -1
  137. package/src/useNavigation.tsx +8 -4
  138. package/src/useNavigationBuilder.tsx +22 -7
  139. package/src/useNavigationCache.tsx +4 -4
  140. package/src/useNavigationState.tsx +3 -3
  141. package/src/useOnAction.tsx +1 -1
  142. package/src/useRoute.tsx +4 -2
  143. package/src/utilities.tsx +17 -11
  144. package/src/validatePathConfig.tsx +1 -0
package/src/types.tsx CHANGED
@@ -55,10 +55,10 @@ export interface RootNavigator {}
55
55
  export interface Theme {}
56
56
 
57
57
  export type RootParamList =
58
- RootNavigator extends PrivateValueStore<[infer ParamList, any, any]>
59
- ? ParamList extends {}
60
- ? ParamList
61
- : {}
58
+ RootNavigator extends PrivateValueStore<
59
+ [infer ParamList extends {}, any, any, any]
60
+ >
61
+ ? ParamList
62
62
  : {};
63
63
 
64
64
  export type DefaultNavigatorOptions<
@@ -273,7 +273,7 @@ export type EventEmitter<in out EventMap extends EventMapBase> = {
273
273
  >;
274
274
  };
275
275
 
276
- export class PrivateValueStore<T extends [any, any, any]> {
276
+ export class PrivateValueStore<T extends [any, any, any, any]> {
277
277
  /**
278
278
  * UGLY HACK! DO NOT USE THE TYPE!!!
279
279
  *
@@ -408,7 +408,7 @@ type NavigationHelpersCommon<
408
408
  * So don't use it in `render`.
409
409
  */
410
410
  getState(): State;
411
- } & PrivateValueStore<[ParamList, unknown, unknown]>;
411
+ };
412
412
 
413
413
  type ParamType<
414
414
  ParamList extends {},
@@ -456,7 +456,8 @@ export type NavigationHelpers<
456
456
  EventMap extends EventMapBase = {},
457
457
  > = NavigationHelpersCommon<ParamList> &
458
458
  EventEmitter<EventMap> &
459
- NavigationHelpersRoute<ParamList, keyof ParamList>;
459
+ NavigationHelpersRoute<ParamList, keyof ParamList> &
460
+ PrivateValueStore<[ParamList, unknown, unknown, unknown]>;
460
461
 
461
462
  export type NavigationContainerProps = {
462
463
  /**
@@ -489,14 +490,17 @@ export type NavigationContainerProps = {
489
490
  children: React.ReactNode;
490
491
  };
491
492
 
492
- export type NavigationProp<
493
+ // Everything in `NavigationProp` except `getParent` and the private brand.
494
+ // The composite navigation prop intersects this directly, so it doesn't have
495
+ // to walk `NavigationProp`'s members with `Omit` to drop `getParent`/the brand.
496
+ type NavigationPropBase<
493
497
  ParamList extends {},
494
498
  RouteName extends keyof ParamList = KeyOf<ParamList>,
495
499
  State extends NavigationState = NavigationState<ParamList>,
496
500
  ScreenOptions extends {} = {},
497
501
  EventMap extends EventMapBase = {},
498
502
  ActionHelpers extends Record<string, (...args: any) => void> = {},
499
- > = Omit<NavigationHelpersCommon<ParamList, State>, 'getParent'> & {
503
+ > = NavigationHelpersCommon<ParamList, State> & {
500
504
  /**
501
505
  * Update the options for the route.
502
506
  * The options object will be shallow merged with default options object.
@@ -504,6 +508,25 @@ export type NavigationProp<
504
508
  * @param options Partial options object for the current screen.
505
509
  */
506
510
  setOptions(options: Partial<ScreenOptions>): void;
511
+ } & NavigationHelpersRoute<ParamList, RouteName> &
512
+ ActionHelpers &
513
+ EventConsumer<EventMap & EventMapCore<State>>;
514
+
515
+ export type NavigationProp<
516
+ ParamList extends {},
517
+ RouteName extends keyof ParamList = KeyOf<ParamList>,
518
+ State extends NavigationState = NavigationState<ParamList>,
519
+ ScreenOptions extends {} = {},
520
+ EventMap extends EventMapBase = {},
521
+ ActionHelpers extends Record<string, (...args: any) => void> = {},
522
+ > = NavigationPropBase<
523
+ ParamList,
524
+ RouteName,
525
+ State,
526
+ ScreenOptions,
527
+ EventMap,
528
+ ActionHelpers
529
+ > & {
507
530
  /**
508
531
  * Returns the navigation prop of the parent screen.
509
532
  * If a route name is provided, the navigation prop from the parent screen with matching route name (including current) will be returned.
@@ -522,10 +545,7 @@ export type NavigationProp<
522
545
  ActionHelpers
523
546
  >;
524
547
  getParent(): NavigationProp<ParamListBase> | undefined;
525
- } & NavigationHelpersRoute<ParamList, RouteName> &
526
- ActionHelpers &
527
- EventConsumer<EventMap & EventMapCore<State>> &
528
- PrivateValueStore<[ParamList, RouteName, EventMap]>;
548
+ } & PrivateValueStore<[ParamList, RouteName, EventMap, ActionHelpers]>;
529
549
 
530
550
  export type RouteProp<
531
551
  in out ParamList extends ParamListBase,
@@ -559,30 +579,38 @@ type CompositeNavigationPropInternal<
559
579
  ParamList extends {},
560
580
  RouteName extends keyof ParamList,
561
581
  EventMap extends EventMapBase,
562
- > = Omit<A & B, keyof NavigationProp<any, any, any, any, any>> &
563
- Omit<
564
- NavigationProp<
582
+ > = // Action helpers are read from the private brand (4th slot) instead of
583
+ // `Omit<A & B, keyof NavigationProp>`, which had to walk the whole (possibly
584
+ // deeply composed) member set of `A & B` to drop the standard members.
585
+ ActionHelpersOfNavigationProp<A> &
586
+ ActionHelpersOfNavigationProp<B> &
587
+ // Intersect the brand-free base directly instead of `Omit`-ing `getParent`
588
+ // off a full `NavigationProp`, so we skip a mapped-type pass per composite.
589
+ NavigationPropBase<
565
590
  ParamList,
566
591
  RouteName,
567
592
  StateOfNavigationProp<A>,
568
593
  ScreenOptionsOfNavigationProp<A>,
569
594
  EventMap
570
- >,
571
- 'getParent'
572
- > & {
573
- getParent: A['getParent'] & B['getParent'];
574
- } & // Mapped types don't preserve protected members
575
- // So `Omit` drops `PrivateValueStore`'s `protected` brand
576
- // We add it back so this can be used for type inference
577
- PrivateValueStore<[ParamList, RouteName, EventMap]>;
578
-
579
- type ParamListOfNavigationProp<T> =
580
- T extends PrivateValueStore<[infer ParamList, any, any]> ? ParamList : never;
581
-
582
- type RouteNameOfNavigationProp<T> =
583
- T extends PrivateValueStore<[any, infer RouteName, any]>
584
- ? RouteName
585
- : unknown;
595
+ > & {
596
+ getParent: A['getParent'] & B['getParent'];
597
+ } & PrivateValueStore<
598
+ [
599
+ ParamList,
600
+ RouteName,
601
+ EventMap,
602
+ ActionHelpersOfNavigationProp<A> & ActionHelpersOfNavigationProp<B>,
603
+ ]
604
+ >;
605
+
606
+ type PrivateValueOfNavigationProp<T> =
607
+ T extends PrivateValueStore<infer Value> ? Value : [never, unknown, {}, {}];
608
+
609
+ type ParamListOfNavigationProp<T> = PrivateValueOfNavigationProp<T>[0];
610
+
611
+ type RouteNameOfNavigationProp<T> = PrivateValueOfNavigationProp<T>[1];
612
+
613
+ type ActionHelpersOfNavigationProp<T> = PrivateValueOfNavigationProp<T>[3];
586
614
 
587
615
  type StateOfNavigationProp<T> = T extends {
588
616
  getState: () => infer State extends NavigationState;
@@ -596,8 +624,7 @@ type ScreenOptionsOfNavigationProp<T> = T extends {
596
624
  ? ScreenOptions
597
625
  : {};
598
626
 
599
- type EventMapOfNavigationProp<T> =
600
- T extends PrivateValueStore<[any, any, infer EventMap]> ? EventMap : {};
627
+ type EventMapOfNavigationProp<T> = PrivateValueOfNavigationProp<T>[2];
601
628
 
602
629
  export type CompositeScreenProps<
603
630
  in out A extends {
@@ -986,7 +1013,12 @@ export type GenericNavigation<ParamList extends {}> = Omit<
986
1013
  export type RouteForName<
987
1014
  ParamList extends {},
988
1015
  RouteName extends string,
989
- > = Extract<ParamListRoute<ParamList>, { name: RouteName }>;
1016
+ > = RouteForNameInternal<RouteName, ParamListRoute<ParamList>>;
1017
+
1018
+ type RouteForNameInternal<
1019
+ RouteName extends string,
1020
+ Routes,
1021
+ > = string extends RouteName ? Routes : Extract<Routes, { name: RouteName }>;
990
1022
 
991
1023
  type ParamListRoute<ParamList extends {}> = {
992
1024
  [RouteName in keyof ParamList]: NavigatorScreenParams<{}> extends ParamList[RouteName]
@@ -1002,11 +1034,10 @@ type MaybeParamListRoute<ParamList extends {}> = ParamList extends ParamListBase
1002
1034
 
1003
1035
  type BasicNavigationComposite<
1004
1036
  Navigation extends NavigationProp<any, any, any, any, any>,
1005
- Parent,
1006
- > =
1007
- Parent extends NavigationProp<any, any, any, any, any>
1008
- ? CompositeNavigationProp<Navigation, Parent>
1009
- : Navigation;
1037
+ Parent extends NavigationProp<any, any, any, any, any> | undefined,
1038
+ > = Parent extends undefined
1039
+ ? Navigation
1040
+ : CompositeNavigationProp<Navigation, NonNullable<Parent>>;
1010
1041
 
1011
1042
  type BasicNavigationList<
1012
1043
  ParamList extends {},
@@ -1018,11 +1049,13 @@ type BasicNavigationList<
1018
1049
  ? NotUndefined<ParamList[RouteName]> extends NavigatorScreenParams<
1019
1050
  infer T
1020
1051
  >
1021
- ? BasicNavigationList<
1022
- T,
1023
- ExcludedRouteNames,
1024
- NavigationProp<ParamList, RouteName>
1025
- >
1052
+ ? keyof T extends ExcludedRouteNames
1053
+ ? {}
1054
+ : BasicNavigationList<
1055
+ T,
1056
+ ExcludedRouteNames,
1057
+ NavigationProp<ParamList, RouteName>
1058
+ >
1026
1059
  : {}
1027
1060
  : {}) &
1028
1061
  (RouteName extends ExcludedRouteNames
@@ -1037,86 +1070,83 @@ type BasicNavigationList<
1037
1070
  >;
1038
1071
 
1039
1072
  export type NavigationListForNavigator<Navigator> =
1040
- Navigator extends TypedNavigator<infer Bag, any>
1041
- ? Bag['NavigationList']
1042
- : Navigator extends PrivateValueStore<[any, infer NavigationList, any]>
1043
- ? NavigationList
1044
- : {};
1045
-
1046
- export type NavigationListForNested<Navigator> = FlatType<
1047
- NavigationListForNestedInternal<Navigator> &
1048
- (Navigator extends TypedNavigator<infer Bag, any>
1049
- ? BasicNavigationList<
1050
- Bag['ParamList'],
1051
- keyof NavigationListForNestedInternal<Navigator>,
1052
- undefined
1053
- >
1054
- : Navigator extends PrivateValueStore<[infer ParamList, any, any]>
1055
- ? ParamList extends {}
1056
- ? BasicNavigationList<
1057
- ParamList,
1058
- keyof NavigationListForNestedInternal<Navigator>,
1059
- undefined
1060
- >
1061
- : {}
1062
- : {})
1063
- >;
1064
-
1065
- type NavigationListForNestedInternal<Navigator> =
1066
- NavigationListForNavigator<Navigator> &
1067
- NavigationListForStaticConfig<
1068
- NavigationListForNavigator<Navigator>,
1069
- Navigator
1070
- >;
1071
-
1072
- type NavigationListWithComposite<
1073
- in out Parent extends NavigationProp<any, any, any, any, any>,
1074
- in out NavigatorList extends Record<string, any>,
1075
- > = {
1076
- [K in keyof NavigatorList]: CompositeNavigationProp<NavigatorList[K], Parent>;
1077
- };
1078
-
1079
- type NavigationListForStaticConfig<ParentList, Navigator> = Navigator extends {
1073
+ Navigator extends PrivateValueStore<infer Value> ? Value[1] : {};
1074
+
1075
+ export type NavigationListForNested<Navigator> =
1076
+ NavigationListForNestedInternal<Navigator> extends infer NavigationList
1077
+ ? Navigator extends PrivateValueStore<[infer ParamList, any, any, any]>
1078
+ ? ParamList extends {}
1079
+ ? NavigationList &
1080
+ BasicNavigationList<ParamList, keyof NavigationList, undefined>
1081
+ : NavigationList
1082
+ : NavigationList
1083
+ : never;
1084
+
1085
+ type NavigationListForNestedInternal<
1086
+ Navigator,
1087
+ Parent = undefined,
1088
+ NavigatorList extends Record<string, any> =
1089
+ NavigationListForNavigator<Navigator>,
1090
+ // This navigator's own routes, each composed with the accumulated parent.
1091
+ // It's threaded into the recursion as the parent for nested navigators so
1092
+ // each route is composed with its ancestors exactly once, instead of
1093
+ // re-wrapping the whole descendant list at every level (which is quadratic
1094
+ // in the nesting depth).
1095
+ ComposedList = ComposeNavigationList<NavigatorList, Parent>,
1096
+ > = Navigator extends {
1080
1097
  readonly config: {
1081
- screens?: any;
1082
- groups?: any;
1098
+ readonly screens?: infer Screens;
1099
+ readonly groups?: infer Groups;
1083
1100
  };
1084
1101
  }
1085
- ? NavigationListForScreens<ParentList, Navigator['config']['screens']> &
1086
- NavigationListForGroups<ParentList, Navigator['config']['groups']>
1102
+ ? ComposedList &
1103
+ NavigationListForScreens<ComposedList, Screens> &
1104
+ NavigationListForGroups<ComposedList, Groups>
1105
+ : ComposedList;
1106
+
1107
+ // Compose every entry in a navigator's list with the accumulated parent.
1108
+ // When there's no parent (root navigator), the list is returned as-is so the
1109
+ // common shallow case doesn't pay for a redundant mapped type.
1110
+ type ComposeNavigationList<NavigatorList extends Record<string, any>, Parent> =
1111
+ Parent extends NavigationProp<any, any, any, any, any>
1112
+ ? {
1113
+ [K in keyof NavigatorList]: CompositeNavigationProp<
1114
+ NavigatorList[K],
1115
+ Parent
1116
+ >;
1117
+ }
1118
+ : NavigatorList;
1119
+
1120
+ type NavigationListForScreens<ParentList, Screens> = Screens extends {}
1121
+ ? UnionToIntersection<
1122
+ {
1123
+ // Only check screens with static config to avoid overly-complex types
1124
+ // Otherwise TypeScript fails to load the types due to complexity
1125
+ [K in keyof Screens]: Screens[K] extends { config: any }
1126
+ ? K extends keyof ParentList
1127
+ ? NavigationListForNestedInternal<Screens[K], ParentList[K]>
1128
+ : never
1129
+ : Screens[K] extends { screen: { config: any } }
1130
+ ? K extends keyof ParentList
1131
+ ? NavigationListForNestedInternal<
1132
+ Screens[K]['screen'],
1133
+ ParentList[K]
1134
+ >
1135
+ : never
1136
+ : never;
1137
+ }[keyof Screens]
1138
+ >
1087
1139
  : {};
1088
1140
 
1089
- type NavigationListForScreens<ParentList, Screens> = UnionToIntersection<
1090
- {
1091
- // Only check screens with static config to avoid overly-complex types
1092
- // Otherwise TypeScript fails to load the types due to complexity
1093
- [K in keyof Screens]: ParentList extends Record<K, any>
1094
- ? Screens[K] extends { config: any }
1095
- ? NavigationListWithComposite<
1096
- ParentList[K],
1097
- NavigationListForNested<Screens[K]>
1098
- >
1099
- : Screens[K] extends { screen: { config: any } }
1100
- ? NavigationListWithComposite<
1101
- ParentList[K],
1102
- NavigationListForNested<Screens[K]['screen']>
1103
- >
1104
- : {}
1105
- : {};
1106
- }[keyof Screens]
1107
- >;
1108
-
1109
- type NavigationListForGroups<ParentList, Groups> =
1110
- Groups extends Record<string, { screens: any }>
1111
- ? UnionToIntersection<
1112
- {
1113
- [K in keyof Groups]: NavigationListForScreens<
1114
- ParentList,
1115
- Groups[K]['screens']
1116
- >;
1117
- }[keyof Groups]
1118
- >
1119
- : {};
1141
+ type NavigationListForGroups<ParentList, Groups> = Groups extends {}
1142
+ ? UnionToIntersection<
1143
+ {
1144
+ [K in keyof Groups]: Groups[K] extends { screens: any }
1145
+ ? NavigationListForScreens<ParentList, Groups[K]['screens']>
1146
+ : never;
1147
+ }[keyof Groups]
1148
+ >
1149
+ : {};
1120
1150
 
1121
1151
  export type NavigationContainerRef<ParamList extends {}> = Omit<
1122
1152
  NavigationHelpers<ParamList>,
@@ -1213,7 +1243,9 @@ type TypedNavigatorComponent<Bag extends NavigatorTypeBagBase> =
1213
1243
  type TypedNavigatorStaticDecorated<Bag extends NavigatorTypeBagBase, Config> = {
1214
1244
  getComponent: () => React.ComponentType<{}>;
1215
1245
  config: Config;
1216
- } & PrivateValueStore<[Bag['ParamList'], Bag['NavigationList'], unknown]>;
1246
+ } & PrivateValueStore<
1247
+ [Bag['ParamList'], Bag['NavigationList'], unknown, unknown]
1248
+ >;
1217
1249
 
1218
1250
  type TypedNavigatorStatic<
1219
1251
  in out Bag extends NavigatorTypeBagBase,
@@ -1241,7 +1273,9 @@ export type TypedNavigator<
1241
1273
  Bag['Navigator']
1242
1274
  >
1243
1275
  : TypedNavigatorStatic<Bag, Config>) &
1244
- PrivateValueStore<[Bag['ParamList'], Bag['NavigationList'], unknown]>;
1276
+ PrivateValueStore<
1277
+ [Bag['ParamList'], Bag['NavigationList'], unknown, unknown]
1278
+ >;
1245
1279
 
1246
1280
  type TypedNavigatorInternal<
1247
1281
  in out ParamList extends ParamListBase,
@@ -1357,6 +1391,17 @@ type PathConfigAlias<Params> = {
1357
1391
  * ```
1358
1392
  */
1359
1393
  parse?: ParseConfig<Params> | undefined;
1394
+ /**
1395
+ * Whether this path can resolve to multiple routes.
1396
+ * Both routes should specify `shared: true` for this to work.
1397
+ * By default, a path can only resolve to one route.
1398
+ *
1399
+ * This is useful when same screen used in multiple navigators,
1400
+ * e.g. tabs with stacks containing profile screen in each stack.
1401
+ *
1402
+ * The path defined first will be the canonical path.
1403
+ */
1404
+ shared?: boolean | undefined;
1360
1405
  };
1361
1406
 
1362
1407
  export type PathConfig<Params> = FlatType<
@@ -114,9 +114,9 @@ export function useDescriptors<
114
114
  emitter,
115
115
  }: Options<State, ScreenOptions, EventMap>) {
116
116
  const theme = React.use(ThemeContext);
117
- const [options, setOptions] = React.useState<Record<string, ScreenOptions>>(
118
- {}
119
- );
117
+ const [options, setOptions] = React.useState<
118
+ Record<string, Partial<ScreenOptions> | undefined>
119
+ >({});
120
120
  const {
121
121
  onDispatchAction,
122
122
  onEmitEvent,
@@ -180,20 +180,20 @@ export function useDescriptors<
180
180
  ScreenOptions,
181
181
  EventMap
182
182
  >,
183
- overrides: Record<string, ScreenOptions>
183
+ overrides: Partial<ScreenOptions> | undefined
184
184
  ) => {
185
185
  const config = screens[route.name];
186
- const screen = config.props;
186
+ const screen = config?.props;
187
187
 
188
188
  const optionsList = [
189
189
  // The default `screenOptions` passed to the navigator
190
190
  screenOptions,
191
191
  // The `screenOptions` props passed to `Group` elements
192
- ...((config.options
192
+ ...((config?.options
193
193
  ? config.options.filter(Boolean)
194
194
  : []) as ScreenOptionsOrCallback<ScreenOptions>[]),
195
195
  // The `options` prop passed to `Screen` elements,
196
- screen.options,
196
+ screen?.options,
197
197
  // The options set via `navigation.setOptions`
198
198
  overrides,
199
199
  ];
@@ -222,7 +222,11 @@ export function useDescriptors<
222
222
  routeState: NavigationState | PartialState<NavigationState> | undefined
223
223
  ) => {
224
224
  const config = screens[route.name];
225
- const screen = config.props;
225
+ const screen = config?.props;
226
+
227
+ if (screen == null) {
228
+ throw new Error(`Couldn't find a screen named '${route.name}'.`);
229
+ }
226
230
 
227
231
  const clearOptions = () =>
228
232
  setOptions((o) => {
@@ -239,7 +243,7 @@ export function useDescriptors<
239
243
  // The `layout` prop passed to `Screen` elements,
240
244
  screen.layout ??
241
245
  // The `screenLayout` props passed to `Group` elements
242
- config.layout ??
246
+ config?.layout ??
243
247
  // The default `screenLayout` passed to the navigator
244
248
  screenLayout;
245
249
 
@@ -294,7 +298,15 @@ export function useDescriptors<
294
298
  >
295
299
  >((acc, route, i) => {
296
300
  const navigation = navigations[route.key];
297
- const customOptions = getOptions(route, navigation, options[route.key]);
301
+ const overrides = options[route.key];
302
+
303
+ if (navigation == null) {
304
+ throw new Error(
305
+ `Couldn't find a navigation object for route '${route.key}'.`
306
+ );
307
+ }
308
+
309
+ const customOptions = getOptions(route, navigation, overrides);
298
310
  const element = render(route, navigation, customOptions, routes[i]?.state);
299
311
 
300
312
  acc[route.key] = {
@@ -20,7 +20,13 @@ export function useFocusEvents<State extends NavigationState>({
20
20
  const navigation = React.use(NavigationContext);
21
21
  const lastFocusedKeyRef = React.useRef<string | undefined>(undefined);
22
22
 
23
- const currentFocusedKey = state.routes[state.index].key;
23
+ const currentFocusedRoute = state.routes[state.index];
24
+
25
+ if (currentFocusedRoute == null) {
26
+ throw new Error(`Couldn't find a route at index ${state.index}.`);
27
+ }
28
+
29
+ const currentFocusedKey = currentFocusedRoute.key;
24
30
 
25
31
  // When the parent screen changes its focus state, we also need to change child's focus
26
32
  // Coz the child screen can't be focused if the parent screen is out of focus
@@ -13,6 +13,8 @@ import type {
13
13
  RootParamList,
14
14
  } from './types';
15
15
 
16
+ type RootNavigation = GenericNavigation<RootParamList>;
17
+
16
18
  /**
17
19
  * Hook to access the navigation prop of the parent screen anywhere.
18
20
  *
@@ -21,15 +23,17 @@ import type {
21
23
  *
22
24
  * @returns Navigation prop of the parent screen.
23
25
  */
24
- export function useNavigation(): GenericNavigation<RootParamList>;
26
+ export function useNavigation(): RootNavigation;
25
27
  export function useNavigation<
26
28
  const Navigator = RootNavigator,
27
29
  >(): NavigationListForNavigator<Navigator>[keyof NavigationListForNavigator<Navigator>];
28
30
  export function useNavigation<
29
31
  const Navigator = RootNavigator,
30
- const RouteName extends keyof NavigationListForNested<Navigator> =
31
- keyof NavigationListForNested<Navigator>,
32
- >(name: RouteName): NavigationListForNested<Navigator>[RouteName];
32
+ const RouteName extends string = string,
33
+ >(
34
+ name: RouteName & keyof NavigationListForNested<Navigator>
35
+ ): NavigationListForNested<Navigator>[RouteName &
36
+ keyof NavigationListForNested<Navigator>];
33
37
  export function useNavigation(name?: string): unknown {
34
38
  const root = React.use(NavigationContainerRefContext);
35
39
  const navigation = React.use(NavigationContext);
@@ -498,7 +498,7 @@ export function useNavigationBuilder<
498
498
  const initialRouteParamList = routeNames.reduce<
499
499
  Record<string, object | undefined>
500
500
  >((acc, curr) => {
501
- const { initialParams } = screens[curr].props;
501
+ const { initialParams } = screens[curr]?.props ?? {};
502
502
  const initialParamsFromParams =
503
503
  route?.params?.state == null &&
504
504
  route?.params?.initial !== false &&
@@ -777,6 +777,11 @@ export function useNavigationBuilder<
777
777
  setCurrentState(undefined);
778
778
  stateCleanupRef.current = true;
779
779
  }
780
+
781
+ // Reset so that StrictMode's second mount re-propagates state correctly.
782
+ // Without this, the guard above sees the same reference and skips setState,
783
+ // causing the initial state to be lost after cleanup wipes the container state.
784
+ lastNotifiedStateRef.current = null;
780
785
  };
781
786
  // eslint-disable-next-line react-hooks/exhaustive-deps
782
787
  }, []);
@@ -829,11 +834,17 @@ export function useNavigationBuilder<
829
834
  }
830
835
 
831
836
  const hasPerScreenListeners = routeNames.some(
832
- (name) => screens[name].props.listeners != null
837
+ (name) => screens[name]?.props.listeners != null
833
838
  );
834
839
 
835
840
  if (screenListeners != null || hasPerScreenListeners) {
836
- const navigation = descriptors[route.key].navigation;
841
+ const descriptor = descriptors[route.key];
842
+
843
+ if (descriptor == null) {
844
+ throw new Error(`Couldn't find a descriptor for route '${route.key}'.`);
845
+ }
846
+
847
+ const navigation = descriptor.navigation;
837
848
 
838
849
  const listeners = ([] as (((e: any) => void) | undefined)[])
839
850
  .concat(
@@ -841,7 +852,7 @@ export function useNavigationBuilder<
841
852
  ...[
842
853
  screenListeners,
843
854
  ...routeNames.map((name) => {
844
- const { listeners } = screens[name].props;
855
+ const { listeners } = screens[name]?.props ?? {};
845
856
  return listeners;
846
857
  }),
847
858
  ].map((listeners) => {
@@ -987,6 +998,12 @@ export function useNavigationBuilder<
987
998
  });
988
999
 
989
1000
  const NavigationContent = useComponent((children: React.ReactNode) => {
1001
+ const focusedRoute = state.routes[state.index];
1002
+
1003
+ if (focusedRoute == null) {
1004
+ throw new Error(`Couldn't find a route at index ${state.index}.`);
1005
+ }
1006
+
990
1007
  const element =
991
1008
  layout != null
992
1009
  ? layout({
@@ -1001,9 +1018,7 @@ export function useNavigationBuilder<
1001
1018
  <NavigationMetaContext.Provider value={undefined}>
1002
1019
  <NavigationHelpersContext.Provider value={navigation}>
1003
1020
  <NavigationStateListenerProvider state={state}>
1004
- <FocusedRouteKeyContext.Provider
1005
- value={state.routes[state.index].key}
1006
- >
1021
+ <FocusedRouteKeyContext.Provider value={focusedRoute.key}>
1007
1022
  <PreventRemoveProvider>{element}</PreventRemoveProvider>
1008
1023
  </FocusedRouteKeyContext.Provider>
1009
1024
  </NavigationStateListenerProvider>
@@ -23,8 +23,8 @@ type Options<
23
23
  Partial<NavigationProp<ParamListBase, string, any, any, any>>;
24
24
  setOptions: (
25
25
  cb: (
26
- options: Record<string, ScreenOptions>
27
- ) => Record<string, ScreenOptions>
26
+ options: Record<string, Partial<ScreenOptions> | undefined>
27
+ ) => Record<string, Partial<ScreenOptions> | undefined>
28
28
  ) => void;
29
29
  router: Router<State, NavigationAction>;
30
30
  emitter: NavigationEventEmitter<EventMap>;
@@ -174,7 +174,7 @@ export function useNavigationCache<
174
174
 
175
175
  return parentNavigationHelpers;
176
176
  },
177
- setOptions: (options: object) => {
177
+ setOptions: (options: Partial<ScreenOptions>) => {
178
178
  setOptions((o) => ({
179
179
  ...o,
180
180
  [route.key]: { ...o[route.key], ...options },
@@ -183,7 +183,7 @@ export function useNavigationCache<
183
183
  isFocused: () => {
184
184
  const state = rest.getState();
185
185
 
186
- if (state.routes[state.index].key !== route.key) {
186
+ if (state.routes[state.index]?.key !== route.key) {
187
187
  return false;
188
188
  }
189
189
 
@@ -15,6 +15,8 @@ type NavigationStateListener = {
15
15
  subscribe: (callback: () => void) => () => void;
16
16
  };
17
17
 
18
+ type UseNavigationForName = (name: string) => NavigationProp<ParamListBase>;
19
+
18
20
  type NavigationStateForNested<
19
21
  Navigator,
20
22
  RouteName extends keyof NavigationListForNested<Navigator>,
@@ -53,9 +55,7 @@ export function useNavigationState(...args: unknown[]): unknown {
53
55
  // `useNavigation` uses `use` internally, so it's fine to call it conditionally
54
56
  // Cast to a non-generic signature to skip overload resolution - otherwise TS
55
57
  // eagerly expands `NavigationListForNested<RootNavigator>` at this call site.
56
- navigation = (
57
- useNavigation as (name: string) => NavigationProp<ParamListBase>
58
- )(args[0]);
58
+ navigation = (useNavigation as UseNavigationForName)(args[0]);
59
59
  selector = args[1];
60
60
  } else {
61
61
  selector = args[0];
@@ -132,7 +132,7 @@ export function useOnAction<State extends NavigationState>({
132
132
  for (let i = actionListeners.length - 1; i >= 0; i--) {
133
133
  const listener = actionListeners[i];
134
134
 
135
- if (listener(action, visitedNavigators)) {
135
+ if (listener?.(action, visitedNavigators)) {
136
136
  return true;
137
137
  }
138
138
  }