@react-navigation/core 8.0.0-alpha.4 → 8.0.0-alpha.40

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 (323) hide show
  1. package/README.md +17 -14
  2. package/lib/module/BaseNavigationContainer.js +168 -87
  3. package/lib/module/BaseNavigationContainer.js.map +1 -1
  4. package/lib/module/ConsumedParamsContext.js +5 -0
  5. package/lib/module/ConsumedParamsContext.js.map +1 -0
  6. package/lib/module/DataLoading.js +129 -0
  7. package/lib/module/DataLoading.js.map +1 -0
  8. package/lib/module/NavigationBuilderContext.js +7 -10
  9. package/lib/module/NavigationBuilderContext.js.map +1 -1
  10. package/lib/module/NavigationIndependentTree.js +54 -9
  11. package/lib/module/NavigationIndependentTree.js.map +1 -1
  12. package/lib/module/NavigationProvider.js +36 -11
  13. package/lib/module/NavigationProvider.js.map +1 -1
  14. package/lib/module/NavigationRootContext.js +8 -0
  15. package/lib/module/NavigationRootContext.js.map +1 -0
  16. package/lib/module/NavigationStateContext.js +3 -0
  17. package/lib/module/NavigationStateContext.js.map +1 -1
  18. package/lib/module/PreventRemoveContext.js.map +1 -1
  19. package/lib/module/PreventRemoveProvider.js +40 -31
  20. package/lib/module/PreventRemoveProvider.js.map +1 -1
  21. package/lib/module/SceneView.js +12 -42
  22. package/lib/module/SceneView.js.map +1 -1
  23. package/lib/module/StaticNavigation.js +219 -67
  24. package/lib/module/StaticNavigation.js.map +1 -1
  25. package/lib/module/StaticTreeContext.js +5 -0
  26. package/lib/module/StaticTreeContext.js.map +1 -0
  27. package/lib/module/createNavigationContainerRef.js +7 -9
  28. package/lib/module/createNavigationContainerRef.js.map +1 -1
  29. package/lib/module/createNavigatorFactory.js +27 -5
  30. package/lib/module/createNavigatorFactory.js.map +1 -1
  31. package/lib/module/findFocusedRoute.js +7 -4
  32. package/lib/module/findFocusedRoute.js.map +1 -1
  33. package/lib/module/getActionFromState.js +45 -20
  34. package/lib/module/getActionFromState.js.map +1 -1
  35. package/lib/module/getPathFromState.js +204 -94
  36. package/lib/module/getPathFromState.js.map +1 -1
  37. package/lib/module/getPatternParts.js +61 -14
  38. package/lib/module/getPatternParts.js.map +1 -1
  39. package/lib/module/getStateFromPath.js +608 -272
  40. package/lib/module/getStateFromPath.js.map +1 -1
  41. package/lib/module/getStateFromRouteParams.js +23 -0
  42. package/lib/module/getStateFromRouteParams.js.map +1 -0
  43. package/lib/module/index.js +7 -6
  44. package/lib/module/index.js.map +1 -1
  45. package/lib/module/internal.js +2 -0
  46. package/lib/module/internal.js.map +1 -0
  47. package/lib/module/isRecordEqual.js +1 -1
  48. package/lib/module/isRecordEqual.js.map +1 -1
  49. package/lib/module/queryString.js +71 -0
  50. package/lib/module/queryString.js.map +1 -0
  51. package/lib/module/theming/useTheme.js +1 -1
  52. package/lib/module/theming/useTheme.js.map +1 -1
  53. package/lib/module/types.js +35 -1
  54. package/lib/module/types.js.map +1 -1
  55. package/lib/module/useDescriptors.js +65 -25
  56. package/lib/module/useDescriptors.js.map +1 -1
  57. package/lib/module/useEventEmitter.js +48 -33
  58. package/lib/module/useEventEmitter.js.map +1 -1
  59. package/lib/module/useFocusEffect.js +4 -2
  60. package/lib/module/useFocusEffect.js.map +1 -1
  61. package/lib/module/useFocusEvents.js +15 -5
  62. package/lib/module/useFocusEvents.js.map +1 -1
  63. package/lib/module/useFocusedListenersChildrenAdapter.js +3 -3
  64. package/lib/module/useFocusedListenersChildrenAdapter.js.map +1 -1
  65. package/lib/module/useIsFocused.js +8 -12
  66. package/lib/module/useIsFocused.js.map +1 -1
  67. package/lib/module/useKeyedChildListeners.js +5 -2
  68. package/lib/module/useKeyedChildListeners.js.map +1 -1
  69. package/lib/module/useLazyValue.js.map +1 -1
  70. package/lib/module/useNavigation.js +4 -17
  71. package/lib/module/useNavigation.js.map +1 -1
  72. package/lib/module/useNavigationBuilder.js +244 -147
  73. package/lib/module/useNavigationBuilder.js.map +1 -1
  74. package/lib/module/useNavigationCache.js +92 -89
  75. package/lib/module/useNavigationCache.js.map +1 -1
  76. package/lib/module/useNavigationHelpers.js +22 -29
  77. package/lib/module/useNavigationHelpers.js.map +1 -1
  78. package/lib/module/useNavigationIndependentTree.js +1 -1
  79. package/lib/module/useNavigationIndependentTree.js.map +1 -1
  80. package/lib/module/useNavigationState.js +158 -46
  81. package/lib/module/useNavigationState.js.map +1 -1
  82. package/lib/module/useOnAction.js +58 -11
  83. package/lib/module/useOnAction.js.map +1 -1
  84. package/lib/module/useOnGetNavigation.js +26 -0
  85. package/lib/module/useOnGetNavigation.js.map +1 -0
  86. package/lib/module/useOnGetState.js +7 -4
  87. package/lib/module/useOnGetState.js.map +1 -1
  88. package/lib/module/useOnPreventRemove.js +40 -31
  89. package/lib/module/useOnPreventRemove.js.map +1 -1
  90. package/lib/module/useOnRouteFocus.js +2 -2
  91. package/lib/module/useOnRouteFocus.js.map +1 -1
  92. package/lib/module/useOptionsGetters.js +34 -24
  93. package/lib/module/useOptionsGetters.js.map +1 -1
  94. package/lib/module/usePreventRemove.js +11 -5
  95. package/lib/module/usePreventRemove.js.map +1 -1
  96. package/lib/module/usePreventRemoveContext.js +2 -2
  97. package/lib/module/usePreventRemoveContext.js.map +1 -1
  98. package/lib/module/useRegisterNavigator.js +3 -4
  99. package/lib/module/useRegisterNavigator.js.map +1 -1
  100. package/lib/module/useRoute.js +2 -0
  101. package/lib/module/useRoute.js.map +1 -1
  102. package/lib/module/useRouteCache.js +51 -35
  103. package/lib/module/useRouteCache.js.map +1 -1
  104. package/lib/module/useScheduleUpdate.js +12 -10
  105. package/lib/module/useScheduleUpdate.js.map +1 -1
  106. package/lib/module/useStateForPath.js +1 -1
  107. package/lib/module/useStateForPath.js.map +1 -1
  108. package/lib/module/useSyncState.js +37 -15
  109. package/lib/module/useSyncState.js.map +1 -1
  110. package/lib/module/validatePathConfig.js +50 -36
  111. package/lib/module/validatePathConfig.js.map +1 -1
  112. package/lib/typescript/src/BaseNavigationContainer.d.ts +6 -3
  113. package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
  114. package/lib/typescript/src/ConsumedParamsContext.d.ts +3 -0
  115. package/lib/typescript/src/ConsumedParamsContext.d.ts.map +1 -0
  116. package/lib/typescript/src/DataLoading.d.ts +21 -0
  117. package/lib/typescript/src/DataLoading.d.ts.map +1 -0
  118. package/lib/typescript/src/EnsureSingleNavigator.d.ts +1 -1
  119. package/lib/typescript/src/EnsureSingleNavigator.d.ts.map +1 -1
  120. package/lib/typescript/src/Group.d.ts +1 -1
  121. package/lib/typescript/src/Group.d.ts.map +1 -1
  122. package/lib/typescript/src/NavigationBuilderContext.d.ts +22 -14
  123. package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
  124. package/lib/typescript/src/NavigationContainerRefContext.d.ts +1 -1
  125. package/lib/typescript/src/NavigationContainerRefContext.d.ts.map +1 -1
  126. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts +4 -4
  127. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts.map +1 -1
  128. package/lib/typescript/src/NavigationHelpersContext.d.ts +1 -1
  129. package/lib/typescript/src/NavigationHelpersContext.d.ts.map +1 -1
  130. package/lib/typescript/src/NavigationIndependentTree.d.ts +1 -1
  131. package/lib/typescript/src/NavigationIndependentTree.d.ts.map +1 -1
  132. package/lib/typescript/src/NavigationProvider.d.ts +21 -18
  133. package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
  134. package/lib/typescript/src/NavigationRootContext.d.ts +8 -0
  135. package/lib/typescript/src/NavigationRootContext.d.ts.map +1 -0
  136. package/lib/typescript/src/NavigationStateContext.d.ts +4 -3
  137. package/lib/typescript/src/NavigationStateContext.d.ts.map +1 -1
  138. package/lib/typescript/src/PreventRemoveContext.d.ts +1 -0
  139. package/lib/typescript/src/PreventRemoveContext.d.ts.map +1 -1
  140. package/lib/typescript/src/PreventRemoveProvider.d.ts +1 -1
  141. package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
  142. package/lib/typescript/src/SceneView.d.ts +5 -2
  143. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  144. package/lib/typescript/src/Screen.d.ts +1 -1
  145. package/lib/typescript/src/Screen.d.ts.map +1 -1
  146. package/lib/typescript/src/StaticContainer.d.ts +1 -1
  147. package/lib/typescript/src/StaticContainer.d.ts.map +1 -1
  148. package/lib/typescript/src/StaticNavigation.d.ts +189 -111
  149. package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
  150. package/lib/typescript/src/StaticTreeContext.d.ts +4 -0
  151. package/lib/typescript/src/StaticTreeContext.d.ts.map +1 -0
  152. package/lib/typescript/src/createNavigationContainerRef.d.ts +1 -1
  153. package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
  154. package/lib/typescript/src/createNavigatorFactory.d.ts +23 -5
  155. package/lib/typescript/src/createNavigatorFactory.d.ts.map +1 -1
  156. package/lib/typescript/src/findFocusedRoute.d.ts +3 -8
  157. package/lib/typescript/src/findFocusedRoute.d.ts.map +1 -1
  158. package/lib/typescript/src/getActionFromState.d.ts +4 -4
  159. package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
  160. package/lib/typescript/src/getPathFromState.d.ts +3 -3
  161. package/lib/typescript/src/getPathFromState.d.ts.map +1 -1
  162. package/lib/typescript/src/getPatternParts.d.ts +5 -2
  163. package/lib/typescript/src/getPatternParts.d.ts.map +1 -1
  164. package/lib/typescript/src/getStateFromPath.d.ts +4 -7
  165. package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
  166. package/lib/typescript/src/getStateFromRouteParams.d.ts +3 -0
  167. package/lib/typescript/src/getStateFromRouteParams.d.ts.map +1 -0
  168. package/lib/typescript/src/index.d.ts +36 -33
  169. package/lib/typescript/src/index.d.ts.map +1 -1
  170. package/lib/typescript/src/internal.d.ts +3 -0
  171. package/lib/typescript/src/internal.d.ts.map +1 -0
  172. package/lib/typescript/src/isRecordEqual.d.ts.map +1 -1
  173. package/lib/typescript/src/queryString.d.ts +5 -0
  174. package/lib/typescript/src/queryString.d.ts.map +1 -0
  175. package/lib/typescript/src/theming/ThemeContext.d.ts +1 -1
  176. package/lib/typescript/src/theming/ThemeContext.d.ts.map +1 -1
  177. package/lib/typescript/src/theming/ThemeProvider.d.ts +2 -2
  178. package/lib/typescript/src/theming/ThemeProvider.d.ts.map +1 -1
  179. package/lib/typescript/src/theming/useTheme.d.ts +1 -1
  180. package/lib/typescript/src/theming/useTheme.d.ts.map +1 -1
  181. package/lib/typescript/src/types.d.ts +265 -167
  182. package/lib/typescript/src/types.d.ts.map +1 -1
  183. package/lib/typescript/src/useChildListeners.d.ts +3 -3
  184. package/lib/typescript/src/useChildListeners.d.ts.map +1 -1
  185. package/lib/typescript/src/useDescriptors.d.ts +13 -11
  186. package/lib/typescript/src/useDescriptors.d.ts.map +1 -1
  187. package/lib/typescript/src/useEventEmitter.d.ts +2 -2
  188. package/lib/typescript/src/useEventEmitter.d.ts.map +1 -1
  189. package/lib/typescript/src/useFocusEffect.d.ts.map +1 -1
  190. package/lib/typescript/src/useFocusEvents.d.ts +2 -2
  191. package/lib/typescript/src/useFocusEvents.d.ts.map +1 -1
  192. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts +2 -2
  193. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts.map +1 -1
  194. package/lib/typescript/src/useIsFocused.d.ts +4 -0
  195. package/lib/typescript/src/useIsFocused.d.ts.map +1 -1
  196. package/lib/typescript/src/useKeyedChildListeners.d.ts +4 -3
  197. package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
  198. package/lib/typescript/src/useLazyValue.d.ts.map +1 -1
  199. package/lib/typescript/src/useNavigation.d.ts +4 -2
  200. package/lib/typescript/src/useNavigation.d.ts.map +1 -1
  201. package/lib/typescript/src/useNavigationBuilder.d.ts +22 -63
  202. package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
  203. package/lib/typescript/src/useNavigationCache.d.ts +6 -5
  204. package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
  205. package/lib/typescript/src/useNavigationContainerRef.d.ts +1 -1
  206. package/lib/typescript/src/useNavigationContainerRef.d.ts.map +1 -1
  207. package/lib/typescript/src/useNavigationHelpers.d.ts +18 -58
  208. package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
  209. package/lib/typescript/src/useNavigationState.d.ts +19 -3
  210. package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
  211. package/lib/typescript/src/useOnAction.d.ts +9 -9
  212. package/lib/typescript/src/useOnAction.d.ts.map +1 -1
  213. package/lib/typescript/src/useOnGetNavigation.d.ts +12 -0
  214. package/lib/typescript/src/useOnGetNavigation.d.ts.map +1 -0
  215. package/lib/typescript/src/useOnGetState.d.ts +1 -1
  216. package/lib/typescript/src/useOnGetState.d.ts.map +1 -1
  217. package/lib/typescript/src/useOnPreventRemove.d.ts +5 -9
  218. package/lib/typescript/src/useOnPreventRemove.d.ts.map +1 -1
  219. package/lib/typescript/src/useOnRouteFocus.d.ts +6 -6
  220. package/lib/typescript/src/useOnRouteFocus.d.ts.map +1 -1
  221. package/lib/typescript/src/useOptionsGetters.d.ts +2 -4
  222. package/lib/typescript/src/useOptionsGetters.d.ts.map +1 -1
  223. package/lib/typescript/src/usePreventRemove.d.ts.map +1 -1
  224. package/lib/typescript/src/usePreventRemoveContext.d.ts +2 -1
  225. package/lib/typescript/src/usePreventRemoveContext.d.ts.map +1 -1
  226. package/lib/typescript/src/useRegisterNavigator.d.ts.map +1 -1
  227. package/lib/typescript/src/useRoute.d.ts +7 -3
  228. package/lib/typescript/src/useRoute.d.ts.map +1 -1
  229. package/lib/typescript/src/useRouteCache.d.ts +7 -12
  230. package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
  231. package/lib/typescript/src/useScheduleUpdate.d.ts +5 -4
  232. package/lib/typescript/src/useScheduleUpdate.d.ts.map +1 -1
  233. package/lib/typescript/src/useStateForPath.d.ts +1 -1
  234. package/lib/typescript/src/useStateForPath.d.ts.map +1 -1
  235. package/lib/typescript/src/useSyncState.d.ts +1 -0
  236. package/lib/typescript/src/useSyncState.d.ts.map +1 -1
  237. package/lib/typescript/src/utilities.d.ts +79 -39
  238. package/lib/typescript/src/utilities.d.ts.map +1 -1
  239. package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
  240. package/package.json +26 -22
  241. package/src/BaseNavigationContainer.tsx +468 -333
  242. package/src/ConsumedParamsContext.tsx +5 -0
  243. package/src/DataLoading.tsx +206 -0
  244. package/src/NavigationBuilderContext.tsx +44 -25
  245. package/src/NavigationFocusedRouteStateContext.tsx +4 -4
  246. package/src/NavigationIndependentTree.tsx +60 -12
  247. package/src/NavigationProvider.tsx +47 -20
  248. package/src/NavigationRootContext.tsx +11 -0
  249. package/src/NavigationStateContext.tsx +9 -6
  250. package/src/PreventRemoveContext.tsx +1 -0
  251. package/src/PreventRemoveProvider.tsx +55 -56
  252. package/src/SceneView.tsx +14 -40
  253. package/src/StaticNavigation.tsx +715 -328
  254. package/src/StaticTreeContext.tsx +7 -0
  255. package/src/createNavigationContainerRef.tsx +12 -11
  256. package/src/createNavigatorFactory.tsx +92 -8
  257. package/src/findFocusedRoute.tsx +16 -16
  258. package/src/getActionFromState.tsx +87 -51
  259. package/src/getPathFromState.tsx +310 -134
  260. package/src/getPatternParts.tsx +98 -16
  261. package/src/getStateFromPath.tsx +971 -344
  262. package/src/getStateFromRouteParams.tsx +59 -0
  263. package/src/index.tsx +57 -6
  264. package/src/internal.tsx +2 -0
  265. package/src/isRecordEqual.tsx +3 -1
  266. package/src/queryString.ts +109 -0
  267. package/src/theming/useTheme.tsx +1 -1
  268. package/src/types.tsx +799 -377
  269. package/src/useDescriptors.tsx +151 -43
  270. package/src/useEventEmitter.tsx +53 -39
  271. package/src/useFocusEffect.tsx +5 -2
  272. package/src/useFocusEvents.tsx +19 -8
  273. package/src/useFocusedListenersChildrenAdapter.tsx +3 -3
  274. package/src/useIsFocused.tsx +18 -21
  275. package/src/useKeyedChildListeners.tsx +5 -2
  276. package/src/useLazyValue.tsx +2 -2
  277. package/src/useNavigation.tsx +9 -26
  278. package/src/useNavigationBuilder.tsx +370 -201
  279. package/src/useNavigationCache.tsx +148 -123
  280. package/src/useNavigationHelpers.tsx +27 -37
  281. package/src/useNavigationIndependentTree.tsx +1 -1
  282. package/src/useNavigationState.tsx +207 -69
  283. package/src/useOnAction.tsx +92 -18
  284. package/src/useOnGetNavigation.tsx +30 -0
  285. package/src/useOnGetState.tsx +8 -4
  286. package/src/useOnPreventRemove.tsx +78 -43
  287. package/src/useOnRouteFocus.tsx +11 -15
  288. package/src/useOptionsGetters.tsx +41 -28
  289. package/src/usePreventRemove.tsx +13 -5
  290. package/src/usePreventRemoveContext.tsx +2 -2
  291. package/src/useRegisterNavigator.tsx +4 -4
  292. package/src/useRoute.tsx +20 -6
  293. package/src/useRouteCache.tsx +57 -35
  294. package/src/useScheduleUpdate.tsx +13 -11
  295. package/src/useStateForPath.tsx +1 -1
  296. package/src/useSyncState.tsx +39 -15
  297. package/src/utilities.tsx +151 -35
  298. package/src/validatePathConfig.tsx +86 -57
  299. package/lib/module/CurrentRenderContext.js +0 -10
  300. package/lib/module/CurrentRenderContext.js.map +0 -1
  301. package/lib/module/NavigationMetaContext.js +0 -15
  302. package/lib/module/NavigationMetaContext.js.map +0 -1
  303. package/lib/module/checkSerializable.js +0 -46
  304. package/lib/module/checkSerializable.js.map +0 -1
  305. package/lib/module/useComponent.js +0 -34
  306. package/lib/module/useComponent.js.map +0 -1
  307. package/lib/module/useCurrentRender.js +0 -19
  308. package/lib/module/useCurrentRender.js.map +0 -1
  309. package/lib/typescript/src/CurrentRenderContext.d.ts +0 -9
  310. package/lib/typescript/src/CurrentRenderContext.d.ts.map +0 -1
  311. package/lib/typescript/src/NavigationMetaContext.d.ts +0 -12
  312. package/lib/typescript/src/NavigationMetaContext.d.ts.map +0 -1
  313. package/lib/typescript/src/checkSerializable.d.ts +0 -10
  314. package/lib/typescript/src/checkSerializable.d.ts.map +0 -1
  315. package/lib/typescript/src/useComponent.d.ts +0 -7
  316. package/lib/typescript/src/useComponent.d.ts.map +0 -1
  317. package/lib/typescript/src/useCurrentRender.d.ts +0 -14
  318. package/lib/typescript/src/useCurrentRender.d.ts.map +0 -1
  319. package/src/CurrentRenderContext.tsx +0 -9
  320. package/src/NavigationMetaContext.tsx +0 -14
  321. package/src/checkSerializable.tsx +0 -74
  322. package/src/useComponent.tsx +0 -37
  323. package/src/useCurrentRender.tsx +0 -31
@@ -6,12 +6,19 @@ import type {
6
6
  import * as React from 'react';
7
7
  import { isValidElementType } from 'react-is';
8
8
 
9
+ import {
10
+ combinePatternParts,
11
+ getPatternParts,
12
+ type PatternPart,
13
+ } from './getPatternParts';
14
+ import { StaticTreeContext } from './StaticTreeContext';
9
15
  import type {
10
- DefaultNavigatorOptions,
11
16
  EventMapBase,
12
17
  NavigationListBase,
18
+ NavigatorProps,
13
19
  NavigatorScreenParams,
14
20
  NavigatorTypeBagBase,
21
+ NavigatorTypeBagFor,
15
22
  PathConfig,
16
23
  PathConfigMap,
17
24
  RouteGroupConfig,
@@ -21,68 +28,107 @@ import type {
21
28
  import { useRoute } from './useRoute';
22
29
  import type {
23
30
  AnyToUnknown,
24
- ExtractParamStrings,
25
- ExtractParamsType,
26
31
  FlatType,
27
32
  HasArguments,
28
- InferParse,
29
- InferPath,
33
+ InferParamsFromLinking,
30
34
  KeysOf,
35
+ NoExcessCallbackReturn,
36
+ NoExcessObject,
37
+ NoExcessValue,
38
+ NotUndefinedObject,
39
+ StandardSchemaV1,
31
40
  UnionToIntersection,
32
41
  ValidPathPattern,
33
42
  } from './utilities';
34
43
 
35
- type ParamsForScreenComponent<T> = T extends (...args: any[]) => any
36
- ? HasArguments<T> extends true
37
- ? T extends React.ComponentType<{ route: { params: infer Params } }>
38
- ? Params
39
- : undefined
44
+ type ScreenComponentParams<T> = [T] extends [
45
+ React.ComponentType<{ route: { params: infer Params } }>,
46
+ ]
47
+ ? Params
48
+ : undefined;
49
+
50
+ type ParamsForScreenComponent<T> = [T] extends [(...args: any[]) => any]
51
+ ? // Don't infer params from a parameterless function component
52
+ // It'd infer `unknown` - but we want `undefined` if no params are accepted
53
+ HasArguments<T> extends true
54
+ ? ScreenComponentParams<T>
40
55
  : undefined
41
- : T extends React.ComponentType<{ route: { params: infer Params } }>
42
- ? Params
56
+ : ScreenComponentParams<T>;
57
+
58
+ // If the initial route's params include `undefined`, the nested navigator itself can be optional.
59
+ // If no initial route is specified, check if every nested route's params include `undefined`.
60
+ // Otherwise the nested navigator needs to be required.
61
+ type ParamsForNestedNavigator<
62
+ T extends { config: any },
63
+ ParamList extends {} = StaticParamList<T>,
64
+ Params = NavigatorScreenParams<ParamList>,
65
+ RouteNames extends keyof ParamList = T['config'] extends {
66
+ initialRouteName: infer RouteName extends keyof ParamList;
67
+ }
68
+ ? RouteName
69
+ : keyof ParamList,
70
+ > = {
71
+ [RouteName in RouteNames]-?: undefined extends ParamList[RouteName]
72
+ ? never
73
+ : RouteName;
74
+ }[RouteNames] extends never
75
+ ? Params | undefined
76
+ : Params;
77
+
78
+ // If the screens were constructed from a `Record<K, V>`,
79
+ // the screen value (`T`) may be a union.
80
+ // A naked `T extends ...` conditional would distribute over every screen in the union,
81
+ // creating a large params union per route.
82
+ // Wrapping `T` in a tuple checks the union as a whole instead of distributing,
83
+ // https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
84
+ type ParamsForScreen<T> = [T] extends [{ config: any }]
85
+ ? ParamsForNestedNavigator<T>
86
+ : [T] extends [React.ComponentType<any>]
87
+ ? ParamsForScreenComponent<T>
43
88
  : undefined;
44
89
 
45
- type ParamsForScreen<T> =
46
- // Nested navigator in screen property
47
- T extends { screen: StaticNavigationBase }
48
- ? NavigatorScreenParams<StaticParamList<T['screen']>> | undefined
49
- : // Direct nested navigator
50
- T extends StaticNavigationBase
51
- ? NavigatorScreenParams<StaticParamList<T>> | undefined
52
- : T extends {
53
- screen: React.ComponentType<any>;
54
- }
55
- ? ParamsForScreenComponent<T['screen']>
56
- : ParamsForScreenComponent<T>;
57
-
58
- type ParamsForLinking<Linking> = Linking extends { path: string }
59
- ? ExtractParamsType<
60
- ExtractParamStrings<InferPath<Linking>>,
61
- InferParse<Linking>
62
- >
63
- : Linking extends string
64
- ? ExtractParamsType<ExtractParamStrings<Linking>, undefined>
65
- : undefined;
90
+ // Unlike `ParamsForScreen`, we want to distribute for `Record<string, Component | StaticNavigation>`
91
+ // This creates union like:
92
+ // `C extends C ? ParamsForScreen<C> : never) | (S extends S ? ParamsForScreen<S> : never)`
93
+ // `= ParamsForScreen<C> | ParamsForScreen<S>`
94
+ type ParamsForScreenEntry<T> = T extends T ? ParamsForScreen<T> : never;
95
+
96
+ // Only infer params from linking if it's a pattern (i.e., contains ':')
97
+ // or if parse is present, which can also define query params.
98
+ // This avoids inferring non-literals like 'string' without parse.
99
+ type ShouldInferFromLinking<Linking> = Linking extends {
100
+ parse: Record<string, unknown>;
101
+ }
102
+ ? true
103
+ : Linking extends ValidPathPattern | { path: ValidPathPattern }
104
+ ? true
105
+ : false;
66
106
 
67
107
  /**
68
- * Inferred params type based on both linking config and screen.
69
- * - When linking is undefined: infers params from screen
70
- * - When screen is a nested navigator: merges path params with navigator screen params
71
- * - Otherwise: merges path params with screen component params
108
+ * Params type derived from both linking and screen.
109
+ *
110
+ * - Linking has no extractable params (no ':' in path, no `parse`): returns
111
+ * screen params alone.
112
+ * - Linking has params + screen is a nested navigator: intersects path params
113
+ * with the navigator's screen params.
114
+ * - Linking has params + screen is a component without route params: returns
115
+ * path params alone (avoids `LP & undefined = never`).
116
+ * - Linking has params + screen has route params: intersects them.
72
117
  */
73
- type ParamsForConfig<Linking, Screen> = undefined extends Linking
74
- ? ParamsForScreen<Screen>
75
- : // Only infer params from linking if it's a pattern (i.e., contains ':')
76
- // This avoids inferring non-literals like 'string'
77
- Linking extends ValidPathPattern | { path: ValidPathPattern }
78
- ? Screen extends StaticNavigationBase
79
- ? FlatType<ParamsForLinking<Linking>> & ParamsForScreen<Screen>
80
- : // Don't combine if `undefined`, otherwise it'll result in `never`
81
- undefined extends ParamsForScreen<Screen>
82
- ? // Only flatten when not a navigator to keep it legible
83
- FlatType<ParamsForLinking<Linking>>
84
- : FlatType<ParamsForLinking<Linking> & ParamsForScreen<Screen>>
85
- : ParamsForScreen<Screen>;
118
+ type ParamsForConfig<Linking, Screen, Params = ParamsForScreen<Screen>> =
119
+ ShouldInferFromLinking<Linking> extends true
120
+ ? [Screen] extends [{ config: any }]
121
+ ? undefined extends Params
122
+ ? FlatType<InferParamsFromLinking<Linking>> & Params
123
+ : // Optional linking params make the whole route params type optional when intersected.
124
+ // e.g. `({...} | undefined) & NavigatorScreenParams<{...}>` adds `| undefined` to the whole type.
125
+ // But if nested navigator had required params, it should still be required.
126
+ // So we remove `| undefined` from linking params before intersecting with nested navigator params.
127
+ FlatType<NotUndefinedObject<InferParamsFromLinking<Linking>>> & Params
128
+ : undefined extends Params
129
+ ? FlatType<InferParamsFromLinking<Linking>>
130
+ : FlatType<InferParamsFromLinking<Linking> & Params>
131
+ : Params;
86
132
 
87
133
  type ParamListForScreens<Screens> = {
88
134
  [Key in KeysOf<Screens>]: Screens[Key] extends StaticScreenConfig<
@@ -91,21 +137,16 @@ type ParamListForScreens<Screens> = {
91
137
  any,
92
138
  any,
93
139
  any,
140
+ any,
141
+ any,
142
+ any,
94
143
  any
95
144
  >
96
145
  ? ParamsForConfig<Linking, Screen>
97
- : ParamsForScreen<Screens[Key]>;
146
+ : ParamsForScreenEntry<Screens[Key]>;
98
147
  };
99
148
 
100
- type ParamListForGroups<
101
- Groups extends
102
- | Readonly<{
103
- [key: string]: {
104
- screens: {};
105
- };
106
- }>
107
- | undefined,
108
- > = Groups extends {
149
+ type ParamListForGroups<Groups> = Groups extends {
109
150
  [key: string]: {
110
151
  screens: infer Screens;
111
152
  };
@@ -113,26 +154,22 @@ type ParamListForGroups<
113
154
  ? ParamListForScreens<UnionToIntersection<Screens>>
114
155
  : {};
115
156
 
116
- type RouteType<Params> = Readonly<
117
- FlatType<
118
- Omit<Route<string, AnyToUnknown<Params>>, 'params'> &
119
- Readonly<
120
- undefined extends Params
121
- ? {
122
- /**
123
- * Params for this route
124
- */
125
- params?: AnyToUnknown<Params>;
126
- }
127
- : {
128
- /**
129
- * Params for this route
130
- */
131
- params: AnyToUnknown<Params>;
132
- }
133
- >
134
- >
135
- >;
157
+ type StaticRouteBase = Readonly<Omit<Route<string>, 'params'>>;
158
+
159
+ type StaticRoute<Params, P = AnyToUnknown<Params>> = StaticRouteBase &
160
+ (undefined extends Params
161
+ ? {
162
+ /**
163
+ * Params for this route
164
+ */
165
+ readonly params?: P extends object ? Readonly<P> : P;
166
+ }
167
+ : {
168
+ /**
169
+ * Params for this route
170
+ */
171
+ readonly params: Readonly<P>;
172
+ });
136
173
 
137
174
  type StaticScreenConfigLinkingAlias = {
138
175
  /**
@@ -147,7 +184,7 @@ type StaticScreenConfigLinkingAlias = {
147
184
  */
148
185
  exact?: boolean;
149
186
  /**
150
- * An object mapping the param name to a function which parses the param value.
187
+ * An object mapping the param name to a parser function or a Standard Schema.
151
188
  *
152
189
  * @example
153
190
  * ```js
@@ -157,10 +194,14 @@ type StaticScreenConfigLinkingAlias = {
157
194
  * }
158
195
  * ```
159
196
  */
160
- parse?: Record<string, (value: string) => unknown>;
197
+ parse?: Record<
198
+ string,
199
+ | ((value: string) => unknown)
200
+ | StandardSchemaV1<string | string[] | null | undefined, unknown>
201
+ >;
161
202
  /**
162
203
  * An object mapping the param name to a function which converts the param value to a string.
163
- * By default, all params are converted to strings using `String(value)`.
204
+ * By default, arrays and null are preserved for query params, and other values are converted using `String(value)`.
164
205
  *
165
206
  * @example
166
207
  * ```js
@@ -170,31 +211,60 @@ type StaticScreenConfigLinkingAlias = {
170
211
  * ```
171
212
  */
172
213
  stringify?: Record<string, (value: unknown) => string>;
214
+ /**
215
+ * Whether this path can resolve to multiple routes.
216
+ * Both routes should specify `shared: true` for this to work.
217
+ *
218
+ * When automatic path generation is enabled,
219
+ * screens using the same path pattern and the same screen component
220
+ * or navigator will be automatically marked as shared.
221
+ * Explicitly specifying the option overrides the automatic detection.
222
+ *
223
+ * This is useful when same screen used in multiple navigators,
224
+ * e.g. tabs with stacks containing profile screen in each stack.
225
+ *
226
+ * The path defined first will be the canonical path.
227
+ */
228
+ shared?: boolean;
229
+ };
230
+
231
+ type StaticScreenConfigLinkingExtras = {
232
+ /**
233
+ * Additional path alias that will be matched to the same screen.
234
+ */
235
+ alias?: (string | StaticScreenConfigLinkingAlias)[];
236
+ /**
237
+ * Name of the initial route to use for the nested navigator when the path matches.
238
+ */
239
+ initialRouteName?: string | undefined;
240
+ /**
241
+ * Path configuration for child screens in the nested navigator.
242
+ * Only supported when the screen renders a navigator with dynamic API.
243
+ */
244
+ screens?: PathConfigMap<ParamListBase> | undefined;
173
245
  };
174
246
 
175
247
  export type StaticScreenConfigLinking =
176
248
  | string
177
- | (StaticScreenConfigLinkingAlias & {
178
- /**
179
- * Additional path alias that will be matched to the same screen.
180
- */
181
- alias?: (string | StaticScreenConfigLinkingAlias)[];
182
- })
249
+ | (StaticScreenConfigLinkingAlias & StaticScreenConfigLinkingExtras)
250
+ | null
183
251
  | undefined;
184
252
 
185
253
  export type StaticScreenConfigScreen =
186
254
  | React.ComponentType<any>
187
- | StaticNavigation<any, any, any>;
188
-
189
- export type StaticScreenConfig<
190
- Linking extends StaticScreenConfigLinking,
191
- Screen,
192
- State extends NavigationState,
193
- ScreenOptions extends {},
194
- EventMap extends EventMapBase,
195
- Navigation,
196
- Params = ParamsForConfig<Linking, Screen>,
197
- > = {
255
+ | StaticNavigation<any>;
256
+
257
+ export interface StaticScreenConfig<
258
+ out Linking extends StaticScreenConfigLinking,
259
+ out Screen,
260
+ in out State extends NavigationState,
261
+ in out ScreenOptions extends {},
262
+ in out EventMap extends EventMapBase,
263
+ in out Navigation,
264
+ in out Params = ParamsForConfig<Linking, Screen>,
265
+ in out ProvidedOptions extends {} = {},
266
+ in out ProvidedListeners extends {} = {},
267
+ > {
198
268
  /**
199
269
  * Static navigation config or Component to render for the screen.
200
270
  */
@@ -228,10 +298,10 @@ export type StaticScreenConfig<
228
298
  options?:
229
299
  | ScreenOptions
230
300
  | ((props: {
231
- route: RouteType<Params>;
301
+ route: StaticRoute<Params>;
232
302
  navigation: Navigation;
233
303
  theme: Theme;
234
- }) => ScreenOptions);
304
+ }) => NoExcessCallbackReturn<ProvidedOptions, ScreenOptions>);
235
305
 
236
306
  /**
237
307
  * Event listeners for this screen.
@@ -248,9 +318,12 @@ export type StaticScreenConfig<
248
318
  listeners?:
249
319
  | ScreenListeners<State, EventMap>
250
320
  | ((props: {
251
- route: RouteType<Params>;
321
+ route: StaticRoute<Params>;
252
322
  navigation: Navigation;
253
- }) => ScreenListeners<State, EventMap>);
323
+ }) => NoExcessCallbackReturn<
324
+ ProvidedListeners,
325
+ ScreenListeners<State, EventMap>
326
+ >);
254
327
 
255
328
  /**
256
329
  * Layout for this screen.
@@ -268,7 +341,7 @@ export type StaticScreenConfig<
268
341
  *
269
342
  */
270
343
  layout?: (props: {
271
- route: RouteType<Params>;
344
+ route: StaticRoute<Params>;
272
345
  options: ScreenOptions;
273
346
  navigation: Navigation;
274
347
  theme: Theme;
@@ -295,7 +368,9 @@ export type StaticScreenConfig<
295
368
  * getId: ({ params }) => params?.userId,
296
369
  * ```
297
370
  */
298
- getId?: (props: { params: AnyToUnknown<Params> }) => string | undefined;
371
+ getId?: (props: {
372
+ params: AnyToUnknown<Params extends object ? Readonly<Params> : Params>;
373
+ }) => string | undefined;
299
374
 
300
375
  /**
301
376
  * Linking config for the screen.
@@ -317,31 +392,75 @@ export type StaticScreenConfig<
317
392
  * Optional key for this screen.
318
393
  */
319
394
  navigationKey?: string;
320
- };
395
+
396
+ /**
397
+ * Loader function to start loading data when the screen is navigated to.
398
+ *
399
+ * @example
400
+ * ```js
401
+ * UNSTABLE_loader: ({ params }) => loadProfile(params.id),
402
+ * ```
403
+ */
404
+ UNSTABLE_loader?: (options: {
405
+ name: string;
406
+ params: AnyToUnknown<Params>;
407
+ }) => Promise<void>;
408
+ }
409
+
410
+ export type StaticScreenFactory<in out Bag extends NavigatorTypeBagBase> = <
411
+ const Linking extends StaticScreenConfigLinking,
412
+ const Screen extends StaticScreenConfigScreen,
413
+ ProvidedOptions extends {} = {},
414
+ ProvidedListeners extends {} = {},
415
+ >(
416
+ config: StaticScreenConfig<
417
+ Linking,
418
+ Screen,
419
+ Bag['State'],
420
+ Bag['ScreenOptions'],
421
+ Bag['EventMap'],
422
+ Bag['NavigationList'][keyof Bag['ParamList']],
423
+ ParamsForConfig<Linking, Screen>,
424
+ ProvidedOptions,
425
+ ProvidedListeners
426
+ >
427
+ ) => StaticScreenConfig<
428
+ Linking,
429
+ Screen,
430
+ Bag['State'],
431
+ Bag['ScreenOptions'],
432
+ Bag['EventMap'],
433
+ Bag['NavigationList'][keyof Bag['ParamList']]
434
+ >;
435
+
436
+ /**
437
+ * Helper to create a typed `createXScreen` for static configuration.
438
+ */
439
+ export function createScreenFactory<
440
+ TypeBag extends NavigatorTypeBagBase,
441
+ >(): StaticScreenFactory<NavigatorTypeBagFor<TypeBag, ParamListBase>> {
442
+ return ((config: unknown) => config) as never;
443
+ }
321
444
 
322
445
  type StaticConfigScreens<
323
- ParamList extends ParamListBase,
324
- State extends NavigationState,
325
- ScreenOptions extends {},
326
- EventMap extends EventMapBase,
327
- NavigationList extends NavigationListBase<ParamList>,
446
+ in out ParamList extends ParamListBase,
447
+ in out State extends NavigationState,
448
+ in out ScreenOptions extends {},
449
+ in out EventMap extends EventMapBase,
450
+ in out NavigationList extends NavigationListBase<ParamList>,
328
451
  > = {
329
452
  [RouteName in keyof ParamList]:
330
- | React.ComponentType<any>
331
- | StaticNavigation<any, any, any>
453
+ | StaticScreenConfigScreen
332
454
  | StaticScreenConfig<
333
- | {
334
- path: string;
335
- parse?: Record<string, (value: string) => any>;
336
- }
337
- | string
338
- | undefined,
339
- StaticNavigation<any, any, any> | React.ComponentType<any>,
455
+ StaticScreenConfigLinking,
456
+ StaticScreenConfigScreen,
340
457
  State,
341
458
  ScreenOptions,
342
459
  EventMap,
343
460
  NavigationList[RouteName],
344
- any
461
+ any,
462
+ {},
463
+ {}
345
464
  >;
346
465
  };
347
466
 
@@ -360,27 +479,6 @@ type StaticConfigGroup<
360
479
  * This can be useful for conditional rendering of group of screens.
361
480
  */
362
481
  if?: () => boolean;
363
- /**
364
- * Linking config for the screens in the group.
365
- * This can be a string to specify the path, or an object following properties:
366
- * - `path`
367
- * - `stringify`
368
- * - `parse`
369
- *
370
- * The path specified will be prepended to the paths of the screens in the group.
371
- * The `parse` and `stringify` properties will be merged.
372
- *
373
- * @example
374
- * ```js
375
- * linking: {
376
- * path: 'users/:id',
377
- * parse: {
378
- * id: (id) => parseInt(id, 10),
379
- * }
380
- * },
381
- * ```
382
- */
383
- linking?: LinkingForGroup;
384
482
  /**
385
483
  * Static navigation config or Component to render for the screen.
386
484
  */
@@ -393,101 +491,160 @@ type StaticConfigGroup<
393
491
  >;
394
492
  };
395
493
 
396
- export type StaticConfig<Bag extends NavigatorTypeBagBase> =
397
- StaticConfigInternal<
494
+ type StaticConfigScreensForBag<Bag extends NavigatorTypeBagBase> =
495
+ StaticConfigScreens<
398
496
  Bag['ParamList'],
399
497
  Bag['State'],
400
498
  Bag['ScreenOptions'],
401
499
  Bag['EventMap'],
402
- Bag['NavigationList'],
403
- Bag['Navigator']
500
+ Bag['NavigationList']
404
501
  >;
405
502
 
406
- type StaticConfigInternal<
407
- ParamList extends ParamListBase,
408
- State extends NavigationState,
409
- ScreenOptions extends {},
410
- EventMap extends EventMapBase,
411
- NavigationList extends NavigationListBase<ParamList>,
412
- Navigator extends React.ComponentType<any>,
413
- > = Omit<
414
- Omit<
415
- React.ComponentProps<Navigator>,
416
- keyof DefaultNavigatorOptions<
417
- ParamListBase,
418
- NavigationState,
419
- {},
420
- EventMapBase,
421
- NavigationList[keyof ParamList]
422
- >
423
- > &
424
- DefaultNavigatorOptions<
425
- ParamList,
426
- State,
427
- ScreenOptions,
428
- EventMap,
429
- NavigationList[keyof ParamList]
430
- >,
503
+ type StaticConfigGroupsForBag<Bag extends NavigatorTypeBagBase> = {
504
+ [key: string]: StaticConfigGroup<
505
+ Bag['ParamList'],
506
+ Bag['State'],
507
+ Bag['ScreenOptions'],
508
+ Bag['EventMap'],
509
+ Bag['NavigationList']
510
+ >;
511
+ };
512
+
513
+ type StaticConfigCommon<Bag extends NavigatorTypeBagBase> = Omit<
514
+ NavigatorProps<
515
+ Bag['ParamList'],
516
+ Bag['State'],
517
+ Bag['ScreenOptions'],
518
+ Bag['EventMap'],
519
+ Bag['NavigationList'][keyof Bag['ParamList']],
520
+ Bag['Navigator']
521
+ >,
431
522
  'screens' | 'children'
432
- > &
523
+ >;
524
+
525
+ type StaticConfigBase<
526
+ Bag extends NavigatorTypeBagBase,
527
+ Screens = StaticConfigScreensForBag<Bag>,
528
+ Groups = StaticConfigGroupsForBag<Bag>,
529
+ > = StaticConfigCommon<Bag> & {
530
+ /**
531
+ * Screens to render in the navigator and their configuration.
532
+ */
533
+ screens?: Screens;
534
+ /**
535
+ * Groups of screens to render in the navigator and their configuration.
536
+ */
537
+ groups?: Groups;
538
+ };
539
+
540
+ export type StaticConfig<
541
+ Bag extends NavigatorTypeBagBase,
542
+ Screens = StaticConfigScreensForBag<Bag>,
543
+ Groups = StaticConfigGroupsForBag<Bag>,
544
+ > = StaticConfigCommon<Bag> &
433
545
  (
434
546
  | {
435
547
  /**
436
548
  * Screens to render in the navigator and their configuration.
437
549
  */
438
- screens: StaticConfigScreens<
439
- ParamList,
440
- State,
441
- ScreenOptions,
442
- EventMap,
443
- NavigationList
444
- >;
550
+ screens: Screens;
445
551
  /**
446
552
  * Groups of screens to render in the navigator and their configuration.
447
553
  */
448
- groups?: {
449
- [key: string]: StaticConfigGroup<
450
- ParamList,
451
- State,
452
- ScreenOptions,
453
- EventMap,
454
- NavigationList
455
- >;
456
- };
554
+ groups?: Groups;
457
555
  }
458
556
  | {
459
557
  /**
460
558
  * Screens to render in the navigator and their configuration.
461
559
  */
462
- screens?: StaticConfigScreens<
463
- ParamList,
464
- State,
465
- ScreenOptions,
466
- EventMap,
467
- NavigationList
468
- >;
560
+ screens?: Screens;
469
561
  /**
470
562
  * Groups of screens to render in the navigator and their configuration.
471
563
  */
472
- groups: {
473
- [key: string]: StaticConfigGroup<
474
- ParamList,
475
- State,
476
- ScreenOptions,
477
- EventMap,
478
- NavigationList
479
- >;
480
- };
564
+ groups: Groups;
481
565
  }
482
566
  );
483
567
 
568
+ type NoExcessScreen<
569
+ Screen,
570
+ ScreenOptions extends {},
571
+ Listeners extends {},
572
+ > = (Screen extends { screen: unknown; options: unknown }
573
+ ? { options: NoExcessValue<Screen['options'], ScreenOptions> }
574
+ : unknown) &
575
+ (Screen extends { screen: unknown; listeners: unknown }
576
+ ? { listeners: NoExcessValue<Screen['listeners'], Listeners> }
577
+ : unknown);
578
+
579
+ type NoExcessScreens<
580
+ Screens,
581
+ ScreenOptions extends {},
582
+ Listeners extends {},
583
+ > = {
584
+ [RouteName in keyof Screens]: NoExcessScreen<
585
+ Screens[RouteName],
586
+ ScreenOptions,
587
+ Listeners
588
+ >;
589
+ };
590
+
591
+ type NoExcessGroups<
592
+ Groups,
593
+ Bag extends NavigatorTypeBagBase,
594
+ ScreenOptions extends {},
595
+ Listeners extends {},
596
+ > = {
597
+ [GroupName in keyof Groups]: NoExcessObject<
598
+ Groups[GroupName],
599
+ StaticConfigGroup<
600
+ ParamListBase,
601
+ NavigationState,
602
+ {},
603
+ EventMapBase,
604
+ NavigationListBase<ParamListBase>
605
+ >
606
+ > &
607
+ NoExcessStaticConfig<Groups[GroupName], Bag, ScreenOptions, Listeners>;
608
+ };
609
+
610
+ // Each property is probed with `Config extends { key: infer X }` and the results are intersected.
611
+ // These conditionals stay deferred while the config is inferred, so they don't interfere with the inference.
612
+ // Indexed access (`Config['screens']`) or a mapped type over the whole config breaks the param list inference.
613
+ export type NoExcessStaticConfig<
614
+ Config,
615
+ Bag extends NavigatorTypeBagBase,
616
+ ScreenOptions extends {} = Bag['ScreenOptions'],
617
+ Listeners extends {} = ScreenListeners<Bag['State'], Bag['EventMap']>,
618
+ > = (Config extends { screenOptions: infer ProvidedOptions }
619
+ ? {
620
+ screenOptions: NoExcessValue<ProvidedOptions, ScreenOptions>;
621
+ }
622
+ : unknown) &
623
+ (Config extends { screenListeners: infer ProvidedListeners }
624
+ ? {
625
+ screenListeners: NoExcessValue<ProvidedListeners, Listeners>;
626
+ }
627
+ : unknown) &
628
+ (Config extends { screens: infer Screens }
629
+ ? {
630
+ screens: NoExcessScreens<Screens, ScreenOptions, Listeners>;
631
+ }
632
+ : unknown) &
633
+ (Config extends { groups: infer Groups }
634
+ ? {
635
+ groups: NoExcessGroups<Groups, Bag, ScreenOptions, Listeners>;
636
+ }
637
+ : unknown);
638
+
484
639
  /**
485
640
  * Props for a screen component which is rendered by a static navigator.
486
641
  * Takes the route params as a generic argument.
487
642
  */
488
- export type StaticScreenProps<T extends Record<string, unknown> | undefined> = {
643
+ export type StaticScreenProps<
644
+ in out T extends Record<string, unknown> | undefined,
645
+ > = {
489
646
  route: {
490
- params: T;
647
+ readonly params: T;
491
648
  };
492
649
  };
493
650
 
@@ -503,17 +660,13 @@ export type StaticParamList<
503
660
  ParamListForGroups<T['config']['groups']>
504
661
  >;
505
662
 
506
- type StaticNavigationBase = {
507
- config: StaticConfig<NavigatorTypeBagBase>;
663
+ export type StaticNavigation<
664
+ in out NavigatorTypeBag extends NavigatorTypeBagBase,
665
+ > = {
666
+ config: StaticConfigBase<NavigatorTypeBag>;
667
+ getComponent: () => React.ComponentType<{}>;
508
668
  };
509
669
 
510
- export type StaticNavigation<NavigatorProps, GroupProps, ScreenProps> =
511
- StaticNavigationBase & {
512
- Navigator: React.ComponentType<NavigatorProps>;
513
- Group: React.ComponentType<GroupProps>;
514
- Screen: React.ComponentType<ScreenProps>;
515
- };
516
-
517
670
  const MemoizedScreen = React.memo(
518
671
  <T extends React.ComponentType<any>>({ component }: { component: T }) => {
519
672
  const route = useRoute();
@@ -525,6 +678,9 @@ const MemoizedScreen = React.memo(
525
678
 
526
679
  MemoizedScreen.displayName = 'Memo(Screen)';
527
680
 
681
+ const hasPropertyGetter = (object: object, property: PropertyKey) =>
682
+ Object.getOwnPropertyDescriptor(object, property)?.get != null;
683
+
528
684
  const getItemsFromScreens = (
529
685
  Screen: React.ComponentType<any>,
530
686
  screens: StaticConfigScreens<any, any, any, any, any>
@@ -535,41 +691,88 @@ const getItemsFromScreens = (
535
691
  let useIf: (() => boolean) | undefined;
536
692
 
537
693
  let isNavigator = false;
694
+ let getComponent: (() => React.ComponentType<any>) | undefined;
538
695
 
539
696
  if ('screen' in item) {
540
- const { screen, if: _if, ...rest } = item;
541
-
542
- useIf = _if;
543
- props = rest;
544
-
545
- if (isValidElementType(screen)) {
546
- component = screen;
547
- } else if ('config' in screen) {
548
- isNavigator = true;
549
- component = createComponentForStaticNavigation(
550
- screen,
551
- `${name}Navigator`
552
- );
697
+ if (hasPropertyGetter(item, 'screen')) {
698
+ const rest: Record<string, unknown> = {};
699
+
700
+ // Iterate over the keys to avoid triggering the getter for 'screen'
701
+ for (const key of Object.keys(item)) {
702
+ if (key === 'screen' || key === 'if') {
703
+ continue;
704
+ }
705
+
706
+ rest[key] = Reflect.get(item, key);
707
+ }
708
+
709
+ useIf = item.if;
710
+ props = rest;
711
+
712
+ getComponent = () => {
713
+ const screen = item.screen;
714
+
715
+ if (isValidElementType(screen)) {
716
+ return screen;
717
+ }
718
+
719
+ if (
720
+ screen != null &&
721
+ typeof screen === 'object' &&
722
+ 'config' in screen
723
+ ) {
724
+ throw new Error(
725
+ `Got a navigator object for the screen '${name}' instead of a component. A navigator cannot be specified when using a getter.`
726
+ );
727
+ }
728
+
729
+ throw new Error(
730
+ `Got an invalid screen component for the screen '${name}'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.`
731
+ );
732
+ };
733
+ } else {
734
+ const { screen, if: _if, ...rest } = item;
735
+
736
+ useIf = _if;
737
+ props = rest;
738
+
739
+ if (isValidElementType(screen)) {
740
+ component = screen;
741
+ } else if ('config' in screen) {
742
+ isNavigator = true;
743
+ component = screen.getComponent();
744
+ }
553
745
  }
554
746
  } else if (isValidElementType(item)) {
555
747
  component = item;
556
748
  } else if ('config' in item) {
557
749
  isNavigator = true;
558
- component = createComponentForStaticNavigation(item, `${name}Navigator`);
750
+ component = item.getComponent();
751
+ }
752
+
753
+ let children: (() => React.JSX.Element) | undefined;
754
+
755
+ if (getComponent != null) {
756
+ let element: React.JSX.Element | undefined;
757
+
758
+ children = () =>
759
+ (element ??= <MemoizedScreen component={getComponent()} />);
760
+ } else if (component != null) {
761
+ const element = isNavigator ? (
762
+ React.createElement(component, {})
763
+ ) : (
764
+ <MemoizedScreen component={component} />
765
+ );
766
+
767
+ children = () => element;
559
768
  }
560
769
 
561
- if (component == null) {
770
+ if (children == null) {
562
771
  throw new Error(
563
772
  `Couldn't find a 'screen' property for the screen '${name}'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.`
564
773
  );
565
774
  }
566
775
 
567
- const element = isNavigator ? (
568
- React.createElement(component, {})
569
- ) : (
570
- <MemoizedScreen component={component} />
571
- );
572
-
573
776
  return () => {
574
777
  const shouldRender = useIf == null || useIf();
575
778
 
@@ -579,7 +782,7 @@ const getItemsFromScreens = (
579
782
 
580
783
  return (
581
784
  <Screen key={name} name={name} {...props}>
582
- {() => element}
785
+ {children}
583
786
  </Screen>
584
787
  );
585
788
  };
@@ -593,8 +796,13 @@ const getItemsFromScreens = (
593
796
  * @param displayName Name of the component to be displayed in React DevTools.
594
797
  * @returns A component which renders the navigator.
595
798
  */
596
- export function createComponentForStaticNavigation<
597
- T extends StaticNavigation<any, any, any>,
799
+ export function createComponentForStaticConfig<
800
+ T extends {
801
+ Navigator: React.ComponentType<any>;
802
+ Group: React.ComponentType<any>;
803
+ Screen: React.ComponentType<any>;
804
+ config: StaticConfig<NavigatorTypeBagBase>;
805
+ },
598
806
  >(
599
807
  tree: T,
600
808
  displayName: string
@@ -643,6 +851,12 @@ export function createComponentForStaticNavigation<
643
851
  }
644
852
  }
645
853
 
854
+ if (items.length === 0) {
855
+ throw new Error(
856
+ "Couldn't find any screens in the 'screens' or 'groups' property. Make sure to define at least one screen in the configuration."
857
+ );
858
+ }
859
+
646
860
  const NavigatorComponent = ({ children: _, ...props }: typeof rest) => {
647
861
  const children = items.map((item) => item());
648
862
 
@@ -659,10 +873,30 @@ export function createComponentForStaticNavigation<
659
873
  })
660
874
  : { ...rest.screenOptions, ...props.screenOptions };
661
875
 
876
+ const screenListeners =
877
+ typeof props.screenListeners === 'function' ||
878
+ typeof rest.screenListeners === 'function'
879
+ ? (options: unknown) => ({
880
+ ...(typeof rest.screenListeners === 'function'
881
+ ? rest.screenListeners(options)
882
+ : rest.screenListeners),
883
+ ...(typeof props.screenListeners === 'function'
884
+ ? props.screenListeners(options)
885
+ : props.screenListeners),
886
+ })
887
+ : { ...rest.screenListeners, ...props.screenListeners };
888
+
662
889
  return (
663
- <Navigator {...rest} {...props} screenOptions={screenOptions}>
664
- {children}
665
- </Navigator>
890
+ <StaticTreeContext.Provider value={tree}>
891
+ <Navigator
892
+ {...rest}
893
+ {...props}
894
+ screenOptions={screenOptions}
895
+ screenListeners={screenListeners}
896
+ >
897
+ {children}
898
+ </Navigator>
899
+ </StaticTreeContext.Provider>
666
900
  );
667
901
  };
668
902
 
@@ -671,33 +905,111 @@ export function createComponentForStaticNavigation<
671
905
  return NavigatorComponent;
672
906
  }
673
907
 
674
- type LinkingForGroup =
675
- | Pick<PathConfig<any>, 'path' | 'stringify' | 'parse'>
676
- | string;
908
+ export type TreeForPathConfig = {
909
+ config: ConfigForPathConfig;
910
+ };
677
911
 
678
- type TreeForPathConfig = {
679
- config: {
680
- initialRouteName?: string;
681
- screens?: StaticConfigScreens<
682
- ParamListBase,
683
- NavigationState,
684
- {},
685
- EventMapBase,
686
- Record<string, unknown>
687
- >;
688
- groups?: {
689
- [key: string]: {
690
- linking?: LinkingForGroup;
691
- screens: StaticConfigScreens<
692
- ParamListBase,
693
- NavigationState,
694
- {},
695
- EventMapBase,
696
- Record<string, unknown>
697
- >;
698
- };
912
+ type ConfigForPathConfig = {
913
+ initialRouteName?: string;
914
+ screens?: Record<string, ScreenForPathConfig>;
915
+ groups?: Record<string, { screens: Record<string, ScreenForPathConfig> }>;
916
+ };
917
+
918
+ type LinkingForPathConfig =
919
+ | string
920
+ | (Partial<StaticScreenConfigLinkingAlias> & StaticScreenConfigLinkingExtras)
921
+ | null
922
+ | undefined;
923
+
924
+ type ScreenValueForPathConfig = React.ComponentType<{}> | TreeForPathConfig;
925
+
926
+ type ScreenForPathConfig =
927
+ | ScreenValueForPathConfig
928
+ | {
929
+ screen: ScreenValueForPathConfig;
930
+ initialParams?: object;
931
+ linking?: LinkingForPathConfig;
932
+ UNSTABLE_loader?: unknown;
699
933
  };
934
+
935
+ type PathConfigMapForStaticNavigation = Record<
936
+ string,
937
+ string | PathConfigForStaticNavigation | undefined
938
+ >;
939
+
940
+ type PathConfigForStaticNavigation = Omit<
941
+ PathConfig<ParamListBase>,
942
+ 'screens'
943
+ > & {
944
+ initialRouteName?: string | undefined;
945
+ screens?: PathConfigMapForStaticNavigation | undefined;
946
+ };
947
+
948
+ // Mark screens that resolve to the same pattern and same component or navigator
949
+ const markSharedPathConfigs = (
950
+ screens: PathConfigMapForStaticNavigation,
951
+ sources: WeakMap<PathConfigForStaticNavigation, ScreenForPathConfig>,
952
+ blocked: WeakSet<PathConfigForStaticNavigation>
953
+ ) => {
954
+ const candidates = new Map<string, PathConfigForStaticNavigation[]>();
955
+
956
+ const collect = (
957
+ screens: PathConfigMapForStaticNavigation,
958
+ parentParts: PatternPart[],
959
+ disabled: boolean
960
+ ) => {
961
+ for (const config of Object.values(screens)) {
962
+ if (config == null || typeof config === 'string') {
963
+ continue;
964
+ }
965
+
966
+ const parts =
967
+ typeof config.path === 'string'
968
+ ? combinePatternParts(
969
+ parentParts,
970
+ getPatternParts(config.path),
971
+ config.exact
972
+ )
973
+ : parentParts;
974
+
975
+ if (sources.has(config) && typeof config.path === 'string') {
976
+ if (disabled) {
977
+ blocked.add(config);
978
+ }
979
+
980
+ const pattern = parts.map((part) => part.segment).join('/');
981
+ const entries = candidates.get(pattern) ?? [];
982
+
983
+ entries.push(config);
984
+ candidates.set(pattern, entries);
985
+ }
986
+
987
+ if (config.screens) {
988
+ collect(config.screens, parts, disabled || config.shared === false);
989
+ }
990
+ }
700
991
  };
992
+
993
+ collect(screens, [], false);
994
+
995
+ for (const entries of candidates.values()) {
996
+ for (const entry of entries) {
997
+ const source = sources.get(entry);
998
+
999
+ if (
1000
+ entry.shared === undefined &&
1001
+ !blocked.has(entry) &&
1002
+ entries.some(
1003
+ (candidate) =>
1004
+ candidate !== entry &&
1005
+ !blocked.has(candidate) &&
1006
+ sources.get(candidate) === source
1007
+ )
1008
+ ) {
1009
+ entry.shared = true;
1010
+ }
1011
+ }
1012
+ }
701
1013
  };
702
1014
 
703
1015
  /**
@@ -719,32 +1031,49 @@ type TreeForPathConfig = {
719
1031
  * };
720
1032
  * ```
721
1033
  */
722
- export function createPathConfigForStaticNavigation(
1034
+ export function createPathConfigForStaticNavigation<ParamList extends {}>(
723
1035
  tree: TreeForPathConfig,
724
1036
  options?: {
725
- initialRouteName?: string;
1037
+ initialRouteName?: string | undefined;
726
1038
  },
727
1039
  auto?: boolean
728
- ): PathConfigMap<ParamListBase> | undefined {
1040
+ ): PathConfigMap<ParamList> | undefined {
729
1041
  let initialScreenHasPath: boolean = false;
730
1042
  let initialScreenConfig: PathConfig<{}> | undefined;
1043
+ let hasEmptyPath = false;
1044
+
1045
+ const blocked = new WeakSet<PathConfigForStaticNavigation>();
1046
+ const sources = new WeakMap<
1047
+ PathConfigForStaticNavigation,
1048
+ ScreenForPathConfig
1049
+ >();
731
1050
 
732
1051
  const createPathConfigForTree = (
733
1052
  t: TreeForPathConfig,
734
- o: { initialRouteName?: string } | undefined,
1053
+ o: { initialRouteName?: string | undefined } | undefined,
735
1054
  // If a screen is a leaf node, but inside a screen with path,
736
1055
  // It should not be used for initial detection
737
- skipInitialDetection: boolean
1056
+ skipInitialDetection: boolean,
1057
+ allowAutoEmptyPath: boolean
738
1058
  ) => {
1059
+ const initialRouteName = o?.initialRouteName ?? t.config.initialRouteName;
1060
+
1061
+ if (initialRouteName != null) {
1062
+ const routeNames = new Set(Object.keys(t.config.screens ?? {}));
1063
+
1064
+ for (const group of Object.values(t.config.groups ?? {})) {
1065
+ Object.keys(group.screens).forEach((name) => routeNames.add(name));
1066
+ }
1067
+
1068
+ if (!routeNames.has(initialRouteName)) {
1069
+ throw new Error(
1070
+ `Couldn't find a screen named '${initialRouteName}' to use as 'initialRouteName'.`
1071
+ );
1072
+ }
1073
+ }
1074
+
739
1075
  const createPathConfigForScreens = (
740
- screens: StaticConfigScreens<
741
- ParamListBase,
742
- NavigationState,
743
- {},
744
- EventMapBase,
745
- Record<string, unknown>
746
- >,
747
- groupLinking: LinkingForGroup | undefined,
1076
+ screens: Record<string, ScreenForPathConfig>,
748
1077
  initialRouteName: string | undefined
749
1078
  ) => {
750
1079
  return Object.fromEntries(
@@ -763,95 +1092,149 @@ export function createPathConfigForStaticNavigation(
763
1092
  return 0;
764
1093
  })
765
1094
  .map(([key, item]) => {
766
- const screenConfig: PathConfig<{}> = {};
767
- const groupPath =
768
- typeof groupLinking === 'string'
769
- ? groupLinking
770
- : groupLinking?.path;
771
-
772
- const normalizePath = (path: string) => {
773
- return `${groupPath ?? ''}/${path}`
774
- .replace(/^\//, '') // Remove extra leading slash
775
- .replace(/\/$/, ''); // Remove extra trailing slash
776
- };
777
-
778
- if ('linking' in item) {
1095
+ const screenConfig: PathConfigForStaticNavigation = {};
1096
+
1097
+ sources.set(
1098
+ screenConfig,
1099
+ typeof item === 'object' &&
1100
+ 'screen' in item &&
1101
+ !hasPropertyGetter(item, 'screen')
1102
+ ? item.screen
1103
+ : item
1104
+ );
1105
+
1106
+ const normalizePath = (path: string) =>
1107
+ path.replace(/^\/+|\/+$/g, '');
1108
+
1109
+ if ('linking' in item && item.linking !== undefined) {
779
1110
  if (typeof item.linking === 'string') {
780
1111
  screenConfig.path = item.linking;
781
- } else {
782
- Object.assign(screenConfig, item.linking);
1112
+ } else if (
1113
+ item.linking != null &&
1114
+ typeof item.linking === 'object'
1115
+ ) {
1116
+ Object.assign(screenConfig, { ...item.linking });
783
1117
  }
784
1118
  }
785
1119
 
786
- if (typeof groupLinking !== 'string') {
787
- if (groupLinking?.parse != null) {
788
- screenConfig.parse = {
789
- ...groupLinking.parse,
790
- ...screenConfig.parse,
791
- };
792
- }
793
-
794
- if (groupLinking?.stringify != null) {
795
- screenConfig.stringify = {
796
- ...groupLinking.stringify,
797
- ...screenConfig.stringify,
798
- };
799
- }
1120
+ if (screenConfig.exact && screenConfig.path == null) {
1121
+ throw new Error(
1122
+ "A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`."
1123
+ );
800
1124
  }
801
1125
 
802
1126
  if (typeof screenConfig.path === 'string') {
803
1127
  screenConfig.path = normalizePath(screenConfig.path);
804
1128
  }
805
1129
 
1130
+ if (screenConfig.alias != null) {
1131
+ screenConfig.alias = screenConfig.alias.map((alias) => {
1132
+ if (typeof alias === 'string') {
1133
+ return normalizePath(alias);
1134
+ }
1135
+
1136
+ return {
1137
+ ...alias,
1138
+ path: normalizePath(alias.path),
1139
+ };
1140
+ });
1141
+ }
1142
+
806
1143
  let screens;
807
1144
 
1145
+ const hasExplicitScreens =
1146
+ 'screens' in screenConfig && screenConfig.screens != null;
1147
+ const hasDisabledLinking =
1148
+ 'linking' in item && item.linking === null;
1149
+ const childOptions =
1150
+ 'initialRouteName' in screenConfig &&
1151
+ typeof screenConfig.initialRouteName === 'string'
1152
+ ? { initialRouteName: screenConfig.initialRouteName }
1153
+ : undefined;
1154
+
1155
+ if (
1156
+ hasExplicitScreens &&
1157
+ childOptions != null &&
1158
+ !Object.keys(screenConfig.screens ?? {}).includes(
1159
+ childOptions.initialRouteName
1160
+ )
1161
+ ) {
1162
+ throw new Error(
1163
+ `Couldn't find a screen named '${childOptions.initialRouteName}' to use as 'initialRouteName'.`
1164
+ );
1165
+ }
1166
+
808
1167
  const skipInitialDetectionInChild =
809
1168
  skipInitialDetection ||
810
1169
  (screenConfig.path != null && screenConfig.path !== '');
1170
+ const allowAutoEmptyPathInChild =
1171
+ allowAutoEmptyPath &&
1172
+ (initialRouteName == null || key === initialRouteName);
811
1173
 
812
- if ('config' in item) {
1174
+ if (
1175
+ !hasExplicitScreens &&
1176
+ !hasDisabledLinking &&
1177
+ 'config' in item
1178
+ ) {
813
1179
  screens = createPathConfigForTree(
814
1180
  item,
815
- undefined,
816
- skipInitialDetectionInChild
1181
+ childOptions,
1182
+ skipInitialDetectionInChild,
1183
+ allowAutoEmptyPathInChild
817
1184
  );
818
1185
  } else if (
1186
+ !hasExplicitScreens &&
1187
+ !hasDisabledLinking &&
819
1188
  'screen' in item &&
1189
+ !hasPropertyGetter(item, 'screen') &&
820
1190
  'config' in item.screen &&
821
1191
  (item.screen.config.screens || item.screen.config.groups)
822
1192
  ) {
823
1193
  screens = createPathConfigForTree(
824
1194
  item.screen,
825
- undefined,
826
- skipInitialDetectionInChild
1195
+ childOptions,
1196
+ skipInitialDetectionInChild,
1197
+ allowAutoEmptyPathInChild
827
1198
  );
828
1199
  }
829
1200
 
830
1201
  if (screens) {
831
- // @ts-expect-error - we can't type this properly
832
1202
  screenConfig.screens = screens;
833
1203
  }
834
1204
 
835
1205
  if (
836
1206
  auto &&
837
1207
  !('screens' in screenConfig && screenConfig.screens) &&
838
- // Skip generating path for screens that specify linking config as `undefined` or `null` explicitly
839
- !('linking' in item && item.linking == null)
1208
+ // Skip generating path for screens that specify linking config as `null` explicitly
1209
+ !hasDisabledLinking
840
1210
  ) {
841
1211
  if (screenConfig.path != null) {
842
1212
  if (!skipInitialDetection) {
843
- if (key === initialRouteName && screenConfig.path != null) {
844
- initialScreenHasPath = true;
845
- } else if (screenConfig.path === '') {
1213
+ if (screenConfig.path === '') {
846
1214
  // We encounter a leaf screen with empty path,
847
1215
  // Clear the initial screen config as it's not needed anymore
848
1216
  initialScreenConfig = undefined;
1217
+ hasEmptyPath = true;
1218
+
1219
+ if (allowAutoEmptyPath && key === initialRouteName) {
1220
+ initialScreenHasPath = true;
1221
+ }
1222
+ } else if (
1223
+ allowAutoEmptyPath &&
1224
+ key === initialRouteName &&
1225
+ // Keep an already discovered fallback unless the initial route
1226
+ // explicitly uses an empty path.
1227
+ initialScreenConfig == null
1228
+ ) {
1229
+ initialScreenHasPath = true;
849
1230
  }
850
1231
  }
851
1232
  } else {
852
1233
  if (
853
- !groupPath &&
854
1234
  !skipInitialDetection &&
1235
+ allowAutoEmptyPath &&
1236
+ (initialRouteName == null || key === initialRouteName) &&
1237
+ !hasEmptyPath &&
855
1238
  initialScreenConfig == null
856
1239
  ) {
857
1240
  initialScreenConfig = screenConfig;
@@ -859,8 +1242,8 @@ export function createPathConfigForStaticNavigation(
859
1242
 
860
1243
  screenConfig.path = normalizePath(
861
1244
  key
862
- .replace(/([A-Z]+)/g, '-$1')
863
- .replace(/^-/, '')
1245
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
1246
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
864
1247
  .toLowerCase()
865
1248
  );
866
1249
  }
@@ -872,7 +1255,7 @@ export function createPathConfigForStaticNavigation(
872
1255
  );
873
1256
  };
874
1257
 
875
- const screens = {};
1258
+ const screens: PathConfigMapForStaticNavigation = {};
876
1259
 
877
1260
  // Loop through the config to find screens and groups
878
1261
  // So we add the screens and groups in the same order as they are defined
@@ -882,7 +1265,6 @@ export function createPathConfigForStaticNavigation(
882
1265
  screens,
883
1266
  createPathConfigForScreens(
884
1267
  t.config.screens,
885
- undefined,
886
1268
  o?.initialRouteName ?? t.config.initialRouteName
887
1269
  )
888
1270
  );
@@ -894,7 +1276,6 @@ export function createPathConfigForStaticNavigation(
894
1276
  screens,
895
1277
  createPathConfigForScreens(
896
1278
  group.screens,
897
- group.linking,
898
1279
  o?.initialRouteName ?? t.config.initialRouteName
899
1280
  )
900
1281
  );
@@ -909,11 +1290,17 @@ export function createPathConfigForStaticNavigation(
909
1290
  return screens;
910
1291
  };
911
1292
 
912
- const screens = createPathConfigForTree(tree, options, false);
1293
+ const screens = createPathConfigForTree(tree, options, false, true);
913
1294
 
914
1295
  if (auto && initialScreenConfig && !initialScreenHasPath) {
915
1296
  initialScreenConfig.path = '';
916
1297
  }
917
1298
 
918
- return screens;
1299
+ if (!screens) {
1300
+ return undefined;
1301
+ }
1302
+
1303
+ markSharedPathConfigs(screens, sources, blocked);
1304
+
1305
+ return screens as PathConfigMap<ParamList>;
919
1306
  }